• Recovery Binary:

  Recovery Binary 是 Android 进入 Recovery 模式所运行的程序,实现了 Recovery 模式下的功能。它由目录 bootable/recovery 下的源代码编译生成。头文件 bootable/recovery/recovery_ui.h 定义了 Recovery UI 的接口,bootable/recovery/default_recovery_ui.c 是其默认实现,每个设备可以有自己不同的实现,然后通过变量 TARGET_RECOVERY_UI_LIB 来指定,否则使用默认实现。

# bootable/recovery/Android.mk

ifeq ($(TARGET_RECOVERY_UI_LIB),)
LOCAL_SRC_FILES + = default_recovery_ui.c
else
LOCAL_STATIC_LIBRARIES + = $( TARGET_RECOVERY_UI_LIB)
endif
  • Recovery Image:

  Recovery Image 的生成规则在文件 build/core/Makefile 中定义,具体分析如下:

# build/core/Makefile

# -----------------------------------------------------------------
# Recovery image

# If neither TARGET_NO_KERNEL nor TARGET_NO_RECOVERY are true
ifeq (,$(filter true, $(TARGET_NO_KERNEL) $(TARGET_NO_RECOVERY) $(BUILD_TINY_ANDROID)))

INSTALLED_RECOVERYIMAGE_TARGET:=$(PRODUCT_OUT)/recovery.img

recovery_initrc :=$(call include-path-for, recovery)/etc/init.rc
recovery_kernel :=$(INSTALLED_KERNEL_TARGET)# same as a non-recovery system
recovery_ramdisk :=$(PRODUCT_OUT)/ramdisk-recovery.img
recovery_build_prop :=$(INSTALLED_BUILD_PROP_TARGET)
recovery_binary :=$(call intermediates-dir-for,EXECUTABLES,recovery)/recovery
recovery_resources_common :=$(call include-path-for, recovery)/res
recovery_resources_private :=$(strip$(wildcard$(TARGET_DEVICE_DIR)/recovery/res))
recovery_resource_deps :=$(shell find$(recovery_resources_common)\
$(recovery_resources_private)-type f)
recovery_fstab :=$(strip$(wildcard$(TARGET_DEVICE_DIR)/recovery.fstab))
recovery_mmc_fstab :=$(strip$(wildcard$(TARGET_DEVICE_DIR)/recovery_mmc.fstab))

ifeq ($(recovery_resources_private),)
$(info No private recovery resourcesforTARGET_DEVICE$(TARGET_DEVICE))
endif

ifeq ($(recovery_fstab),)
$(info No recovery.fstabforTARGET_DEVICE$(TARGET_DEVICE))
endif

INTERNAL_RECOVERYIMAGE_ARGS :=\
$(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET))\
--kernel$(recovery_kernel)\
--ramdisk$(recovery_ramdisk)

# Assumes this has already been stripped
ifdef BOARD_KERNEL_CMDLINE
INTERNAL_RECOVERYIMAGE_ARGS +=--cmdline"$(BOARD_KERNEL_CMDLINE)"
endif
ifdef BOARD_KERNEL_BASE
INTERNAL_RECOVERYIMAGE_ARGS +=--base$(BOARD_KERNEL_BASE)
endif
BOARD_KERNEL_PAGESIZE :=$(strip$(BOARD_KERNEL_PAGESIZE))
ifdef BOARD_KERNEL_PAGESIZE
INTERNAL_RECOVERYIMAGE_ARGS +=--pagesize$(BOARD_KERNEL_PAGESIZE)
endif

INSTALLED_BOOTIMAGE_TARGET :=$(PRODUCT_OUT)/boot.img
kernel:$(INSTALLED_BOOTIMAGE_TARGET)
.PHONY: kernel

# Keys authorized to sign OTA packages this build will accept. The
# build always uses test-keys for this; release packaging tools will
# substitute other keys for this one.
OTA_PUBLIC_KEYS :=$(SRC_TARGET_DIR)/product/security/testkey.x509.pem

# Generate a file containing the keys that will be read by the
# recovery binary.
RECOVERY_INSTALL_OTA_KEYS :=\
$(call intermediates-dir-for,PACKAGING,ota_keys)/keys
DUMPKEY_JAR :=$(HOST_OUT_JAVA_LIBRARIES)/dumpkey.jar
$(RECOVERY_INSTALL_OTA_KEYS): PRIVATE_OTA_PUBLIC_KEYS :=$(OTA_PUBLIC_KEYS)
$(RECOVERY_INSTALL_OTA_KEYS):$(OTA_PUBLIC_KEYS)$(DUMPKEY_JAR)
@echo"DumpPublicKey: $@ <= $(PRIVATE_OTA_PUBLIC_KEYS)"
@rm -rf$@
@mkdir -p$(dir$@)
java -jar$(DUMPKEY_JAR)$(PRIVATE_OTA_PUBLIC_KEYS)>$@

