當前位置:首頁 > 芯聞號 > 充電吧
[導讀]一、前言recovery的最主要功能就是升級,而升級文件就是升級包了,那么升級包時如何編譯出來的呢?文就這個問題做個簡要的分析。 注:本文中的敘述純屬個人理解,歡迎批評指正。二、升級包編譯命令1.so

一、前言

recovery的最主要功能就是升級,而升級文件就是升級包了,那么升級包時如何編譯出來的呢?文就這個問題做個簡要的分析。
注:本文中的敘述純屬個人理解,歡迎批評指正。

二、升級包編譯命令

1.source build/envsetup.sh
2.lunch (選擇合適的配置)
3.make otapackage
注:有些平臺可能沒有將“recoveryimage”、“bootimage”等目標添加為“otapackage”目標的依賴,而otapackage目標必定會依賴“boot.img”和“recovery.img”這些文件,這時就需要先執(zhí)行編譯對應image文件的命令之后才能使“make otapackage”命令順利執(zhí)行,最終生成升級包。

三、從makefile分析升級包編譯流程

尋找otapackage目標(我以正在進行的一個項目為例)
首先我們在makefile中找到otapackage目標,然后順藤摸瓜來分析整個編譯的過程。下面我貼出相關的makefile代碼,代碼路徑:rootdir/build/core/Makefile

$(BUILT_TARGET_FILES_PACKAGE):?
????????$(INSTALLED_BOOTIMAGE_TARGET)????-------------------------------(1)?
????????$(INSTALLED_RADIOIMAGE_TARGET)?
????????$(INSTALLED_RECOVERYIMAGE_TARGET)?
????????$(INSTALLED_SYSTEMIMAGE)?
????????$(INSTALLED_USERDATAIMAGE_TARGET)?
????????$(INSTALLED_CACHEIMAGE_TARGET)?
????????$(INSTALLED_VENDORIMAGE_TARGET)?
????????$(INSTALLED_CUSTOMIMAGE_TARGET)????
????????$(INSTALLED_ANDROID_INFO_TXT_TARGET)?
????????$(SELINUX_FC)?
????????$(built_ota_tools)?
????????$(APKCERTS_FILE)?
????????$(HOST_OUT_EXECUTABLES)/fs_config?
????????|?$(ACP)??????????????????????????????????????-----------------(2)?
????@echo?"Package?target?files:?$@"
????$(hide)?rm?-rf?$@?$(zip_root)
????$(hide)?mkdir?-p?$(dir?$@)?$(zip_root)??????????????????--------------(3)?
????@#?Components?of?the?recovery?image
????$(hide)?mkdir?-p?$(zip_root)/RECOVERY
????$(hide)?$(call?package_files-copy-root,?????????????????-------------(4)?
????????$(TARGET_RECOVERY_ROOT_OUT),$(zip_root)/RECOVERY/RAMDISK)
????$(hide)?mkdir?-p?$(zip_root)/OTHER
????$(hide)?$(ACP)?
????????$(INSTALLED_UBOOT_TARGET)?$(zip_root)/OTHER/bootloader?????---(5)?
????$(hide)?$(ACP)?
????????$(INSTALLED_DTB_TARGET)?$(zip_root)/OTHER/dtb
????$(hide)?$(ACP)?
????????$(INSTALLED_BOOTIMAGE_TARGET)?$(zip_root)/OTHER/boot.img
????$(hide)?$(ACP)?
????????$(INSTALLED_LDFW_TARGET)?$(zip_root)/OTHER/ldfw
????$(hide)?$(ACP)?
????????$(INSTALLED_RECOVERY_TARGET)?$(zip_root)/OTHER/recovery.img

