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
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,6 +130,20 @@ std::unique_ptr<const IdmapHeader> IdmapHeader::FromBinaryStream(std::istream& s
|
||||
}
|
||||
|
||||
Result<Unit> IdmapHeader::IsUpToDate() const {
|
||||
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 = GetPackageCrc(*target_zip);
|
||||
if (!target_crc) {
|
||||
return Error("failed to get 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);
|
||||
}
|
||||
@@ -138,19 +152,9 @@ Result<Unit> IdmapHeader::IsUpToDate() const {
|
||||
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);
|
||||
if (!target_crc) {
|
||||
return Error("failed to get target crc");
|
||||
}
|
||||
|
||||
if (target_crc_ != *target_crc) {
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user