$(INSTALLED_RECOVERYIMAGE_TARGET):$(MKBOOTFS)$(MKBOOTIMG)$(MINIGZIP)\
$(INSTALLED_RAMDISK_TARGET)\
$(INSTALLED_BOOTIMAGE_TARGET)\
$(recovery_binary)\
$(recovery_initrc)$(recovery_kernel)\
$(INSTALLED_2NDBOOTLOADER_TARGET)\
$(recovery_build_prop)$(recovery_resource_deps)\
$(recovery_fstab)\
$(RECOVERY_INSTALL_OTA_KEYS)

/* 以正常系统的根文件系统为基础构建 Recovery 的根文件系统 */
@echo ----- Making recovery image ------
rm -rf$(TARGET_RECOVERY_OUT)
mkdir -p$(TARGET_RECOVERY_OUT)
mkdir -p$(TARGET_RECOVERY_ROOT_OUT)
mkdir -p$(TARGET_RECOVERY_ROOT_OUT)/etc
mkdir -p$(TARGET_RECOVERY_ROOT_OUT)/tmp
echoCopying baseline ramdisk...
cp -R$(TARGET_ROOT_OUT)$(TARGET_RECOVERY_OUT)

/* 删除所有的 Init 脚本,使用 Recovery 特定的 Init 脚本 */
rm$(TARGET_RECOVERY_ROOT_OUT)/init*.rc
echoModifying ramdisk contents...
cp -f$(recovery_initrc)$(TARGET_RECOVERY_ROOT_OUT)/

/* 添加 Recovery Binary */
cp -f$(recovery_binary)$(TARGET_RECOVERY_ROOT_OUT)/sbin/

/* 添加通用的和设备特定的 Recovery 资源 */
cp -rf$(recovery_resources_common)$(TARGET_RECOVERY_ROOT_OUT)/
$(foreach item,$(recovery_resources_private),\
cp -rf$(item)$(TARGET_RECOVERY_ROOT_OUT)/)

/* 添加设备特定的文件系统表 */
$(foreach item,$(recovery_fstab),\
cp -f$(item)$(TARGET_RECOVERY_ROOT_OUT)/etc/recovery.fstab)
$(foreach item,$(recovery_mmc_fstab),\
cp -f$(item)$(TARGET_RECOVERY_ROOT_OUT)/etc/recovery_mmc.fstab)

/* 内嵌验证签名的公钥 */
cp$(RECOVERY_INSTALL_OTA_KEYS)$(TARGET_RECOVERY_ROOT_OUT)/res/keys

/* 生成 Recovery 模式的默认属性文件 */
cat$(INSTALLED_DEFAULT_PROP_TARGET)$(recovery_build_prop)\
>$(TARGET_RECOVERY_ROOT_OUT)/default.prop

/* 生成 Recovery 的根文件系统 ramdisk-recovery.img */
$(MKBOOTFS)$(TARGET_RECOVERY_ROOT_OUT) |$(MINIGZIP)>$(recovery_ramdisk)

/* 把正常系统的内核跟 ramdisk-recovery.img 打包生成 Recovery Image */
$(MKBOOTIMG)$(INTERNAL_RECOVERYIMAGE_ARGS)--output$@
@echo ----- Made recovery image --------$@

/* 验证生成的 Recovery Image 有没有超出 Recovery 分区的大小 */
$(hide)$(call assert-max-image-size,$@,$(BOARD_RECOVERYIMAGE_PARTITION_SIZE),raw)

else
INSTALLED_RECOVERYIMAGE_TARGET :=
endif

.PHONY: recoveryimage
recoveryimage:$(INSTALLED_RECOVERYIMAGE_TARGET)

  • Recovery Init Script:

  从上面的分析可以看出 recovery.img 和 boot.img 的区别不大,主要是 init 脚本不一样,recovery 的 init 脚本相对简单,系统起来后只运行 ueventd、recovery、adbd 三个服务。

# bootable/recovery/etc/init.rc

on early-init
start ueventd

on init
exportPATH /sbin
exportANDROID_ROOT /system
exportANDROID_DATA /data
exportEXTERNAL_STORAGE /sdcard

symlink /system/etc /etc

mkdir /sdcard
mkdir /system
mkdir /data
mkdir /cache

mount /tmp /tmp tmpfs

on boot
ifup lo
hostname localhost
domainname localdomain

class_start default

service ueventd /sbin/ueventd
critical

service recovery /sbin/recovery

service adbd /sbin/adbd recovery
disabled

on property:persist.service.adb.enable=1
start adbd

