Android OTA升级包制作脚本详解(一,参数解析)

写在前面:

“build/tools/releasetools/ota_from_target_files-u lk.bin-n target.zip update.zip”这是制作整包的命令,很显然这里支持lk升级。本系列博文主要对该命令的执行流程及原理进行一个系统的分析,涉及到/build/tools/releasetools/目录下多个模块如ota_from_target_files、common等。由于本人对python了解粗浅,文中所涉及到的python语法大都做了注释,以便帮助部分对python有兴趣的同学能够读懂相应的语句。

整个流程看起来有些繁琐冗杂,希望有兴趣的同学能够耐心的去看,已经比较熟悉python语法的同学可以挑选感兴趣的部分作为参考。

一,执行脚本

那么首先,我们从命令中可以看到整包的制作流程是从ota_from_target_files模块开始的。而ota_from_target_files模块最先执行的方法是从下面这段语句开始的,如下:

#__name__作为模块的内置属性,指.py文件的调用方式;.py文件有两种使用方式:作为模块被调用和直接使用。如果它等于"__main__"就表示是直接执行。也就是说在if __name__ == "__main__":之后的语句作为模块被调用的时候不执行;直接使用的时候,语句之后的代码执行。而这里很显然是直接使用。

if __name__ == '__main__': try:common.CloseInheritedPipes()"""MAC系统中却是一些描述文件(PIPE),这里在开始之前关闭fds;这里主要是根据当前所使用的操作系统做的一些调整"""main(sys.argv[1:])"""这是编译脚本主要的方法""" except common.ExternalError, e:printprint " ERROR: %s" % (e,)printsys.exit(1) 下面是脚本的入口函数main(arg)

def main(argv): """将用户设定的 Option 存入 OPTIONS 变量中。OPTIONS是一个Python Class, 我们将其理解为一个C Struct或者一个java的封装即可""" def option_handler(o, a):if o in ("-b", "–board_config"):#in是一个布尔操作符,用来测试左边的操作数是否包含于右边的元祖,这里用来判断参数o所传入的值是否包含在("-b", "–board_config")中;pass # deprecatedelif o in ("-k", "–package_key"):OPTIONS.package_key = aelif o in ("-i", "–incremental_from"):OPTIONS.incremental_source = aelif o in ("-w", "–wipe_user_data"):OPTIONS.wipe_user_data = Trueelif o in ("-n", "–no_prereq"):OPTIONS.omit_prereq = Trueelif o in ("-e", "–extra_script"):OPTIONS.extra_script = aelif o in ("-a", "–aslr_mode"):if a in ("on", "On", "true", "True", "yes", "Yes"):OPTIONS.aslr_mode = Trueelse:OPTIONS.aslr_mode = Falseelif o in ("–worker_threads"):OPTIONS.worker_threads = int(a)elif o in ("-2", "–two_step"):OPTIONS.two_step = Trueelif o in ("-r", "–preloader"):OPTIONS.preloader = aelif o in ("-l", "–logo"):OPTIONS.logo = aelif o in ("-u", "–uboot"):OPTIONS.uboot = aelif o in ("-d", "–dsp"):OPTIONS.dsp = aelif o in ("-f", "–special_factory_reset"):OPTIONS.special_factory_reset = Trueelif o in ("-g", "–ubifs"):OPTIONS.ubifs = Trueelif o in ("-t", "–tee"):OPTIONS.tee = aelif o in ("-z", "–trustonic"):OPTIONS.trustonic = aelse:return Falsereturn True二,解析参数

#解析参数 args = common.ParseOptions(argv, __doc__,extra_opts="b:k:i:d:wfgne:r:l:u:t:z:d:a:s:2",extra_long_opts=["board_config=","package_key=","incremental_from=","wipe_user_data","special_factory_reset","ubifs","no_prereq","extra_script=","preloader=","logo=","uboot=","tee=","trustonic=","dsp=","worker_threads=","aslr_mode=","two_step",],extra_option_handler=option_handler) 上面解析参数的操作实际上是封装在了common.py模块来进行,这里我们对extra_option_handler=option_handler简单的解释一下,在Python中函数是可以直接复制给一个变量的,option_handler是上面定义的一个方法,而这里并没有执行,而是直接赋值给了extra_option_handler,而且我们需要注意的是赋值并不会执行option_handler中内容,而是在实际调用的时候才会执行。那么既然变量可以指向函数,所以一个函数可以接收另外一个函数作为参数。

那么我们接着来了解函数解析的流程,,首先看代码:

#在python中,getopt模块是专门用来处理命令行参数的,这里args是个列表,包含那些没有"-"或"–"的参数,格式如下[‘target.zip’,’update.zip’],而opts是个包含元祖的列表,每个元祖是分析出来的格式信息,如[(‘-u’, ‘lk.bin’),(‘-n’, ”),(‘-i’, ‘base.zip’)] ;如果想了解getopt具体的逻辑请参考这篇博文python中getopt的使用。

#解析参数def ParseOptions(argv,docstring,extra_opts="", extra_long_opts=(),extra_option_handler=None): """Parse the options in argv and return any arguments that aren't flags. docstring is the calling module's docstring, to be displayed for errors and -h. extra_opts and extra_long_opts are for flags defined by the caller, which are processed by passing them to extra_option_handler.""" try:opts, args = getopt.getopt(argv, "hvp:s:x:" + extra_opts,["help", "verbose", "path=", "signapk_path=", "extra_signapk_args=","java_path=", "public_key_suffix=", "private_key_suffix=","device_specific=", "extra="] +list(extra_long_opts))#那么我们可以在这里添加log来查看opts、args中的值print("begin")for i in range(len(opts)):print(opts[i])print("************")for i in range(len(args)):print(args[i])print("end")except getopt.GetoptError, err:Usage(docstring)print "**", str(err), "**"sys.exit(2) path_specified = False for o, a in opts:if o in ("-h", "–help"):Usage(docstring)sys.exit()elif o in ("-v", "–verbose"):OPTIONS.verbose = Trueelif o in ("-p", "–path"):OPTIONS.search_path = aelif o in ("–signapk_path",):OPTIONS.signapk_path = aelif o in ("–extra_signapk_args",):OPTIONS.extra_signapk_args = shlex.split(a)elif o in ("–java_path",):OPTIONS.java_path = aelif o in ("–public_key_suffix",):OPTIONS.public_key_suffix = aelif o in ("–private_key_suffix",):OPTIONS.private_key_suffix = aelif o in ("-s", "–device_specific"):OPTIONS.device_specific = aelif o in ("-x", "–extra"):key, value = a.split("=", 1)OPTIONS.extras[key] = valueelse:if extra_option_handler is None or not extra_option_handler(o, a):assert False, "unknown option \&;%s\&;" % (o,) #环境变量 os.environ["PATH"] = (os.path.join(OPTIONS.search_path, "bin") +os.pathsep + os.environ["PATH"]) return args

下面是具体log打印的信息:

我们大都接受的是正面的教育,

Android OTA升级包制作脚本详解(一,参数解析)

相关文章:

你感兴趣的文章:

标签云: