diff options
author | Ryan Mitchell <rtmitchell@google.com> | 2020-04-24 17:45:25 -0700 |
---|---|---|
committer | Ryan Mitchell <rtmitchell@google.com> | 2020-04-28 18:07:00 +0000 |
commit | 7d53f19089829409075d8ad3dbf3447e80f0f2ac (patch) | |
tree | 756901a0bfb3e27e5c46a240f5fd647d601865ae /cmds/idmap2 | |
parent | ac774e3304d1c52d1f9057aabaa39bcb1249c656 (diff) |
Reduce OMS start time
This change attempts to reduce the amount of time initializing the
OMS. The change:
1) Reduces the amount of time between subsequent attempts to connect
to the idmap2d service when it is not alive.
2) Caches package infos retrieved from getOverlayPackages
3) Caches the crc of the android package to preventing having to
retrieve it for every overlay package targeting the framework
This chance reduced OMS start up time from ~500ms to ~100ms on a
Pixel 3. If the idmap2d service is running when system sever starts
then start up time will be around ~70ms.
Bug: 151481016
Test: adb shell stop && adb shell start && [capture trace]
Change-Id: I6137c385baf099413b62e98557419fffb9fd2d93
Diffstat (limited to 'cmds/idmap2')
-rw-r--r-- | cmds/idmap2/idmap2d/Idmap2Service.cpp | 32 | ||||
-rw-r--r-- | cmds/idmap2/idmap2d/Idmap2Service.h | 4 | ||||
-rw-r--r-- | cmds/idmap2/include/idmap2/Idmap.h | 5 | ||||
-rw-r--r-- | cmds/idmap2/libidmap2/Idmap.cpp | 38 |
4 files changed, 60 insertions, 19 deletions
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp index 75fc7f714ce3..a93184ff4787 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.cpp +++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp @@ -34,11 +34,13 @@ #include "idmap2/FileUtils.h" #include "idmap2/Idmap.h" #include "idmap2/SysTrace.h" +#include "idmap2/ZipFile.h" #include "utils/String8.h" using android::IPCThreadState; using android::binder::Status; using android::idmap2::BinaryStreamVisitor; +using android::idmap2::GetPackageCrc; using android::idmap2::Idmap; using android::idmap2::IdmapHeader; using android::idmap2::utils::kIdmapCacheDir; @@ -49,6 +51,8 @@ using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask namespace { +constexpr const char* kFrameworkPath = "/system/framework/framework-res.apk"; + Status ok() { return Status::ok(); } @@ -109,8 +113,32 @@ Status Idmap2Service::verifyIdmap(const std::string& target_apk_path, return error("failed to parse idmap header"); } - *_aidl_return = - strcmp(header->GetTargetPath().data(), target_apk_path.data()) == 0 && header->IsUpToDate(); + if (strcmp(header->GetTargetPath().data(), target_apk_path.data()) != 0) { + *_aidl_return = false; + return ok(); + } + + if (target_apk_path != kFrameworkPath) { + *_aidl_return = (bool) header->IsUpToDate(); + } else { + if (!android_crc_) { + // Loading the framework zip can take several milliseconds. Cache the crc of the framework + // resource APK to reduce repeated work during boot. + const auto target_zip = idmap2::ZipFile::Open(target_apk_path); + if (!target_zip) { + return error(base::StringPrintf("failed to open target %s", target_apk_path.c_str())); + } + + const auto target_crc = GetPackageCrc(*target_zip); + if (!target_crc) { + return error(target_crc.GetErrorMessage()); + } + + android_crc_ = *target_crc; + } + + *_aidl_return = (bool) header->IsUpToDate(android_crc_.value()); + } // TODO(b/119328308): Check that the set of fulfilled policies of the overlay has not changed return ok(); diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h index 0ed55a1bb6a4..55fb5ad07781 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.h +++ b/cmds/idmap2/idmap2d/Idmap2Service.h @@ -46,6 +46,10 @@ class Idmap2Service : public BinderService<Idmap2Service>, public BnIdmap2 { const std::string& overlay_apk_path, int32_t fulfilled_policies, bool enforce_overlayable, int32_t user_id, aidl::nullable<std::string>* _aidl_return) override; + + private: + // Cache the crc of the android framework package since the crc cannot change without a reboot. + std::optional<uint32_t> android_crc_; }; } // namespace android::os diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h index 2e4836e297ec..77a7b30a230e 100644 --- a/cmds/idmap2/include/idmap2/Idmap.h +++ b/cmds/idmap2/include/idmap2/Idmap.h @@ -74,6 +74,7 @@ #include "androidfw/ResourceTypes.h" #include "androidfw/StringPiece.h" #include "idmap2/ResourceMapping.h" +#include "idmap2/ZipFile.h" namespace android::idmap2 { @@ -93,6 +94,9 @@ static constexpr const uint32_t kIdmapCurrentVersion = android::kIdmapCurrentVer // terminating null) static constexpr const size_t kIdmapStringLength = 256; +// Retrieves a crc generated using all of the files within the zip that can affect idmap generation. +Result<uint32_t> GetPackageCrc(const ZipFile& zip_info); + class IdmapHeader { public: static std::unique_ptr<const IdmapHeader> FromBinaryStream(std::istream& stream); @@ -129,6 +133,7 @@ class IdmapHeader { // field *must* be incremented. Because of this, we know that if the idmap // header is up-to-date the entire file is up-to-date. Result<Unit> IsUpToDate() const; + Result<Unit> IsUpToDate(uint32_t target_crc_) const; void accept(Visitor* v) const; diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp index 7f2cd9596c95..706b842b3b47 100644 --- a/cmds/idmap2/libidmap2/Idmap.cpp +++ b/cmds/idmap2/libidmap2/Idmap.cpp @@ -100,7 +100,9 @@ Result<std::string> ReadString(std::istream& stream) { return buf; } -Result<uint32_t> GetCrc(const ZipFile& zip) { +} // namespace + +Result<uint32_t> GetPackageCrc(const ZipFile& zip) { const Result<uint32_t> a = zip.Crc("resources.arsc"); const Result<uint32_t> b = zip.Crc("AndroidManifest.xml"); return a && b @@ -108,8 +110,6 @@ Result<uint32_t> GetCrc(const ZipFile& zip) { : Error("failed to get CRC for \"%s\"", a ? "AndroidManifest.xml" : "resources.arsc"); } -} // namespace - std::unique_ptr<const IdmapHeader> IdmapHeader::FromBinaryStream(std::istream& stream) { std::unique_ptr<IdmapHeader> idmap_header(new IdmapHeader()); @@ -130,27 +130,31 @@ std::unique_ptr<const IdmapHeader> IdmapHeader::FromBinaryStream(std::istream& s } Result<Unit> IdmapHeader::IsUpToDate() const { - if (magic_ != kIdmapMagic) { - return Error("bad magic: actual 0x%08x, expected 0x%08x", magic_, kIdmapMagic); - } - - if (version_ != kIdmapCurrentVersion) { - return Error("bad version: actual 0x%08x, expected 0x%08x", version_, kIdmapCurrentVersion); - } - const std::unique_ptr<const ZipFile> target_zip = ZipFile::Open(target_path_); if (!target_zip) { return Error("failed to open target %s", GetTargetPath().to_string().c_str()); } - Result<uint32_t> target_crc = GetCrc(*target_zip); + Result<uint32_t> target_crc = GetPackageCrc(*target_zip); if (!target_crc) { return Error("failed to get target crc"); } - if (target_crc_ != *target_crc) { + return IsUpToDate(*target_crc); +} + +Result<Unit> IdmapHeader::IsUpToDate(uint32_t target_crc) const { + if (magic_ != kIdmapMagic) { + return Error("bad magic: actual 0x%08x, expected 0x%08x", magic_, kIdmapMagic); + } + + if (version_ != kIdmapCurrentVersion) { + return Error("bad version: actual 0x%08x, expected 0x%08x", version_, kIdmapCurrentVersion); + } + + if (target_crc_ != target_crc) { return Error("bad target crc: idmap version 0x%08x, file system version 0x%08x", target_crc_, - *target_crc); + target_crc); } const std::unique_ptr<const ZipFile> overlay_zip = ZipFile::Open(overlay_path_); @@ -158,7 +162,7 @@ Result<Unit> IdmapHeader::IsUpToDate() const { return Error("failed to open overlay %s", GetOverlayPath().to_string().c_str()); } - Result<uint32_t> overlay_crc = GetCrc(*overlay_zip); + Result<uint32_t> overlay_crc = GetPackageCrc(*overlay_zip); if (!overlay_crc) { return Error("failed to get overlay crc"); } @@ -304,13 +308,13 @@ Result<std::unique_ptr<const Idmap>> Idmap::FromApkAssets(const ApkAssets& targe header->magic_ = kIdmapMagic; header->version_ = kIdmapCurrentVersion; - Result<uint32_t> crc = GetCrc(*target_zip); + Result<uint32_t> crc = GetPackageCrc(*target_zip); if (!crc) { return Error(crc.GetError(), "failed to get zip CRC for target"); } header->target_crc_ = *crc; - crc = GetCrc(*overlay_zip); + crc = GetPackageCrc(*overlay_zip); if (!crc) { return Error(crc.GetError(), "failed to get zip CRC for overlay"); } |