Android OTA升級包製作指令碼詳解(解壓縮)

來源:互聯網
上載者:User

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 directory and return the name.  If filename is of the form "foo.zip+bar.zip", unzip foo.zip into a  temp dir, then unzip bar.zip into that_dir/BOOTABLE_IMAGES.  Returns (tempdir, zipobj) where zipobj is a zipfile.ZipFile (of the  main file), open for reading.  """  # 該函數用於建立一個臨時檔案夾,參數指的是臨時檔案夾的首碼,傳回值tmp是臨時檔案夾的絕對路徑,並賦給OPTIONS的tempfiles屬性  tmp = tempfile.mkdtemp(prefix="targetfiles-")  OPTIONS.tempfiles.append(tmp)  def unzip_to_dir(filename, dirname):    #這裡設定了一個變數名cmd的數組,裡面存放的是需要執行的命令和參數,這個命令也就是“unzip -o -q filename -d dirname”    cmd = ["unzip", "-o", "-q", filename, "-d", dirname]    if pattern is not None:      cmd.append(pattern)#這裡調用了Run方法    p = Run(cmd, stdout=subprocess.PIPE)"""Popen.communicate(input=None)與子進程進行互動。向stdin發送資料,或從stdout和stderr中讀取資料。選擇性參數input指定發送到子進程的參數。Communicate()返回一個元組:(stdoutdata,stderrdata)。注意:如果希望通過進程的stdin向其發送資料,在建立Popen對象的時候,參數stdin必須被設定為PIPE。同樣,如果希望從stdout和stderr擷取資料,必須將stdout和stderr設定為PIPE。"""    p.communicate()    if p.returncode != 0:      raise ExternalError("failed to unzip input target-files \"%s\"" %                          (filename,))  #match :只從字串的開始與Regex匹配,匹配成功返回所匹配的項,否則返回none;  m = re.match(r"^(.*[.]zip)\+(.*[.]zip)$", filename, re.IGNORECASE)  #如果這裡加上並執行"""print m"""語句的話,結果為"""[target.zip]"""  if m:    unzip_to_dir(m.group(1), tmp)    unzip_to_dir(m.group(2), os.path.join(tmp, "BOOTABLE_IMAGES"))    filename = m.group(1)  else:    #這裡執行解壓操作,檔案名稱的值為"target.zip",tem的值為"/tmp/targetfiles-fEX9aH",並且調用upzip_to_dir方法來執行解壓縮命令    unzip_to_dir(filename, tmp)  #這裡返回臨時路徑和儲存了zipfile內容的變數  # 這裡的第二個參數用r表示是讀取zip檔案,w是建立一個zip檔案  return tmp, zipfile.ZipFile(filename, "r")
#這裡開啟新的進程來執行解壓縮的命令
def Run(args, **kwargs):  """Create and return a subprocess.Popen object, printing the command  line on the terminal if -v was specified."""  if OPTIONS.verbose:    print "  running: ", " ".join(args)  """這裡調用Popen模組開啟新的進程用來執行系統命令,這種方式可運用對進程的控制,將返回結果複製給變數,更方便去處理。args的值實際上是一個list,用於指定進程的可執行檔及其參數。"""  return subprocess.Popen(args, **kwargs)
接著回到main函數中對解壓縮返回的結果進行處理

 

 

  OPTIONS.target_tmp = OPTIONS.input_tmp  OPTIONS.info_dict = common.LoadInfoDict(input_zip)
第二步,解析target.zip中META/misc_info.txt、imagesizes.txt中的資訊,如:

 

這是misc_info.txt中的內容:

 

recovery_api_version=3fstab_version=2tool_extensions=out/target/product/wt98360/obj/CUSTGEN/config/../commondefault_system_dev_certificate=build/target/product/security/testkeymkbootimg_args=use_set_metadata=1update_rename_support=1fs_type=ext4system_size=1363148800userdata_size=1152385024cache_size=132120576extfs_sparse_flag=-smkyaffs2_extra_flags=-c 2048 -s 64   selinux_fc=out/target/product/wt98360/root/file_contexts

 

具體代碼如下:

def LoadInfoDict(zip):  """Read and parse the META/misc_info.txt key/value pairs from the  input target files and return a dict."""  #定義一個字典變數用於儲存處理後的資訊  d = {}  try:    #這裡zip.read()方法開啟update.zip中的META/misc_info.txt,並按"\n"進行切片    for line in zip.read("META/misc_info.txt").split("\n"):      line = line.strip()#用於移除字串頭尾指定的字元(預設為空白格)      if not line or line.startswith("#"): continue#跳過注釋資訊      k, v = line.split("=", 1)#這裡按照第一個"="進行切片      d[k] = v#封裝成資料字典  except KeyError:    # ok if misc_info.txt doesn't exist    pass  # backwards compatibility: These values used to be in their own  # files.  Look for them, in case we're processing an old  # target_files zip.  if "mkyaffs2_extra_flags" not in d:    try:      d["mkyaffs2_extra_flags"] = zip.read("META/mkyaffs2-extra-flags.txt").strip()    except KeyError:      # ok if flags don't exist      pass  if "recovery_api_version" not in d:    try:      d["recovery_api_version"] = zip.read("META/recovery-api-version.txt").strip()    except KeyError:      raise ValueError("can't find recovery API version in input target-files")  if "tool_extensions" not in d:    try:      d["tool_extensions"] = zip.read("META/tool-extensions.txt").strip()    except KeyError:      # ok if extensions don't exist      pass  if "fstab_version" not in d:    d["fstab_version"] = "1"  try:    data = zip.read("META/imagesizes.txt")    for line in data.split("\n"):      if not line: continue      name, value = line.split(" ", 1)      if not value: continue      if name == "blocksize":        d[name] = value      else:        d[name + "_size"] = value  except KeyError:    pass  def makeint(key):    if key in d:      if d[key].endswith('M'):        d[key] = d[key].split("M")[0]        d[key] = int(d[key], 0) * 1024 * 1024      else:        d[key] = int(d[key], 0)  makeint("recovery_api_version")  makeint("blocksize")  makeint("system_size")  makeint("userdata_size")  makeint("cache_size")  makeint("recovery_size")  makeint("boot_size")  makeint("fstab_version")  #wschen 2012-11-07   makeint("custom_size")  d["fstab"] = LoadRecoveryFSTab(zip, d["fstab_version"])  d["build.prop"] = LoadBuildProp(zip)  return d

 

上面的代碼中,在方法的末尾有分別去解析了分區表和Build屬性,那麼具體的操作流程,我們下面進行詳細的分析

第三步,解析recovery分區資訊
這裡fastab_version的版本是2,因此

def LoadRecoveryFSTab(zip, fstab_version):
class Partition(object):
pass
try:
data = zip.read("RECOVERY/RAMDISK/etc/recovery.fstab")#當前target.zip中並沒有這檔案,因此這裡暫不作詳解
except KeyError:
print "Warning: could not find RECOVERY/RAMDISK/etc/recovery.fstab in %s." % zip
data = ""
if fstab_version == 1:
d = {}
for line in data.split("\n"):
line = line.strip()
if not line or line.startswith("#"): continue
pieces = line.split()
if not (3 <= len(pieces) <= 4):
raise ValueError("malformed recovery.fstab line: \"%s\"" % (line,))
p = Partition()
p.mount_point = pieces[0]
p.fs_type = pieces[1]
p.device = pieces[2]
p.length = 0
options = None
if len(pieces) >= 4:
if pieces[3].startswith("/"):
p.device2 = pieces[3]
if len(pieces) >= 5:
options = pieces[4]
else:
p.device2 = None
options = pieces[3]
else:
p.device2 = None
if options:
options = options.split(",")
for i in options:
if i.startswith("length="):
p.length = int(i[7:])
else:
print "%s: unknown option \"%s\"" % (p.mount_point, i)
d[p.mount_point] = p

elif fstab_version == 2:
d = {}
for line in data.split("\n"):
line = line.strip()
if not line or line.startswith("#"): continue
pieces = line.split()
if len(pieces) != 5:
raise ValueError("malformed recovery.fstab line: \"%s\"" % (line,))
# Ignore entries that are managed by vold
options = pieces[4]
if "voldmanaged=" in options: continue
# It's a good line, parse it
p = Partition()
p.device = pieces[0]
p.mount_point = pieces[1]
p.fs_type = pieces[2]
p.device2 = None
p.length = 0
options = options.split(",")
for i in options:
if i.startswith("length="):
p.length = int(i[7:])
else:
# Ignore all unknown options in the unified fstab
continue
d[p.mount_point] = p
else:
raise ValueError("Unknown fstab_version: \"%d\"" % (fstab_version,))
return d
第四步,解析SYSTEM/build.prop屬性資訊,將解析的屬性資訊儲存為一個資料字典,並返回

 

def LoadBuildProp(zip):  try:    data = zip.read("SYSTEM/build.prop")  except KeyError:    print "Warning: could not find SYSTEM/build.prop in %s" % zip    data = ""  d = {}  for line in data.split("\n"):    line = line.strip()    if not line or line.startswith("#"): continue    name, value = line.split("=", 1)    d[name] = value  return d


 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.