Always pass --dm-fd to dex2oat and change reason to "install-dm".
Bug: 255944781
Test: atest ArtServiceTests
Test: m test-art-host-gtest-art_artd_tests
Ignore-AOSP-First: ART Services.
Change-Id: Ibb8ffd6da39186cb571dbd9e59847bc2161ebd15
diff --git a/artd/artd.cc b/artd/artd.cc
index 32c89c3..2e86b38 100644
--- a/artd/artd.cc
+++ b/artd/artd.cc
@@ -74,6 +74,7 @@
namespace {
using ::aidl::com::android::server::art::ArtifactsPath;
+using ::aidl::com::android::server::art::DexMetadataPath;
using ::aidl::com::android::server::art::DexoptOptions;
using ::aidl::com::android::server::art::DexoptResult;
using ::aidl::com::android::server::art::DexoptTrigger;
@@ -550,6 +551,13 @@
return ScopedAStatus::ok();
}
+ndk::ScopedAStatus Artd::getDmFileVisibility(const DexMetadataPath& in_dmFile,
+ FileVisibility* _aidl_return) {
+ std::string dm_path = OR_RETURN_FATAL(BuildDexMetadataPath(in_dmFile));
+ *_aidl_return = OR_RETURN_NON_FATAL(GetFileVisibility(dm_path));
+ return ScopedAStatus::ok();
+}
+
ndk::ScopedAStatus Artd::mergeProfiles(const std::vector<ProfilePath>& in_profiles,
const std::optional<ProfilePath>& in_referenceProfile,
OutputProfile* in_outputProfile,
@@ -691,6 +699,7 @@
const std::string& in_compilerFilter,
const std::optional<ProfilePath>& in_profile,
const std::optional<VdexPath>& in_inputVdex,
+ const std::optional<DexMetadataPath>& in_dmFile,
PriorityClass in_priorityClass,
const DexoptOptions& in_dexoptOptions,
const std::shared_ptr<IArtdCancellationSignal>& in_cancellationSignal,
@@ -783,18 +792,20 @@
std::unique_ptr<File> input_vdex_file = nullptr;
if (in_inputVdex.has_value()) {
- if (in_inputVdex->getTag() == VdexPath::dexMetadataPath) {
- std::string input_vdex_path = OR_RETURN_FATAL(BuildDexMetadataPath(in_inputVdex.value()));
- input_vdex_file = OR_RETURN_NON_FATAL(OpenFileForReading(input_vdex_path));
- args.Add("--dm-fd=%d", input_vdex_file->Fd());
- } else {
- std::string input_vdex_path = OR_RETURN_FATAL(BuildVdexPath(in_inputVdex.value()));
- input_vdex_file = OR_RETURN_NON_FATAL(OpenFileForReading(input_vdex_path));
- args.Add("--input-vdex-fd=%d", input_vdex_file->Fd());
- }
+ std::string input_vdex_path = OR_RETURN_FATAL(BuildVdexPath(in_inputVdex.value()));
+ input_vdex_file = OR_RETURN_NON_FATAL(OpenFileForReading(input_vdex_path));
+ args.Add("--input-vdex-fd=%d", input_vdex_file->Fd());
fd_logger.Add(*input_vdex_file);
}
+ std::unique_ptr<File> dm_file = nullptr;
+ if (in_dmFile.has_value()) {
+ std::string dm_path = OR_RETURN_FATAL(BuildDexMetadataPath(in_dmFile.value()));
+ dm_file = OR_RETURN_NON_FATAL(OpenFileForReading(dm_path));
+ args.Add("--dm-fd=%d", dm_file->Fd());
+ fd_logger.Add(*dm_file);
+ }
+
std::unique_ptr<File> profile_file = nullptr;
if (profile_path.has_value()) {
profile_file = OR_RETURN_NON_FATAL(OpenFileForReading(profile_path.value()));
diff --git a/artd/artd.h b/artd/artd.h
index 1230ee8..b729c78 100644
--- a/artd/artd.h
+++ b/artd/artd.h
@@ -120,6 +120,10 @@
const std::string& in_dexFile,
aidl::com::android::server::art::FileVisibility* _aidl_return) override;
+ ndk::ScopedAStatus getDmFileVisibility(
+ const aidl::com::android::server::art::DexMetadataPath& in_dmFile,
+ aidl::com::android::server::art::FileVisibility* _aidl_return) override;
+
ndk::ScopedAStatus getDexoptNeeded(
const std::string& in_dexFile,
const std::string& in_instructionSet,
@@ -136,6 +140,7 @@
const std::string& in_compilerFilter,
const std::optional<aidl::com::android::server::art::ProfilePath>& in_profile,
const std::optional<aidl::com::android::server::art::VdexPath>& in_inputVdex,
+ const std::optional<aidl::com::android::server::art::DexMetadataPath>& in_dmFile,
aidl::com::android::server::art::PriorityClass in_priorityClass,
const aidl::com::android::server::art::DexoptOptions& in_dexoptOptions,
const std::shared_ptr<aidl::com::android::server::art::IArtdCancellationSignal>&
diff --git a/artd/artd_test.cc b/artd/artd_test.cc
index 68d23db..a2ba7f5 100644
--- a/artd/artd_test.cc
+++ b/artd/artd_test.cc
@@ -299,6 +299,8 @@
PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "primary"},
.id = "12345"};
profile_path_ = tmp_profile_path;
+ vdex_path_ = artifacts_path_;
+ dm_path_ = DexMetadataPath{.dexPath = dex_file_};
std::filesystem::create_directories(
std::filesystem::path(OR_FATAL(BuildFinalProfilePath(tmp_profile_path))).parent_path());
}
@@ -311,7 +313,7 @@
void RunDexopt(binder_exception_t expected_status = EX_NONE,
Matcher<DexoptResult> aidl_return_matcher = Field(&DexoptResult::cancelled, false),
std::shared_ptr<IArtdCancellationSignal> cancellation_signal = nullptr) {
- InitDexoptInputFiles();
+ InitFilesBeforeDexopt();
if (cancellation_signal == nullptr) {
ASSERT_TRUE(artd_->createCancellationSignal(&cancellation_signal).isOk());
}
@@ -323,6 +325,7 @@
compiler_filter_,
profile_path_,
vdex_path_,
+ dm_path_,
priority_class_,
dexopt_options_,
cancellation_signal,
@@ -360,23 +363,32 @@
std::optional<std::string> class_loader_context_;
std::string compiler_filter_;
std::optional<VdexPath> vdex_path_;
+ std::optional<DexMetadataPath> dm_path_;
PriorityClass priority_class_ = PriorityClass::BACKGROUND;
DexoptOptions dexopt_options_;
std::optional<ProfilePath> profile_path_;
private:
- void InitDexoptInputFiles() {
+ void InitFilesBeforeDexopt() {
+ // Required files.
CreateFile(dex_file_);
+
+ // Optional files.
if (vdex_path_.has_value()) {
- if (vdex_path_->getTag() == VdexPath::dexMetadataPath) {
- CreateFile(OR_FATAL(BuildDexMetadataPath(vdex_path_.value())));
- } else {
- CreateFile(OR_FATAL(BuildVdexPath(vdex_path_.value())));
- }
+ CreateFile(OR_FATAL(BuildVdexPath(vdex_path_.value())), "old_vdex");
+ }
+ if (dm_path_.has_value()) {
+ CreateFile(OR_FATAL(BuildDexMetadataPath(dm_path_.value())));
}
if (profile_path_.has_value()) {
CreateFile(OR_FATAL(BuildProfileOrDmPath(profile_path_.value())));
}
+
+ // Files to be replaced.
+ std::string oat_path = OR_FATAL(BuildOatPath(artifacts_path_));
+ CreateFile(oat_path, "old_oat");
+ CreateFile(OatPathToVdexPath(oat_path), "old_vdex");
+ CreateFile(OatPathToArtPath(oat_path), "old_art");
}
};
@@ -485,16 +497,18 @@
WhenSplitBy(
"--",
AllOf(Contains(art_root_ + "/bin/art_exec"), Contains("--drop-capabilities")),
- AllOf(Contains(art_root_ + "/bin/dex2oat32"),
- Contains(Flag("--zip-fd=", FdOf(dex_file_))),
- Contains(Flag("--zip-location=", dex_file_)),
- Contains(Flag("--oat-location=", scratch_path_ + "/a/oat/arm64/b.odex")),
- Contains(Flag("--instruction-set=", "arm64")),
- Contains(Flag("--compiler-filter=", "speed")),
- Contains(
- Flag("--profile-file-fd=",
- FdOf(android_data_ +
- "/misc/profiles/ref/com.android.foo/primary.prof.12345.tmp"))))),
+ AllOf(
+ Contains(art_root_ + "/bin/dex2oat32"),
+ Contains(Flag("--zip-fd=", FdOf(dex_file_))),
+ Contains(Flag("--zip-location=", dex_file_)),
+ Contains(Flag("--oat-location=", scratch_path_ + "/a/oat/arm64/b.odex")),
+ Contains(Flag("--instruction-set=", "arm64")),
+ Contains(Flag("--compiler-filter=", "speed")),
+ Contains(Flag("--profile-file-fd=",
+ FdOf(android_data_ +
+ "/misc/profiles/ref/com.android.foo/primary.prof.12345.tmp"))),
+ Contains(Flag("--input-vdex-fd=", FdOf(scratch_path_ + "/a/oat/arm64/b.vdex"))),
+ Contains(Flag("--dm-fd=", FdOf(scratch_path_ + "/a/b.dm"))))),
_,
_))
.WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--oat-fd=", "oat")),
@@ -542,47 +556,23 @@
RunDexopt();
}
-TEST_F(ArtdTest, dexoptNoInputVdex) {
+TEST_F(ArtdTest, dexoptNoOptionalInputFiles) {
+ profile_path_ = std::nullopt;
+ vdex_path_ = std::nullopt;
+ dm_path_ = std::nullopt;
+
EXPECT_CALL(*mock_exec_utils_,
DoExecAndReturnCode(WhenSplitBy("--",
_,
- AllOf(Not(Contains(Flag("--dm-fd=", _))),
- Not(Contains(Flag("--input-vdex-fd=", _))))),
+ AllOf(Not(Contains(Flag("--profile-file-fd=", _))),
+ Not(Contains(Flag("--input-vdex-fd=", _))),
+ Not(Contains(Flag("--dm-fd=", _))))),
_,
_))
.WillOnce(Return(0));
RunDexopt();
}
-TEST_F(ArtdTest, dexoptInputVdex) {
- vdex_path_ = artifacts_path_;
- EXPECT_CALL(*mock_exec_utils_,
- DoExecAndReturnCode(
- WhenSplitBy("--",
- _,
- AllOf(Not(Contains(Flag("--dm-fd=", _))),
- Contains(Flag("--input-vdex-fd=",
- FdOf(scratch_path_ + "/a/oat/arm64/b.vdex"))))),
- _,
- _))
- .WillOnce(Return(0));
- RunDexopt();
-}
-
-TEST_F(ArtdTest, dexoptInputVdexDm) {
- vdex_path_ = DexMetadataPath{.dexPath = dex_file_};
- EXPECT_CALL(*mock_exec_utils_,
- DoExecAndReturnCode(
- WhenSplitBy("--",
- _,
- AllOf(Contains(Flag("--dm-fd=", FdOf(scratch_path_ + "/a/b.dm"))),
- Not(Contains(Flag("--input-vdex-fd=", _))))),
- _,
- _))
- .WillOnce(Return(0));
- RunDexopt();
-}
-
TEST_F(ArtdTest, dexoptPriorityClassBoot) {
priority_class_ = PriorityClass::BOOT;
EXPECT_CALL(*mock_exec_utils_,
@@ -873,15 +863,15 @@
TEST_F(ArtdTest, dexoptFailed) {
dexopt_options_.generateAppImage = true;
EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
- .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--oat-fd=", "oat")),
- WithArg<0>(WriteToFdFlag("--output-vdex-fd=", "vdex")),
- WithArg<0>(WriteToFdFlag("--app-image-fd=", "art")),
+ .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--oat-fd=", "new_oat")),
+ WithArg<0>(WriteToFdFlag("--output-vdex-fd=", "new_vdex")),
+ WithArg<0>(WriteToFdFlag("--app-image-fd=", "new_art")),
Return(1)));
RunDexopt(EX_SERVICE_SPECIFIC);
- EXPECT_FALSE(std::filesystem::exists(scratch_path_ + "/a/oat/arm64/b.odex"));
- EXPECT_FALSE(std::filesystem::exists(scratch_path_ + "/a/oat/arm64/b.vdex"));
- EXPECT_FALSE(std::filesystem::exists(scratch_path_ + "/a/oat/arm64/b.art"));
+ CheckContent(scratch_path_ + "/a/oat/arm64/b.odex", "old_oat");
+ CheckContent(scratch_path_ + "/a/oat/arm64/b.vdex", "old_vdex");
+ CheckContent(scratch_path_ + "/a/oat/arm64/b.art", "old_art");
}
TEST_F(ArtdTest, dexoptCancelledBeforeDex2oat) {
@@ -902,8 +892,9 @@
RunDexopt(EX_NONE, Field(&DexoptResult::cancelled, true), cancellation_signal);
- EXPECT_FALSE(std::filesystem::exists(scratch_path_ + "/a/oat/arm64/b.odex"));
- EXPECT_FALSE(std::filesystem::exists(scratch_path_ + "/a/oat/arm64/b.vdex"));
+ CheckContent(scratch_path_ + "/a/oat/arm64/b.odex", "old_oat");
+ CheckContent(scratch_path_ + "/a/oat/arm64/b.vdex", "old_vdex");
+ CheckContent(scratch_path_ + "/a/oat/arm64/b.art", "old_art");
}
TEST_F(ArtdTest, dexoptCancelledDuringDex2oat) {
@@ -948,8 +939,9 @@
t.join();
// Step 6.
- EXPECT_FALSE(std::filesystem::exists(scratch_path_ + "/a/oat/arm64/b.odex"));
- EXPECT_FALSE(std::filesystem::exists(scratch_path_ + "/a/oat/arm64/b.vdex"));
+ CheckContent(scratch_path_ + "/a/oat/arm64/b.odex", "old_oat");
+ CheckContent(scratch_path_ + "/a/oat/arm64/b.vdex", "old_vdex");
+ CheckContent(scratch_path_ + "/a/oat/arm64/b.art", "old_art");
}
TEST_F(ArtdTest, dexoptCancelledAfterDex2oat) {
@@ -959,11 +951,13 @@
constexpr pid_t kPid = 123;
EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
- .WillOnce([&](auto, const ExecCallbacks& callbacks, auto) {
- callbacks.on_start(kPid);
- callbacks.on_end(kPid);
- return 0;
- });
+ .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--oat-fd=", "new_oat")),
+ WithArg<0>(WriteToFdFlag("--output-vdex-fd=", "new_vdex")),
+ [&](auto, const ExecCallbacks& callbacks, auto) {
+ callbacks.on_start(kPid);
+ callbacks.on_end(kPid);
+ return 0;
+ }));
EXPECT_CALL(mock_kill_, Call).Times(0);
RunDexopt(EX_NONE, Field(&DexoptResult::cancelled, false), cancellation_signal);
@@ -971,8 +965,9 @@
// This signal should be ignored.
cancellation_signal->cancel();
- EXPECT_TRUE(std::filesystem::exists(scratch_path_ + "/a/oat/arm64/b.odex"));
- EXPECT_TRUE(std::filesystem::exists(scratch_path_ + "/a/oat/arm64/b.vdex"));
+ CheckContent(scratch_path_ + "/a/oat/arm64/b.odex", "new_oat");
+ CheckContent(scratch_path_ + "/a/oat/arm64/b.vdex", "new_vdex");
+ EXPECT_FALSE(std::filesystem::exists(scratch_path_ + "/a/oat/arm64/b.art"));
}
TEST_F(ArtdTest, isProfileUsable) {
@@ -1158,128 +1153,138 @@
EXPECT_TRUE(artd_->deleteProfile(profile_path_.value()).isOk());
}
-TEST_F(ArtdTest, getProfileVisibilityOtherReadable) {
- std::string profile_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
- CreateFile(profile_file);
- std::filesystem::permissions(
- profile_file, std::filesystem::perms::others_read, std::filesystem::perm_options::add);
+class ArtdGetVisibilityTest : public ArtdTest {
+ protected:
+ template <typename PathType>
+ using Method = ndk::ScopedAStatus (Artd::*)(const PathType&, FileVisibility*);
- FileVisibility result;
- ASSERT_TRUE(artd_->getProfileVisibility(profile_path_.value(), &result).isOk());
- EXPECT_EQ(result, FileVisibility::OTHER_READABLE);
+ template <typename PathType>
+ void TestGetVisibilityOtherReadable(Method<PathType> method,
+ const PathType& input,
+ const std::string& path) {
+ CreateFile(path);
+ std::filesystem::permissions(
+ path, std::filesystem::perms::others_read, std::filesystem::perm_options::add);
+
+ FileVisibility result;
+ ASSERT_TRUE(((*artd_).*method)(input, &result).isOk());
+ EXPECT_EQ(result, FileVisibility::OTHER_READABLE);
+ }
+
+ template <typename PathType>
+ void TestGetVisibilityNotOtherReadable(Method<PathType> method,
+ const PathType& input,
+ const std::string& path) {
+ CreateFile(path);
+ std::filesystem::permissions(
+ path, std::filesystem::perms::others_read, std::filesystem::perm_options::remove);
+
+ FileVisibility result;
+ ASSERT_TRUE(((*artd_).*method)(input, &result).isOk());
+ EXPECT_EQ(result, FileVisibility::NOT_OTHER_READABLE);
+ }
+
+ template <typename PathType>
+ void TestGetVisibilityNotFound(Method<PathType> method, const PathType& input) {
+ FileVisibility result;
+ ASSERT_TRUE(((*artd_).*method)(input, &result).isOk());
+ EXPECT_EQ(result, FileVisibility::NOT_FOUND);
+ }
+
+ template <typename PathType>
+ void TestGetVisibilityPermissionDenied(Method<PathType> method,
+ const PathType& input,
+ const std::string& path) {
+ CreateFile(path);
+
+ auto scoped_inaccessible = ScopedInaccessible(std::filesystem::path(path).parent_path());
+ auto scoped_unroot = ScopedUnroot();
+
+ FileVisibility result;
+ ndk::ScopedAStatus status = ((*artd_).*method)(input, &result);
+ EXPECT_FALSE(status.isOk());
+ EXPECT_EQ(status.getExceptionCode(), EX_SERVICE_SPECIFIC);
+ EXPECT_THAT(status.getMessage(), HasSubstr("Failed to get status of"));
+ }
+};
+
+TEST_F(ArtdGetVisibilityTest, getProfileVisibilityOtherReadable) {
+ TestGetVisibilityOtherReadable(&Artd::getProfileVisibility,
+ profile_path_.value(),
+ OR_FATAL(BuildProfileOrDmPath(profile_path_.value())));
}
-TEST_F(ArtdTest, getProfileVisibilityNotOtherReadable) {
- std::string profile_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
- CreateFile(profile_file);
- std::filesystem::permissions(
- profile_file, std::filesystem::perms::others_read, std::filesystem::perm_options::remove);
-
- FileVisibility result;
- ASSERT_TRUE(artd_->getProfileVisibility(profile_path_.value(), &result).isOk());
- EXPECT_EQ(result, FileVisibility::NOT_OTHER_READABLE);
+TEST_F(ArtdGetVisibilityTest, getProfileVisibilityNotOtherReadable) {
+ TestGetVisibilityNotOtherReadable(&Artd::getProfileVisibility,
+ profile_path_.value(),
+ OR_FATAL(BuildProfileOrDmPath(profile_path_.value())));
}
-TEST_F(ArtdTest, getProfileVisibilityNotFound) {
- FileVisibility result;
- ASSERT_TRUE(artd_->getProfileVisibility(profile_path_.value(), &result).isOk());
- EXPECT_EQ(result, FileVisibility::NOT_FOUND);
+TEST_F(ArtdGetVisibilityTest, getProfileVisibilityNotFound) {
+ TestGetVisibilityNotFound(&Artd::getProfileVisibility, profile_path_.value());
}
-TEST_F(ArtdTest, getProfileVisibilityPermissionDenied) {
- std::string profile_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
- CreateFile(profile_file);
-
- auto scoped_inaccessible = ScopedInaccessible(std::filesystem::path(profile_file).parent_path());
- auto scoped_unroot = ScopedUnroot();
-
- FileVisibility result;
- ndk::ScopedAStatus status = artd_->getProfileVisibility(profile_path_.value(), &result);
- EXPECT_FALSE(status.isOk());
- EXPECT_EQ(status.getExceptionCode(), EX_SERVICE_SPECIFIC);
- EXPECT_THAT(status.getMessage(),
- ContainsRegex(R"re(Failed to get status of .*primary\.prof\.12345\.tmp)re"));
+TEST_F(ArtdGetVisibilityTest, getProfileVisibilityPermissionDenied) {
+ TestGetVisibilityPermissionDenied(&Artd::getProfileVisibility,
+ profile_path_.value(),
+ OR_FATAL(BuildProfileOrDmPath(profile_path_.value())));
}
-TEST_F(ArtdTest, getArtifactsVisibilityOtherReadable) {
- std::string oat_file = OR_FATAL(BuildOatPath(artifacts_path_));
- CreateFile(oat_file);
- std::filesystem::permissions(
- oat_file, std::filesystem::perms::others_read, std::filesystem::perm_options::add);
-
- FileVisibility result;
- ASSERT_TRUE(artd_->getArtifactsVisibility(artifacts_path_, &result).isOk());
- EXPECT_EQ(result, FileVisibility::OTHER_READABLE);
+TEST_F(ArtdGetVisibilityTest, getArtifactsVisibilityOtherReadable) {
+ TestGetVisibilityOtherReadable(
+ &Artd::getArtifactsVisibility, artifacts_path_, OR_FATAL(BuildOatPath(artifacts_path_)));
}
-TEST_F(ArtdTest, getArtifactsVisibilityNotOtherReadable) {
- std::string oat_file = OR_FATAL(BuildOatPath(artifacts_path_));
- CreateFile(oat_file);
- std::filesystem::permissions(
- oat_file, std::filesystem::perms::others_read, std::filesystem::perm_options::remove);
-
- FileVisibility result;
- ASSERT_TRUE(artd_->getArtifactsVisibility(artifacts_path_, &result).isOk());
- EXPECT_EQ(result, FileVisibility::NOT_OTHER_READABLE);
+TEST_F(ArtdGetVisibilityTest, getArtifactsVisibilityNotOtherReadable) {
+ TestGetVisibilityNotOtherReadable(
+ &Artd::getArtifactsVisibility, artifacts_path_, OR_FATAL(BuildOatPath(artifacts_path_)));
}
-TEST_F(ArtdTest, getArtifactsVisibilityNotFound) {
- FileVisibility result;
- ASSERT_TRUE(artd_->getArtifactsVisibility(artifacts_path_, &result).isOk());
- EXPECT_EQ(result, FileVisibility::NOT_FOUND);
+TEST_F(ArtdGetVisibilityTest, getArtifactsVisibilityNotFound) {
+ TestGetVisibilityNotFound(&Artd::getArtifactsVisibility, artifacts_path_);
}
-TEST_F(ArtdTest, getArtifactsVisibilityPermissionDenied) {
- std::string oat_file = OR_FATAL(BuildOatPath(artifacts_path_));
- CreateFile(oat_file);
-
- auto scoped_inaccessible = ScopedInaccessible(std::filesystem::path(oat_file).parent_path());
- auto scoped_unroot = ScopedUnroot();
-
- FileVisibility result;
- ndk::ScopedAStatus status = artd_->getArtifactsVisibility(artifacts_path_, &result);
- EXPECT_FALSE(status.isOk());
- EXPECT_EQ(status.getExceptionCode(), EX_SERVICE_SPECIFIC);
- EXPECT_THAT(status.getMessage(), ContainsRegex(R"re(Failed to get status of .*b\.odex)re"));
+TEST_F(ArtdGetVisibilityTest, getArtifactsVisibilityPermissionDenied) {
+ TestGetVisibilityPermissionDenied(
+ &Artd::getArtifactsVisibility, artifacts_path_, OR_FATAL(BuildOatPath(artifacts_path_)));
}
-TEST_F(ArtdTest, getDexFileVisibilityOtherReadable) {
- CreateFile(dex_file_);
- std::filesystem::permissions(
- dex_file_, std::filesystem::perms::others_read, std::filesystem::perm_options::add);
-
- FileVisibility result;
- ASSERT_TRUE(artd_->getDexFileVisibility(dex_file_, &result).isOk());
- EXPECT_EQ(result, FileVisibility::OTHER_READABLE);
+TEST_F(ArtdGetVisibilityTest, getDexFileVisibilityOtherReadable) {
+ TestGetVisibilityOtherReadable(&Artd::getDexFileVisibility, dex_file_, dex_file_);
}
-TEST_F(ArtdTest, getDexFileVisibilityNotOtherReadable) {
- CreateFile(dex_file_);
- std::filesystem::permissions(
- dex_file_, std::filesystem::perms::others_read, std::filesystem::perm_options::remove);
-
- FileVisibility result;
- ASSERT_TRUE(artd_->getDexFileVisibility(dex_file_, &result).isOk());
- EXPECT_EQ(result, FileVisibility::NOT_OTHER_READABLE);
+TEST_F(ArtdGetVisibilityTest, getDexFileVisibilityNotOtherReadable) {
+ TestGetVisibilityNotOtherReadable(&Artd::getDexFileVisibility, dex_file_, dex_file_);
}
-TEST_F(ArtdTest, getDexFileVisibilityNotFound) {
- FileVisibility result;
- ASSERT_TRUE(artd_->getDexFileVisibility(dex_file_, &result).isOk());
- EXPECT_EQ(result, FileVisibility::NOT_FOUND);
+TEST_F(ArtdGetVisibilityTest, getDexFileVisibilityNotFound) {
+ TestGetVisibilityNotFound(&Artd::getDexFileVisibility, dex_file_);
}
-TEST_F(ArtdTest, getDexFileVisibilityPermissionDenied) {
- CreateFile(dex_file_);
+TEST_F(ArtdGetVisibilityTest, getDexFileVisibilityPermissionDenied) {
+ TestGetVisibilityPermissionDenied(&Artd::getDexFileVisibility, dex_file_, dex_file_);
+}
- auto scoped_inaccessible = ScopedInaccessible(std::filesystem::path(dex_file_).parent_path());
- auto scoped_unroot = ScopedUnroot();
+TEST_F(ArtdGetVisibilityTest, getDmFileVisibilityOtherReadable) {
+ TestGetVisibilityOtherReadable(&Artd::getDmFileVisibility,
+ dm_path_.value(),
+ OR_FATAL(BuildDexMetadataPath(dm_path_.value())));
+}
- FileVisibility result;
- ndk::ScopedAStatus status = artd_->getDexFileVisibility(dex_file_, &result);
- EXPECT_FALSE(status.isOk());
- EXPECT_EQ(status.getExceptionCode(), EX_SERVICE_SPECIFIC);
- EXPECT_THAT(status.getMessage(), ContainsRegex(R"re(Failed to get status of .*/a/b\.apk)re"));
+TEST_F(ArtdGetVisibilityTest, getDmFileVisibilityNotOtherReadable) {
+ TestGetVisibilityNotOtherReadable(&Artd::getDmFileVisibility,
+ dm_path_.value(),
+ OR_FATAL(BuildDexMetadataPath(dm_path_.value())));
+}
+
+TEST_F(ArtdGetVisibilityTest, getDmFileVisibilityNotFound) {
+ TestGetVisibilityNotFound(&Artd::getDmFileVisibility, dm_path_.value());
+}
+
+TEST_F(ArtdGetVisibilityTest, getDmFileVisibilityPermissionDenied) {
+ TestGetVisibilityPermissionDenied(&Artd::getDmFileVisibility,
+ dm_path_.value(),
+ OR_FATAL(BuildDexMetadataPath(dm_path_.value())));
}
TEST_F(ArtdTest, mergeProfiles) {
diff --git a/artd/binder/com/android/server/art/IArtd.aidl b/artd/binder/com/android/server/art/IArtd.aidl
index d575adf..19c1d66 100644
--- a/artd/binder/com/android/server/art/IArtd.aidl
+++ b/artd/binder/com/android/server/art/IArtd.aidl
@@ -110,6 +110,14 @@
com.android.server.art.FileVisibility getDexFileVisibility(@utf8InCpp String dexFile);
/**
+ * Returns the visibility of the DM file.
+ *
+ * Throws fatal and non-fatal errors.
+ */
+ com.android.server.art.FileVisibility getDmFileVisibility(
+ in com.android.server.art.DexMetadataPath dmFile);
+
+ /**
* Returns true if dexopt is needed. `dexoptTrigger` is a bit field that consists of values
* defined in `com.android.server.art.DexoptTrigger`.
*
@@ -131,6 +139,7 @@
@nullable @utf8InCpp String classLoaderContext, @utf8InCpp String compilerFilter,
in @nullable com.android.server.art.ProfilePath profile,
in @nullable com.android.server.art.VdexPath inputVdex,
+ in @nullable com.android.server.art.DexMetadataPath dmFile,
com.android.server.art.PriorityClass priorityClass,
in com.android.server.art.DexoptOptions dexoptOptions,
in com.android.server.art.IArtdCancellationSignal cancellationSignal);
diff --git a/artd/binder/com/android/server/art/VdexPath.aidl b/artd/binder/com/android/server/art/VdexPath.aidl
index ec23a0e..6112e7a 100644
--- a/artd/binder/com/android/server/art/VdexPath.aidl
+++ b/artd/binder/com/android/server/art/VdexPath.aidl
@@ -24,6 +24,4 @@
union VdexPath {
/** Represents a VDEX file as part of the artifacts. */
com.android.server.art.ArtifactsPath artifactsPath;
- /** Represents a VDEX file in a dex metadata file. */
- com.android.server.art.DexMetadataPath dexMetadataPath;
}
diff --git a/artd/path_utils.cc b/artd/path_utils.cc
index 8dcc1e9..295b023 100644
--- a/artd/path_utils.cc
+++ b/artd/path_utils.cc
@@ -210,11 +210,6 @@
return ReplaceFileExtension(dex_metadata_path.dexPath, "dm");
}
-Result<std::string> BuildDexMetadataPath(const VdexPath& vdex_path) {
- DCHECK(vdex_path.getTag() == VdexPath::dexMetadataPath);
- return BuildDexMetadataPath(vdex_path.get<VdexPath::dexMetadataPath>());
-}
-
Result<std::string> BuildProfileOrDmPath(const ProfilePath& profile_path) {
switch (profile_path.getTag()) {
case ProfilePath::primaryRefProfilePath:
diff --git a/artd/path_utils.h b/artd/path_utils.h
index bfbbd80..0cc017e 100644
--- a/artd/path_utils.h
+++ b/artd/path_utils.h
@@ -70,9 +70,6 @@
android::base::Result<std::string> BuildDexMetadataPath(
const aidl::com::android::server::art::DexMetadataPath& dex_metadata_path);
-android::base::Result<std::string> BuildDexMetadataPath(
- const aidl::com::android::server::art::VdexPath& vdex_path);
-
android::base::Result<std::string> BuildProfileOrDmPath(
const aidl::com::android::server::art::ProfilePath& profile_path);
diff --git a/artd/path_utils_test.cc b/artd/path_utils_test.cc
index 508d8c2..b0e1a25 100644
--- a/artd/path_utils_test.cc
+++ b/artd/path_utils_test.cc
@@ -241,11 +241,6 @@
EXPECT_THAT(BuildDexMetadataPath(DexMetadataPath{.dexPath = "/a/b.apk"}), HasValue("/a/b.dm"));
}
-TEST_F(PathUtilsTest, BuildDexMetadataPathForVdex) {
- EXPECT_THAT(BuildDexMetadataPath(VdexPath(DexMetadataPath{.dexPath = "/a/b.apk"})),
- HasValue("/a/b.dm"));
-}
-
TEST_F(PathUtilsTest, BuildProfilePath) {
EXPECT_THAT(BuildProfileOrDmPath(PrimaryRefProfilePath{.packageName = "com.android.foo",
.profileName = "primary"}),
diff --git a/libartservice/service/java/com/android/server/art/DexOptimizer.java b/libartservice/service/java/com/android/server/art/DexOptimizer.java
index 8cfe8ad..356d74b 100644
--- a/libartservice/service/java/com/android/server/art/DexOptimizer.java
+++ b/libartservice/service/java/com/android/server/art/DexOptimizer.java
@@ -148,13 +148,13 @@
long wallTimeMs = 0;
long cpuTimeMs = 0;
try {
- DexoptTarget target = DexoptTarget.builder()
+ var target = DexoptTarget.<DexInfoType>builder()
.setDexInfo(dexInfo)
.setIsa(abi.isa())
.setIsInDalvikCache(isInDalvikCache())
.setCompilerFilter(compilerFilter)
.build();
- GetDexoptNeededOptions options =
+ var options =
GetDexoptNeededOptions.builder()
.setProfileMerged(profileMerged)
.setFlags(mParams.getFlags())
@@ -346,7 +346,7 @@
}
@NonNull
- GetDexoptNeededResult getDexoptNeeded(@NonNull DexoptTarget target,
+ GetDexoptNeededResult getDexoptNeeded(@NonNull DexoptTarget<DexInfoType> target,
@NonNull GetDexoptNeededOptions options) throws RemoteException {
int dexoptTrigger = getDexoptTrigger(target, options);
@@ -362,8 +362,8 @@
return result;
}
- int getDexoptTrigger(@NonNull DexoptTarget target, @NonNull GetDexoptNeededOptions options)
- throws RemoteException {
+ int getDexoptTrigger(@NonNull DexoptTarget<DexInfoType> target,
+ @NonNull GetDexoptNeededOptions options) throws RemoteException {
if ((options.flags() & ArtFlags.FLAG_FORCE) != 0) {
return DexoptTrigger.COMPILER_FILTER_IS_BETTER | DexoptTrigger.COMPILER_FILTER_IS_SAME
| DexoptTrigger.COMPILER_FILTER_IS_WORSE
@@ -396,8 +396,8 @@
return dexoptTrigger;
}
- private DexoptResult dexoptFile(@NonNull DexoptTarget target, @Nullable ProfilePath profile,
- @NonNull GetDexoptNeededResult getDexoptNeededResult,
+ private DexoptResult dexoptFile(@NonNull DexoptTarget<DexInfoType> target,
+ @Nullable ProfilePath profile, @NonNull GetDexoptNeededResult getDexoptNeededResult,
@NonNull PermissionSettings permissionSettings, @PriorityClass int priorityClass,
@NonNull DexoptOptions dexoptOptions, IArtdCancellationSignal artdCancellationSignal)
throws RemoteException {
@@ -407,9 +407,25 @@
VdexPath inputVdex =
getInputVdex(getDexoptNeededResult, target.dexInfo().dexPath(), target.isa());
+ DexMetadataPath dmFile = getDmFile(target.dexInfo());
+ if (dmFile != null
+ && ReasonMapping.REASONS_FOR_INSTALL.contains(dexoptOptions.compilationReason)) {
+ // If the DM file is passed to dex2oat, then add the "-dm" suffix to the reason (e.g.,
+ // "install-dm").
+ // Note that this only applies to reasons for app install because the goal is to give
+ // Play a signal that a DM file is downloaded at install time. We actually pass the DM
+ // file regardless of the compilation reason, but we don't append a suffix when the
+ // compilation reason is not a reason for app install.
+ // Also note that the "-dm" suffix does NOT imply anything in the DM file being used by
+ // dex2oat. dex2oat may ignore some contents of the DM file when appropriate. The
+ // compilation reason can still be "install-dm" even if dex2oat left all contents of the
+ // DM file unused or an empty DM file is passed to dex2oat.
+ dexoptOptions.compilationReason = dexoptOptions.compilationReason + "-dm";
+ }
+
return mInjector.getArtd().dexopt(outputArtifacts, target.dexInfo().dexPath(), target.isa(),
target.dexInfo().classLoaderContext(), target.compilerFilter(), profile, inputVdex,
- priorityClass, dexoptOptions, artdCancellationSignal);
+ dmFile, priorityClass, dexoptOptions, artdCancellationSignal);
}
@Nullable
@@ -426,7 +442,8 @@
return VdexPath.artifactsPath(
AidlUtils.buildArtifactsPath(dexPath, isa, false /* isInDalvikCache */));
case ArtifactsLocation.DM:
- return VdexPath.dexMetadataPath(AidlUtils.buildDexMetadataPath(dexPath));
+ // The DM file is passed to dex2oat as a separate flag whenever it exists.
+ return null;
default:
// This should never happen as the value is got from artd.
throw new IllegalStateException(
@@ -434,6 +451,22 @@
}
}
+ @Nullable
+ private DexMetadataPath getDmFile(@NonNull DexInfoType dexInfo) throws RemoteException {
+ DexMetadataPath path = buildDmPath(dexInfo);
+ if (path == null) {
+ return null;
+ }
+ try {
+ if (mInjector.getArtd().getDmFileVisibility(path) != FileVisibility.NOT_FOUND) {
+ return path;
+ }
+ } catch (ServiceSpecificException e) {
+ Log.e(TAG, "Failed to check DM file for " + dexInfo.dexPath(), e);
+ }
+ return null;
+ }
+
private boolean commitProfileChanges(@NonNull TmpProfilePath profile) throws RemoteException {
try {
mInjector.getArtd().commitTmpProfile(profile);
@@ -525,24 +558,30 @@
/** Returns the paths to the current profiles of the given dex file. */
@NonNull protected abstract List<ProfilePath> getCurProfiles(@NonNull DexInfoType dexInfo);
+ /**
+ * Returns the path to the DM file that should be passed to dex2oat, or null if no DM file
+ * should be passed.
+ */
+ @Nullable protected abstract DexMetadataPath buildDmPath(@NonNull DexInfoType dexInfo);
+
@AutoValue
- abstract static class DexoptTarget {
- abstract @NonNull DetailedDexInfo dexInfo();
+ abstract static class DexoptTarget<DexInfoType extends DetailedDexInfo> {
+ abstract @NonNull DexInfoType dexInfo();
abstract @NonNull String isa();
abstract boolean isInDalvikCache();
abstract @NonNull String compilerFilter();
- static Builder builder() {
- return new AutoValue_DexOptimizer_DexoptTarget.Builder();
+ static <DexInfoType extends DetailedDexInfo> Builder<DexInfoType> builder() {
+ return new AutoValue_DexOptimizer_DexoptTarget.Builder<DexInfoType>();
}
@AutoValue.Builder
- abstract static class Builder {
- abstract Builder setDexInfo(@NonNull DetailedDexInfo value);
+ abstract static class Builder<DexInfoType extends DetailedDexInfo> {
+ abstract Builder setDexInfo(@NonNull DexInfoType value);
abstract Builder setIsa(@NonNull String value);
abstract Builder setIsInDalvikCache(boolean value);
abstract Builder setCompilerFilter(@NonNull String value);
- abstract DexoptTarget build();
+ abstract DexoptTarget<DexInfoType> build();
}
}
diff --git a/libartservice/service/java/com/android/server/art/PrimaryDexOptimizer.java b/libartservice/service/java/com/android/server/art/PrimaryDexOptimizer.java
index 032f2ae..ee36b08 100644
--- a/libartservice/service/java/com/android/server/art/PrimaryDexOptimizer.java
+++ b/libartservice/service/java/com/android/server/art/PrimaryDexOptimizer.java
@@ -206,6 +206,12 @@
return profiles;
}
+ @Override
+ @Nullable
+ protected DexMetadataPath buildDmPath(@NonNull DetailedPrimaryDexInfo dexInfo) {
+ return AidlUtils.buildDexMetadataPath(dexInfo.dexPath());
+ }
+
private boolean isSharedLibrary() {
// TODO(b/242688548): Package manager should provide a better API for this.
return !TextUtils.isEmpty(mPkg.getSdkLibraryName())
diff --git a/libartservice/service/java/com/android/server/art/ReasonMapping.java b/libartservice/service/java/com/android/server/art/ReasonMapping.java
index 88a330c..08140ad 100644
--- a/libartservice/service/java/com/android/server/art/ReasonMapping.java
+++ b/libartservice/service/java/com/android/server/art/ReasonMapping.java
@@ -27,6 +27,8 @@
import dalvik.system.DexFile;
+import java.util.Set;
+
/**
* Maps a compilation reason to a compiler filter and a priority class.
*
@@ -57,6 +59,11 @@
public static final String REASON_INSTALL_BULK_SECONDARY_DOWNGRADED =
"install-bulk-secondary-downgraded";
+ /** @hide */
+ public static final Set<String> REASONS_FOR_INSTALL = Set.of(REASON_INSTALL,
+ REASON_INSTALL_FAST, REASON_INSTALL_BULK, REASON_INSTALL_BULK_SECONDARY,
+ REASON_INSTALL_BULK_DOWNGRADED, REASON_INSTALL_BULK_SECONDARY_DOWNGRADED);
+
/**
* Loads the compiler filter from the system property for the given reason and checks for
* validity.
diff --git a/libartservice/service/java/com/android/server/art/SecondaryDexOptimizer.java b/libartservice/service/java/com/android/server/art/SecondaryDexOptimizer.java
index 95b9ddb..73987fe 100644
--- a/libartservice/service/java/com/android/server/art/SecondaryDexOptimizer.java
+++ b/libartservice/service/java/com/android/server/art/SecondaryDexOptimizer.java
@@ -135,6 +135,12 @@
return List.of(AidlUtils.buildProfilePathForSecondaryCur(dexInfo.dexPath()));
}
+ @Override
+ @Nullable
+ protected DexMetadataPath buildDmPath(@NonNull DetailedSecondaryDexInfo dexInfo) {
+ return null;
+ }
+
private int getUid(@NonNull DetailedSecondaryDexInfo dexInfo) {
return dexInfo.userHandle().getUid(mPkgState.getAppId());
}
diff --git a/libartservice/service/java/com/android/server/art/model/OptimizationStatus.java b/libartservice/service/java/com/android/server/art/model/OptimizationStatus.java
index 2fdf1ce..4abf4c3 100644
--- a/libartservice/service/java/com/android/server/art/model/OptimizationStatus.java
+++ b/libartservice/service/java/com/android/server/art/model/OptimizationStatus.java
@@ -109,6 +109,17 @@
* <li>{@code "unknown"}: if the reason is empty or the optimized artifacts do not exist.
* <li>{@code "error"}: if an unexpected error occurs.
* </ul>
+ *
+ * Note that this value can differ from the requested compilation reason passed to {@link
+ * OptimizeParams.Builder}. Specifically, if the requested reason is for app install (e.g.,
+ * "install"), and a DM file is passed to {@code dex2oat}, a "-dm" suffix will be appended
+ * to the actual reason (e.g., "install-dm"). Other compilation reasons remain unchanged
+ * even if a DM file is passed to {@code dex2oat}.
+ *
+ * Also note that the "-dm" suffix does <b>not</b> imply anything in the DM file being used
+ * by {@code dex2oat}. The compilation reason can still be "install-dm" even if {@code
+ * dex2oat} left all contents of the DM file unused or an empty DM file is passed to
+ * {@code dex2oat}.
*/
public abstract @NonNull String getCompilationReason();
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerParameterizedTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerParameterizedTest.java
index 407fd61..bff34ee 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerParameterizedTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerParameterizedTest.java
@@ -209,6 +209,7 @@
dexoptOptions.hiddenApiPolicyEnabled = mParams.mExpectedIsHiddenApiPolicyEnabled;
when(mArtd.createCancellationSignal()).thenReturn(mock(IArtdCancellationSignal.class));
+ when(mArtd.getDmFileVisibility(any())).thenReturn(FileVisibility.NOT_FOUND);
// The first one is normal.
doReturn(dexoptIsNeeded())
@@ -222,8 +223,8 @@
mParams.mExpectedIsInDalvikCache, permissionSettings)),
eq("/data/app/foo/base.apk"), eq("arm64"), eq("PCL[]"),
eq(mParams.mExpectedCompilerFilter), isNull() /* profile */,
- isNull() /* inputVdex */, eq(PriorityClass.INTERACTIVE),
- deepEq(dexoptOptions), any());
+ isNull() /* inputVdex */, isNull() /* dmFile */,
+ eq(PriorityClass.INTERACTIVE), deepEq(dexoptOptions), any());
// The second one fails on `dexopt`.
doReturn(dexoptIsNeeded())
@@ -236,8 +237,8 @@
mParams.mExpectedIsInDalvikCache, permissionSettings)),
eq("/data/app/foo/base.apk"), eq("arm"), eq("PCL[]"),
eq(mParams.mExpectedCompilerFilter), isNull() /* profile */,
- isNull() /* inputVdex */, eq(PriorityClass.INTERACTIVE),
- deepEq(dexoptOptions), any());
+ isNull() /* inputVdex */, isNull() /* dmFile */,
+ eq(PriorityClass.INTERACTIVE), deepEq(dexoptOptions), any());
// The third one doesn't need dexopt.
doReturn(dexoptIsNotNeeded())
@@ -257,8 +258,8 @@
mParams.mExpectedIsInDalvikCache, permissionSettings)),
eq("/data/app/foo/split_0.apk"), eq("arm"), eq("PCL[base.apk]"),
eq(mParams.mExpectedCompilerFilter), isNull() /* profile */,
- isNull() /* inputVdex */, eq(PriorityClass.INTERACTIVE),
- deepEq(dexoptOptions), any());
+ isNull() /* inputVdex */, isNull() /* dmFile */,
+ eq(PriorityClass.INTERACTIVE), deepEq(dexoptOptions), any());
assertThat(mPrimaryDexOptimizer.dexopt())
.comparingElementsUsing(TestingUtils.<DexContainerFileOptimizeResult>deepEquality())
diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerTest.java
index 5b9264d..ff74e15 100644
--- a/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerTest.java
+++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexOptimizerTest.java
@@ -73,6 +73,7 @@
AidlUtils.buildProfilePathForPrimaryRef(PKG_NAME, "primary");
private final ProfilePath mPrebuiltProfile = AidlUtils.buildProfilePathForPrebuilt(mDexPath);
private final ProfilePath mDmProfile = AidlUtils.buildProfilePathForDm(mDexPath);
+ private final DexMetadataPath mDmFile = AidlUtils.buildDexMetadataPath(mDexPath);
private final OutputProfile mPublicOutputProfile = AidlUtils.buildOutputProfileForPrimary(
PKG_NAME, "primary", Process.SYSTEM_UID, SHARED_GID, true /* isOtherReadable */);
private final OutputProfile mPrivateOutputProfile = AidlUtils.buildOutputProfileForPrimary(
@@ -106,13 +107,16 @@
lenient().when(mArtd.isProfileUsable(any(), any())).thenReturn(false);
lenient().when(mArtd.copyAndRewriteProfile(any(), any(), any())).thenReturn(false);
+ // By default, no DM file exists.
+ lenient().when(mArtd.getDmFileVisibility(any())).thenReturn(FileVisibility.NOT_FOUND);
+
// Dexopt is by default needed and successful.
lenient()
.when(mArtd.getDexoptNeeded(any(), any(), any(), any(), anyInt()))
.thenReturn(dexoptIsNeeded());
lenient()
- .when(mArtd.dexopt(
- any(), any(), any(), any(), any(), any(), any(), anyInt(), any(), any()))
+ .when(mArtd.dexopt(any(), any(), any(), any(), any(), any(), any(), any(), anyInt(),
+ any(), any()))
.thenReturn(mDexoptResult);
lenient()
@@ -133,8 +137,8 @@
.getDexoptNeeded(eq(mDexPath), eq("arm64"), any(), any(), anyInt());
doReturn(mDexoptResult)
.when(mArtd)
- .dexopt(any(), eq(mDexPath), eq("arm64"), any(), any(), any(), isNull(), anyInt(),
- any(), any());
+ .dexopt(any(), eq(mDexPath), eq("arm64"), any(), any(), any(), isNull(), any(),
+ anyInt(), any(), any());
// ArtifactsPath, isInDalvikCache=true.
doReturn(dexoptIsNeeded(ArtifactsLocation.DALVIK_CACHE))
@@ -145,7 +149,7 @@
.dexopt(any(), eq(mDexPath), eq("arm"), any(), any(), any(),
deepEq(VdexPath.artifactsPath(AidlUtils.buildArtifactsPath(
mDexPath, "arm", true /* isInDalvikCache */))),
- anyInt(), any(), any());
+ any(), anyInt(), any(), any());
// ArtifactsPath, isInDalvikCache=false.
doReturn(dexoptIsNeeded(ArtifactsLocation.NEXT_TO_DEX))
@@ -156,7 +160,7 @@
.dexopt(any(), eq(mSplit0DexPath), eq("arm64"), any(), any(), any(),
deepEq(VdexPath.artifactsPath(AidlUtils.buildArtifactsPath(
mSplit0DexPath, "arm64", false /* isInDalvikCache */))),
- anyInt(), any(), any());
+ any(), anyInt(), any(), any());
// DexMetadataPath.
doReturn(dexoptIsNeeded(ArtifactsLocation.DM))
@@ -164,15 +168,34 @@
.getDexoptNeeded(eq(mSplit0DexPath), eq("arm"), any(), any(), anyInt());
doReturn(mDexoptResult)
.when(mArtd)
- .dexopt(any(), eq(mSplit0DexPath), eq("arm"), any(), any(), any(),
- deepEq(VdexPath.dexMetadataPath(
- AidlUtils.buildDexMetadataPath(mSplit0DexPath))),
+ .dexopt(any(), eq(mSplit0DexPath), eq("arm"), any(), any(), any(), isNull(), any(),
anyInt(), any(), any());
mPrimaryDexOptimizer.dexopt();
}
@Test
+ public void testDexoptDm() throws Exception {
+ lenient()
+ .when(mArtd.getDmFileVisibility(deepEq(mDmFile)))
+ .thenReturn(FileVisibility.OTHER_READABLE);
+
+ mPrimaryDexOptimizer.dexopt();
+
+ verify(mArtd, times(2))
+ .dexopt(any(), eq(mDexPath), any(), any(), any(), any(), any(), deepEq(mDmFile),
+ anyInt(),
+ argThat(dexoptOptions
+ -> dexoptOptions.compilationReason.equals("install-dm")),
+ any());
+ verify(mArtd, times(2))
+ .dexopt(any(), eq(mSplit0DexPath), any(), any(), any(), any(), any(), isNull(),
+ anyInt(),
+ argThat(dexoptOptions -> dexoptOptions.compilationReason.equals("install")),
+ any());
+ }
+
+ @Test
public void testDexoptUsesRefProfile() throws Exception {
makeProfileUsable(mRefProfile);
when(mArtd.getProfileVisibility(deepEq(mRefProfile)))
@@ -342,8 +365,8 @@
makeProfileNotUsable(mPrebuiltProfile);
makeProfileUsable(mDmProfile);
- when(mArtd.dexopt(any(), eq(mDexPath), any(), any(), any(), any(), any(), anyInt(), any(),
- any()))
+ when(mArtd.dexopt(any(), eq(mDexPath), any(), any(), any(), any(), any(), any(), anyInt(),
+ any(), any()))
.thenThrow(ServiceSpecificException.class);
mPrimaryDexOptimizer.dexopt();
@@ -448,7 +471,7 @@
true /* cancelled */, 200 /* wallTimeMs */, 200 /* cpuTimeMs */);
})
.when(mArtd)
- .dexopt(any(), any(), any(), any(), any(), any(), any(), anyInt(), any(),
+ .dexopt(any(), any(), any(), any(), any(), any(), any(), any(), anyInt(), any(),
same(artdCancellationSignal));
// The result should only contain one element: the result of the first file with
@@ -462,7 +485,8 @@
// It shouldn't continue after being cancelled on the first file.
verify(mArtd, times(1)).createCancellationSignal();
verify(mArtd, times(1))
- .dexopt(any(), any(), any(), any(), any(), any(), any(), anyInt(), any(), any());
+ .dexopt(any(), any(), any(), any(), any(), any(), any(), any(), anyInt(), any(),
+ any());
}
@Test
@@ -481,7 +505,7 @@
true /* cancelled */, 200 /* wallTimeMs */, 200 /* cpuTimeMs */);
})
.when(mArtd)
- .dexopt(any(), any(), any(), any(), any(), any(), any(), anyInt(), any(),
+ .dexopt(any(), any(), any(), any(), any(), any(), any(), any(), anyInt(), any(),
same(artdCancellationSignal));
doAnswer(invocation -> {
dexoptCancelled.release();
@@ -507,7 +531,8 @@
// It shouldn't continue after being cancelled on the first file.
verify(mArtd, times(1)).createCancellationSignal();
verify(mArtd, times(1))
- .dexopt(any(), any(), any(), any(), any(), any(), any(), anyInt(), any(), any());
+ .dexopt(any(), any(), any(), any(), any(), any(), any(), any(), anyInt(), any(),
+ any());
}
private void checkDexoptWithPublicProfile(
@@ -515,8 +540,8 @@
artd.dexopt(
argThat(artifacts
-> artifacts.permissionSettings.fileFsPermission.isOtherReadable == true),
- eq(dexPath), eq(isa), any(), eq("speed-profile"), deepEq(profile), any(), anyInt(),
- argThat(dexoptOptions -> dexoptOptions.generateAppImage == true), any());
+ eq(dexPath), eq(isa), any(), eq("speed-profile"), deepEq(profile), any(), any(),
+ anyInt(), argThat(dexoptOptions -> dexoptOptions.generateAppImage == true), any());
}
private void checkDexoptWithPrivateProfile(
@@ -524,8 +549,8 @@
artd.dexopt(
argThat(artifacts
-> artifacts.permissionSettings.fileFsPermission.isOtherReadable == false),
- eq(dexPath), eq(isa), any(), eq("speed-profile"), deepEq(profile), any(), anyInt(),
- argThat(dexoptOptions -> dexoptOptions.generateAppImage == true), any());
+ eq(dexPath), eq(isa), any(), eq("speed-profile"), deepEq(profile), any(), any(),
+ anyInt(), argThat(dexoptOptions -> dexoptOptions.generateAppImage == true), any());
}
private void checkDexoptWithNoProfile(
@@ -533,7 +558,7 @@
artd.dexopt(
argThat(artifacts
-> artifacts.permissionSettings.fileFsPermission.isOtherReadable == true),
- eq(dexPath), eq(isa), any(), eq(compilerFilter), isNull(), any(), anyInt(),
+ eq(dexPath), eq(isa), any(), eq(compilerFilter), isNull(), any(), any(), anyInt(),
argThat(dexoptOptions -> dexoptOptions.generateAppImage == false), any());
}
diff --git a/libartservice/service/javatests/com/android/server/art/SecondaryDexOptimizerTest.java b/libartservice/service/javatests/com/android/server/art/SecondaryDexOptimizerTest.java
index 7b967e4..4e9a7f1 100644
--- a/libartservice/service/javatests/com/android/server/art/SecondaryDexOptimizerTest.java
+++ b/libartservice/service/javatests/com/android/server/art/SecondaryDexOptimizerTest.java
@@ -145,8 +145,8 @@
.when(mArtd.getDexoptNeeded(any(), any(), any(), any(), anyInt()))
.thenReturn(dexoptIsNeeded());
lenient()
- .when(mArtd.dexopt(
- any(), any(), any(), any(), any(), any(), any(), anyInt(), any(), any()))
+ .when(mArtd.dexopt(any(), any(), any(), any(), any(), any(), any(), any(), anyInt(),
+ any(), any()))
.thenReturn(createDexoptResult());
lenient()
@@ -316,7 +316,7 @@
OutputArtifacts outputArtifacts = AidlUtils.buildOutputArtifacts(
dexPath, isa, false /* isInDalvikCache */, permissionSettings);
artd.dexopt(deepEq(outputArtifacts), eq(dexPath), eq(isa), eq(classLoaderContext),
- eq("speed-profile"), deepEq(profile), any(), anyInt(),
+ eq("speed-profile"), deepEq(profile), any(), isNull() /* dmFile */, anyInt(),
argThat(dexoptOptions -> dexoptOptions.generateAppImage == false), any());
}
@@ -326,7 +326,7 @@
OutputArtifacts outputArtifacts = AidlUtils.buildOutputArtifacts(
dexPath, isa, false /* isInDalvikCache */, permissionSettings);
artd.dexopt(deepEq(outputArtifacts), eq(dexPath), eq(isa), eq(classLoaderContext),
- eq(compilerFilter), isNull(), any(), anyInt(),
+ eq(compilerFilter), isNull(), any(), isNull() /* dmFile */, anyInt(),
argThat(dexoptOptions -> dexoptOptions.generateAppImage == false), any());
}