on property:persist.service.adb.enable=0
stop adbd

  • Android <----> Recovery Binary <----> Bootloader:

  有时候 Android 需要不同的模式互相协助来完成一项任务,这样不同模式之间就要有一种机制来交换信息。Recovery Binary 和 Bootloader 之间是通过 misc 分区来传递信息的,如果是 MTD 设备,则使用 misc 分区的第二个页面,如果是块设备,则使用 misc 分区的第一块,交换的信息通过如下结构体封装。Recovery Binary 和 Android 之间是通过 cache 分区下的如下几个固定文件来传递信息的。

/* Recovery Binary <----> Bootloader */

struct bootloader_message {
char command [ 32 ];
char status [ 32 ];
char recovery [ 1024 ];
};

/* Recovery Binary <----> Android */

/cache/recovery/command
/cache/recovery/intent
/cache/recovery/log
/cache/recovery/last_log

  • Updater Binary:

  Updater Binary 是 OTA package 的安装程序,被打包到 OTA package 中一起发布。Updater Binary 的源代码位于目录 bootable/recovery/updater 中。每个设备都可以为 Updater Binary 添加自己特定的扩展,然后通过变量TARGET_RECOVERY_UPDATER_LIBS 和 TARGET_RECOVERY_UPDATER_EXTRA_LIBS 来指定。

# bootable/recovery/updater/Android.mk

LOCAL_STATIC_LIBRARIES += $( TARGET_RECOVERY_UPDATER_LIBS) \
$( TARGET_RECOVERY_UPDATER_EXTRA_LIBS)
LOCAL_STATIC_LIBRARIES + = libapplypatch libedify libmtdutils libminzip libz
LOCAL_STATIC_LIBRARIES + = libmincrypt libbz
LOCAL_STATIC_LIBRARIES + = libcutils libstdc++ libc
LOCAL_C_INCLUDES + = $( LOCAL_PATH) /..

# Each library in TARGET_RECOVERY_UPDATER_LIBS should have a function
# named "Register_<libname>()". Here we emit a little C function that
# gets #included by updater.c. It calls all those registration
# functions.

# Devices can also add libraries to TARGET_RECOVERY_UPDATER_EXTRA_LIBS.
# These libs are also linked in with updater, but we don't try to call
# any sort of registration function for these. Use this variable for
# any subsidiary static libraries required for your registered
# extension libs.

inc :=$(call intermediates-dir-for,PACKAGING,updater_extensions)/register.inc

# During the first pass of reading the makefiles, we dump the list of
# extension libs to a temp file, then copy that to the ".list" file if
# it is different than the existing .list (if any). The register.inc
# file then uses the .list as a prerequisite, so it is only rebuilt
# (and updater.o recompiled) when the list of extension libs changes.

junk :=$(shell mkdir -p$(dir$(inc));\
echo$(TARGET_RECOVERY_UPDATER_LIBS)>$(inc).temp;\
diff -q$(inc).temp$(inc).list||cp -f$(inc).temp$(inc).list)

$(inc): libs :=$(TARGET_RECOVERY_UPDATER_LIBS)
$(inc):$(inc).list
$(hide)mkdir -p$(dir$@)
$(hide)echo"">$@
$(hide)$(foreach lib,$(libs),echo"extern void Register_$(lib)(void);">>$@)
$(hide)echo"void RegisterDeviceExtensions() {">>$@
$(hide)$(foreach lib,$(libs),echo" Register_$(lib)();">>$@)
$(hide)echo"}">>$@

$(call intermediates-dir-for,EXECUTABLES,updater)/updater.o :$(inc)
LOCAL_C_INCLUDES +=$(dir$(inc))

更多相关文章

  1. Android(安卓)系统分区分析
  2. Ubuntu16.04配置ADB调试环境
  3. android 详细解答json解析与生成 JSONObject JSONArray
  4. android我的官方文档--No.1 Introduction to Android
  5. Android开发者指南(11) —— Optimizing Apps for Android(安卓)
  6. Android开发笔记之adb参数指南
  7. Android(安卓)输入系统
  8. Android(安卓)开发 环境的配置 Eclipse +SDK +ADT
  9. Android开发笔记之adb参数指南

随机推荐

  1. 【Nest教程】Nest项目集成JWT接口认证
  2. 【Nest教程】自定义拦截器处理处理响应数
  3. 【Nest教程】Nest项目用户密码加密
  4. 【Nest教程】基于Nest初始化Web API项目
  5. Vue项目中Axios的简单封装
  6. 【Nest教程】Nest项目部署在ubuntu服务器
  7. 讲一讲Vue+Ant Design表单验证
  8. 【Nest教程】Nest项目配置http和https
  9. 【Nest教程】实现一个简单的用户增删改查
  10. Vue3动态添加路由及生成菜单