www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 芯聞號(hào) > 充電吧
[導(dǎo)讀]一、前言recovery的最主要功能就是升級(jí),而升級(jí)文件就是升級(jí)包了,那么升級(jí)包時(shí)如何編譯出來(lái)的呢?文就這個(gè)問(wèn)題做個(gè)簡(jiǎn)要的分析。 注:本文中的敘述純屬個(gè)人理解,歡迎批評(píng)指正。二、升級(jí)包編譯命令1.so

一、前言

recovery的最主要功能就是升級(jí),而升級(jí)文件就是升級(jí)包了,那么升級(jí)包時(shí)如何編譯出來(lái)的呢?文就這個(gè)問(wèn)題做個(gè)簡(jiǎn)要的分析。
注:本文中的敘述純屬個(gè)人理解,歡迎批評(píng)指正。

二、升級(jí)包編譯命令

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

三、從makefile分析升級(jí)包編譯流程

尋找otapackage目標(biāo)(我以正在進(jìn)行的一個(gè)項(xiàng)目為例)
首先我們?cè)趍akefile中找到otapackage目標(biāo),然后順藤摸瓜來(lái)分析整個(gè)編譯的過(guò)程。下面我貼出相關(guān)的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

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

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

四、ota_from_target_files腳本分析

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

再來(lá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對(duì)象,因此走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文件,下面會(huì)分析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
??----下面幾個(gè)if語(yǔ)句就是判斷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:????---我的項(xiàng)目中沒(méi)有這個(gè)文件,不分析了
????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的用處,后面用到了再來(lái)分析,總之,很多時(shí)候我們編譯升級(jí)包出錯(cuò)都是因?yàn)镺PTONS.info_dict的內(nèi)容不合法導(dǎo)致的。
(6)這里應(yīng)該是指定一個(gè)OEM廠商自己定制的一個(gè)Python腳本(可以通過(guò)-s參數(shù)傳入),完成一些廠商自己定制的一些功能。我當(dāng)前的項(xiàng)目沒(méi)有指定-s參數(shù),根據(jù)代碼分析會(huì)使用OPTONS.info_dict中的tool_extensions:device/*/m96/../common,這顯然不是一個(gè)Python腳本,如果后面使用到的話會(huì)報(bào)錯(cuò)的,然而我當(dāng)前沒(méi)有使用,這里就不去深究了。
(7)可以通過(guò)–no_signing參數(shù)指定不對(duì)升級(jí)包簽名,當(dāng)然一般廠商是不會(huì)這么做的。
(8)cache_size就是misc_info.txt中的“cache_size=536870912”這個(gè)字段,如果misc_info.txt文件中沒(méi)有這個(gè)字段的話就會(huì)終止編譯。順便說(shuō)一下cache_size的值是在BoardConfig.mk中設(shè)置的:
BOARD_CACHEIMAGE_PARTITION_SIZE := 536870912
(9)通過(guò)-i參數(shù)可以使OPTIONS.incremental_source=True,由于本文講述的是全量升級(jí)包的編譯,所有這里只講述if分支的流程。
(10)全量升級(jí)包的生成由這個(gè)方法完成,前面的代碼都是浮云。下面就來(lái)仔細(xì)看看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
本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

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

關(guān)鍵字: 阿維塔 塞力斯 華為

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

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

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

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

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

關(guān)鍵字: 騰訊 編碼器 CPU

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

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

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

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

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

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

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

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

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

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