Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1385709
  • 博文数量: 478
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 4833
  • 用 户 组: 普通用户
  • 注册时间: 2014-06-28 11:12
文章分类

全部博文(478)

文章存档

2019年(1)

2018年(27)

2017年(21)

2016年(171)

2015年(258)

我的朋友

分类: Android平台

2016-05-26 11:44:50

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__":之后的语句作为模块被调用的时候不执行;直接使用的时候,语句之后的代码执行。而这里很显然是直接使用。


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



[python] view plain copy
 print?
  1. def main(argv):  
  2.   """将用户设定的 Option 存入 OPTIONS 变量中。OPTIONS是一个Python Class, 我们将其理解为一个C Struct或者一个java的封装即可"""  
  3.   def option_handler(o, a):  
  4.     if o in ("-b""--board_config"):#in是一个布尔操作符,用来测试左边的操作数是否包含于右边的元祖,这里用来判断参数o所传入的值是否包含在("-b", "--board_config")中;  
  5.       pass   # deprecated  
  6.     elif o in ("-k""--package_key"):  
  7.       OPTIONS.package_key = a  
  8.     elif o in ("-i""--incremental_from"):  
  9.       OPTIONS.incremental_source = a  
  10.     elif o in ("-w""--wipe_user_data"):  
  11.       OPTIONS.wipe_user_data = True  
  12.     elif o in ("-n""--no_prereq"):  
  13.       OPTIONS.omit_prereq = True  
  14.     elif o in ("-e""--extra_script"):  
  15.       OPTIONS.extra_script = a  
  16.     elif o in ("-a""--aslr_mode"):  
  17.       if a in ("on""On""true""True""yes""Yes"):  
  18.         OPTIONS.aslr_mode = True  
  19.       else:  
  20.         OPTIONS.aslr_mode = False  
  21.     elif o in ("--worker_threads"):  
  22.       OPTIONS.worker_threads = int(a)  
  23.     elif o in ("-2""--two_step"):  
  24.       OPTIONS.two_step = True  
  25.     elif o in ("-r""--preloader"):  
  26.       OPTIONS.preloader = a  
  27.     elif o in ("-l""--logo"):  
  28.       OPTIONS.logo = a  
  29.     elif o in ("-u""--uboot"):  
  30.       OPTIONS.uboot = a  
  31.     elif o in ("-d""--dsp"):  
  32.       OPTIONS.dsp = a  
  33.     elif o in ("-f""--special_factory_reset"):  
  34.       OPTIONS.special_factory_reset = True  
  35.     elif o in ("-g""--ubifs"):  
  36.       OPTIONS.ubifs = True    
  37.     elif o in ("-t""--tee"):  
  38.       OPTIONS.tee = a   
  39.     elif o in ("-z""--trustonic"):  
  40.       OPTIONS.trustonic = a  
  41.     else:  
  42.       return False  
  43.     return True  

二,解析参数



