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:
    print
    print "   ERROR: %s" % (e,)
    print
    sys.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   # deprecated
    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):
  """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 = 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()

下面我们来看解压的流程。

时间: 2024-10-14 02:17:11

Android OTA升级包制作脚本详解(一,参数解析)的相关文章

Android OTA升级包制作脚本详解(二,解压缩)

第一步:解压缩(ota_from_target_files) print "unzipping target target-files..." OPTIONS.input_tmp, input_zip = common.UnzipTemp(args[0]) 上面的代码是开始进行解压缩的入口 def UnzipTemp(filename, pattern=None): """Unzip the given archive into a temporary d

Android OTA升级包制作脚本详解(四,生成升级脚本updater-script)

updater-script简介: updater-script是我们升级时所具体使用到的脚本文件,它主要用以控制升级流程的主要逻辑.具体位置位于更新包中/META-INFO/com/google/android/目录下,在我们制作升级包的时候产生. updater-script生成: 那么升级脚本updater-script是如何产生的呢,我们来看ota_from_target_file中的一条语句,这个之前有过介绍. #在/build/tools/releasetools/目录下的模块edi

Android OTA升级包制作脚本详解(五,升级脚本updater-script的执行<1>)

写在前面: 首先当我们执行升级脚本updater-script的时候,就表示我们已经进入了升级安装状态.那么在我们就从实际的安装作为入口开始分析.也就是说我们从install.cpp中的install_package函数开始一步步来分析. 这里主要分析与脚本相关的部分,其他的请参考这位朋友的博文http://blog.chinaunix.net/uid-22028566-id-3533856.html,我也很受启发.这里也借用一张图来帮助流程上的分析. 下面是调用的流程:install_pack

Android OTA升级包制作脚本详解(三,打包)

这是在ota_from_target_files中mian函数中打包的主要流程语句: #抽象一个新的临时文件 temp_zip_file = tempfile.NamedTemporaryFile() #创建一个zip包用来进行打包 output_zip = zipfile.ZipFile(temp_zip_file, "w", compression=zipfile.ZIP_DEFLATED) #判断是差分还是整包 if OPTIONS.incremental_source is N

android OTA升级包制作

0.签名 java -Xmx2048m -jar out/host/linux-x86/framework/signapk.jar -w build/target/product/security/testkey.x509.pem build/target/product/security/testkey.pk8 这个key是debug模式下自动生成的key 你也可以通过openssl创建自己私有的key OTA打包过程中会自动使用生成的key进行签名,OTA升级包里签名的位置如下 │ [OTA

android OTA升级包制作【转】

本文转载自:http://www.thinksaas.cn/topics/0/445/445670.html 0.签名 java -Xmx2048m -jar out/host/linux-x86/framework/signapk.jar -w build/target/product/security/testkey.x509.pem build/target/product/security/testkey.pk8 这个key是debug模式下自动生成的key 你也可以通过openssl创

OTA升级包制作工具处理过程分析

http://blog.csdn.net/ly890700/article/details/56048815 Android Recovery(30) 1.概述 OTA升级包制作工具是一个用python实现的命令行工具.工具位于source_root/ \build\tools\releasetools目录下,入口文件是ota_from_target_files.此工具可对编译生成的源或目标软件版本包进行处理,生成最终的OAT完整升级包(默认),或通过参数-i控制,生成OTA增量升级包(差分包)

Android SDK离线安装方法详解(加速安装)

AndroidSDK在国内下载一直很慢··有时候通宵都下不了一点点,最后只有选择离线安装,现在发出离线安装地址和方法,希望对大家有帮助 一,首先下载SDK的安装包,android-sdk_r10-windows.zip(安装工具)解压到目录,如我的目录D:\programs\android-sdk-windows 下载地址:http://dl.google.com/android/android-sdk_r10-windows.zip(目前最新版) 二,然后新建以下 几个文件夹 platform

[Android新手区] SQLite 操作详解--SQL语法

该文章完全摘自转自:北大青鸟[Android新手区] SQLite 操作详解--SQL语法  :http://home.bdqn.cn/thread-49363-1-1.html SQLite库可以解析大部分标准SQL语言.但它也省去了一些特性并且加入了一些自己的新特性.这篇文档就是试图描述那些SQLite支持/不支持的SQL语法的.查看关键字列表. 如下语法表格中,纯文本用蓝色粗体显示.非终极符号为斜体红色.作为语法一部分的运算符用黑色Roman字体表示. 这篇文档只是对SQLite实现的SQ