A/B系统是Google推的一种方便OTA升级版本的特性,好像是N就开始了。之前有好几个问题都是异常进recovery的,不过A/B系统里已经去掉recovery分区了,不再编译recovery.img,那系统是怎么进的recovery?带着这个问题来看下。
先看看Google对recovery的介绍:
recovery: The recovery partition stores the recovery image, booted during the OTA process. If the device supports A/B updates, recovery can be a RAM disk contained in the boot image rather than a separate image.
说的很清楚,recovery已经不作为独立的image存在,而是包含在boot image里。
看下makefile:
ifeq ($(ENABLE_AB) , true)AB_OTA_UPDATER := true AB_OTA_PARTITIONS ?= boot system BOARD_BUILD_SYSTEM_ROOT_IMAGE := true TARGET_NO_RECOVERY := true BOARD_USES_RECOVERY_AS_BOOT := true else BOARD_RECOVERYIMAGE_PARTITION_SIZE := 0x04000000 BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4 BOARD_CACHEIMAGE_PARTITION_SIZE := 268435456 TARGET_RECOVERY_UPDATER_LIBS += librecovery_updater_msm BOARD_BUILD_SYSTEM_ROOT_IMAGE := true endif
A/B系统定义了TARGET_NO_RECOVERY
去recovery,BOARD_USES_RECOVERY_AS_BOOT
意思就是build recovery作为boot image.
再看看这个宏的管控下都做了什么:
ifeq (,$(filter true, $(TARGET_NO_KERNEL) $(TARGET_NO_RECOVERY) ) )INSTALLED_RECOVERYIMAGE_TARGET := $(PRODUCT_OUT) /recovery.img else INSTALLED_RECOVERYIMAGE_TARGET := endif ... ifneq (,$(INSTALLED_RECOVERYIMAGE_TARGET) $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT) ) )
有独立的recovery.img or BOARD_USES_RECOVERY_AS_BOOT=true都进来。
继续看:
INTERNAL_RECOVERYIMAGE_FILES := $(filter $(TARGET_RECOVERY_OUT) /%, \ $(ALL_DEFAULT_INSTALLED_MODULES) )
TARGET_COPY_OUT_RECOVERY := recovery ... TARGET_RECOVERY_OUT := $(PRODUCT_OUT) /$(TARGET_COPY_OUT_RECOVERY) TARGET_RECOVERY_ROOT_OUT := $(TARGET_RECOVERY_OUT) /root
obj下能看到recovery目录,里面只有root。
继续看:
recovery_kernel := $(INSTALLED_KERNEL_TARGET) recovery_ramdisk := $(PRODUCT_OUT) /ramdisk-recovery.img
recovery_kernel用的就是那kernel:
ifneq ($(strip $(TARGET_NO_KERNEL) ) ,true) INSTALLED_KERNEL_TARGET := $(PRODUCT_OUT) /kernel else INSTALLED_KERNEL_TARGET := endif
继续看:
INTERNAL_RECOVERYIMAGE_ARGS := \ $(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET) ) \ --kernel $(recovery_kernel) \ --ramdisk $(recovery_ramdisk) ifdef INTERNAL_KERNEL_CMDLINE INTERNAL_RECOVERYIMAGE_ARGS += --cmdline "$(INTERNAL_KERNEL_CMDLINE) " endif ifdef BOARD_KERNEL_BASE INTERNAL_RECOVERYIMAGE_ARGS += --base $(BOARD_KERNEL_BASE) endif ifdef BOARD_KERNEL_PAGESIZE INTERNAL_RECOVERYIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE) endif ifdef BOARD_INCLUDE_RECOVERY_DTBO INTERNAL_RECOVERYIMAGE_ARGS += --recovery_dtbo $(BOARD_PREBUILT_DTBOIMAGE) endif
定义了许多参数, 接下来进入重要时刻, 咳咳:
define build-recoveryimage-target ...
这里有许多hide你可以放开看看。是谁在call build-recoveryimage-target
?在下面:
NSTALLED_BOOTIMAGE_TARGET := $(PRODUCT_OUT) /boot.img ... ifeq ($(BOARD_USES_RECOVERY_AS_BOOT) ,true)... $(INSTALLED_BOOTIMAGE_TARGET) : $(MKBOOTFS) $(MKBOOTIMG) $(MINIGZIP) $(ADBD) \ $(INSTALLED_RAMDISK_TARGET) \ $(INTERNAL_RECOVERYIMAGE_FILES) \ $(recovery_initrc) $(recovery_sepolicy) $(recovery_kernel) \ $(INSTALLED_2NDBOOTLOADER_TARGET) \ $(recovery_build_props) $(recovery_resource_deps) \ $(recovery_fstab) \ $(RECOVERY_INSTALL_OTA_KEYS) \ $(INSTALLED_VENDOR_DEFAULT_PROP_TARGET) \ $(BOARD_RECOVERY_KERNEL_MODULES) \ $(DEPMOD) $(call pretty,"Target boot image from recovery: $@ ") $(call build-recoveryimage-target, $@ ) endif
接下来的基本上是给独立image用的了:
$(INSTALLED_RECOVERYIMAGE_TARGET) : $(MKBOOTFS) $(MKBOOTIMG) $(MINIGZIP) $(ADBD) \ $(INSTALLED_RAMDISK_TARGET) \ $(INSTALLED_BOOTIMAGE_TARGET) \ $(INTERNAL_RECOVERYIMAGE_FILES) \ $(recovery_initrc) $(recovery_sepolicy) $(recovery_kernel) \ $(INSTALLED_2NDBOOTLOADER_TARGET) \ $(recovery_build_props) $(recovery_resource_deps) \ $(recovery_fstab) \ $(RECOVERY_INSTALL_OTA_KEYS) \ $(INSTALLED_VENDOR_DEFAULT_PROP_TARGET) \ $(BOARD_RECOVERY_KERNEL_MODULES) \ $(DEPMOD) $(call build-recoveryimage-target, $@ ) ifdef RECOVERY_RESOURCE_ZIP$(RECOVERY_RESOURCE_ZIP) : $(INSTALLED_RECOVERYIMAGE_TARGET) | $(ZIPTIME) $(hide) mkdir -p $(dir $@ ) $(hide) find $(TARGET_RECOVERY_ROOT_OUT) /res -type f | sort | zip -0qrjX $@ -@ $(remove-timestamps-from-package) endif .PHONY : recoveryimage-nodepsrecoveryimage-nodeps: @echo "make $@ : ignoring dependencies" $(call build-recoveryimage-target, $(INSTALLED_RECOVERYIMAGE_TARGET) ) else RECOVERY_RESOURCE_ZIP := endif .PHONY : recoveryimagerecoveryimage: $(INSTALLED_RECOVERYIMAGE_TARGET) $(RECOVERY_RESOURCE_ZIP)
那bootable/recovery下的代码是编译成什么的了?
来看Android.mk:
include $(CLEAR_VARS) LOCAL_SRC_FILES := \ adb_install.cpp \ device.cpp \ fuse_sdcard_provider.cpp \ recovery.cpp \ roots.cpp \ rotate_logs.cpp \ screen_ui.cpp \ ui.cpp \ vr_ui.cpp \ wear_ui.cpp \ LOCAL_MODULE := recovery
恢复模式的”Can’t load Android System”就在recovery.cpp里,很明显是编译成recovery可执行文件,具体在obj目录能找到:
./recovery/root/sbin/recovery
应该是放到recovery_ramdisk里了,这个ramdisk是怎么生成了的,其实就是上面提到的build-recoveryimage-target
:
TARGET_RECOVERY_ROOT_OUT := $(TARGET_RECOVERY_OUT) /root ... $(hide) $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_RECOVERY_ROOT_OUT) | $(MINIGZIP) > $(recovery_ramdisk)
可见TARGET_RECOVERY_ROOT_OUT就是ramdisk的来源。
very clear, ehe…
版权声明: 本站所有文章均采用 CC BY-NC-SA 4.0 CN 许可协议。转载请注明原文链接!