[python] view plain copy
 print?
  1. #解析参数  
  2. args = common.ParseOptions(argv, __doc__,  
  3.                            extra_opts="b:k:i:d:wfgne:r:l:u:t:z:d:a:s:2",  
  4.                            extra_long_opts=["board_config=",  
  5.                                             "package_key=",  
  6.                                             "incremental_from=",  
  7.                                             "wipe_user_data",  
  8.                                             "special_factory_reset",  
  9.                                             "ubifs",  
  10.                                             "no_prereq",  
  11.                                             "extra_script=",  
  12.                                             "preloader=",  
  13.                                             "logo=",  
  14.                                             "uboot=",  
  15.                                             "tee=",  
  16.                                             "trustonic=",  
  17.                                             "dsp=",  
  18.                                             "worker_threads=",  
  19.                                             "aslr_mode=",  
  20.                                             "two_step",  
  21.                                             ],  
  22.                            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的使用


[python] view plain copy
 print?
  1. #解析参数  
  2. def ParseOptions(argv,  
  3.                  docstring,  
  4.                  extra_opts="", extra_long_opts=(),  
  5.                  extra_option_handler=None):  
  6.   """Parse the options in argv and return any arguments that aren't 
  7.   flags.  docstring is the calling module's docstring, to be displayed 
  8.   for errors and -h.  extra_opts and extra_long_opts are for flags 
  9.   defined by the caller, which are processed by passing them to 
  10.   extra_option_handler."""  
  11.   
  12.   try:  
  13.     opts, args = getopt.getopt(  
  14.         argv, "hvp:s:x:" + extra_opts,  
  15.         ["help""verbose""path=""signapk_path=""extra_signapk_args=",  
  16.          "java_path=""public_key_suffix=""private_key_suffix=",  
  17.          "device_specific=""extra="] +  
  18.         list(extra_long_opts))  
  19.           
  20.           
  21.     #那么我们可以在这里添加log来查看opts、args中的值  
  22.     print("begin")  
  23.     for i in range(len(opts)):  
  24.         print(opts[i])  
  25.     print("************")  
  26.     for i in range(len(args)):  
  27.         print(args[i])  
  28.     print("end")  
  29.       
  30.       
  31.   except getopt.GetoptError, err:  
  32.     Usage(docstring)  
  33.     print "**", str(err), "**"  
  34.     sys.exit(2)  
  35.   
  36.   path_specified = False  
  37.   
  38.   for o, a in opts:  
  39.     if o in ("-h""--help"):  
  40.       Usage(docstring)  
  41.       sys.exit()  
  42.     elif o in ("-v""--verbose"):  
  43.       OPTIONS.verbose = True  
  44.     elif o in ("-p""--path"):  
  45.       OPTIONS.search_path = a  
  46.     elif o in ("--signapk_path",):  
  47.       OPTIONS.signapk_path = a  
  48.     elif o in ("--extra_signapk_args",):  
  49.       OPTIONS.extra_signapk_args = shlex.split(a)  
  50.     elif o in ("--java_path",):  
  51.       OPTIONS.java_path = a  
  52.     elif o in ("--public_key_suffix",):  
  53.       OPTIONS.public_key_suffix = a  
  54.     elif o in ("--private_key_suffix",):  
  55.       OPTIONS.private_key_suffix = a  
  56.     elif o in ("-s""--device_specific"):  
  57.       OPTIONS.device_specific = a  
  58.     elif o in ("-x""--extra"):  
  59.       key, value = a.split("="1)  
  60.       OPTIONS.extras[key] = value  
  61.     else:  
  62.       if extra_option_handler is None or not extra_option_handler(o, a):  
  63.         assert False"unknown option \"%s\"" % (o,)  
  64.   #环境变量  
  65.   os.environ["PATH"] = (os.path.join(OPTIONS.search_path, "bin") +  
  66.                         os.pathsep + os.environ["PATH"])  
  67.   
  68.   return args  


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


[plain] view plain copy
 print?
  1. begin  
  2. ('-u', 'lk.bin')  
  3. ('-n', '')  
  4. ('-i', 'base.zip')  
  5. ******  
  6. target.zip  
  7. update.zip  
  8. end  
那么参数解析完毕之后,执行流程继续回到ota_from_target_files中的main函数。我们顺着流程接着看。


下面是对完成参数解析的返回值的长度进行一个过滤,这里固定是2,无论是整包或者差分包的制作。

[python] view plain copy
 print?
  1. if len(args) != 2:  
  2.   common.Usage(__doc__)  
  3.   sys.exit(1)  
#这里没有额外的脚本,因此OPTIONS.extra_script的值为None。
[python] view plain copy
 print?
  1. if OPTIONS.extra_script is not None:  
  2.   OPTIONS.extra_script = open(OPTIONS.extra_script).read()  
下面我们来看解压的流程。






阅读(1784) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~