Merge "libutils: remove the unused StopWatch lap functionality."
diff --git a/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp b/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp
index 17f4c4e..1c95cf0 100644
--- a/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp
+++ b/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp
@@ -122,6 +122,7 @@
const size_t padding_size) {
VBMetaImage vbmeta_image;
vbmeta_image.path = test_dir_.Append(output_file_name);
+ GTEST_LOG_(INFO) << "ExtractVBMetaImage: " << image_path << " to " << output_file_name;
EXPECT_COMMAND(0,
"avbtool extract_vbmeta_image"
" --image %s"
diff --git a/fs_mgr/libsnapshot/cow_snapuserd_test.cpp b/fs_mgr/libsnapshot/cow_snapuserd_test.cpp
index 313eb64..3888eb1 100644
--- a/fs_mgr/libsnapshot/cow_snapuserd_test.cpp
+++ b/fs_mgr/libsnapshot/cow_snapuserd_test.cpp
@@ -96,7 +96,8 @@
class CowSnapuserdTest final {
public:
bool Setup();
- bool SetupCopyOverlap();
+ bool SetupCopyOverlap_1();
+ bool SetupCopyOverlap_2();
bool Merge();
void ValidateMerge();
void ReadSnapshotDeviceAndValidate();
@@ -115,7 +116,9 @@
void StartMerge();
void CreateCowDevice();
- void CreateCowDeviceWithCopyOverlap();
+ void CreateCowDeviceWithCopyOverlap_1();
+ void CreateCowDeviceWithCopyOverlap_2();
+ bool SetupDaemon();
void CreateBaseDevice();
void InitCowDevice();
void SetDeviceControlName();
@@ -193,10 +196,19 @@
return setup_ok_;
}
-bool CowSnapuserdTest::SetupCopyOverlap() {
+bool CowSnapuserdTest::SetupCopyOverlap_1() {
CreateBaseDevice();
- CreateCowDeviceWithCopyOverlap();
+ CreateCowDeviceWithCopyOverlap_1();
+ return SetupDaemon();
+}
+bool CowSnapuserdTest::SetupCopyOverlap_2() {
+ CreateBaseDevice();
+ CreateCowDeviceWithCopyOverlap_2();
+ return SetupDaemon();
+}
+
+bool CowSnapuserdTest::SetupDaemon() {
SetDeviceControlName();
StartSnapuserdDaemon();
@@ -275,7 +287,59 @@
ASSERT_EQ(memcmp(snapuserd_buffer.get(), (char*)orig_buffer_.get() + (size_ * 3), size_), 0);
}
-void CowSnapuserdTest::CreateCowDeviceWithCopyOverlap() {
+void CowSnapuserdTest::CreateCowDeviceWithCopyOverlap_2() {
+ std::string path = android::base::GetExecutableDirectory();
+ cow_system_ = std::make_unique<TemporaryFile>(path);
+
+ CowOptions options;
+ options.compression = "gz";
+ CowWriter writer(options);
+
+ ASSERT_TRUE(writer.Initialize(cow_system_->fd));
+
+ size_t num_blocks = size_ / options.block_size;
+ size_t x = num_blocks;
+ size_t blk_src_copy = 0;
+
+ // Create overlapping copy operations
+ while (1) {
+ ASSERT_TRUE(writer.AddCopy(blk_src_copy, blk_src_copy + 1));
+ x -= 1;
+ if (x == 1) {
+ break;
+ }
+ blk_src_copy += 1;
+ }
+
+ // Flush operations
+ ASSERT_TRUE(writer.Finalize());
+
+ // Construct the buffer required for validation
+ orig_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
+
+ // Read the entire base device
+ ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, orig_buffer_.get(), total_base_size_, 0),
+ true);
+
+ // Merged operations required for validation
+ int block_size = 4096;
+ x = num_blocks;
+ loff_t src_offset = block_size;
+ loff_t dest_offset = 0;
+
+ while (1) {
+ memmove((char*)orig_buffer_.get() + dest_offset, (char*)orig_buffer_.get() + src_offset,
+ block_size);
+ x -= 1;
+ if (x == 1) {
+ break;
+ }
+ src_offset += block_size;
+ dest_offset += block_size;
+ }
+}
+
+void CowSnapuserdTest::CreateCowDeviceWithCopyOverlap_1() {
std::string path = android::base::GetExecutableDirectory();
cow_system_ = std::make_unique<TemporaryFile>(path);
@@ -770,19 +834,19 @@
de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
ASSERT_EQ(de->old_chunk, 21);
- ASSERT_EQ(de->new_chunk, 536);
- offset += sizeof(struct disk_exception);
-
- de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
- ASSERT_EQ(de->old_chunk, 22);
ASSERT_EQ(de->new_chunk, 537);
offset += sizeof(struct disk_exception);
de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
- ASSERT_EQ(de->old_chunk, 23);
+ ASSERT_EQ(de->old_chunk, 22);
ASSERT_EQ(de->new_chunk, 538);
offset += sizeof(struct disk_exception);
+ de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
+ ASSERT_EQ(de->old_chunk, 23);
+ ASSERT_EQ(de->new_chunk, 539);
+ offset += sizeof(struct disk_exception);
+
// End of metadata
de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
ASSERT_EQ(de->old_chunk, 0);
@@ -821,9 +885,17 @@
harness.Shutdown();
}
-TEST(Snapuserd_Test, Snapshot_COPY_Overlap_TEST) {
+TEST(Snapuserd_Test, Snapshot_COPY_Overlap_TEST_1) {
CowSnapuserdTest harness;
- ASSERT_TRUE(harness.SetupCopyOverlap());
+ ASSERT_TRUE(harness.SetupCopyOverlap_1());
+ ASSERT_TRUE(harness.Merge());
+ harness.ValidateMerge();
+ harness.Shutdown();
+}
+
+TEST(Snapuserd_Test, Snapshot_COPY_Overlap_TEST_2) {
+ CowSnapuserdTest harness;
+ ASSERT_TRUE(harness.SetupCopyOverlap_2());
ASSERT_TRUE(harness.Merge());
harness.ValidateMerge();
harness.Shutdown();
@@ -831,7 +903,7 @@
TEST(Snapuserd_Test, Snapshot_COPY_Overlap_Merge_Resume_TEST) {
CowSnapuserdTest harness;
- ASSERT_TRUE(harness.SetupCopyOverlap());
+ ASSERT_TRUE(harness.SetupCopyOverlap_1());
harness.MergeInterrupt();
harness.ValidateMerge();
harness.Shutdown();
diff --git a/fs_mgr/libsnapshot/snapuserd.cpp b/fs_mgr/libsnapshot/snapuserd.cpp
index 2ccc750..3210983 100644
--- a/fs_mgr/libsnapshot/snapuserd.cpp
+++ b/fs_mgr/libsnapshot/snapuserd.cpp
@@ -437,6 +437,7 @@
int num_ra_ops_per_iter = ((GetBufferDataSize()) / BLOCK_SZ);
std::optional<chunk_t> prev_id = {};
std::map<uint64_t, const CowOperation*> map;
+ std::set<uint64_t> dest_blocks;
size_t pending_copy_ops = exceptions_per_area_ - num_ops;
uint64_t total_copy_ops = reader_->total_copy_ops();
@@ -555,10 +556,15 @@
if (diff != 1) {
break;
}
+
+ if (dest_blocks.count(cow_op->new_block) || map.count(cow_op->source) > 0) {
+ break;
+ }
}
metadata_found = true;
pending_copy_ops -= 1;
map[cow_op->new_block] = cow_op;
+ dest_blocks.insert(cow_op->source);
prev_id = cow_op->new_block;
cowop_riter_->Next();
} while (!cowop_riter_->Done() && pending_copy_ops);
@@ -620,6 +626,7 @@
}
}
map.clear();
+ dest_blocks.clear();
prev_id.reset();
}
diff --git a/fs_mgr/libsnapshot/snapuserd_server.cpp b/fs_mgr/libsnapshot/snapuserd_server.cpp
index ff8a259..3b0af3e 100644
--- a/fs_mgr/libsnapshot/snapuserd_server.cpp
+++ b/fs_mgr/libsnapshot/snapuserd_server.cpp
@@ -191,7 +191,7 @@
}
case DaemonOperations::DETACH: {
terminating_ = true;
- return Sendmsg(fd, "success");
+ return true;
}
default: {
LOG(ERROR) << "Received unknown message type from client";
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index 83174ef..eb2919b 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -325,14 +325,14 @@
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
std::string fstab_contents = R"fs(
-source / ext4 ro,barrier=1 wait,slotselect,avb
+source / ext4 ro,barrier=1 wait,avb
source /metadata ext4 noatime,nosuid,nodev,discard wait,formattable
source /data f2fs noatime,nosuid,nodev,discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier latemount,wait,check,fileencryption=ice,keydirectory=/metadata/vold/metadata_encryption,quota,formattable,sysfs_path=/sys/devices/platform/soc/1d84000.ufshc,reservedsize=128M
source /misc emmc defaults defaults
-source /vendor/firmware_mnt vfat ro,shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,context=u:object_r:firmware_file:s0 wait,slotselect
+source /vendor/firmware_mnt vfat ro,shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,context=u:object_r:firmware_file:s0 wait
source auto vfat defaults voldmanaged=usb:auto
source none swap defaults zramsize=1073741824,max_comp_streams=8
@@ -412,8 +412,8 @@
ASSERT_TRUE(tf.fd != -1);
std::string fstab_contents = R"fs(
source none0 swap defaults wait,check,nonremovable,recoveryonly,verifyatboot,verify
-source none1 swap defaults avb,noemulatedsd,notrim,formattable,slotselect,nofail
-source none2 swap defaults first_stage_mount,latemount,quota,logical,slotselect_other
+source none1 swap defaults avb,noemulatedsd,notrim,formattable,nofail
+source none2 swap defaults first_stage_mount,latemount,quota,logical
source none3 swap defaults checkpoint=block
source none4 swap defaults checkpoint=fs
source none5 swap defaults defaults
@@ -445,7 +445,6 @@
flags.no_emulated_sd = true;
flags.no_trim = true;
flags.formattable = true;
- flags.slot_select = true;
flags.no_fail = true;
EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
}
@@ -458,7 +457,6 @@
flags.late_mount = true;
flags.quota = true;
flags.logical = true;
- flags.slot_select_other = true;
EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
}
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 9f1ebcf..ff9da42 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -94,6 +94,12 @@
namespace android {
namespace init {
+constexpr auto FINGERPRINT_PROP = "ro.build.fingerprint";
+constexpr auto LEGACY_FINGERPRINT_PROP = "ro.build.legacy.fingerprint";
+constexpr auto ID_PROP = "ro.build.id";
+constexpr auto LEGACY_ID_PROP = "ro.build.legacy.id";
+constexpr auto VBMETA_DIGEST_PROP = "ro.boot.vbmeta.digest";
+constexpr auto DIGEST_SIZE_USED = 8;
static bool persistent_properties_loaded = false;
@@ -857,15 +863,33 @@
}
}
-// If the ro.build.fingerprint property has not been set, derive it from constituent pieces
-static void property_derive_build_fingerprint() {
- std::string build_fingerprint = GetProperty("ro.build.fingerprint", "");
- if (!build_fingerprint.empty()) {
+static void property_initialize_build_id() {
+ std::string build_id = GetProperty(ID_PROP, "");
+ if (!build_id.empty()) {
return;
}
+ std::string legacy_build_id = GetProperty(LEGACY_ID_PROP, "");
+ std::string vbmeta_digest = GetProperty(VBMETA_DIGEST_PROP, "");
+ if (vbmeta_digest.size() < DIGEST_SIZE_USED) {
+ LOG(ERROR) << "vbmeta digest size too small " << vbmeta_digest;
+ // Still try to set the id field in the unexpected case.
+ build_id = legacy_build_id;
+ } else {
+ // Derive the ro.build.id by appending the vbmeta digest to the base value.
+ build_id = legacy_build_id + "." + vbmeta_digest.substr(0, DIGEST_SIZE_USED);
+ }
+
+ std::string error;
+ auto res = PropertySet(ID_PROP, build_id, &error);
+ if (res != PROP_SUCCESS) {
+ LOG(ERROR) << "Failed to set " << ID_PROP << " to " << build_id;
+ }
+}
+
+static std::string ConstructBuildFingerprint(bool legacy) {
const std::string UNKNOWN = "unknown";
- build_fingerprint = GetProperty("ro.product.brand", UNKNOWN);
+ std::string build_fingerprint = GetProperty("ro.product.brand", UNKNOWN);
build_fingerprint += '/';
build_fingerprint += GetProperty("ro.product.name", UNKNOWN);
build_fingerprint += '/';
@@ -873,7 +897,10 @@
build_fingerprint += ':';
build_fingerprint += GetProperty("ro.build.version.release_or_codename", UNKNOWN);
build_fingerprint += '/';
- build_fingerprint += GetProperty("ro.build.id", UNKNOWN);
+
+ std::string build_id =
+ legacy ? GetProperty(LEGACY_ID_PROP, UNKNOWN) : GetProperty(ID_PROP, UNKNOWN);
+ build_fingerprint += build_id;
build_fingerprint += '/';
build_fingerprint += GetProperty("ro.build.version.incremental", UNKNOWN);
build_fingerprint += ':';
@@ -881,13 +908,49 @@
build_fingerprint += '/';
build_fingerprint += GetProperty("ro.build.tags", UNKNOWN);
- LOG(INFO) << "Setting property 'ro.build.fingerprint' to '" << build_fingerprint << "'";
+ return build_fingerprint;
+}
+
+// Derive the legacy build fingerprint if we overwrite the build id at runtime.
+static void property_derive_legacy_build_fingerprint() {
+ std::string legacy_build_fingerprint = GetProperty(LEGACY_FINGERPRINT_PROP, "");
+ if (!legacy_build_fingerprint.empty()) {
+ return;
+ }
+
+ // The device doesn't have a legacy build id, skipping the legacy fingerprint.
+ std::string legacy_build_id = GetProperty(LEGACY_ID_PROP, "");
+ if (legacy_build_id.empty()) {
+ return;
+ }
+
+ legacy_build_fingerprint = ConstructBuildFingerprint(true /* legacy fingerprint */);
+ LOG(INFO) << "Setting property '" << LEGACY_FINGERPRINT_PROP << "' to '"
+ << legacy_build_fingerprint << "'";
std::string error;
- uint32_t res = PropertySet("ro.build.fingerprint", build_fingerprint, &error);
+ uint32_t res = PropertySet(LEGACY_FINGERPRINT_PROP, legacy_build_fingerprint, &error);
if (res != PROP_SUCCESS) {
- LOG(ERROR) << "Error setting property 'ro.build.fingerprint': err=" << res << " (" << error
- << ")";
+ LOG(ERROR) << "Error setting property '" << LEGACY_FINGERPRINT_PROP << "': err=" << res
+ << " (" << error << ")";
+ }
+}
+
+// If the ro.build.fingerprint property has not been set, derive it from constituent pieces
+static void property_derive_build_fingerprint() {
+ std::string build_fingerprint = GetProperty("ro.build.fingerprint", "");
+ if (!build_fingerprint.empty()) {
+ return;
+ }
+
+ build_fingerprint = ConstructBuildFingerprint(false /* legacy fingerprint */);
+ LOG(INFO) << "Setting property '" << FINGERPRINT_PROP << "' to '" << build_fingerprint << "'";
+
+ std::string error;
+ uint32_t res = PropertySet(FINGERPRINT_PROP, build_fingerprint, &error);
+ if (res != PROP_SUCCESS) {
+ LOG(ERROR) << "Error setting property '" << FINGERPRINT_PROP << "': err=" << res << " ("
+ << error << ")";
}
}
@@ -1035,7 +1098,9 @@
}
property_initialize_ro_product_props();
+ property_initialize_build_id();
property_derive_build_fingerprint();
+ property_derive_legacy_build_fingerprint();
property_initialize_ro_cpu_abilist();
update_sys_usb_config();
diff --git a/init/property_service_test.cpp b/init/property_service_test.cpp
index c6dcfa2..ac6b7b2 100644
--- a/init/property_service_test.cpp
+++ b/init/property_service_test.cpp
@@ -23,6 +23,7 @@
#include <android-base/properties.h>
#include <android-base/scopeguard.h>
+#include <android-base/strings.h>
#include <gtest/gtest.h>
using android::base::GetProperty;
@@ -90,5 +91,39 @@
EXPECT_FALSE(SetProperty("sys.powerctl", "reboot,userspace"));
}
+TEST(property_service, check_fingerprint_with_legacy_build_id) {
+ std::string legacy_build_id = GetProperty("ro.build.legacy.id", "");
+ if (legacy_build_id.empty()) {
+ GTEST_SKIP() << "Skipping test, legacy build id isn't set.";
+ }
+
+ std::string vbmeta_digest = GetProperty("ro.boot.vbmeta.digest", "");
+ ASSERT_GE(vbmeta_digest.size(), 8u);
+ std::string build_id = GetProperty("ro.boot.build.id", "");
+ // Check that the build id is constructed with the prefix of vbmeta digest
+ std::string expected_build_id = legacy_build_id + "." + vbmeta_digest.substr(0, 8);
+ ASSERT_EQ(expected_build_id, build_id);
+ // Check that the fingerprint is constructed with the expected format.
+ std::string fingerprint = GetProperty("ro.build.fingerprint", "");
+ std::vector<std::string> fingerprint_fields = {
+ GetProperty("ro.product.brand", ""),
+ "/",
+ GetProperty("ro.product.name", ""),
+ "/",
+ GetProperty("ro.product.device", ""),
+ ":",
+ GetProperty("ro.build.version.release_or_codename", ""),
+ "/",
+ expected_build_id,
+ "/",
+ GetProperty("ro.build.version.incremental", ""),
+ ":",
+ GetProperty("ro.build.type", ""),
+ "/",
+ GetProperty("ro.build.tags", "")};
+
+ ASSERT_EQ(android::base::Join(fingerprint_fields, ""), fingerprint);
+}
+
} // namespace init
} // namespace android
diff --git a/libutils/README b/libutils/README
deleted file mode 100644
index 01741e0..0000000
--- a/libutils/README
+++ /dev/null
@@ -1,289 +0,0 @@
-Android Utility Function Library
-================================
-
-
-If you need a feature that is native to Linux but not present on other
-platforms, construct a platform-dependent implementation that shares
-the Linux interface. That way the actual device runs as "light" as
-possible.
-
-If that isn't feasible, create a system-independent interface and hide
-the details.
-
-The ultimate goal is *not* to create a super-duper platform abstraction
-layer. The goal is to provide an optimized solution for Linux with
-reasonable implementations for other platforms.
-
-
-
-Resource overlay
-================
-
-
-Introduction
-------------
-
-Overlay packages are special .apk files which provide no code but
-additional resource values (and possibly new configurations) for
-resources in other packages. When an application requests resources,
-the system will return values from either the application's original
-package or any associated overlay package. Any redirection is completely
-transparent to the calling application.
-
-Resource values have the following precedence table, listed in
-descending precedence.
-
- * overlay package, matching config (eg res/values-en-land)
-
- * original package, matching config
-
- * overlay package, no config (eg res/values)
-
- * original package, no config
-
-During compilation, overlay packages are differentiated from regular
-packages by passing the -o flag to aapt.
-
-
-Background
-----------
-
-This section provides generic background material on resources in
-Android.
-
-
-How resources are bundled in .apk files
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Android .apk files are .zip files, usually housing .dex code,
-certificates and resources, though packages containing resources but
-no code are possible. Resources can be divided into the following
-categories; a `configuration' indicates a set of phone language, display
-density, network operator, etc.
-
- * assets: uncompressed, raw files packaged as part of an .apk and
- explicitly referenced by filename. These files are
- independent of configuration.
-
- * res/drawable: bitmap or xml graphics. Each file may have different
- values depending on configuration.
-
- * res/values: integers, strings, etc. Each resource may have different
- values depending on configuration.
-
-Resource meta information and information proper is stored in a binary
-format in a named file resources.arsc, bundled as part of the .apk.
-
-Resource IDs and lookup
-~~~~~~~~~~~~~~~~~~~~~~~
-During compilation, the aapt tool gathers application resources and
-generates a resources.arsc file. Each resource name is assigned an
-integer ID 0xppttiii (translated to a symbolic name via R.java), where
-
- * pp: corresponds to the package namespace (details below).
-
- * tt: corresponds to the resource type (string, int, etc). Every
- resource of the same type within the same package has the same
- tt value, but depending on available types, the actual numerical
- value may be different between packages.
-
- * iiii: sequential number, assigned in the order resources are found.
-
-Resource values are specified paired with a set of configuration
-constraints (the default being the empty set), eg res/values-sv-port
-which imposes restrictions on language (Swedish) and display orientation
-(portrait). During lookup, every constraint set is matched against the
-current configuration, and the value corresponding to the best matching
-constraint set is returned (ResourceTypes.{h,cpp}).
-
-Parsing of resources.arsc is handled by ResourceTypes.cpp; this utility
-is governed by AssetManager.cpp, which tracks loaded resources per
-process.
-
-Assets are looked up by path and filename in AssetManager.cpp. The path
-to resources in res/drawable are located by ResourceTypes.cpp and then
-handled like assets by AssetManager.cpp. Other resources are handled
-solely by ResourceTypes.cpp.
-
-Package ID as namespace
-~~~~~~~~~~~~~~~~~~~~~~~
-The pp part of a resource ID defines a namespace. Android currently
-defines two namespaces:
-
- * 0x01: system resources (pre-installed in framework-res.apk)
-
- * 0x7f: application resources (bundled in the application .apk)
-
-ResourceTypes.cpp supports package IDs between 0x01 and 0x7f
-(inclusive); values outside this range are invalid.
-
-Each running (Dalvik) process is assigned a unique instance of
-AssetManager, which in turn keeps a forest structure of loaded
-resource.arsc files. Normally, this forest is structured as follows,
-where mPackageMap is the internal vector employed in ResourceTypes.cpp.
-
-mPackageMap[0x00] -> system package
-mPackageMap[0x01] -> NULL
-mPackageMap[0x02] -> NULL
-...
-mPackageMap[0x7f - 2] -> NULL
-mPackageMap[0x7f - 1] -> application package
-
-
-
-The resource overlay extension
-------------------------------
-
-The resource overlay mechanism aims to (partly) shadow and extend
-existing resources with new values for defined and new configurations.
-Technically, this is achieved by adding resource-only packages (called
-overlay packages) to existing resource namespaces, like so:
-
-mPackageMap[0x00] -> system package -> system overlay package
-mPackageMap[0x01] -> NULL
-mPackageMap[0x02] -> NULL
-...
-mPackageMap[0x7f - 2] -> NULL
-mPackageMap[0x7f - 1] -> application package -> overlay 1 -> overlay 2
-
-The use of overlay resources is completely transparent to
-applications; no additional resource identifiers are introduced, only
-configuration/value pairs. Any number of overlay packages may be loaded
-at a time; overlay packages are agnostic to what they target -- both
-system and application resources are fair game.
-
-The package targeted by an overlay package is called the target or
-original package.
-
-Resource overlay operates on symbolic resources names. Hence, to
-override the string/str1 resources in a package, the overlay package
-would include a resource also named string/str1. The end user does not
-have to worry about the numeric resources IDs assigned by aapt, as this
-is resolved automatically by the system.
-
-As of this writing, the use of resource overlay has not been fully
-explored. Until it has, only OEMs are trusted to use resource overlay.
-For this reason, overlay packages must reside in /system/overlay.
-
-
-Resource ID mapping
-~~~~~~~~~~~~~~~~~~~
-Resource identifiers must be coherent within the same namespace (ie
-PackageGroup in ResourceTypes.cpp). Calling applications will refer to
-resources using the IDs defined in the original package, but there is no
-guarantee aapt has assigned the same ID to the corresponding resource in
-an overlay package. To translate between the two, a resource ID mapping
-{original ID -> overlay ID} is created during package installation
-(PackageManagerService.java) and used during resource lookup. The
-mapping is stored in /data/resource-cache, with a @idmap file name
-suffix.
-
-The idmap file format is documented in a separate section, below.
-
-
-Package management
-~~~~~~~~~~~~~~~~~~
-Packages are managed by the PackageManagerService. Addition and removal
-of packages are monitored via the inotify framework, exposed via
-android.os.FileObserver.
-
-During initialization of a Dalvik process, ActivityThread.java requests
-the process' AssetManager (by proxy, via AssetManager.java and JNI)
-to load a list of packages. This list includes overlay packages, if
-present.
-
-When a target package or a corresponding overlay package is installed,
-the target package's process is stopped and a new idmap is generated.
-This is similar to how applications are stopped when their packages are
-upgraded.
-
-
-Creating overlay packages
--------------------------
-
-Overlay packages should contain no code, define (some) resources with
-the same type and name as in the original package, and be compiled with
-the -o flag passed to aapt.
-
-The aapt -o flag instructs aapt to create an overlay package.
-Technically, this means the package will be assigned package id 0x00.
-
-There are no restrictions on overlay packages names, though the naming
-convention <original.package.name>.overlay.<name> is recommended.
-
-
-Example overlay package
-~~~~~~~~~~~~~~~~~~~~~~~
-
-To overlay the resource bool/b in package com.foo.bar, to be applied
-when the display is in landscape mode, create a new package with
-no source code and a single .xml file under res/values-land, with
-an entry for bool/b. Compile with aapt -o and place the results in
-/system/overlay by adding the following to Android.mk:
-
-LOCAL_AAPT_FLAGS := -o com.foo.bar
-LOCAL_MODULE_PATH := $(TARGET_OUT)/overlay
-
-
-The ID map (idmap) file format
-------------------------------
-
-The idmap format is designed for lookup performance. However, leading
-and trailing undefined overlay values are discarded to reduce the memory
-footprint.
-
-
-idmap grammar
-~~~~~~~~~~~~~
-All atoms (names in square brackets) are uint32_t integers. The
-idmap-magic constant spells "idmp" in ASCII. Offsets are given relative
-to the data_header, not to the beginning of the file.
-
-map := header data
-header := idmap-magic <crc32-original-pkg> <crc32-overlay-pkg>
-idmap-magic := <0x706d6469>
-data := data_header type_block+
-data_header := <m> header_block{m}
-header_block := <0> | <type_block_offset>
-type_block := <n> <id_offset> entry{n}
-entry := <resource_id_in_target_package>
-
-
-idmap example
-~~~~~~~~~~~~~
-Given a pair of target and overlay packages with CRC sums 0x216a8fe2
-and 0x6b9beaec, each defining the following resources
-
-Name Target package Overlay package
-string/str0 0x7f010000 -
-string/str1 0x7f010001 0x7f010000
-string/str2 0x7f010002 -
-string/str3 0x7f010003 0x7f010001
-string/str4 0x7f010004 -
-bool/bool0 0x7f020000 -
-integer/int0 0x7f030000 0x7f020000
-integer/int1 0x7f030001 -
-
-the corresponding resource map is
-
-0x706d6469 0x216a8fe2 0x6b9beaec 0x00000003 \
-0x00000004 0x00000000 0x00000009 0x00000003 \
-0x00000001 0x7f010000 0x00000000 0x7f010001 \
-0x00000001 0x00000000 0x7f020000
-
-or, formatted differently
-
-0x706d6469 # magic: all idmap files begin with this constant
-0x216a8fe2 # CRC32 of the resources.arsc file in the original package
-0x6b9beaec # CRC32 of the resources.arsc file in the overlay package
-0x00000003 # header; three types (string, bool, integer) in the target package
-0x00000004 # header_block for type 0 (string) is located at offset 4
-0x00000000 # no bool type exists in overlay package -> no header_block
-0x00000009 # header_block for type 2 (integer) is located at offset 9
-0x00000003 # header_block for string; overlay IDs span 3 elements
-0x00000001 # the first string in target package is entry 1 == offset
-0x7f010000 # target 0x7f01001 -> overlay 0x7f010000
-0x00000000 # str2 not defined in overlay package
-0x7f010001 # target 0x7f010003 -> overlay 0x7f010001
-0x00000001 # header_block for integer; overlay IDs span 1 element
-0x00000000 # offset == 0
-0x7f020000 # target 0x7f030000 -> overlay 0x7f020000