From 4e358ab2c3635439db5bd1a1ef424d5c1250ce00 Mon Sep 17 00:00:00 2001 From: Alex Light Date: Thu, 16 Jun 2016 14:47:10 -0700 Subject: [PATCH] Add system_other partition, install odex files For AB devices, support flashing two system partitions for factory use. The normal system image on one partition, but without dex preopt. And a system_other image that just contains the odex files. The dex files will not be stripped out of the system image, in case the second system partition is wiped. Setting BOARD_USES_SYSTEM_OTHER_ODEX := true in the BoardConfig.mk enables this behavior. One can control which directories are placed in system_other by the SYSTEM_OTHER_ODEX_FILTER configuration variable. Currently we default to only copying only app and priv-app odexs. Bug: 29278988 Change-Id: I7f4e87da919e7dc6a89fd8c668193cd4e98631bc --- CleanSpec.mk | 4 ++ core/Makefile | 62 +++++++++++++++++++ core/cleanbuild.mk | 1 + core/dex_preopt.mk | 4 ++ core/dex_preopt_libart.mk | 15 +++++ core/dex_preopt_odex_install.mk | 16 ++--- core/envsetup.mk | 3 + core/main.mk | 9 ++- core/setup_one_odex.mk | 4 +- tools/releasetools/add_img_to_target_files.py | 23 +++++++ tools/releasetools/build_image.py | 15 +++++ 11 files changed, 146 insertions(+), 10 deletions(-) diff --git a/CleanSpec.mk b/CleanSpec.mk index 3c8d6ceb9..a97c71a49 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -374,6 +374,10 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/*) # $(PRODUCT_OUT)/recovery/root/sdcard goes from symlink to folder. $(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/sdcard) +# Add BOARD_USES_SYSTEM_OTHER_ODEX +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/*) + # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST # ************************************************ diff --git a/core/Makefile b/core/Makefile index 1e81c1435..3b17767e4 100644 --- a/core/Makefile +++ b/core/Makefile @@ -1415,6 +1415,59 @@ IGNORE_CACHE_LINK := --exclude=cache endif # BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE +# ----------------------------------------------------------------- +# system_other partition image +ifeq ($(BOARD_USES_SYSTEM_OTHER_ODEX),true) +BOARD_USES_SYSTEM_OTHER := true + +# Marker file to identify that odex files are installed +INSTALLED_SYSTEM_OTHER_ODEX_MARKER := $(TARGET_OUT_SYSTEM_OTHER)/system-other-odex-marker +ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_SYSTEM_OTHER_ODEX_MARKER) +$(INSTALLED_SYSTEM_OTHER_ODEX_MARKER): + $(hide) touch $@ +endif + +ifdef BOARD_USES_SYSTEM_OTHER +INTERNAL_SYSTEMOTHERIMAGE_FILES := \ + $(filter $(TARGET_OUT_SYSTEM_OTHER)/%,\ + $(ALL_DEFAULT_INSTALLED_MODULES)\ + $(ALL_PDK_FUSION_FILES)) + +INSTALLED_FILES_FILE_SYSTEMOTHER := $(PRODUCT_OUT)/installed-files-system-other.txt +$(INSTALLED_FILES_FILE_SYSTEMOTHER) : $(INTERNAL_SYSTEMOTHERIMAGE_FILES) + @echo Installed file list: $@ + @mkdir -p $(dir $@) + @rm -f $@ + $(hide) build/tools/fileslist.py $(TARGET_OUT_SYSTEM_OTHER) > $@ + +systemotherimage_intermediates := \ + $(call intermediates-dir-for,PACKAGING,system_other) +BUILT_SYSTEMOTHERIMAGE_TARGET := $(PRODUCT_OUT)/system_other.img + +# Note that we assert the size is SYSTEMIMAGE_PARTITION_SIZE since this is the 'b' system image. +define build-systemotherimage-target + $(call pretty,"Target system_other fs image: $(INSTALLED_SYSTEMOTHERIMAGE_TARGET)") + @mkdir -p $(TARGET_OUT_SYSTEM_OTHER) + @mkdir -p $(systemotherimage_intermediates) && rm -rf $(systemotherimage_intermediates)/system_other_image_info.txt + $(call generate-userimage-prop-dictionary, $(systemotherimage_intermediates)/system_other_image_info.txt, skip_fsck=true) + $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \ + ./build/tools/releasetools/build_image.py \ + $(TARGET_OUT_SYSTEM_OTHER) $(systemotherimage_intermediates)/system_other_image_info.txt $(INSTALLED_SYSTEMOTHERIMAGE_TARGET) $(TARGET_OUT) + $(hide) $(call assert-max-image-size,$(INSTALLED_SYSTEMOTHERIMAGE_TARGET),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE)) +endef + +# We just build this directly to the install location. +INSTALLED_SYSTEMOTHERIMAGE_TARGET := $(BUILT_SYSTEMOTHERIMAGE_TARGET) +$(INSTALLED_SYSTEMOTHERIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_SYSTEMOTHERIMAGE_FILES) $(INSTALLED_FILES_FILE_SYSTEMOTHER) + $(build-systemotherimage-target) + +.PHONY: systemotherimage-nodeps +systemotherimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS) + $(build-systemotherimage-target) + +endif # BOARD_USES_SYSTEM_OTHER + + # ----------------------------------------------------------------- # vendor partition image ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE @@ -1646,6 +1699,7 @@ $(BUILT_TARGET_FILES_PACKAGE): \ $(INSTALLED_USERDATAIMAGE_TARGET) \ $(INSTALLED_CACHEIMAGE_TARGET) \ $(INSTALLED_VENDORIMAGE_TARGET) \ + $(INSTALLED_SYSTEMOTHERIMAGE_TARGET) \ $(INSTALLED_ANDROID_INFO_TXT_TARGET) \ $(SELINUX_FC) \ $(APKCERTS_FILE) \ @@ -1718,6 +1772,11 @@ ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE @# Contents of the vendor image $(hide) $(call package_files-copy-root, \ $(TARGET_OUT_VENDOR),$(zip_root)/VENDOR) +endif +ifdef INSTALLED_SYSTEMOTHERIMAGE_TARGET + @# Contents of the system_other image + $(hide) $(call package_files-copy-root, \ + $(TARGET_OUT_SYSTEM_OTHER),$(zip_root)/SYSTEM_OTHER) endif @# Extra contents of the OTA package $(hide) mkdir -p $(zip_root)/OTA @@ -1832,6 +1891,9 @@ endif $(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 ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),) $(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 +endif +ifdef INSTALLED_SYSTEMOTHERIMAGE_TARGET + $(hide) zipinfo -1 $@ | awk 'BEGIN { FS="SYSTEM_OTHER/" } /^SYSTEM_OTHER\// { print "system/" $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -D $(TARGET_OUT) -S $(SELINUX_FC) > $(zip_root)/META/system_other_filesystem_config.txt endif $(hide) (cd $(zip_root) && zip -qX ../$(notdir $@) META/*filesystem_config.txt) $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \ diff --git a/core/cleanbuild.mk b/core/cleanbuild.mk index 0d6a406ce..e46d93415 100644 --- a/core/cleanbuild.mk +++ b/core/cleanbuild.mk @@ -242,6 +242,7 @@ installclean_files := \ $(PRODUCT_OUT)/recovery \ $(PRODUCT_OUT)/root \ $(PRODUCT_OUT)/system \ + $(PRODUCT_OUT)/system_other \ $(PRODUCT_OUT)/vendor \ $(PRODUCT_OUT)/oem \ $(PRODUCT_OUT)/dex_bootjars \ diff --git a/core/dex_preopt.mk b/core/dex_preopt.mk index d182dc073..5df9dc30a 100644 --- a/core/dex_preopt.mk +++ b/core/dex_preopt.mk @@ -19,6 +19,10 @@ DEXPREOPT_BOOT_JAR_DIR_FULL_PATH := $(DEXPREOPT_PRODUCT_DIR_FULL_PATH)/$(DEXPREO # The default value for LOCAL_DEX_PREOPT DEX_PREOPT_DEFAULT ?= true +# The default filter for which files go into the system_other image (if it is +# being used). To bundle everything one should set this to '%' +SYSTEM_OTHER_ODEX_FILTER ?= app/% priv-app/% + # The default values for pre-opting: always preopt PIC. # Conditional to building on linux, as dex2oat currently does not work on darwin. ifeq ($(HOST_OS),linux) diff --git a/core/dex_preopt_libart.mk b/core/dex_preopt_libart.mk index 9410c3ccc..acd4a02dd 100644 --- a/core/dex_preopt_libart.mk +++ b/core/dex_preopt_libart.mk @@ -59,6 +59,21 @@ define get-odex-file-path $(dir $(2))oat/$(1)/$(basename $(notdir $(2))).odex endef +# Returns the full path to the installed .odex file. +# This handles BOARD_USES_SYSTEM_OTHER_ODEX to install odex files into another +# partition. +# $(1): the arch name. +# $(2): the full install path (including file name) of the corresponding .apk. +ifeq ($(BOARD_USES_SYSTEM_OTHER_ODEX),true) +define get-odex-installed-file-path +$(if $(filter $(foreach f,$(SYSTEM_OTHER_ODEX_FILTER),$(TARGET_OUT)/$(f)),$(2)), + $(call get-odex-file-path,$(1),$(patsubst $(TARGET_OUT)/%,$(TARGET_OUT_SYSTEM_OTHER)/%,$(2))), + $(call get-odex-file-path,$(1),$(2))) +endef +else +get-odex-installed-file-path = $(get-odex-file-path) +endif + # Returns the path to the image file (such as "/system/framework//boot.art" # $(1): the arch name (such as "arm") # $(2): the image location (such as "/system/framework/boot.art") diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk index 4e486d52a..b05d4da3d 100644 --- a/core/dex_preopt_odex_install.mk +++ b/core/dex_preopt_odex_install.mk @@ -39,6 +39,14 @@ ifeq ($(filter $(DEXPREOPT_BOOT_JARS_MODULES),$(LOCAL_MODULE)),) LOCAL_DEX_PREOPT := endif endif +# if installing into system, and odex are being installed into system_other, don't strip +ifeq ($(BOARD_USES_SYSTEM_OTHER_ODEX),true) +ifeq ($(LOCAL_DEX_PREOPT),true) +ifneq ($(filter $(foreach f,$(SYSTEM_OTHER_ODEX_FILTER),$(TARGET_OUT)/$(f)),$(my_module_path)),) +LOCAL_DEX_PREOPT := nostripping +endif +endif +endif built_odex := installed_odex := @@ -100,14 +108,6 @@ endif endif $(built_odex): PRIVATE_DEX_PREOPT_FLAGS := $(LOCAL_DEX_PREOPT_FLAGS) - -# Use pattern rule - we may have multiple installed odex files. -# Ugly syntax - See the definition get-odex-file-path. -$(installed_odex) : $(dir $(LOCAL_INSTALLED_MODULE))%$(notdir $(word 1,$(installed_odex))) \ - : $(dir $(LOCAL_BUILT_MODULE))%$(notdir $(word 1,$(built_odex))) \ - | $(ACP) - @echo "Install: $@" - $(copy-file-to-target) endif # Add the installed_odex to the list of installed files for this module. diff --git a/core/envsetup.mk b/core/envsetup.mk index 0a7260337..ce31ddbee 100644 --- a/core/envsetup.mk +++ b/core/envsetup.mk @@ -109,6 +109,7 @@ HOST_PREBUILT_TAG := $(BUILD_OS)-$(HOST_PREBUILT_ARCH) # TARGET_COPY_OUT_* are all relative to the staging directory, ie PRODUCT_OUT. # Define them here so they can be used in product config files. TARGET_COPY_OUT_SYSTEM := system +TARGET_COPY_OUT_SYSTEM_OTHER := system_other TARGET_COPY_OUT_DATA := data TARGET_COPY_OUT_OEM := oem TARGET_COPY_OUT_ODM := odm @@ -322,6 +323,8 @@ TARGET_OUT_ETC := $(TARGET_OUT)/etc TARGET_OUT_NOTICE_FILES := $(TARGET_OUT_INTERMEDIATES)/NOTICE_FILES TARGET_OUT_FAKE := $(PRODUCT_OUT)/fake_packages +TARGET_OUT_SYSTEM_OTHER := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_SYSTEM_OTHER) + # Out for TARGET_2ND_ARCH TARGET_2ND_ARCH_VAR_PREFIX := $(HOST_2ND_ARCH_VAR_PREFIX) TARGET_2ND_ARCH_MODULE_SUFFIX := $(HOST_2ND_ARCH_MODULE_SUFFIX) diff --git a/core/main.mk b/core/main.mk index 651ba98de..a612f835d 100644 --- a/core/main.mk +++ b/core/main.mk @@ -81,6 +81,7 @@ dont_bother_goals := clean clobber dataclean installclean \ userdataimage-nodeps userdatatarball-nodeps \ cacheimage-nodeps \ vendorimage-nodeps \ + systemotherimage-nodeps \ ramdisk-nodeps \ bootimage-nodeps \ recoveryimage-nodeps \ @@ -928,6 +929,9 @@ cacheimage: $(INSTALLED_CACHEIMAGE_TARGET) .PHONY: vendorimage vendorimage: $(INSTALLED_VENDORIMAGE_TARGET) +.PHONY: systemotherimage +systemotherimage: $(INSTALLED_SYSTEMOTHERIMAGE_TARGET) + .PHONY: bootimage bootimage: $(INSTALLED_BOOTIMAGE_TARGET) @@ -955,8 +959,10 @@ droidcore: files \ $(INSTALLED_USERDATAIMAGE_TARGET) \ $(INSTALLED_CACHEIMAGE_TARGET) \ $(INSTALLED_VENDORIMAGE_TARGET) \ + $(INSTALLED_SYSTEMOTHERIMAGE_TARGET) \ $(INSTALLED_FILES_FILE) \ - $(INSTALLED_FILES_FILE_VENDOR) + $(INSTALLED_FILES_FILE_VENDOR) \ + $(INSTALLED_FILES_FILE_SYSTEMOTHER) # dist_files only for putting your library into the dist directory with a full build. .PHONY: dist_files @@ -1017,6 +1023,7 @@ else # TARGET_BUILD_APPS $(SYMBOLS_ZIP) \ $(INSTALLED_FILES_FILE) \ $(INSTALLED_FILES_FILE_VENDOR) \ + $(INSTALLED_FILES_FILE_SYSTEMOTHER) \ $(INSTALLED_BUILD_PROP_TARGET) \ $(BUILT_TARGET_FILES_PACKAGE) \ $(INSTALLED_ANDROID_INFO_TXT_TARGET) \ diff --git a/core/setup_one_odex.mk b/core/setup_one_odex.mk index ec8a28a5b..36b68171b 100644 --- a/core/setup_one_odex.mk +++ b/core/setup_one_odex.mk @@ -32,7 +32,9 @@ $(my_built_odex) : $($(my_2nd_arch_prefix)DEXPREOPT_ONE_FILE_DEPENDENCY_BUILT_BO $(DEXPREOPT_ONE_FILE_DEPENDENCY_TOOLS) \ $(my_dex_preopt_image_filename) -my_installed_odex := $(call get-odex-file-path,$($(my_2nd_arch_prefix)DEX2OAT_TARGET_ARCH),$(LOCAL_INSTALLED_MODULE)) +my_installed_odex := $(call get-odex-installed-file-path,$($(my_2nd_arch_prefix)DEX2OAT_TARGET_ARCH),$(LOCAL_INSTALLED_MODULE)) + +$(eval $(call copy-one-file,$(my_built_odex),$(my_installed_odex))) built_odex += $(my_built_odex) installed_odex += $(my_installed_odex) diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py index 7cb907260..ddc0d0b29 100755 --- a/tools/releasetools/add_img_to_target_files.py +++ b/tools/releasetools/add_img_to_target_files.py @@ -78,6 +78,24 @@ def BuildSystem(input_dir, info_dict, block_list=None): return CreateImage(input_dir, info_dict, "system", block_list=block_list) +def AddSystemOther(output_zip, prefix="IMAGES/"): + """Turn the contents of SYSTEM_OTHER into a system_other image + and store it in output_zip.""" + + prebuilt_path = os.path.join(OPTIONS.input_tmp, prefix, "system_other.img") + if os.path.exists(prebuilt_path): + print "system_other.img already exists in %s, no need to rebuild..." % (prefix,) + return + + imgname = BuildSystemOther(OPTIONS.input_tmp, OPTIONS.info_dict) + common.ZipWrite(output_zip, imgname, prefix + "system_other.img") + +def BuildSystemOther(input_dir, info_dict): + """Build the (sparse) system_other image and return the name of a temp + file containing it.""" + return CreateImage(input_dir, info_dict, "system_other", block_list=None) + + def AddVendor(output_zip, prefix="IMAGES/"): """Turn the contents of VENDOR into a vendor image and store in it output_zip.""" @@ -268,6 +286,8 @@ def AddImagesToTargetFiles(filename): except KeyError: has_vendor = False + has_system_other = "SYSTEM_OTHER/" in input_zip.namelist() + OPTIONS.info_dict = common.LoadInfoDict(input_zip, OPTIONS.input_tmp) common.ZipClose(input_zip) @@ -314,6 +334,9 @@ def AddImagesToTargetFiles(filename): if has_vendor: banner("vendor") AddVendor(output_zip) + if has_system_other: + banner("system_other") + AddSystemOther(output_zip) banner("userdata") AddUserdata(output_zip) banner("cache") diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py index 3d41e83e1..a9217eed8 100755 --- a/tools/releasetools/build_image.py +++ b/tools/releasetools/build_image.py @@ -556,6 +556,19 @@ def ImagePropFromGlobalDict(glob_dict, mount_point): copy_prop("system_squashfs_block_size", "squashfs_block_size") copy_prop("system_squashfs_disable_4k_align", "squashfs_disable_4k_align") copy_prop("system_base_fs_file", "base_fs_file") + elif mount_point == "system_other": + # We inherit the selinux policies of /system since we contain some of its files. + d["mount_point"] = "system" + copy_prop("fs_type", "fs_type") + copy_prop("system_fs_type", "fs_type") + copy_prop("system_size", "partition_size") + copy_prop("system_journal_size", "journal_size") + copy_prop("system_verity_block_device", "verity_block_device") + copy_prop("has_ext4_reserved_blocks", "has_ext4_reserved_blocks") + copy_prop("system_squashfs_compressor", "squashfs_compressor") + copy_prop("system_squashfs_compressor_opt", "squashfs_compressor_opt") + copy_prop("system_squashfs_block_size", "squashfs_block_size") + copy_prop("system_base_fs_file", "base_fs_file") elif mount_point == "data": # Copy the generic fs type first, override with specific one if available. copy_prop("fs_type", "fs_type") @@ -618,6 +631,8 @@ def main(argv): mount_point = "" if image_filename == "system.img": mount_point = "system" + elif image_filename == "system_other.img": + mount_point = "system_other" elif image_filename == "userdata.img": mount_point = "data" elif image_filename == "cache.img":