http://blog.csdn.net/huangyabin001/article/details/43731545
写在前面:
“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语法的同学可以挑选感兴趣的部分作为参考。
一,执行脚本
那么首先,我们从命令中可以看到整包的制作流程是从ota_from_target_files模块开始的。而ota_from_target_files模块最先执行的方法是从下面这段语句开始的,如下:
#__name__作为模块的内置属性,指.py文件的调用方式;.py文件有两种使用方式:作为模块被调用和直接使用。如果它等于"__main__"就表示是直接执行。也就是说在if __name__ == "__main__":之后的语句作为模块被调用的时候不执行;直接使用的时候,语句之后的代码执行。而这里很显然是直接使用。
-
if __name__ == '__main__':
-
try:
-
common.CloseInheritedPipes()
-
main(sys.argv[1:])
-
except common.ExternalError, e:
-
print
-
print " ERROR: %s" % (e,)
-
print
-
sys.exit(1)
下面是脚本的入口函数main(arg)
-
def main(argv):
-
-
def option_handler(o, a):
-
if o in ("-b", "--board_config"):
-
pass
-
elif o in ("-k", "--package_key"):
-
OPTIONS.package_key = a
-
elif o in ("-i", "--incremental_from"):
-
OPTIONS.incremental_source = a
-
elif o in ("-w", "--wipe_user_data"):
-
OPTIONS.wipe_user_data = True
-
elif o in ("-n", "--no_prereq"):
-
OPTIONS.omit_prereq = True
-
elif o in ("-e", "--extra_script"):
-
OPTIONS.extra_script = a
-
elif o in ("-a", "--aslr_mode"):
-
if a in ("on", "On", "true", "True", "yes", "Yes"):
-
OPTIONS.aslr_mode = True
-
else:
-
OPTIONS.aslr_mode = False
-
elif o in ("--worker_threads"):
-
OPTIONS.worker_threads = int(a)
-
elif o in ("-2", "--two_step"):
-
OPTIONS.two_step = True
-
elif o in ("-r", "--preloader"):
-
OPTIONS.preloader = a
-
elif o in ("-l", "--logo"):
-
OPTIONS.logo = a
-
elif o in ("-u", "--uboot"):
-
OPTIONS.uboot = a
-
elif o in ("-d", "--dsp"):
-
OPTIONS.dsp = a
-
elif o in ("-f", "--special_factory_reset"):
-
OPTIONS.special_factory_reset = True
-
elif o in ("-g", "--ubifs"):
-
OPTIONS.ubifs = True
-
elif o in ("-t", "--tee"):
-
OPTIONS.tee = a
-
elif o in ("-z", "--trustonic"):
-
OPTIONS.trustonic = a
-
else:
-
return False
-
return 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):
-
-
-
-
-
-
-
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))
-
-
-
-
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 = True
-
elif o in ("-p", "--path"):
-
OPTIONS.search_path = a
-
elif o in ("--signapk_path",):
-
OPTIONS.signapk_path = a
-
elif o in ("--extra_signapk_args",):
-
OPTIONS.extra_signapk_args = shlex.split(a)
-
elif o in ("--java_path",):
-
OPTIONS.java_path = a
-
elif o in ("--public_key_suffix",):
-
OPTIONS.public_key_suffix = a
-
elif o in ("--private_key_suffix",):
-
OPTIONS.private_key_suffix = a
-
elif o in ("-s", "--device_specific"):
-
OPTIONS.device_specific = a
-
elif o in ("-x", "--extra"):
-
key, value = a.split("=", 1)
-
OPTIONS.extras[key] = value
-
else:
-
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打印的信息:
-
begin
-
('-u', 'lk.bin')
-
('-n', '')
-
('-i', 'base.zip')
-
******
-
target.zip
-
update.zip
-
end
那么参数解析完毕之后,执行流程继续回到ota_from_target_files中的main函数。我们顺着流程接着看。
下面是对完成参数解析的返回值的长度进行一个过滤,这里固定是2,无论是整包或者差分包的制作。
-
if len(args) != 2:
-
common.Usage(__doc__)
-
sys.exit(1)
#这里没有额外的脚本,因此OPTIONS.extra_script的值为None。
-
if OPTIONS.extra_script is not None:
-
OPTIONS.extra_script = open(OPTIONS.extra_script).read()
下面我们来看解压的流程。
阅读(1784) | 评论(0) | 转发(0) |