ifdef?BOARD_KERNEL_BASE
????$(hide)?echo?"$(BOARD_KERNEL_BASE)"?>?$(zip_root)/RECOVERY/base
endif
ifdef?BOARD_KERNEL_PAGESIZE
????$(hide)?echo?"$(BOARD_KERNEL_PAGESIZE)"?>?$(zip_root)/RECOVERY/pagesize
endif
????@#?Components?of?the?boot?image
????$(hide)?mkdir?-p?$(zip_root)/BOOT
????$(hide)?$(call?package_files-copy-root,?
????????$(TARGET_ROOT_OUT),$(zip_root)/BOOT/RAMDISK)
ifdef?INSTALLED_KERNEL_TARGET
????$(hide)?$(ACP)?$(INSTALLED_KERNEL_TARGET)?$(zip_root)/BOOT/kernel
endif
ifdef?INSTALLED_2NDBOOTLOADER_TARGET
????$(hide)?$(ACP)?
????????$(INSTALLED_2NDBOOTLOADER_TARGET)?$(zip_root)/BOOT/second
endif
ifdef?BOARD_KERNEL_CMDLINE
????$(hide)?echo?"$(BOARD_KERNEL_CMDLINE)"?>?$(zip_root)/BOOT/cmdline
endif
ifdef?BOARD_KERNEL_BASE
????$(hide)?echo?"$(BOARD_KERNEL_BASE)"?>?$(zip_root)/BOOT/base
endif
ifdef?BOARD_KERNEL_PAGESIZE
????$(hide)?echo?"$(BOARD_KERNEL_PAGESIZE)"?>?$(zip_root)/BOOT/pagesize
endif
????$(hide)?$(foreach?t,$(INSTALLED_RADIOIMAGE_TARGET),
????????????????mkdir?-p?$(zip_root)/RADIO;?
????????????????$(ACP)?$(t)?$(zip_root)/RADIO/$(notdir?$(t));)
????@#?Contents?of?the?system?image
????$(hide)?$(call?package_files-copy-root,?
????????$(SYSTEMIMAGE_SOURCE_DIR),$(zip_root)/SYSTEM)
????@#?Contents?of?the?data?image
????$(hide)?$(call?package_files-copy-root,?
????????$(TARGET_OUT_DATA),$(zip_root)/DATA)
ifdef?BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
????@#?Contents?of?the?vendor?image
????$(hide)?$(call?package_files-copy-root,?
????????$(TARGET_OUT_VENDOR),$(zip_root)/VENDOR)
endif
????@#?Extra?contents?of?the?OTA?package
????$(hide)?mkdir?-p?$(zip_root)/OTA/bin
????$(hide)?$(ACP)?$(INSTALLED_ANDROID_INFO_TXT_TARGET)?$(zip_root)/OTA/
????$(hide)?$(ACP)?$(PRIVATE_OTA_TOOLS)?$(zip_root)/OTA/bin/
????@#?Files?that?do?not?end?up?in?any?images,?but?are?necessary?to
????@#?build?them.
????$(hide)?mkdir?-p?$(zip_root)/META
????@#?imei.dat?information?of?the?OTA?package
????@echo?"[imei.dat]?Adding?imei.dat?to?OTA?package"
????@echo?"[imei.dat]?path?:?bootable/recovery/etc/META-INF/imei.dat"
????$(hide)?$(ACP)?bootable/recovery/etc/META-INF/imei.dat?$(zip_root)/META/
????@#?machine_match?information?of?the?OTA?package
????@echo?"[machine_match]?Adding?machine_match?to?OTA?package"
????$(hide)?$(ACP)?$(machine_match_binary)?$(PRODUCT_OUT)/
????$(hide)?$(ACP)?$(APKCERTS_FILE)?$(zip_root)/META/apkcerts.txt
????$(hide)?if?test?-e?$(tool_extensions)/releasetools.py;?then?$(ACP)?$(tool_extensions)/releasetools.py?$(zip_root)/META/;?fi
????$(hide)?echo?"$(PRODUCT_OTA_PUBLIC_KEYS)"?>?$(zip_root)/META/otakeys.txt
????$(hide)?echo?"recovery_api_version=$(PRIVATE_RECOVERY_API_VERSION)"?>?$(zip_root)/META/misc_info.txt????????-------------------------------------------------------------------------------------(6)
????$(hide)?echo?"fstab_version=$(PRIVATE_RECOVERY_FSTAB_VERSION)"?>>?$(zip_root)/META/misc_info.txt??
????$(hide)?-$(ACP)?$(PRODUCT_OUT)/firmware_type?$(zip_root)/META/
ifdef?BOARD_FLASH_BLOCK_SIZE
????$(hide)?echo?"blocksize=$(BOARD_FLASH_BLOCK_SIZE)"?>>?$(zip_root)/META/misc_info.txt
endif
ifdef?BOARD_BOOTIMAGE_PARTITION_SIZE
????$(hide)?echo?"boot_size=$(BOARD_BOOTIMAGE_PARTITION_SIZE)"?>>?$(zip_root)/META/misc_info.txt?
endif
ifdef?BOARD_RECOVERYIMAGE_PARTITION_SIZE
????$(hide)?echo?"recovery_size=$(BOARD_RECOVERYIMAGE_PARTITION_SIZE)"?>>?$(zip_root)/META/misc_info.txt
endif
ifdef?BOARD_HAS_EXT4_RESERVED_BLOCKS
????$(hide)?echo?"has_ext4_reserved_blocks=$(BOARD_HAS_EXT4_RESERVED_BLOCKS)"?>>?$(zip_root)/META/misc_info.txt
endif
ifdef?TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS
????@#?TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS?can?be?empty?to?indicate?that?nothing?but?defaults?should?be?used.
????$(hide)?echo?"recovery_mount_options=$(TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS)"?>>?$(zip_root)/META/misc_info.txt
else
????$(hide)?echo?"recovery_mount_options=$(DEFAULT_TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS)"?>>?$(zip_root)/META/misc_info.txt
endif
????$(hide)?echo?"tool_extensions=$(tool_extensions)"?>>?$(zip_root)/META/misc_info.txt
????$(hide)?echo?"default_system_dev_certificate=$(DEFAULT_SYSTEM_DEV_CERTIFICATE)"?>>?$(zip_root)/META/misc_info.txt
ifdef?PRODUCT_EXTRA_RECOVERY_KEYS
????$(hide)?echo?"extra_recovery_keys=$(PRODUCT_EXTRA_RECOVERY_KEYS)"?>>?$(zip_root)/META/misc_info.txt
endif
????$(hide)?echo?'mkbootimg_args=$(BOARD_MKBOOTIMG_ARGS)'?>>?$(zip_root)/META/misc_info.txt
????$(hide)?echo?"use_set_metadata=1"?>>?$(zip_root)/META/misc_info.txt
????$(hide)?echo?"multistage_support=1"?>>?$(zip_root)/META/misc_info.txt
????$(hide)?echo?"update_rename_support=1"?>>?$(zip_root)/META/misc_info.txt
????$(hide)?echo?"blockimgdiff_versions=1,2,3"?>>?$(zip_root)/META/misc_info.txt
ifneq?($(OEM_THUMBPRINT_PROPERTIES),)
????#?OTA?scripts?are?only?interested?in?fingerprint?related?properties
????$(hide)?echo?"oem_fingerprint_properties=$(OEM_THUMBPRINT_PROPERTIES)"?>>?$(zip_root)/META/misc_info.txt
endif
????$(call?generate-userimage-prop-dictionary,?$(zip_root)/META/misc_info.txt)
????$(hide)?PATH=$(foreach?p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH?MKBOOTIMG=$(MKBOOTIMG)?
	????./build/tools/releasetools/make_recovery_patch?$(zip_root)?$(zip_root)
	@#?Zip?everything?up,?preserving?symlinks
	$(hide)?(cd?$(zip_root)?&&?zip?-qry?../$(notdir?$@)?.)
	@#?Run?fs_config?on?all?the?system,?vendor,?boot?ramdisk,
	@#?and?recovery?ramdisk?files?in?the?zip,?and?save?the?output
	$(hide)?zipinfo?-1?$@?|?awk?'BEGIN?{?FS="SYSTEM/"?}?/^SYSTEM//?{print?"system/"?$$2}'?|?$(HOST_OUT_EXECUTABLES)/fs_config?-C?-D?$(TARGET_OUT)?-S?$(SELINUX_FC)?>?$(zip_root)/META/filesystem_config.txt??????????????????????????????????????????????????????????????????????---------(7)
	$(hide)?zipinfo?-1?$@?|?awk?'BEGIN?{?FS="VENDOR/"?}?/^VENDOR//?{print?"vendor/"?$$2}'?|?$(HOST_OUT_EXECUTABLES)/fs_config?-C?-D?$(TARGET_OUT)?-S?$(SELINUX_FC)?>?$(zip_root)/META/vendor_filesystem_config.txt
	$(hide)?zipinfo?-1?$@?|?awk?'BEGIN?{?FS="BOOT/RAMDISK/"?}?/^BOOT/RAMDISK//?{print?$$2}'?|?$(HOST_OUT_EXECUTABLES)/fs_config?-C?-D?$(TARGET_OUT)?-S?$(SELINUX_FC)?>?$(zip_root)/META/boot_filesystem_config.txt
	$(hide)?zipinfo?-1?$@?|?awk?'BEGIN?{?FS="RECOVERY/RAMDISK/"?}?/^RECOVERY/RAMDISK//?{print?$$2}'?|?$(HOST_OUT_EXECUTABLES)/fs_config?-C?-D?$(TARGET_OUT)?-S?$(SELINUX_FC)?>?$(zip_root)/META/recovery_filesystem_config.txt
	$(hide)?(cd?$(zip_root)?&&?zip?-q?../$(notdir?$@)?META/*filesystem_config.txt)????????????????????????????????????--------------------------------------------------------------------------(8)
	$(hide)?PATH=$(foreach?p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH?MKBOOTIMG=$(MKBOOTIMG)?
????????./build/tools/releasetools/add_img_to_target_files?-p?$(HOST_OUT)?$@????????????????????????????????????????--------------------------------------------------------------------------------(9)
????$(hide)?./build/tools/releasetools/replace_img_from_target_files.py?$@?$(PRODUCT_OUT)????????????-----------------------------------------------------------------------------------------------(10)

.PHONY:?target-files-package
target-files-package:?$(BUILT_TARGET_FILES_PACKAGE)

ifneq?($(filter?$(MAKECMDGOALS),target-files-package),)
$(call?dist-for-goals,?target-files-package,?$(BUILT_TARGET_FILES_PACKAGE))
endif

ifneq?($(TARGET_PRODUCT),sdk)
ifeq?($(filter?generic%,$(TARGET_DEVICE)),)
ifneq?($(TARGET_NO_KERNEL),true)
ifneq?($(recovery_fstab),)

#?-----------------------------------------------------------------
#?OTA?update?package

name?:=?$(TARGET_PRODUCT)
ifeq?($(TARGET_BUILD_TYPE),debug)
??name?:=?$(name)_debug
endif
name?:=?$(name)-ota-$(FILE_NAME_TAG)

INTERNAL_OTA_PACKAGE_TARGET?:=?$(PRODUCT_OUT)/$(name).zip

$(INTERNAL_OTA_PACKAGE_TARGET):?KEY_CERT_PAIR?:=?$(DEFAULT_KEY_CERT_PAIR)

$(INTERNAL_OTA_PACKAGE_TARGET):?$(BUILT_TARGET_FILES_PACKAGE)?$(DISTTOOLS)
????@echo?"Package?OTA:?$@"
????$(hide)?PATH=$(foreach?p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH?MKBOOTIMG=$(MKBOOTIMG)?
???????./build/tools/releasetools/ota_from_target_files?-v???????------------------(11)???????
???????--block?
???????-p?$(HOST_OUT)?
???????-k?$(KEY_CERT_PAIR)?
???????$(if?$(OEM_OTA_CONFIG),?-o?$(OEM_OTA_CONFIG))?
???????$(BUILT_TARGET_FILES_PACKAGE)?$@

.PHONY:?otapackage
otapackage:?$(INTERNAL_OTA_PACKAGE_TARGET)

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179

下面來分析一下makefile代碼:
首先otapackage是一個偽目標,它有個INTERNAL_OTA_PACKAGE_TARGET的依賴,INTERNAL_OTA_PACKAGE_TARGET := $(PRODUCT_OUT)/$(name).zip,就是最終的那個升級包。我們繼續(xù)看下面:
$(INTERNAL_OTA_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(DISTTOOLS)
$(INTERNAL_OTA_PACKAGE_TARGET)又有一些依賴,這里我只關心 $(BUILT_TARGET_FILES_PACKAGE) , $(BUILT_TARGET_FILES_PACKAGE) 目標在代碼片段的最開始定義,現(xiàn)在重點分析一下 $(BUILT_TARGET_FILES_PACKAGE) 目標。
我們可以通過閱讀makefile可以知道,$(BUILT_TARGET_FILES_PACKAGE) =out/target/product//obj/PACKAGING/target_files_intermediates/*target_files-.zip,target_files-.zip(后續(xù)我們簡稱為target_file.zip)中保存著生成升級包需要的文件。下面分析代碼
(1)一些依賴目標
(2)在依賴前加“|”的意思是”|”后面的依賴要比其他依賴優(yōu)先編譯
(3)生成目錄out/target/product//obj/PACKAGING/target_files_intermediates/*target_files-(后續(xù)我們簡稱為target_file),后面會把一些中間文件拷貝到這個目錄,最終打包成out/target/product/*/obj/PACKAGING/target_files_intermediates/target_files-.zip
(4)把生成recovery的中間文件也拷貝到target_file目錄,因為升級包中的recovery.img不是跟out/target/product/*/recovery.img相同的,在執(zhí)行ota_from_target_files 腳本的過程中會重新生成recovery.img。當然,現(xiàn)在的Android都是通過打patch(recovery.img基于boot.img的patch)的方式升級recovery的。
(5)拷貝一些文件到target_file的OTHER目錄,最終的升級包一般直接把這些文件拷貝過去就ok了。
(6)把一些編譯信息放在文件中,方便后面編譯升級包時使用,比如分區(qū)信息(編譯升級包時需要檢測升級文件的大小是否大于對應的分區(qū)大小,如果大于的話當然無法升級了,只能終止編譯)。
(7)先看下面命令的執(zhí)行結果

這是在提取分區(qū)中文件的信息,包括文件權限,selinux相關的信息,這些信息將會在制作文件系統(tǒng)的時候使用。
(8)打包target_file.zip
(9)生成img文件,并將它們拷貝到target_file/IMAGE目錄,后面可能會使用。
(10)調(diào)用replace_img_from_target_files.py腳本把target_file/IMAGE目錄下面的img文件拷貝到out/target/product/目錄。調(diào)用這個腳本的目的是使out/target/product/和升級包中的升級img文件保持一致,這跟Android的一個設計缺陷有關。下面就來了解一下
我們知道out/target/product//system.img文件是由out/target/product//system編譯來的,按理說升級包中的system分區(qū)的文件來源也應該是out/target/product//system,但實際上升級包中的system分區(qū)的文件來源是target_file/SYSTEM。如果說out/target/product//system與target_file/SYSTEM兩個目錄的文件內(nèi)容一樣那也沒什么問題,問題是這兩個目錄是不一樣的,因為在執(zhí)行ota_from_target_file腳本的時候會生成一個install_recovery.sh腳本(這個腳本就是在Android啟動的時候執(zhí)行,用來升級recovery的),然后把install_recovery.sh拷貝到target_file/SYSTEM,所以造成了最終out/target/product/*/system.img和升級包中的system(升級包中沒有system.img,recovery用一種新的方法來升級system)的差異,這會引發(fā)下面的問題:
(a)如果你是用fastboot燒錄system,那么你就會用到out/target/product/*/system.img,同時你升級recovery的方式是用install_recovery.sh來升級的,那你會發(fā)現(xiàn)你的recovery其實是沒法升級的,因為在你的系統(tǒng)中壓根就沒有install_recovery.sh這個文件。
(b)如果你說,沒關系,我是在recovery中直接把recovery.img寫到recovery中升級的,(a)問題對我沒影響。那你可能會發(fā)現(xiàn)你無法進行增量升級。因為增量升級包是通過比較兩個版本的target_file.zip生成的,現(xiàn)在你的板子里面的system和增量包的基準版本不一致。
(11)執(zhí)行 ./build/tools/releasetools/ota_from_target_files腳本,最終生成升級包。下面來分析一下 ./build/tools/releasetools/ota_from_target_files。

四、ota_from_target_files腳本分析

1.使用說明(常用)
-k:指定key的路徑,如build/target/product/security/testkey
-i:編譯增量升級包, ./build/tools/releasetools/ota_from_target_files -i

def?main(argv):

??def?option_handler(o,?a):??????????????????????????????----------------------------------(1)
????if?o?==?"--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?==?"--full_radio":
??????OPTIONS.full_radio?=?True
????elif?o?==?"--full_bootloader":
??????OPTIONS.full_bootloader?=?True
????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?("-o",?"--oem_settings"):
??????OPTIONS.oem_source?=?a
????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?("-t",?"--worker_threads"):
??????if?a.isdigit():
????????OPTIONS.worker_threads?=?int(a)
??????else:
????????raise?ValueError("Cannot?parse?value?%r?for?option?%r?-?only?"
?????????????????????????"integers?are?allowed."?%?(a,?o))
????elif?o?in?("-2",?"--two_step"):
??????OPTIONS.two_step?=?True
????elif?o?==?"--no_signing":
??????OPTIONS.no_signing?=?True
????elif?o?==?"--verify":
??????OPTIONS.verify?=?True
????elif?o?==?"--block":
??????OPTIONS.block_based?=?True
????elif?o?in?("-b",?"--binary"):
??????OPTIONS.updater_binary?=?a
????elif?o?in?("--no_fallback_to_full",):
??????OPTIONS.fallback_to_full?=?False
????elif?o?==?"--stash_threshold":
??????try:
????????OPTIONS.stash_threshold?=?float(a)
??????except?ValueError:
????????raise?ValueError("Cannot?parse?value?%r?for?option?%r?-?expecting?"
?????????????????????????"a?float"?%?(a,?o))
????else:
??????return?False
????return?True

??args?=?common.ParseOptions(argv,?__doc__,?????????------------------------------------(2)
?????????????????????????????extra_opts="b:k:i:d:wne:t:a:2o:",
?????????????????????????????extra_long_opts=[
?????????????????????????????????"board_config=",
?????????????????????????????????"package_key=",
?????????????????????????????????"incremental_from=",
?????????????????????????????????"full_radio",
?????????????????????????????????"full_bootloader",
?????????????????????????????????"wipe_user_data",
?????????????????????????????????"no_prereq",
?????????????????????????????????"extra_script=",
?????????????????????????????????"worker_threads=",
?????????????????????????????????"aslr_mode=",
?????????????????????????????????"two_step",
?????????????????????????????????"no_signing",
?????????????????????????????????"block",
?????????????????????????????????"binary=",
?????????????????????????????????"oem_settings=",
?????????????????????????????????"verify",
?????????????????????????????????"no_fallback_to_full",
?????????????????????????????????"stash_threshold=",
?????????????????????????????],?extra_option_handler=option_handler)

??if?len(args)?!=?2:
????common.Usage(__doc__)
????sys.exit(1)

??if?OPTIONS.extra_script?is?not?None:???????????????????????????????--------------------(3)
????OPTIONS.extra_script?=?open(OPTIONS.extra_script).read()

??print?"unzipping?target?target-files..."
??OPTIONS.input_tmp,?input_zip?=?common.UnzipTemp(args[0])??????????---------------------(4)

??OPTIONS.target_tmp?=?OPTIONS.input_tmp
??OPTIONS.info_dict?=?common.LoadInfoDict(input_zip)???????????????----------------------(5)

??#?If?this?image?was?originally?labelled?with?SELinux?contexts,?make?sure?we
??#?also?apply?the?labels?in?our?new?image.?During?building,?the?"file_contexts"
??#?is?in?the?out/?directory?tree,?but?for?repacking?from?target-files.zip?it's
??#?in?the?root?directory?of?the?ramdisk.
??if?"selinux_fc"?in?OPTIONS.info_dict:
????OPTIONS.info_dict["selinux_fc"]?=?os.path.join(
????????OPTIONS.input_tmp,?"BOOT",?"RAMDISK",?"file_contexts")

??if?OPTIONS.verbose:
????print?"---?target?info?---"
????common.DumpInfoDict(OPTIONS.info_dict)

??#?If?the?caller?explicitly?specified?the?device-specific?extensions
??#?path?via?-s/--device_specific,?use?that.??Otherwise,?use
??#?META/releasetools.py?if?it?is?present?in?the?target?target_files.
??#?Otherwise,?take?the?path?of?the?file?from?'tool_extensions'?in?the
??#?info?dict?and?look?for?that?in?the?local?filesystem,?relative?to
??#?the?current?directory.

??if?OPTIONS.device_specific?is?None:???????????????-------------------------(6)
????from_input?=?os.path.join(OPTIONS.input_tmp,?"META",?"releasetools.py")
????if?os.path.exists(from_input):
??????print?"(using?device-specific?extensions?from?target_files)"
??????OPTIONS.device_specific?=?from_input
????else:
??????OPTIONS.device_specific?=?OPTIONS.info_dict.get("tool_extensions",?None)

??if?OPTIONS.device_specific?is?not?None:
????OPTIONS.device_specific?=?os.path.abspath(OPTIONS.device_specific)

??while?True:

????if?OPTIONS.no_signing:???????????????????????---------------------------(7)
??????if?os.path.exists(args[1]):
????????os.unlink(args[1])
??????output_zip?=?zipfile.ZipFile(args[1],?"w",
???????????????????????????????????compression=zipfile.ZIP_DEFLATED)
????else:
??????temp_zip_file?=?tempfile.NamedTemporaryFile()
??????output_zip?=?zipfile.ZipFile(temp_zip_file,?"w",
???????????????????????????????????compression=zipfile.ZIP_DEFLATED)

????cache_size?=?OPTIONS.info_dict.get("cache_size",?None)
????if?cache_size?is?None:?????????????????????????-------------------------------(8)
??????raise?RuntimeError("can't?determine?the?cache?partition?size")
????OPTIONS.cache_size?=?cache_size

????if?OPTIONS.incremental_source?is?None:?????????-------------------------------(9)
??????WriteFullOTAPackage(input_zip,?output_zip)???-------------------------------(10)
??????if?OPTIONS.package_key?is?None:
????????OPTIONS.package_key?=?OPTIONS.info_dict.get(
????????????"default_system_dev_certificate",
????????????"build/target/product/security/testkey")
??????common.ZipClose(output_zip)
??????break

????else:
??????print?"unzipping?source?target-files..."
??????OPTIONS.source_tmp,?source_zip?=?common.UnzipTemp(
??????????OPTIONS.incremental_source)
??????OPTIONS.target_info_dict?=?OPTIONS.info_dict
??????OPTIONS.source_info_dict?=?common.LoadInfoDict(source_zip)
??????if?"selinux_fc"?in?OPTIONS.source_info_dict:
????????OPTIONS.source_info_dict["selinux_fc"]?=?os.path.join(
????????????OPTIONS.source_tmp,?"BOOT",?"RAMDISK",?"file_contexts")
??????if?OPTIONS.package_key?is?None:
????????OPTIONS.package_key?=?OPTIONS.source_info_dict.get(
????????????"default_system_dev_certificate",
????????????"build/target/product/security/testkey")
??????if?OPTIONS.verbose:
????????print?"---?source?info?---"
????????common.DumpInfoDict(OPTIONS.source_info_dict)
??????try:
????????WriteIncrementalOTAPackage(input_zip,?source_zip,?output_zip)
????????common.ZipClose(output_zip)
????????break
??????except?ValueError:
????????if?not?OPTIONS.fallback_to_full:
??????????raise
????????print?"---?failed?to?build?incremental;?falling?back?to?full?---"
????????OPTIONS.incremental_source?=?None
????????common.ZipClose(output_zip)

??if?not?OPTIONS.no_signing:
????SignOutput(temp_zip_file.name,?args[1])??????????????????????---------------------(11)
????temp_zip_file.close()

??print?"done."

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178

(1)首先定義一個命令參數(shù)處理的回調(diào)函數(shù)option_handler,這個回調(diào)方法把參數(shù)對應的值存儲在一個全局的OPTIONS變量中,后續(xù)的編譯通過判斷OPTIONS變量執(zhí)行不同的流程。
(2)調(diào)用common.ParseOptions方法()位于commom.py文件中,該方法的功能就是處理一些自己能處理的參數(shù)(如-h),自己不能處理的參數(shù)就交給option_handler來處理。
(3)當用戶使用-e參數(shù)指定一個文件時,最終會在升級包腳本的適當位置添加指定文件的內(nèi)容。這為一些私有的命令插入updater-script提供了方便。
(4)OPTIONS.input_tmp是target_file.zip解壓后的臨時目錄;input_zip是target_file的句柄,后面可以通過這個句柄來操作target_file.zip??梢詤⒖碿ommon.py的UnzipTemp方法。
(5)根據(jù)target_file.zip中的META/misc_info.txt文件初始化字典,這個要重點分析一下,因為這個字典里面存放著一些重要的信息。
首先我們看看misc_info.txt的內(nèi)容:

再來看看具體處理misc_info.txt的流程:

def?LoadInfoDict(input_file):????????---這里的input_file就是target_file.zip
??"""Read?and?parse?the?META/misc_info.txt?key/value?pairs?from?the
??input?target?files?and?return?a?dict."""
??---由上面的注釋可以知道,LoadInfoDict方法的功能是解析target_file.zip中的META/misc_info.txt文件,并以key:value的形式存放在OPTIONS.info_dict字典中
??def?read_helper(fn):
????if?isinstance(input_file,?zipfile.ZipFile):????
??????return?input_file.read(fn)????????---input_file就是zipfile.ZipFile對象,因此走if分支
????else:
??????path?=?os.path.join(input_file,?*fn.split("/"))
??????try:
????????with?open(path)?as?f:
??????????return?f.read()
??????except?IOError?as?e:
????????if?e.errno?==?errno.ENOENT:
??????????raise?KeyError(fn)
??d?=?{}
??try:
????d?=?LoadDictionaryFromLines(read_helper("META/misc_info.txt").split("n"))????---處理misc_info.txt文件,下面會分析LoadDictionaryFromLines方法
??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"]?=?read_helper(
??????????"META/mkyaffs2-extra-flags.txt").strip()
????except?KeyError:
??????#?ok?if?flags?don't?exist
??????pass
??----下面幾個if語句就是判斷misc_info.txt文件的正確性了
??if?"recovery_api_version"?not?in?d:
????try:
??????d["recovery_api_version"]?=?read_helper(
??????????"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"]?=?read_helper("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?=?read_helper("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

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364651234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465

最終OPTONS.info_dict={recovery_api_version:3, fstab_version:2, blocksize:4096, recovery_size:33554432, custom_size:536870912
recovery_mount_options:ext4=max_batch_time=0,commit=1,data=ordered,barrier=1,errors=panic,nodelalloc
tool_extensions:device/*/m96/../common,
default_system_dev_certificate:build/target/product/security/testkey,

}
至于OPTONS.info_dict的用處,后面用到了再來分析,總之,很多時候我們編譯升級包出錯都是因為OPTONS.info_dict的內(nèi)容不合法導致的。
(6)這里應該是指定一個OEM廠商自己定制的一個Python腳本(可以通過-s參數(shù)傳入),完成一些廠商自己定制的一些功能。我當前的項目沒有指定-s參數(shù),根據(jù)代碼分析會使用OPTONS.info_dict中的tool_extensions:device/*/m96/../common,這顯然不是一個Python腳本,如果后面使用到的話會報錯的,然而我當前沒有使用,這里就不去深究了。
(7)可以通過–no_signing參數(shù)指定不對升級包簽名,當然一般廠商是不會這么做的。
(8)cache_size就是misc_info.txt中的“cache_size=536870912”這個字段,如果misc_info.txt文件中沒有這個字段的話就會終止編譯。順便說一下cache_size的值是在BoardConfig.mk中設置的:
BOARD_CACHEIMAGE_PARTITION_SIZE := 536870912
(9)通過-i參數(shù)可以使OPTIONS.incremental_source=True,由于本文講述的是全量升級包的編譯,所有這里只講述if分支的流程。
(10)全量升級包的生成由這個方法完成,前面的代碼都是浮云。下面就來仔細看看WriteFullOTAPackage方法

def?WriteFullOTAPackage(input_zip,?output_zip):
??#?TODO:?how?to?determine?this???We?don't?know?what?version?it?will
??#?be?installed?on?top?of.?For?now,?we?expect?the?API?just?won't
??#?change?very?often.?Similarly?for?fstab,?it?might?have?changed
??#?in?the?target?build.
??script?=?edify_generator.EdifyGenerator(3,?OPTIONS.info_dict)???????????--------------------(a)

??oem_props?=?OPTIONS.info_dict.get("oem_fingerprint_properties")???????????????????????
??recovery_mount_options?=?OPTIONS.info_dict.get("recovery_mount_options")--------------------(b)
??oem_dict?=?None
??if?oem_props?is?not?None?and?len(oem_props)?>?0:
????if?OPTIONS.oem_source?is?None:
??????raise?common.ExternalError("OEM?source?required?for?this?build")
????script.Mount("/oem",?recovery_mount_options)
????oem_dict?=?common.LoadDictionaryFromLines(
????????open(OPTIONS.oem_source).readlines())

??metadata?=?{
??????"post-build":?CalculateFingerprint(oem_props,?oem_dict,
?????????????????????????????????????????OPTIONS.info_dict),
??????"pre-device":?GetOemProperty("ro.product.device",?oem_props,?oem_dict,
???????????????????????????????????OPTIONS.info_dict),
??????"post-timestamp":?GetBuildProp("ro.build.date.utc",?OPTIONS.info_dict),
??}

??device_specific?=?common.DeviceSpecificParams(???????????????????????
??????input_zip=input_zip,
??????input_version=OPTIONS.info_dict["recovery_api_version"],
??????output_zip=output_zip,
??????script=script,
??????input_tmp=OPTIONS.input_tmp,
??????metadata=metadata,
??????info_dict=OPTIONS.info_dict)

??has_recovery_patch?=?HasRecoveryPatch(input_zip)??????????????---------------------------(c)
??block_based?=?OPTIONS.block_based?and?has_recovery_patch??????---------------------------(d)

??if?not?OPTIONS.omit_prereq:???????????????????????????????????---------------------------(e)
????ts?=?GetBuildProp("ro.build.date.utc",?OPTIONS.info_dict)
????ts_text?=?GetBuildProp("ro.build.date",?OPTIONS.info_dict)
????script.AssertOlderBuild(ts,?ts_text)

??AppendAssertions(script,?OPTIONS.info_dict,?oem_dict)
??device_specific.FullOTA_Assertions()
??#?delete?/cache/backup
??script.AppendExtra('delete_recursive("/cache/backup");')
??kernel_img?=?common.GetOtherImage("boot.img",?"boot.img",?------------------------------(f)
??????????????????????????????????????OPTIONS.input_tmp,?"OTHER")
??ldfw_img?=?common.GetOtherImage("ldfw",?"ldfw",
??????????????????????????????????????OPTIONS.input_tmp,?"OTHER")

??if?OPTIONS.two_step:???????????????????????????????????????-----------------------------(g)
????if?not?OPTIONS.info_dict.get("multistage_support",?None):
??????assert?False,?"two-step?packages?not?supported?by?this?build"
????fs?=?OPTIONS.info_dict["fstab"]["/misc"]
????assert?fs.fs_type.upper()?==?"EMMC",?
????????"two-step?packages?only?supported?on?devices?with?EMMC?/misc?partitions"
????bcb_dev?=?{"bcb_dev":?fs.device}
????common.CheckSize(recovery_img.data,?"recovery",?OPTIONS.info_dict)
????common.ZipWriteStr(output_zip,?"recovery",?recovery_img.data)
????script.AppendExtra("""
if?get_stage("%(bcb_dev)s")?==?"2/3"?then
"""?%?bcb_dev)
????script.WriteRawImage("/recovery",?"recovery")
????script.WriteRawImage("/ldfw",?"ldfw")
????script.AppendExtra("""
set_stage("%(bcb_dev)s",?"3/3");
reboot_now("%(bcb_dev)s",?"recovery");
else?if?get_stage("%(bcb_dev)s")?==?"3/3"?then
"""?%?bcb_dev)

??#?Dump?fingerprints
??script.Print("Target:?%s"?%?CalculateFingerprint(
??????oem_props,?oem_dict,?OPTIONS.info_dict))

??device_specific.FullOTA_InstallBegin()

??system_progress?=?0.95

??if?OPTIONS.wipe_user_data:
????system_progress?-=?0.1
??if?HasVendorPartition(input_zip):
????system_progress?-=?0.1

??if?"selinux_fc"?in?OPTIONS.info_dict:
????WritePolicyConfig(OPTIONS.info_dict["selinux_fc"],?output_zip)

??recovery_mount_options?=?OPTIONS.info_dict.get("recovery_mount_options")

??system_items?=?ItemSet("system",?"META/filesystem_config.txt")
??script.ShowProgress(system_progress,?100)

??if?block_based:????????????????????????????????????????----------------------(h)
????#?Full?OTA?is?done?as?an?"incremental"?against?an?empty?source
????#?image.??This?has?the?effect?of?writing?new?data?from?the?package
????#?to?the?entire?partition,?but?lets?us?reuse?the?updater?code?that
????#?writes?incrementals?to?do?it.
????system_tgt?=?GetImage("system",?OPTIONS.input_tmp,?OPTIONS.info_dict)
????system_tgt.ResetFileMap()
????system_diff?=?common.BlockDifference("system",?system_tgt,?src=None)
????system_diff.WriteScript(script,?output_zip)
??else:
????script.FormatPartition("/system")
????script.Mount("/system",?recovery_mount_options)
????if?not?has_recovery_patch:
??????script.UnpackPackageDir("recovery",?"/system")
????script.UnpackPackageDir("system",?"/system")

????symlinks?=?CopyPartitionFiles(system_items,?input_zip,?output_zip)
????script.MakeSymlinks(symlinks)

??boot_img?=?common.GetOtherImage("boot.img",?"boot.img",
?????????????????????????????????????OPTIONS.input_tmp,?"OTHER")

??if?not?block_based:
????def?output_sink(fn,?data):
??????common.ZipWriteStr(output_zip,?"recovery/"?+?fn,?data)
??????system_items.Get("system/"?+?fn)

????common.MakeRecoveryPatch(OPTIONS.input_tmp,?output_sink,
?????????????????????????????recovery_img,?boot_img)

????system_items.GetMetadata(input_zip)
????system_items.Get("system").SetPermissions(script)

??if?HasVendorPartition(input_zip):
????vendor_items?=?ItemSet("vendor",?"META/vendor_filesystem_config.txt")
????script.ShowProgress(0.1,?0)

????if?block_based:
??????vendor_tgt?=?GetImage("vendor",?OPTIONS.input_tmp,?OPTIONS.info_dict)
??????vendor_tgt.ResetFileMap()
??????vendor_diff?=?common.BlockDifference("vendor",?vendor_tgt)
??????vendor_diff.WriteScript(script,?output_zip)
????else:
??????script.FormatPartition("/vendor")
??????script.Mount("/vendor",?recovery_mount_options)
??????script.UnpackPackageDir("vendor",?"/vendor")

??????symlinks?=?CopyPartitionFiles(vendor_items,?input_zip,?output_zip)
??????script.MakeSymlin
本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