diff options
author | 2022-10-18 10:59:10 +0100 | |
---|---|---|
committer | 2022-10-20 14:32:59 +0000 | |
commit | ca32797f26d82feb93bb760a886805e9f173c791 (patch) | |
tree | 97aca6f55f10517b451fd5b527211c12c6035bc0 | |
parent | 2617a9d2ec3c5c7506733a703ab36bd08e6a6dc5 (diff) |
Update artd to support profiles for secondary dex files.
Bug: 249984283
Test: atest ArtServiceTests
Test: m test-art-host-gtest-art_artd_tests
Ignore-AOSP-First: ART Services.
Change-Id: I35e19e7fa2147717754feddbc72a46983dc0d9d8
-rw-r--r-- | artd/artd.cc | 12 | ||||
-rw-r--r-- | artd/artd.h | 2 | ||||
-rw-r--r-- | artd/artd_test.cc | 81 | ||||
-rw-r--r-- | artd/binder/com/android/server/art/IArtd.aidl | 2 | ||||
-rw-r--r-- | artd/binder/com/android/server/art/OutputProfile.aidl | 2 | ||||
-rw-r--r-- | artd/binder/com/android/server/art/ProfilePath.aidl | 52 | ||||
-rw-r--r-- | artd/path_utils.cc | 89 | ||||
-rw-r--r-- | artd/path_utils.h | 27 | ||||
-rw-r--r-- | artd/path_utils_test.cc | 158 | ||||
-rw-r--r-- | libartservice/service/java/com/android/server/art/AidlUtils.java | 117 | ||||
-rw-r--r-- | libartservice/service/java/com/android/server/art/PrimaryDexOptimizer.java | 54 | ||||
-rw-r--r-- | libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerTest.java | 42 |
12 files changed, 410 insertions, 228 deletions
diff --git a/artd/artd.cc b/artd/artd.cc index bf2f7b3a9a..ce42a8650b 100644 --- a/artd/artd.cc +++ b/artd/artd.cc @@ -102,7 +102,7 @@ using ::ndk::ScopedAStatus; using ::fmt::literals::operator""_format; // NOLINT using ArtifactsLocation = GetDexoptNeededResult::ArtifactsLocation; -using TmpRefProfilePath = ProfilePath::TmpRefProfilePath; +using TmpProfilePath = ProfilePath::TmpProfilePath; constexpr const char* kServiceName = "artd"; constexpr const char* kArtdCancellationSignalType = "ArtdCancellationSignal"; @@ -448,7 +448,7 @@ ndk::ScopedAStatus Artd::copyAndRewriteProfile(const ProfilePath& in_src, const std::string& in_dexFile, bool* _aidl_return) { std::string src_path = OR_RETURN_FATAL(BuildProfileOrDmPath(in_src)); - std::string dst_path = OR_RETURN_FATAL(BuildRefProfilePath(in_dst->profilePath.refProfilePath)); + std::string dst_path = OR_RETURN_FATAL(BuildFinalProfilePath(in_dst->profilePath)); OR_RETURN_FATAL(ValidateDexPath(in_dexFile)); CmdlineBuilder args; @@ -504,9 +504,9 @@ ndk::ScopedAStatus Artd::copyAndRewriteProfile(const ProfilePath& in_src, return ScopedAStatus::ok(); } -ndk::ScopedAStatus Artd::commitTmpProfile(const TmpRefProfilePath& in_profile) { - std::string tmp_profile_path = OR_RETURN_FATAL(BuildTmpRefProfilePath(in_profile)); - std::string ref_profile_path = OR_RETURN_FATAL(BuildRefProfilePath(in_profile.refProfilePath)); +ndk::ScopedAStatus Artd::commitTmpProfile(const TmpProfilePath& in_profile) { + std::string tmp_profile_path = OR_RETURN_FATAL(BuildTmpProfilePath(in_profile)); + std::string ref_profile_path = OR_RETURN_FATAL(BuildFinalProfilePath(in_profile)); std::error_code ec; std::filesystem::rename(tmp_profile_path, ref_profile_path, ec); @@ -557,7 +557,7 @@ ndk::ScopedAStatus Artd::mergeProfiles(const std::vector<ProfilePath>& in_profil profile_paths.push_back(std::move(profile_path)); } std::string output_profile_path = - OR_RETURN_FATAL(BuildRefProfilePath(in_outputProfile->profilePath.refProfilePath)); + OR_RETURN_FATAL(BuildFinalProfilePath(in_outputProfile->profilePath)); OR_RETURN_FATAL(ValidateDexPath(in_dexFile)); CmdlineBuilder args; diff --git a/artd/artd.h b/artd/artd.h index 9c65ed245c..c775c4a796 100644 --- a/artd/artd.h +++ b/artd/artd.h @@ -95,7 +95,7 @@ class Artd : public aidl::com::android::server::art::BnArtd { bool* _aidl_return) override; ndk::ScopedAStatus commitTmpProfile( - const aidl::com::android::server::art::ProfilePath::TmpRefProfilePath& in_profile) override; + const aidl::com::android::server::art::ProfilePath::TmpProfilePath& in_profile) override; ndk::ScopedAStatus deleteProfile( const aidl::com::android::server::art::ProfilePath& in_profile) override; diff --git a/artd/artd_test.cc b/artd/artd_test.cc index 6b545176fd..76cba8895c 100644 --- a/artd/artd_test.cc +++ b/artd/artd_test.cc @@ -97,9 +97,9 @@ using ::testing::Return; using ::testing::SetArgPointee; using ::testing::WithArg; -using CurProfilePath = ProfilePath::CurProfilePath; -using RefProfilePath = ProfilePath::RefProfilePath; -using TmpRefProfilePath = ProfilePath::TmpRefProfilePath; +using PrimaryCurProfilePath = ProfilePath::PrimaryCurProfilePath; +using PrimaryRefProfilePath = ProfilePath::PrimaryRefProfilePath; +using TmpProfilePath = ProfilePath::TmpProfilePath; using ::fmt::literals::operator""_format; // NOLINT @@ -294,14 +294,13 @@ class ArtdTest : public CommonArtTest { clc_2_ = GetTestDexFileName("Nested"); class_loader_context_ = "PCL[{}:{}]"_format(clc_1_, clc_2_); compiler_filter_ = "speed"; - TmpRefProfilePath tmp_ref_profile_path{ - .refProfilePath = - RefProfilePath{.packageName = "com.android.foo", .profileName = "primary"}, + TmpProfilePath tmp_profile_path{ + .finalPath = + PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "primary"}, .id = "12345"}; - profile_path_ = tmp_ref_profile_path; + profile_path_ = tmp_profile_path; std::filesystem::create_directories( - std::filesystem::path(OR_FATAL(BuildTmpRefProfilePath(tmp_ref_profile_path))) - .parent_path()); + std::filesystem::path(OR_FATAL(BuildFinalProfilePath(tmp_profile_path))).parent_path()); } void TearDown() override { @@ -1019,8 +1018,8 @@ TEST_F(ArtdTest, isProfileUsableFailed) { } TEST_F(ArtdTest, copyAndRewriteProfile) { - const TmpRefProfilePath& src = profile_path_->get<ProfilePath::tmpRefProfilePath>(); - std::string src_file = OR_FATAL(BuildTmpRefProfilePath(src)); + const TmpProfilePath& src = profile_path_->get<ProfilePath::tmpProfilePath>(); + std::string src_file = OR_FATAL(BuildTmpProfilePath(src)); CreateFile(src_file, "abc"); OutputProfile dst{.profilePath = src, .fsPermission = FsPermission{.uid = -1, .gid = -1}}; dst.profilePath.id = ""; @@ -1045,12 +1044,12 @@ TEST_F(ArtdTest, copyAndRewriteProfile) { EXPECT_TRUE(artd_->copyAndRewriteProfile(src, &dst, dex_file_, &result).isOk()); EXPECT_TRUE(result); EXPECT_THAT(dst.profilePath.id, Not(IsEmpty())); - CheckContent(OR_FATAL(BuildTmpRefProfilePath(dst.profilePath)), "def"); + CheckContent(OR_FATAL(BuildTmpProfilePath(dst.profilePath)), "def"); } TEST_F(ArtdTest, copyAndRewriteProfileFalse) { - const TmpRefProfilePath& src = profile_path_->get<ProfilePath::tmpRefProfilePath>(); - std::string src_file = OR_FATAL(BuildTmpRefProfilePath(src)); + const TmpProfilePath& src = profile_path_->get<ProfilePath::tmpProfilePath>(); + std::string src_file = OR_FATAL(BuildTmpProfilePath(src)); CreateFile(src_file, "abc"); OutputProfile dst{.profilePath = src, .fsPermission = FsPermission{.uid = -1, .gid = -1}}; dst.profilePath.id = ""; @@ -1068,7 +1067,7 @@ TEST_F(ArtdTest, copyAndRewriteProfileFalse) { TEST_F(ArtdTest, copyAndRewriteProfileNotFound) { CreateFile(dex_file_); - const TmpRefProfilePath& src = profile_path_->get<ProfilePath::tmpRefProfilePath>(); + const TmpProfilePath& src = profile_path_->get<ProfilePath::tmpProfilePath>(); OutputProfile dst{.profilePath = src, .fsPermission = FsPermission{.uid = -1, .gid = -1}}; dst.profilePath.id = ""; @@ -1078,8 +1077,8 @@ TEST_F(ArtdTest, copyAndRewriteProfileNotFound) { } TEST_F(ArtdTest, copyAndRewriteProfileFailed) { - const TmpRefProfilePath& src = profile_path_->get<ProfilePath::tmpRefProfilePath>(); - std::string src_file = OR_FATAL(BuildTmpRefProfilePath(src)); + const TmpProfilePath& src = profile_path_->get<ProfilePath::tmpProfilePath>(); + std::string src_file = OR_FATAL(BuildTmpProfilePath(src)); CreateFile(src_file, "abc"); OutputProfile dst{.profilePath = src, .fsPermission = FsPermission{.uid = -1, .gid = -1}}; dst.profilePath.id = ""; @@ -1097,19 +1096,18 @@ TEST_F(ArtdTest, copyAndRewriteProfileFailed) { } TEST_F(ArtdTest, commitTmpProfile) { - const TmpRefProfilePath& tmp_profile_path = profile_path_->get<ProfilePath::tmpRefProfilePath>(); - std::string tmp_profile_file = OR_FATAL(BuildTmpRefProfilePath(tmp_profile_path)); + const TmpProfilePath& tmp_profile_path = profile_path_->get<ProfilePath::tmpProfilePath>(); + std::string tmp_profile_file = OR_FATAL(BuildTmpProfilePath(tmp_profile_path)); CreateFile(tmp_profile_file); EXPECT_TRUE(artd_->commitTmpProfile(tmp_profile_path).isOk()); EXPECT_FALSE(std::filesystem::exists(tmp_profile_file)); - EXPECT_TRUE( - std::filesystem::exists(OR_FATAL(BuildProfileOrDmPath(tmp_profile_path.refProfilePath)))); + EXPECT_TRUE(std::filesystem::exists(OR_FATAL(BuildFinalProfilePath(tmp_profile_path)))); } TEST_F(ArtdTest, commitTmpProfileFailed) { - const TmpRefProfilePath& tmp_profile_path = profile_path_->get<ProfilePath::tmpRefProfilePath>(); + const TmpProfilePath& tmp_profile_path = profile_path_->get<ProfilePath::tmpProfilePath>(); ndk::ScopedAStatus status = artd_->commitTmpProfile(tmp_profile_path); EXPECT_FALSE(status.isOk()); @@ -1118,8 +1116,7 @@ TEST_F(ArtdTest, commitTmpProfileFailed) { status.getMessage(), ContainsRegex(R"re(Failed to move .*primary\.prof\.12345\.tmp.* to .*primary\.prof)re")); - EXPECT_FALSE( - std::filesystem::exists(OR_FATAL(BuildProfileOrDmPath(tmp_profile_path.refProfilePath)))); + EXPECT_FALSE(std::filesystem::exists(OR_FATAL(BuildFinalProfilePath(tmp_profile_path)))); } TEST_F(ArtdTest, deleteProfile) { @@ -1231,19 +1228,18 @@ TEST_F(ArtdTest, getArtifactsVisibilityPermissionDenied) { } TEST_F(ArtdTest, mergeProfiles) { - const TmpRefProfilePath& reference_profile_path = - profile_path_->get<ProfilePath::tmpRefProfilePath>(); - std::string reference_profile_file = OR_FATAL(BuildTmpRefProfilePath(reference_profile_path)); + const TmpProfilePath& reference_profile_path = profile_path_->get<ProfilePath::tmpProfilePath>(); + std::string reference_profile_file = OR_FATAL(BuildTmpProfilePath(reference_profile_path)); CreateFile(reference_profile_file, "abc"); // Doesn't exist. - CurProfilePath profile_0_path{ + PrimaryCurProfilePath profile_0_path{ .userId = 0, .packageName = "com.android.foo", .profileName = "primary"}; - std::string profile_0_file = OR_FATAL(BuildCurProfilePath(profile_0_path)); + std::string profile_0_file = OR_FATAL(BuildPrimaryCurProfilePath(profile_0_path)); - CurProfilePath profile_1_path{ + PrimaryCurProfilePath profile_1_path{ .userId = 1, .packageName = "com.android.foo", .profileName = "primary"}; - std::string profile_1_file = OR_FATAL(BuildCurProfilePath(profile_1_path)); + std::string profile_1_file = OR_FATAL(BuildPrimaryCurProfilePath(profile_1_path)); CreateFile(profile_1_file, "def"); OutputProfile output_profile{.profilePath = reference_profile_path, @@ -1277,16 +1273,16 @@ TEST_F(ArtdTest, mergeProfiles) { .isOk()); EXPECT_TRUE(result); EXPECT_THAT(output_profile.profilePath.id, Not(IsEmpty())); - CheckContent(OR_FATAL(BuildTmpRefProfilePath(output_profile.profilePath)), "merged"); + CheckContent(OR_FATAL(BuildTmpProfilePath(output_profile.profilePath)), "merged"); } TEST_F(ArtdTest, mergeProfilesEmptyReferenceProfile) { - CurProfilePath profile_0_path{ + PrimaryCurProfilePath profile_0_path{ .userId = 0, .packageName = "com.android.foo", .profileName = "primary"}; - std::string profile_0_file = OR_FATAL(BuildCurProfilePath(profile_0_path)); + std::string profile_0_file = OR_FATAL(BuildPrimaryCurProfilePath(profile_0_path)); CreateFile(profile_0_file, "def"); - OutputProfile output_profile{.profilePath = profile_path_->get<ProfilePath::tmpRefProfilePath>(), + OutputProfile output_profile{.profilePath = profile_path_->get<ProfilePath::tmpProfilePath>(), .fsPermission = FsPermission{.uid = -1, .gid = -1}}; output_profile.profilePath.id = ""; @@ -1312,24 +1308,23 @@ TEST_F(ArtdTest, mergeProfilesEmptyReferenceProfile) { .isOk()); EXPECT_TRUE(result); EXPECT_THAT(output_profile.profilePath.id, Not(IsEmpty())); - CheckContent(OR_FATAL(BuildTmpRefProfilePath(output_profile.profilePath)), "merged"); + CheckContent(OR_FATAL(BuildTmpProfilePath(output_profile.profilePath)), "merged"); } TEST_F(ArtdTest, mergeProfilesProfilesDontExist) { - const TmpRefProfilePath& reference_profile_path = - profile_path_->get<ProfilePath::tmpRefProfilePath>(); - std::string reference_profile_file = OR_FATAL(BuildTmpRefProfilePath(reference_profile_path)); + const TmpProfilePath& reference_profile_path = profile_path_->get<ProfilePath::tmpProfilePath>(); + std::string reference_profile_file = OR_FATAL(BuildTmpProfilePath(reference_profile_path)); CreateFile(reference_profile_file, "abc"); // Doesn't exist. - CurProfilePath profile_0_path{ + PrimaryCurProfilePath profile_0_path{ .userId = 0, .packageName = "com.android.foo", .profileName = "primary"}; - std::string profile_0_file = OR_FATAL(BuildCurProfilePath(profile_0_path)); + std::string profile_0_file = OR_FATAL(BuildPrimaryCurProfilePath(profile_0_path)); // Doesn't exist. - CurProfilePath profile_1_path{ + PrimaryCurProfilePath profile_1_path{ .userId = 1, .packageName = "com.android.foo", .profileName = "primary"}; - std::string profile_1_file = OR_FATAL(BuildCurProfilePath(profile_1_path)); + std::string profile_1_file = OR_FATAL(BuildPrimaryCurProfilePath(profile_1_path)); OutputProfile output_profile{.profilePath = reference_profile_path, .fsPermission = FsPermission{.uid = -1, .gid = -1}}; diff --git a/artd/binder/com/android/server/art/IArtd.aidl b/artd/binder/com/android/server/art/IArtd.aidl index 7bed2ff78f..782334b8bb 100644 --- a/artd/binder/com/android/server/art/IArtd.aidl +++ b/artd/binder/com/android/server/art/IArtd.aidl @@ -60,7 +60,7 @@ interface IArtd { * * Throws fatal and non-fatal errors. */ - void commitTmpProfile(in com.android.server.art.ProfilePath.TmpRefProfilePath profile); + void commitTmpProfile(in com.android.server.art.ProfilePath.TmpProfilePath profile); /** * Deletes the profile. Does nothing of the profile doesn't exist. diff --git a/artd/binder/com/android/server/art/OutputProfile.aidl b/artd/binder/com/android/server/art/OutputProfile.aidl index cd9627bd5c..50efda2053 100644 --- a/artd/binder/com/android/server/art/OutputProfile.aidl +++ b/artd/binder/com/android/server/art/OutputProfile.aidl @@ -27,7 +27,7 @@ parcelable OutputProfile { * * Only outputing to a temporary file is supported to avoid race condition. */ - com.android.server.art.ProfilePath.TmpRefProfilePath profilePath; + com.android.server.art.ProfilePath.TmpProfilePath profilePath; /** The permission of the file. */ com.android.server.art.FsPermission fsPermission; diff --git a/artd/binder/com/android/server/art/ProfilePath.aidl b/artd/binder/com/android/server/art/ProfilePath.aidl index afd0fd6d4b..fd413a94ec 100644 --- a/artd/binder/com/android/server/art/ProfilePath.aidl +++ b/artd/binder/com/android/server/art/ProfilePath.aidl @@ -22,29 +22,24 @@ package com.android.server.art; * @hide */ union ProfilePath { - RefProfilePath refProfilePath; - TmpRefProfilePath tmpRefProfilePath; + PrimaryRefProfilePath primaryRefProfilePath; PrebuiltProfilePath prebuiltProfilePath; - CurProfilePath curProfilePath; + PrimaryCurProfilePath primaryCurProfilePath; + SecondaryRefProfilePath secondaryRefProfilePath; + SecondaryCurProfilePath secondaryCurProfilePath; + TmpProfilePath tmpProfilePath; + /** Represents a profile in the dex metadata file. */ com.android.server.art.DexMetadataPath dexMetadataPath; /** Represents a reference profile. */ - parcelable RefProfilePath { + parcelable PrimaryRefProfilePath { /** The name of the package. */ @utf8InCpp String packageName; /** The stem of the profile file */ @utf8InCpp String profileName; } - /** Represents a temporary reference profile. */ - parcelable TmpRefProfilePath { - /** The reference profile that this temporary file is for. */ - RefProfilePath refProfilePath; - /** A unique identifier to distinguish this temporary file from others. Filled by artd. */ - @utf8InCpp String id; - } - /** * Represents a profile next to a dex file. This is usually a prebuilt profile in the system * image, but it can also be a profile that package manager can potentially put along with the @@ -57,7 +52,7 @@ union ProfilePath { } /** Represents a current profile. */ - parcelable CurProfilePath { + parcelable PrimaryCurProfilePath { /** The user ID of the user that owns the profile. */ int userId; /** The name of the package. */ @@ -65,4 +60,35 @@ union ProfilePath { /** The stem of the profile file */ @utf8InCpp String profileName; } + + /** Represents a reference profile of a secondary dex file. */ + parcelable SecondaryRefProfilePath { + /** + * The path to the dex file that the profile is next to. + * + * Currently, possible paths are in the format of + * `{/data,/mnt/expand/<volume-uuid>}/{user,user_de}/<user-id>/<package-name>/...`. + */ + @utf8InCpp String dexPath; + } + + /** Represents a current profile of a secondary dex file. */ + parcelable SecondaryCurProfilePath { + /** The path to the dex file that the profile is next to. */ + @utf8InCpp String dexPath; + } + + /** All types of profile paths that artd can write to. */ + union WritableProfilePath { + PrimaryRefProfilePath forPrimary; + SecondaryRefProfilePath forSecondary; + } + + /** Represents a temporary profile. */ + parcelable TmpProfilePath { + /** The path that this temporary file will eventually be committed to. */ + WritableProfilePath finalPath; + /** A unique identifier to distinguish this temporary file from others. Filled by artd. */ + @utf8InCpp String id; + } } diff --git a/artd/path_utils.cc b/artd/path_utils.cc index 8314241861..8dcc1e9607 100644 --- a/artd/path_utils.cc +++ b/artd/path_utils.cc @@ -43,10 +43,13 @@ using ::android::base::Result; using ::fmt::literals::operator""_format; // NOLINT -using CurProfilePath = ProfilePath::CurProfilePath; using PrebuiltProfilePath = ProfilePath::PrebuiltProfilePath; -using RefProfilePath = ProfilePath::RefProfilePath; -using TmpRefProfilePath = ProfilePath::TmpRefProfilePath; +using PrimaryCurProfilePath = ProfilePath::PrimaryCurProfilePath; +using PrimaryRefProfilePath = ProfilePath::PrimaryRefProfilePath; +using SecondaryCurProfilePath = ProfilePath::SecondaryCurProfilePath; +using SecondaryRefProfilePath = ProfilePath::SecondaryRefProfilePath; +using TmpProfilePath = ProfilePath::TmpProfilePath; +using WritableProfilePath = ProfilePath::WritableProfilePath; Result<void> ValidateAbsoluteNormalPath(const std::string& path_str) { if (path_str.empty()) { @@ -145,19 +148,13 @@ Result<std::string> BuildOatPath(const ArtifactsPath& artifacts_path) { } } -Result<std::string> BuildRefProfilePath(const RefProfilePath& ref_profile_path) { - OR_RETURN(ValidatePathElement(ref_profile_path.packageName, "packageName")); - OR_RETURN(ValidatePathElementSubstring(ref_profile_path.profileName, "profileName")); +Result<std::string> BuildPrimaryRefProfilePath( + const PrimaryRefProfilePath& primary_ref_profile_path) { + OR_RETURN(ValidatePathElement(primary_ref_profile_path.packageName, "packageName")); + OR_RETURN(ValidatePathElementSubstring(primary_ref_profile_path.profileName, "profileName")); return "{}/misc/profiles/ref/{}/{}.prof"_format(OR_RETURN(GetAndroidDataOrError()), - ref_profile_path.packageName, - ref_profile_path.profileName); -} - -Result<std::string> BuildTmpRefProfilePath(const TmpRefProfilePath& tmp_ref_profile_path) { - OR_RETURN(ValidatePathElementSubstring(tmp_ref_profile_path.id, "id")); - return NewFile::BuildTempPath( - OR_RETURN(BuildRefProfilePath(tmp_ref_profile_path.refProfilePath)).c_str(), - tmp_ref_profile_path.id.c_str()); + primary_ref_profile_path.packageName, + primary_ref_profile_path.profileName); } Result<std::string> BuildPrebuiltProfilePath(const PrebuiltProfilePath& prebuilt_profile_path) { @@ -165,13 +162,47 @@ Result<std::string> BuildPrebuiltProfilePath(const PrebuiltProfilePath& prebuilt return prebuilt_profile_path.dexPath + ".prof"; } -Result<std::string> BuildCurProfilePath(const CurProfilePath& cur_profile_path) { - OR_RETURN(ValidatePathElement(cur_profile_path.packageName, "packageName")); - OR_RETURN(ValidatePathElementSubstring(cur_profile_path.profileName, "profileName")); +Result<std::string> BuildPrimaryCurProfilePath( + const PrimaryCurProfilePath& primary_cur_profile_path) { + OR_RETURN(ValidatePathElement(primary_cur_profile_path.packageName, "packageName")); + OR_RETURN(ValidatePathElementSubstring(primary_cur_profile_path.profileName, "profileName")); return "{}/misc/profiles/cur/{}/{}/{}.prof"_format(OR_RETURN(GetAndroidDataOrError()), - cur_profile_path.userId, - cur_profile_path.packageName, - cur_profile_path.profileName); + primary_cur_profile_path.userId, + primary_cur_profile_path.packageName, + primary_cur_profile_path.profileName); +} + +Result<std::string> BuildSecondaryRefProfilePath( + const SecondaryRefProfilePath& secondary_ref_profile_path) { + OR_RETURN(ValidateDexPath(secondary_ref_profile_path.dexPath)); + std::filesystem::path dex_path(secondary_ref_profile_path.dexPath); + return "{}/oat/{}.prof"_format(dex_path.parent_path().string(), dex_path.filename().string()); +} + +Result<std::string> BuildSecondaryCurProfilePath( + const SecondaryCurProfilePath& secondary_cur_profile_path) { + OR_RETURN(ValidateDexPath(secondary_cur_profile_path.dexPath)); + std::filesystem::path dex_path(secondary_cur_profile_path.dexPath); + return "{}/oat/{}.cur.prof"_format(dex_path.parent_path().string(), dex_path.filename().string()); +} + +Result<std::string> BuildFinalProfilePath(const TmpProfilePath& tmp_profile_path) { + const WritableProfilePath& final_path = tmp_profile_path.finalPath; + switch (final_path.getTag()) { + case WritableProfilePath::forPrimary: + return BuildPrimaryRefProfilePath(final_path.get<WritableProfilePath::forPrimary>()); + case WritableProfilePath::forSecondary: + return BuildSecondaryRefProfilePath(final_path.get<WritableProfilePath::forSecondary>()); + // No default. All cases should be explicitly handled, or the compilation will fail. + } + // This should never happen. Just in case we get a non-enumerator value. + LOG(FATAL) << "Unexpected writable profile path type {}"_format(final_path.getTag()); +} + +Result<std::string> BuildTmpProfilePath(const TmpProfilePath& tmp_profile_path) { + OR_RETURN(ValidatePathElementSubstring(tmp_profile_path.id, "id")); + return NewFile::BuildTempPath(OR_RETURN(BuildFinalProfilePath(tmp_profile_path)), + tmp_profile_path.id); } Result<std::string> BuildDexMetadataPath(const DexMetadataPath& dex_metadata_path) { @@ -186,14 +217,18 @@ Result<std::string> BuildDexMetadataPath(const VdexPath& vdex_path) { Result<std::string> BuildProfileOrDmPath(const ProfilePath& profile_path) { switch (profile_path.getTag()) { - case ProfilePath::refProfilePath: - return BuildRefProfilePath(profile_path.get<ProfilePath::refProfilePath>()); - case ProfilePath::tmpRefProfilePath: - return BuildTmpRefProfilePath(profile_path.get<ProfilePath::tmpRefProfilePath>()); + case ProfilePath::primaryRefProfilePath: + return BuildPrimaryRefProfilePath(profile_path.get<ProfilePath::primaryRefProfilePath>()); case ProfilePath::prebuiltProfilePath: return BuildPrebuiltProfilePath(profile_path.get<ProfilePath::prebuiltProfilePath>()); - case ProfilePath::curProfilePath: - return BuildCurProfilePath(profile_path.get<ProfilePath::curProfilePath>()); + case ProfilePath::primaryCurProfilePath: + return BuildPrimaryCurProfilePath(profile_path.get<ProfilePath::primaryCurProfilePath>()); + case ProfilePath::secondaryRefProfilePath: + return BuildSecondaryRefProfilePath(profile_path.get<ProfilePath::secondaryRefProfilePath>()); + case ProfilePath::secondaryCurProfilePath: + return BuildSecondaryCurProfilePath(profile_path.get<ProfilePath::secondaryCurProfilePath>()); + case ProfilePath::tmpProfilePath: + return BuildTmpProfilePath(profile_path.get<ProfilePath::tmpProfilePath>()); case ProfilePath::dexMetadataPath: return BuildDexMetadataPath(profile_path.get<ProfilePath::dexMetadataPath>()); // No default. All cases should be explicitly handled, or the compilation will fail. diff --git a/artd/path_utils.h b/artd/path_utils.h index 5b2b1d3c32..bfbbd80664 100644 --- a/artd/path_utils.h +++ b/artd/path_utils.h @@ -42,17 +42,30 @@ inline std::string OatPathToArtPath(const std::string& oat_path) { return ReplaceFileExtension(oat_path, "art"); } -android::base::Result<std::string> BuildRefProfilePath( - const aidl::com::android::server::art::ProfilePath::RefProfilePath& ref_profile_path); - -android::base::Result<std::string> BuildTmpRefProfilePath( - const aidl::com::android::server::art::ProfilePath::TmpRefProfilePath& tmp_ref_profile_path); +android::base::Result<std::string> BuildPrimaryRefProfilePath( + const aidl::com::android::server::art::ProfilePath::PrimaryRefProfilePath& + primary_ref_profile_path); android::base::Result<std::string> BuildPrebuiltProfilePath( const aidl::com::android::server::art::ProfilePath::PrebuiltProfilePath& prebuilt_profile_path); -android::base::Result<std::string> BuildCurProfilePath( - const aidl::com::android::server::art::ProfilePath::CurProfilePath& cur_profile_path); +android::base::Result<std::string> BuildPrimaryCurProfilePath( + const aidl::com::android::server::art::ProfilePath::PrimaryCurProfilePath& + primary_cur_profile_path); + +android::base::Result<std::string> BuildSecondaryRefProfilePath( + const aidl::com::android::server::art::ProfilePath::SecondaryRefProfilePath& + secondary_ref_profile_path); + +android::base::Result<std::string> BuildSecondaryCurProfilePath( + const aidl::com::android::server::art::ProfilePath::SecondaryCurProfilePath& + secondary_cur_profile_path); + +android::base::Result<std::string> BuildFinalProfilePath( + const aidl::com::android::server::art::ProfilePath::TmpProfilePath& tmp_profile_path); + +android::base::Result<std::string> BuildTmpProfilePath( + const aidl::com::android::server::art::ProfilePath::TmpProfilePath& tmp_profile_path); android::base::Result<std::string> BuildDexMetadataPath( const aidl::com::android::server::art::DexMetadataPath& dex_metadata_path); diff --git a/artd/path_utils_test.cc b/artd/path_utils_test.cc index 8188000c4e..508d8c2b73 100644 --- a/artd/path_utils_test.cc +++ b/artd/path_utils_test.cc @@ -33,10 +33,12 @@ using ::android::base::testing::HasError; using ::android::base::testing::HasValue; using ::android::base::testing::WithMessage; -using CurProfilePath = ProfilePath::CurProfilePath; using PrebuiltProfilePath = ProfilePath::PrebuiltProfilePath; -using RefProfilePath = ProfilePath::RefProfilePath; -using TmpRefProfilePath = ProfilePath::TmpRefProfilePath; +using PrimaryCurProfilePath = ProfilePath::PrimaryCurProfilePath; +using PrimaryRefProfilePath = ProfilePath::PrimaryRefProfilePath; +using SecondaryCurProfilePath = ProfilePath::SecondaryCurProfilePath; +using SecondaryRefProfilePath = ProfilePath::SecondaryRefProfilePath; +using TmpProfilePath = ProfilePath::TmpProfilePath; using std::literals::operator""s; // NOLINT @@ -104,80 +106,110 @@ TEST_F(PathUtilsTest, OatPathToArtPath) { EXPECT_EQ(OatPathToArtPath("/a/oat/arm64/b.odex"), "/a/oat/arm64/b.art"); } -TEST_F(PathUtilsTest, BuildRefProfilePath) { - EXPECT_THAT(BuildRefProfilePath( - RefProfilePath{.packageName = "com.android.foo", .profileName = "primary"}), +TEST_F(PathUtilsTest, BuildPrimaryRefProfilePath) { + EXPECT_THAT(BuildPrimaryRefProfilePath(PrimaryRefProfilePath{.packageName = "com.android.foo", + .profileName = "primary"}), HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof")); } -TEST_F(PathUtilsTest, BuildRefProfilePathPackageNameOk) { - EXPECT_THAT(BuildRefProfilePath(RefProfilePath{.packageName = "...", .profileName = "primary"}), +TEST_F(PathUtilsTest, BuildPrimaryRefProfilePathPackageNameOk) { + EXPECT_THAT(BuildPrimaryRefProfilePath( + PrimaryRefProfilePath{.packageName = "...", .profileName = "primary"}), HasValue(android_data_ + "/misc/profiles/ref/.../primary.prof")); - EXPECT_THAT(BuildRefProfilePath( - RefProfilePath{.packageName = "!@#$%^&*()_+-=", .profileName = "primary"}), + EXPECT_THAT(BuildPrimaryRefProfilePath( + PrimaryRefProfilePath{.packageName = "!@#$%^&*()_+-=", .profileName = "primary"}), HasValue(android_data_ + "/misc/profiles/ref/!@#$%^&*()_+-=/primary.prof")); } -TEST_F(PathUtilsTest, BuildRefProfilePathPackageNameWrong) { - EXPECT_THAT(BuildRefProfilePath(RefProfilePath{.packageName = "", .profileName = "primary"}), +TEST_F(PathUtilsTest, BuildPrimaryRefProfilePathPackageNameWrong) { + EXPECT_THAT(BuildPrimaryRefProfilePath( + PrimaryRefProfilePath{.packageName = "", .profileName = "primary"}), HasError(WithMessage("packageName is empty"))); - EXPECT_THAT(BuildRefProfilePath(RefProfilePath{.packageName = ".", .profileName = "primary"}), + EXPECT_THAT(BuildPrimaryRefProfilePath( + PrimaryRefProfilePath{.packageName = ".", .profileName = "primary"}), HasError(WithMessage("Invalid packageName '.'"))); - EXPECT_THAT(BuildRefProfilePath(RefProfilePath{.packageName = "..", .profileName = "primary"}), + EXPECT_THAT(BuildPrimaryRefProfilePath( + PrimaryRefProfilePath{.packageName = "..", .profileName = "primary"}), HasError(WithMessage("Invalid packageName '..'"))); - EXPECT_THAT(BuildRefProfilePath(RefProfilePath{.packageName = "a/b", .profileName = "primary"}), + EXPECT_THAT(BuildPrimaryRefProfilePath( + PrimaryRefProfilePath{.packageName = "a/b", .profileName = "primary"}), HasError(WithMessage("packageName 'a/b' has invalid character '/'"))); - EXPECT_THAT(BuildRefProfilePath(RefProfilePath{.packageName = "a\0b"s, .profileName = "primary"}), + EXPECT_THAT(BuildPrimaryRefProfilePath( + PrimaryRefProfilePath{.packageName = "a\0b"s, .profileName = "primary"}), HasError(WithMessage("packageName 'a\0b' has invalid character '\\0'"s))); } -TEST_F(PathUtilsTest, BuildRefProfilePathProfileNameOk) { - EXPECT_THAT( - BuildRefProfilePath(RefProfilePath{.packageName = "com.android.foo", .profileName = "."}), - HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/..prof")); - EXPECT_THAT( - BuildRefProfilePath(RefProfilePath{.packageName = "com.android.foo", .profileName = ".."}), - HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/...prof")); - EXPECT_THAT(BuildRefProfilePath(RefProfilePath{.packageName = "com.android.foo", - .profileName = "!@#$%^&*()_+-="}), +TEST_F(PathUtilsTest, BuildPrimaryRefProfilePathProfileNameOk) { + EXPECT_THAT(BuildPrimaryRefProfilePath( + PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "."}), + HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/..prof")); + EXPECT_THAT(BuildPrimaryRefProfilePath( + PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = ".."}), + HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/...prof")); + EXPECT_THAT(BuildPrimaryRefProfilePath(PrimaryRefProfilePath{.packageName = "com.android.foo", + .profileName = "!@#$%^&*()_+-="}), HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/!@#$%^&*()_+-=.prof")); } -TEST_F(PathUtilsTest, BuildRefProfilePathProfileNameWrong) { - EXPECT_THAT( - BuildRefProfilePath(RefProfilePath{.packageName = "com.android.foo", .profileName = ""}), - HasError(WithMessage("profileName is empty"))); - EXPECT_THAT( - BuildRefProfilePath(RefProfilePath{.packageName = "com.android.foo", .profileName = "a/b"}), - HasError(WithMessage("profileName 'a/b' has invalid character '/'"))); - EXPECT_THAT( - BuildRefProfilePath(RefProfilePath{.packageName = "com.android.foo", .profileName = "a\0b"s}), - HasError(WithMessage("profileName 'a\0b' has invalid character '\\0'"s))); +TEST_F(PathUtilsTest, BuildPrimaryRefProfilePathProfileNameWrong) { + EXPECT_THAT(BuildPrimaryRefProfilePath( + PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = ""}), + HasError(WithMessage("profileName is empty"))); + EXPECT_THAT(BuildPrimaryRefProfilePath( + PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "a/b"}), + HasError(WithMessage("profileName 'a/b' has invalid character '/'"))); + EXPECT_THAT(BuildPrimaryRefProfilePath( + PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "a\0b"s}), + HasError(WithMessage("profileName 'a\0b' has invalid character '\\0'"s))); +} + +TEST_F(PathUtilsTest, BuildFinalProfilePathForPrimary) { + EXPECT_THAT(BuildFinalProfilePath(TmpProfilePath{ + .finalPath = PrimaryRefProfilePath{.packageName = "com.android.foo", + .profileName = "primary"}, + .id = "12345"}), + HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof")); } -TEST_F(PathUtilsTest, BuildTmpRefProfilePath) { +TEST_F(PathUtilsTest, BuildFinalProfilePathForSecondary) { + EXPECT_THAT(BuildFinalProfilePath(TmpProfilePath{ + .finalPath = SecondaryRefProfilePath{.dexPath = android_data_ + + "/user/0/com.android.foo/a.apk"}, + .id = "12345"}), + HasValue(android_data_ + "/user/0/com.android.foo/oat/a.apk.prof")); +} + +TEST_F(PathUtilsTest, BuildTmpProfilePathForPrimary) { EXPECT_THAT( - BuildTmpRefProfilePath(TmpRefProfilePath{ - .refProfilePath = - RefProfilePath{.packageName = "com.android.foo", .profileName = "primary"}, + BuildTmpProfilePath(TmpProfilePath{ + .finalPath = + PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "primary"}, .id = "12345"}), HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof.12345.tmp")); } -TEST_F(PathUtilsTest, BuildTmpRefProfilePathIdWrong) { - EXPECT_THAT(BuildTmpRefProfilePath(TmpRefProfilePath{ - .refProfilePath = - RefProfilePath{.packageName = "com.android.foo", .profileName = "primary"}, +TEST_F(PathUtilsTest, BuildTmpProfilePathForSecondary) { + EXPECT_THAT(BuildTmpProfilePath(TmpProfilePath{ + .finalPath = SecondaryRefProfilePath{.dexPath = android_data_ + + "/user/0/com.android.foo/a.apk"}, + .id = "12345"}), + HasValue(android_data_ + "/user/0/com.android.foo/oat/a.apk.prof.12345.tmp")); +} + +TEST_F(PathUtilsTest, BuildTmpProfilePathIdWrong) { + EXPECT_THAT(BuildTmpProfilePath(TmpProfilePath{ + .finalPath = PrimaryRefProfilePath{.packageName = "com.android.foo", + .profileName = "primary"}, .id = ""}), HasError(WithMessage("id is empty"))); - EXPECT_THAT(BuildTmpRefProfilePath(TmpRefProfilePath{ - .refProfilePath = - RefProfilePath{.packageName = "com.android.foo", .profileName = "primary"}, + EXPECT_THAT(BuildTmpProfilePath(TmpProfilePath{ + .finalPath = PrimaryRefProfilePath{.packageName = "com.android.foo", + .profileName = "primary"}, .id = "123/45"}), HasError(WithMessage("id '123/45' has invalid character '/'"))); - EXPECT_THAT(BuildTmpRefProfilePath(TmpRefProfilePath{ - .refProfilePath = - RefProfilePath{.packageName = "com.android.foo", .profileName = "primary"}, + EXPECT_THAT(BuildTmpProfilePath(TmpProfilePath{ + .finalPath = PrimaryRefProfilePath{.packageName = "com.android.foo", + .profileName = "primary"}, .id = "123\0a"s}), HasError(WithMessage("id '123\0a' has invalid character '\\0'"s))); } @@ -187,12 +219,24 @@ TEST_F(PathUtilsTest, BuildPrebuiltProfilePath) { HasValue("/a/b.apk.prof")); } -TEST_F(PathUtilsTest, BuildCurProfilePath) { - EXPECT_THAT(BuildCurProfilePath(CurProfilePath{ +TEST_F(PathUtilsTest, BuildPrimaryCurProfilePath) { + EXPECT_THAT(BuildPrimaryCurProfilePath(PrimaryCurProfilePath{ .userId = 1, .packageName = "com.android.foo", .profileName = "primary"}), HasValue(android_data_ + "/misc/profiles/cur/1/com.android.foo/primary.prof")); } +TEST_F(PathUtilsTest, BuildSecondaryRefProfilePath) { + EXPECT_THAT(BuildSecondaryRefProfilePath(SecondaryRefProfilePath{ + .dexPath = android_data_ + "/user/0/com.android.foo/a.apk"}), + HasValue(android_data_ + "/user/0/com.android.foo/oat/a.apk.prof")); +} + +TEST_F(PathUtilsTest, BuildSecondaryCurProfilePath) { + EXPECT_THAT(BuildSecondaryCurProfilePath(SecondaryCurProfilePath{ + .dexPath = android_data_ + "/user/0/com.android.foo/a.apk"}), + HasValue(android_data_ + "/user/0/com.android.foo/oat/a.apk.cur.prof")); +} + TEST_F(PathUtilsTest, BuildDexMetadataPath) { EXPECT_THAT(BuildDexMetadataPath(DexMetadataPath{.dexPath = "/a/b.apk"}), HasValue("/a/b.dm")); } @@ -203,18 +247,18 @@ TEST_F(PathUtilsTest, BuildDexMetadataPathForVdex) { } TEST_F(PathUtilsTest, BuildProfilePath) { - EXPECT_THAT(BuildProfileOrDmPath( - RefProfilePath{.packageName = "com.android.foo", .profileName = "primary"}), + EXPECT_THAT(BuildProfileOrDmPath(PrimaryRefProfilePath{.packageName = "com.android.foo", + .profileName = "primary"}), HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof")); EXPECT_THAT( - BuildProfileOrDmPath(TmpRefProfilePath{ - .refProfilePath = - RefProfilePath{.packageName = "com.android.foo", .profileName = "primary"}, + BuildProfileOrDmPath(TmpProfilePath{ + .finalPath = + PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "primary"}, .id = "12345"}), HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof.12345.tmp")); EXPECT_THAT(BuildProfileOrDmPath(PrebuiltProfilePath{.dexPath = "/a/b.apk"}), HasValue("/a/b.apk.prof")); - EXPECT_THAT(BuildProfileOrDmPath(CurProfilePath{ + EXPECT_THAT(BuildProfileOrDmPath(PrimaryCurProfilePath{ .userId = 1, .packageName = "com.android.foo", .profileName = "primary"}), HasValue(android_data_ + "/misc/profiles/cur/1/com.android.foo/primary.prof")); EXPECT_THAT(BuildProfileOrDmPath(DexMetadataPath{.dexPath = "/a/b.apk"}), HasValue("/a/b.dm")); diff --git a/libartservice/service/java/com/android/server/art/AidlUtils.java b/libartservice/service/java/com/android/server/art/AidlUtils.java index 26d5df8da4..f7df305dfc 100644 --- a/libartservice/service/java/com/android/server/art/AidlUtils.java +++ b/libartservice/service/java/com/android/server/art/AidlUtils.java @@ -18,10 +18,13 @@ package com.android.server.art; import static com.android.server.art.OutputArtifacts.PermissionSettings; import static com.android.server.art.OutputArtifacts.PermissionSettings.SeContext; -import static com.android.server.art.ProfilePath.CurProfilePath; import static com.android.server.art.ProfilePath.PrebuiltProfilePath; -import static com.android.server.art.ProfilePath.RefProfilePath; -import static com.android.server.art.ProfilePath.TmpRefProfilePath; +import static com.android.server.art.ProfilePath.PrimaryCurProfilePath; +import static com.android.server.art.ProfilePath.PrimaryRefProfilePath; +import static com.android.server.art.ProfilePath.SecondaryCurProfilePath; +import static com.android.server.art.ProfilePath.SecondaryRefProfilePath; +import static com.android.server.art.ProfilePath.TmpProfilePath; +import static com.android.server.art.ProfilePath.WritableProfilePath; import android.annotation.NonNull; import android.annotation.Nullable; @@ -83,18 +86,26 @@ public final class AidlUtils { } @NonNull - public static RefProfilePath buildRefProfilePath( + public static PrimaryRefProfilePath buildPrimaryRefProfilePath( @NonNull String packageName, @NonNull String profileName) { - var refProfilePath = new RefProfilePath(); - refProfilePath.packageName = packageName; - refProfilePath.profileName = profileName; - return refProfilePath; + var primaryRefProfilePath = new PrimaryRefProfilePath(); + primaryRefProfilePath.packageName = packageName; + primaryRefProfilePath.profileName = profileName; + return primaryRefProfilePath; } @NonNull - public static ProfilePath buildProfilePathForRef( + public static SecondaryRefProfilePath buildSecondaryRefProfilePath(@NonNull String dexPath) { + var secondaryRefProfilePath = new SecondaryRefProfilePath(); + secondaryRefProfilePath.dexPath = dexPath; + return secondaryRefProfilePath; + } + + @NonNull + public static ProfilePath buildProfilePathForPrimaryRef( @NonNull String packageName, @NonNull String profileName) { - return ProfilePath.refProfilePath(buildRefProfilePath(packageName, profileName)); + return ProfilePath.primaryRefProfilePath( + buildPrimaryRefProfilePath(packageName, profileName)); } @NonNull @@ -110,23 +121,89 @@ public final class AidlUtils { } @NonNull - public static ProfilePath buildProfilePathForCur( + public static ProfilePath buildProfilePathForPrimaryCur( int userId, @NonNull String packageName, @NonNull String profileName) { - var curProfilePath = new CurProfilePath(); - curProfilePath.userId = userId; - curProfilePath.packageName = packageName; - curProfilePath.profileName = profileName; - return ProfilePath.curProfilePath(curProfilePath); + var primaryCurProfilePath = new PrimaryCurProfilePath(); + primaryCurProfilePath.userId = userId; + primaryCurProfilePath.packageName = packageName; + primaryCurProfilePath.profileName = profileName; + return ProfilePath.primaryCurProfilePath(primaryCurProfilePath); } @NonNull - public static OutputProfile buildOutputProfile(@NonNull String packageName, - @NonNull String profileName, int uid, int gid, boolean isPublic) { + public static ProfilePath buildProfilePathForSecondaryRef(@NonNull String dexPath) { + return ProfilePath.secondaryRefProfilePath(buildSecondaryRefProfilePath(dexPath)); + } + + @NonNull + public static ProfilePath buildProfilePathForSecondaryCur(@NonNull String dexPath) { + var secondaryCurProfilePath = new SecondaryCurProfilePath(); + secondaryCurProfilePath.dexPath = dexPath; + return ProfilePath.secondaryCurProfilePath(secondaryCurProfilePath); + } + + @NonNull + private static OutputProfile buildOutputProfile( + @NonNull WritableProfilePath finalPath, int uid, int gid, boolean isPublic) { var outputProfile = new OutputProfile(); - outputProfile.profilePath = new TmpRefProfilePath(); - outputProfile.profilePath.refProfilePath = buildRefProfilePath(packageName, profileName); + outputProfile.profilePath = new TmpProfilePath(); + outputProfile.profilePath.finalPath = finalPath; outputProfile.profilePath.id = ""; // Will be filled by artd. outputProfile.fsPermission = buildFsPermission(uid, gid, isPublic); return outputProfile; } + + @NonNull + public static OutputProfile buildOutputProfileForPrimary(@NonNull String packageName, + @NonNull String profileName, int uid, int gid, boolean isPublic) { + return buildOutputProfile(WritableProfilePath.forPrimary( + buildPrimaryRefProfilePath(packageName, profileName)), + uid, gid, isPublic); + } + + @NonNull + public static OutputProfile buildOutputProfileForSecondary( + @NonNull String dexPath, int uid, int gid, boolean isPublic) { + return buildOutputProfile( + WritableProfilePath.forSecondary(buildSecondaryRefProfilePath(dexPath)), uid, gid, + isPublic); + } + + @NonNull + public static String toString(@NonNull PrimaryRefProfilePath profile) { + return String.format( + "[packageName = %s, profileName = %s]", profile.packageName, profile.profileName); + } + + @NonNull + public static String toString(@NonNull SecondaryRefProfilePath profile) { + return String.format("[dexPath = %s]", profile.dexPath); + } + + @NonNull + public static String toString(@NonNull WritableProfilePath profile) { + switch (profile.getTag()) { + case WritableProfilePath.forPrimary: + return toString(profile.getForPrimary()); + case WritableProfilePath.forSecondary: + return toString(profile.getForSecondary()); + default: + throw new IllegalStateException( + "Unknown WritableProfilePath tag " + profile.getTag()); + } + } + + @NonNull + public static String toString(@NonNull ProfilePath profile) { + switch (profile.getTag()) { + case ProfilePath.primaryRefProfilePath: + return toString(profile.getPrimaryRefProfilePath()); + case ProfilePath.secondaryRefProfilePath: + return toString(profile.getSecondaryRefProfilePath()); + default: + throw new UnsupportedOperationException( + "Only reference profile paths are supported to be converted to string, got " + + profile.getTag()); + } + } } diff --git a/libartservice/service/java/com/android/server/art/PrimaryDexOptimizer.java b/libartservice/service/java/com/android/server/art/PrimaryDexOptimizer.java index a80bb0562d..ef7d659240 100644 --- a/libartservice/service/java/com/android/server/art/PrimaryDexOptimizer.java +++ b/libartservice/service/java/com/android/server/art/PrimaryDexOptimizer.java @@ -20,8 +20,8 @@ import static com.android.server.art.GetDexoptNeededResult.ArtifactsLocation; import static com.android.server.art.OutputArtifacts.PermissionSettings; import static com.android.server.art.OutputArtifacts.PermissionSettings.SeContext; import static com.android.server.art.PrimaryDexUtils.DetailedPrimaryDexInfo; -import static com.android.server.art.ProfilePath.RefProfilePath; -import static com.android.server.art.ProfilePath.TmpRefProfilePath; +import static com.android.server.art.ProfilePath.TmpProfilePath; +import static com.android.server.art.ProfilePath.WritableProfilePath; import static com.android.server.art.Utils.Abi; import static com.android.server.art.model.ArtFlags.OptimizeFlags; import static com.android.server.art.model.OptimizeResult.DexContainerFileOptimizeResult; @@ -134,8 +134,7 @@ public class PrimaryDexOptimizer { ProfilePath mergedProfile = mergeProfiles(pkgState, dexInfo, appId, sharedGid, profile); if (mergedProfile != null) { - if (profile != null - && profile.getTag() == ProfilePath.tmpRefProfilePath) { + if (profile != null && profile.getTag() == ProfilePath.tmpProfilePath) { mInjector.getArtd().deleteProfile(profile); } profile = mergedProfile; @@ -236,9 +235,9 @@ public class PrimaryDexOptimizer { } if (profile != null && succeeded) { - if (profile.getTag() == ProfilePath.tmpRefProfilePath) { + if (profile.getTag() == ProfilePath.tmpProfilePath) { // Commit the profile only if dexopt succeeds. - if (commitProfileChanges(profile.getTmpRefProfilePath())) { + if (commitProfileChanges(profile.getTmpProfilePath())) { profile = null; } } @@ -256,7 +255,7 @@ public class PrimaryDexOptimizer { } } } finally { - if (profile != null && profile.getTag() == ProfilePath.tmpRefProfilePath) { + if (profile != null && profile.getTag() == ProfilePath.tmpProfilePath) { mInjector.getArtd().deleteProfile(profile); } } @@ -315,7 +314,7 @@ public class PrimaryDexOptimizer { private ProfilePath initReferenceProfile(@NonNull PackageState pkgState, @NonNull DetailedPrimaryDexInfo dexInfo, int uid, int gid) throws RemoteException { String profileName = getProfileName(dexInfo.splitName()); - OutputProfile output = AidlUtils.buildOutputProfile( + OutputProfile output = AidlUtils.buildOutputProfileForPrimary( pkgState.getPackageName(), profileName, uid, gid, true /* isPublic */); ProfilePath prebuiltProfile = AidlUtils.buildProfilePathForPrebuilt(dexInfo.dexPath()); @@ -327,26 +326,24 @@ public class PrimaryDexOptimizer { // case is necessary. if (mInjector.getArtd().copyAndRewriteProfile( prebuiltProfile, output, dexInfo.dexPath())) { - return ProfilePath.tmpRefProfilePath(output.profilePath); + return ProfilePath.tmpProfilePath(output.profilePath); } } catch (ServiceSpecificException e) { Log.e(TAG, - String.format( - "Failed to use prebuilt profile [packageName = %s, profileName = %s]", - pkgState.getPackageName(), profileName), + "Failed to use prebuilt profile " + + AidlUtils.toString(output.profilePath.finalPath), e); } ProfilePath dmProfile = AidlUtils.buildProfilePathForDm(dexInfo.dexPath()); try { if (mInjector.getArtd().copyAndRewriteProfile(dmProfile, output, dexInfo.dexPath())) { - return ProfilePath.tmpRefProfilePath(output.profilePath); + return ProfilePath.tmpProfilePath(output.profilePath); } } catch (ServiceSpecificException e) { Log.e(TAG, - String.format("Failed to use profile in dex metadata file " - + "[packageName = %s, profileName = %s]", - pkgState.getPackageName(), profileName), + "Failed to use profile in dex metadata file " + + AidlUtils.toString(output.profilePath.finalPath), e); } @@ -366,7 +363,7 @@ public class PrimaryDexOptimizer { @NonNull DetailedPrimaryDexInfo dexInfo, int uid, int gid) throws RemoteException { String profileName = getProfileName(dexInfo.splitName()); ProfilePath refProfile = - AidlUtils.buildProfilePathForRef(pkgState.getPackageName(), profileName); + AidlUtils.buildProfilePathForPrimaryRef(pkgState.getPackageName(), profileName); try { if (mInjector.getArtd().isProfileUsable(refProfile, dexInfo.dexPath())) { boolean isOtherReadable = mInjector.getArtd().getProfileVisibility(refProfile) @@ -375,9 +372,8 @@ public class PrimaryDexOptimizer { } } catch (ServiceSpecificException e) { Log.e(TAG, - String.format("Failed to use the existing reference profile " - + "[packageName = %s, profileName = %s]", - pkgState.getPackageName(), profileName), + "Failed to use the existing reference profile " + + AidlUtils.toString(refProfile), e); } @@ -529,17 +525,12 @@ public class PrimaryDexOptimizer { } } - private boolean commitProfileChanges(@NonNull TmpRefProfilePath profile) - throws RemoteException { + private boolean commitProfileChanges(@NonNull TmpProfilePath profile) throws RemoteException { try { mInjector.getArtd().commitTmpProfile(profile); return true; } catch (ServiceSpecificException e) { - RefProfilePath refProfilePath = profile.refProfilePath; - Log.e(TAG, - String.format( - "Failed to commit profile changes [packageName = %s, profileName = %s]", - refProfilePath.packageName, refProfilePath.profileName), + Log.e(TAG, "Failed to commit profile changes " + AidlUtils.toString(profile.finalPath), e); return false; } @@ -550,18 +541,17 @@ public class PrimaryDexOptimizer { @NonNull DetailedPrimaryDexInfo dexInfo, int uid, int gid, @Nullable ProfilePath referenceProfile) throws RemoteException { String profileName = getProfileName(dexInfo.splitName()); - OutputProfile output = AidlUtils.buildOutputProfile( + OutputProfile output = AidlUtils.buildOutputProfileForPrimary( pkgState.getPackageName(), profileName, uid, gid, false /* isPublic */); try { if (mInjector.getArtd().mergeProfiles(getCurProfiles(pkgState, dexInfo), referenceProfile, output, dexInfo.dexPath())) { - return ProfilePath.tmpRefProfilePath(output.profilePath); + return ProfilePath.tmpProfilePath(output.profilePath); } } catch (ServiceSpecificException e) { Log.e(TAG, - String.format("Failed to merge profiles [packageName = %s, profileName = %s]", - pkgState.getPackageName(), getProfileName(dexInfo.splitName())), + "Failed to merge profiles " + AidlUtils.toString(output.profilePath.finalPath), e); } @@ -584,7 +574,7 @@ public class PrimaryDexOptimizer { int userId = handle.getIdentifier(); PackageUserState userState = pkgState.getStateForUser(handle); if (userState.isInstalled()) { - profiles.add(AidlUtils.buildProfilePathForCur( + profiles.add(AidlUtils.buildProfilePathForPrimaryCur( userId, pkgState.getPackageName(), getProfileName(dexInfo.splitName()))); } } diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerTest.java index 2eae691ae3..504be9055c 100644 --- a/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerTest.java +++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerTest.java @@ -68,17 +68,18 @@ public class PrimaryDexOptimizerTest extends PrimaryDexOptimizerTestBase { new OptimizeParams.Builder("install").setCompilerFilter("speed-profile").build(); private final String mDexPath = "/data/app/foo/base.apk"; - private final ProfilePath mRefProfile = AidlUtils.buildProfilePathForRef(PKG_NAME, "primary"); + private final ProfilePath mRefProfile = + AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME, "primary"); private final ProfilePath mPrebuiltProfile = AidlUtils.buildProfilePathForPrebuilt(mDexPath); private final ProfilePath mDmProfile = AidlUtils.buildProfilePathForDm(mDexPath); - private final OutputProfile mPublicOutputProfile = AidlUtils.buildOutputProfile( + private final OutputProfile mPublicOutputProfile = AidlUtils.buildOutputProfileForPrimary( PKG_NAME, "primary", UID, SHARED_GID, true /* isOtherReadable */); - private final OutputProfile mPrivateOutputProfile = AidlUtils.buildOutputProfile( + private final OutputProfile mPrivateOutputProfile = AidlUtils.buildOutputProfileForPrimary( PKG_NAME, "primary", UID, SHARED_GID, false /* isOtherReadable */); private final String mSplit0DexPath = "/data/app/foo/split_0.apk"; private final ProfilePath mSplit0RefProfile = - AidlUtils.buildProfilePathForRef(PKG_NAME, "split_0.split"); + AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME, "split_0.split"); private final int mDefaultDexoptTrigger = DexoptTrigger.COMPILER_FILTER_IS_BETTER | DexoptTrigger.PRIMARY_BOOT_IMAGE_BECOMES_USABLE; @@ -232,9 +233,9 @@ public class PrimaryDexOptimizerTest extends PrimaryDexOptimizerTestBase { deepEq(mPrebuiltProfile), deepEq(mPublicOutputProfile), eq(mDexPath)); checkDexoptWithPublicProfile(inOrder.verify(mArtd), mDexPath, "arm64", - ProfilePath.tmpRefProfilePath(mPublicOutputProfile.profilePath)); + ProfilePath.tmpProfilePath(mPublicOutputProfile.profilePath)); checkDexoptWithPublicProfile(inOrder.verify(mArtd), mDexPath, "arm", - ProfilePath.tmpRefProfilePath(mPublicOutputProfile.profilePath)); + ProfilePath.tmpProfilePath(mPublicOutputProfile.profilePath)); inOrder.verify(mArtd).commitTmpProfile(deepEq(mPublicOutputProfile.profilePath)); @@ -258,28 +259,29 @@ public class PrimaryDexOptimizerTest extends PrimaryDexOptimizerTestBase { InOrder inOrder = inOrder(mArtd); inOrder.verify(mArtd).mergeProfiles( - deepEq(List.of( - AidlUtils.buildProfilePathForCur(0 /* userId */, PKG_NAME, "primary"), - AidlUtils.buildProfilePathForCur(2 /* userId */, PKG_NAME, "primary"))), + deepEq(List.of(AidlUtils.buildProfilePathForPrimaryCur( + 0 /* userId */, PKG_NAME, "primary"), + AidlUtils.buildProfilePathForPrimaryCur( + 2 /* userId */, PKG_NAME, "primary"))), deepEq(mRefProfile), deepEq(mPrivateOutputProfile), eq(mDexPath)); // It should use `mBetterOrSameDexoptTrigger` and the merged profile for both ISAs. inOrder.verify(mArtd).getDexoptNeeded(eq(mDexPath), eq("arm64"), any(), eq("speed-profile"), eq(mBetterOrSameDexoptTrigger)); checkDexoptWithPrivateProfile(inOrder.verify(mArtd), mDexPath, "arm64", - ProfilePath.tmpRefProfilePath(mPrivateOutputProfile.profilePath)); + ProfilePath.tmpProfilePath(mPrivateOutputProfile.profilePath)); inOrder.verify(mArtd).getDexoptNeeded(eq(mDexPath), eq("arm"), any(), eq("speed-profile"), eq(mBetterOrSameDexoptTrigger)); checkDexoptWithPrivateProfile(inOrder.verify(mArtd), mDexPath, "arm", - ProfilePath.tmpRefProfilePath(mPrivateOutputProfile.profilePath)); + ProfilePath.tmpProfilePath(mPrivateOutputProfile.profilePath)); inOrder.verify(mArtd).commitTmpProfile(deepEq(mPrivateOutputProfile.profilePath)); - inOrder.verify(mArtd).deleteProfile( - deepEq(AidlUtils.buildProfilePathForCur(0 /* userId */, PKG_NAME, "primary"))); - inOrder.verify(mArtd).deleteProfile( - deepEq(AidlUtils.buildProfilePathForCur(2 /* userId */, PKG_NAME, "primary"))); + inOrder.verify(mArtd).deleteProfile(deepEq( + AidlUtils.buildProfilePathForPrimaryCur(0 /* userId */, PKG_NAME, "primary"))); + inOrder.verify(mArtd).deleteProfile(deepEq( + AidlUtils.buildProfilePathForPrimaryCur(2 /* userId */, PKG_NAME, "primary"))); } @Test @@ -320,9 +322,9 @@ public class PrimaryDexOptimizerTest extends PrimaryDexOptimizerTestBase { deepEq(mDmProfile), deepEq(mPublicOutputProfile), eq(mDexPath)); checkDexoptWithPublicProfile(verify(mArtd), mDexPath, "arm64", - ProfilePath.tmpRefProfilePath(mPublicOutputProfile.profilePath)); + ProfilePath.tmpProfilePath(mPublicOutputProfile.profilePath)); checkDexoptWithPublicProfile(verify(mArtd), mDexPath, "arm", - ProfilePath.tmpRefProfilePath(mPublicOutputProfile.profilePath)); + ProfilePath.tmpProfilePath(mPublicOutputProfile.profilePath)); verifyProfileNotUsed(mRefProfile); verifyProfileNotUsed(mPrebuiltProfile); @@ -341,7 +343,7 @@ public class PrimaryDexOptimizerTest extends PrimaryDexOptimizerTestBase { mPrimaryDexOptimizer.dexopt(mPkgState, mPkg, mOptimizeParams, mCancellationSignal); verify(mArtd).deleteProfile( - deepEq(ProfilePath.tmpRefProfilePath(mPublicOutputProfile.profilePath))); + deepEq(ProfilePath.tmpProfilePath(mPublicOutputProfile.profilePath))); verify(mArtd, never()).commitTmpProfile(deepEq(mPublicOutputProfile.profilePath)); } @@ -372,12 +374,12 @@ public class PrimaryDexOptimizerTest extends PrimaryDexOptimizerTestBase { verify(mArtd).getDexoptNeeded( eq(mDexPath), eq("arm64"), any(), eq("speed-profile"), eq(mForceDexoptTrigger)); checkDexoptWithPublicProfile(verify(mArtd), mDexPath, "arm64", - ProfilePath.tmpRefProfilePath(mPublicOutputProfile.profilePath)); + ProfilePath.tmpProfilePath(mPublicOutputProfile.profilePath)); verify(mArtd).getDexoptNeeded( eq(mDexPath), eq("arm"), any(), eq("speed-profile"), eq(mForceDexoptTrigger)); checkDexoptWithPublicProfile(verify(mArtd), mDexPath, "arm", - ProfilePath.tmpRefProfilePath(mPublicOutputProfile.profilePath)); + ProfilePath.tmpProfilePath(mPublicOutputProfile.profilePath)); checkDexoptWithNoProfile(verify(mArtd), mSplit0DexPath, "arm64", "speed"); checkDexoptWithNoProfile(verify(mArtd), mSplit0DexPath, "arm", "speed"); |