diff options
-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 | ||||
-rw-r--r-- | services/core/java/com/android/server/om/IdmapDaemon.java | 2 | ||||
-rw-r--r-- | services/core/java/com/android/server/om/OverlayManagerService.java | 6 |
6 files changed, 66 insertions, 21 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"); } diff --git a/services/core/java/com/android/server/om/IdmapDaemon.java b/services/core/java/com/android/server/om/IdmapDaemon.java index 7df8fc7e34ed..910ed44df0f8 100644 --- a/services/core/java/com/android/server/om/IdmapDaemon.java +++ b/services/core/java/com/android/server/om/IdmapDaemon.java @@ -44,7 +44,7 @@ class IdmapDaemon { // The amount of time in milliseconds to wait when attempting to connect to idmap service. private static final int SERVICE_CONNECT_TIMEOUT_MS = 5000; - private static final int SERVICE_CONNECT_INTERVAL_SLEEP_MS = 200; + private static final int SERVICE_CONNECT_INTERVAL_SLEEP_MS = 5; private static final String IDMAP_DAEMON = "idmap2d"; diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index 84e43fcc9056..6a8e465529d7 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -1120,7 +1120,11 @@ public final class OverlayManagerService extends SystemService { @Override public List<PackageInfo> getOverlayPackages(final int userId) { - return mPackageManagerInternal.getOverlayPackages(userId); + final List<PackageInfo> overlays = mPackageManagerInternal.getOverlayPackages(userId); + for (final PackageInfo info : overlays) { + cachePackageInfo(info.packageName, userId, info); + } + return overlays; } @Nullable |