Merge "[installd] Extend profile operations to take the profile name"
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 950c9a0..e4f8f04 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -107,10 +107,6 @@
constexpr const char* kDump = "android.permission.DUMP";
-// TODO(calin): We can stop hardcoding this here once the PM passes the profile
-// name for all profile related operations.
-constexpr const char* kPrimaryProfileName = "primary.prof";
-
static binder::Status ok() {
return binder::Status::ok();
}
@@ -389,14 +385,6 @@
return false;
}
- const std::string profile_file = create_current_profile_path(userId, packageName,
- kPrimaryProfileName, /*is_secondary_dex*/false);
- // read-write only for the app user.
- if (fs_prepare_file_strict(profile_file.c_str(), 0600, uid, uid) != 0) {
- PLOG(ERROR) << "Failed to prepare " << profile_file;
- return false;
- }
-
const std::string ref_profile_path =
create_primary_reference_profile_package_dir_path(packageName);
@@ -545,16 +533,17 @@
}
-binder::Status InstalldNativeService::clearAppProfiles(const std::string& packageName) {
+binder::Status InstalldNativeService::clearAppProfiles(const std::string& packageName,
+ const std::string& profileName) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
std::lock_guard<std::recursive_mutex> lock(mLock);
binder::Status res = ok();
- if (!clear_primary_reference_profile(packageName, kPrimaryProfileName)) {
+ if (!clear_primary_reference_profile(packageName, profileName)) {
res = error("Failed to clear reference profile for " + packageName);
}
- if (!clear_primary_current_profiles(packageName, kPrimaryProfileName)) {
+ if (!clear_primary_current_profiles(packageName, profileName)) {
res = error("Failed to clear current profiles for " + packageName);
}
return res;
@@ -604,11 +593,6 @@
res = error("Failed to delete contents of " + path);
}
}
- if (!only_cache) {
- if (!clear_primary_current_profile(packageName, kPrimaryProfileName, userId)) {
- res = error("Failed to clear current profile for " + packageName);
- }
- }
}
return res;
}
@@ -1856,37 +1840,34 @@
// Dumps the contents of a profile file, using pkgname's dex files for pretty
// printing the result.
binder::Status InstalldNativeService::dumpProfiles(int32_t uid, const std::string& packageName,
- const std::string& codePaths, bool* _aidl_return) {
+ const std::string& profileName, const std::string& codePath, bool* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
std::lock_guard<std::recursive_mutex> lock(mLock);
- const char* pkgname = packageName.c_str();
- const char* code_paths = codePaths.c_str();
-
- *_aidl_return = dump_profiles(uid, pkgname, code_paths);
+ *_aidl_return = dump_profiles(uid, packageName, profileName, codePath);
return ok();
}
// Copy the contents of a system profile over the data profile.
binder::Status InstalldNativeService::copySystemProfile(const std::string& systemProfile,
- int32_t packageUid, const std::string& packageName, bool* _aidl_return) {
+ int32_t packageUid, const std::string& packageName, const std::string& profileName,
+ bool* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
std::lock_guard<std::recursive_mutex> lock(mLock);
- *_aidl_return = copy_system_profile(systemProfile, packageUid, packageName,
- kPrimaryProfileName);
+ *_aidl_return = copy_system_profile(systemProfile, packageUid, packageName, profileName);
return ok();
}
// TODO: Consider returning error codes.
binder::Status InstalldNativeService::mergeProfiles(int32_t uid, const std::string& packageName,
- bool* _aidl_return) {
+ const std::string& profileName, bool* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
std::lock_guard<std::recursive_mutex> lock(mLock);
- *_aidl_return = analyze_primary_profiles(uid, packageName, kPrimaryProfileName);
+ *_aidl_return = analyze_primary_profiles(uid, packageName, profileName);
return ok();
}
@@ -1918,7 +1899,8 @@
int32_t dexoptNeeded, const std::unique_ptr<std::string>& outputPath, int32_t dexFlags,
const std::string& compilerFilter, const std::unique_ptr<std::string>& uuid,
const std::unique_ptr<std::string>& classLoaderContext,
- const std::unique_ptr<std::string>& seInfo, bool downgrade, int32_t targetSdkVersion) {
+ const std::unique_ptr<std::string>& seInfo, bool downgrade, int32_t targetSdkVersion,
+ const std::unique_ptr<std::string>& profileName) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
if (packageName && *packageName != "*") {
@@ -1934,10 +1916,10 @@
const char* volume_uuid = uuid ? uuid->c_str() : nullptr;
const char* class_loader_context = classLoaderContext ? classLoaderContext->c_str() : nullptr;
const char* se_info = seInfo ? seInfo->c_str() : nullptr;
-
+ const char* profile_name = profileName ? profileName->c_str() : nullptr;
int res = android::installd::dexopt(apk_path, uid, pkgname, instruction_set, dexoptNeeded,
oat_dir, dexFlags, compiler_filter, volume_uuid, class_loader_context, se_info,
- downgrade, targetSdkVersion, kPrimaryProfileName);
+ downgrade, targetSdkVersion, profile_name);
return res ? error(res, "Failed to dexopt") : ok();
}
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 7bd9c21..ce5c1a0 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -85,22 +85,24 @@
const std::string& compilerFilter, const std::unique_ptr<std::string>& uuid,
const std::unique_ptr<std::string>& classLoaderContext,
const std::unique_ptr<std::string>& seInfo, bool downgrade,
- int32_t targetSdkVersion);
+ int32_t targetSdkVersion, const std::unique_ptr<std::string>& profileName);
binder::Status rmdex(const std::string& codePath, const std::string& instructionSet);
- binder::Status mergeProfiles(int32_t uid, const std::string& packageName, bool* _aidl_return);
+ binder::Status mergeProfiles(int32_t uid, const std::string& packageName,
+ const std::string& profileName, bool* _aidl_return);
binder::Status dumpProfiles(int32_t uid, const std::string& packageName,
- const std::string& codePaths, bool* _aidl_return);
+ const std::string& profileName, const std::string& codePath, bool* _aidl_return);
binder::Status copySystemProfile(const std::string& systemProfile,
- int32_t uid, const std::string& packageName, bool* _aidl_return);
- binder::Status clearAppProfiles(const std::string& packageName);
+ int32_t uid, const std::string& packageName, const std::string& profileName,
+ bool* _aidl_return);
+ binder::Status clearAppProfiles(const std::string& packageName, const std::string& profileName);
binder::Status destroyAppProfiles(const std::string& packageName);
binder::Status createProfileSnapshot(int32_t appId, const std::string& packageName,
- const std::string& codePath, bool* _aidl_return);
+ const std::string& profileName, bool* _aidl_return);
binder::Status destroyProfileSnapshot(const std::string& packageName,
- const std::string& codePath);
+ const std::string& profileName);
binder::Status idmap(const std::string& targetApkPath, const std::string& overlayApkPath,
int32_t uid);
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index ba7efd0..d457a2a 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -51,20 +51,22 @@
@nullable @utf8InCpp String outputPath, int dexFlags,
@utf8InCpp String compilerFilter, @nullable @utf8InCpp String uuid,
@nullable @utf8InCpp String sharedLibraries,
- @nullable @utf8InCpp String seInfo, boolean downgrade, int targetSdkVersion);
+ @nullable @utf8InCpp String seInfo, boolean downgrade, int targetSdkVersion,
+ @nullable @utf8InCpp String profileName);
void rmdex(@utf8InCpp String codePath, @utf8InCpp String instructionSet);
- boolean mergeProfiles(int uid, @utf8InCpp String packageName);
- boolean dumpProfiles(int uid, @utf8InCpp String packageName, @utf8InCpp String codePaths);
+ boolean mergeProfiles(int uid, @utf8InCpp String packageName, @utf8InCpp String profileName);
+ boolean dumpProfiles(int uid, @utf8InCpp String packageName, @utf8InCpp String profileName,
+ @utf8InCpp String codePath);
boolean copySystemProfile(@utf8InCpp String systemProfile, int uid,
- @utf8InCpp String packageName);
- void clearAppProfiles(@utf8InCpp String packageName);
+ @utf8InCpp String packageName, @utf8InCpp String profileName);
+ void clearAppProfiles(@utf8InCpp String packageName, @utf8InCpp String profileName);
void destroyAppProfiles(@utf8InCpp String packageName);
boolean createProfileSnapshot(int appId, @utf8InCpp String packageName,
- @utf8InCpp String codePath);
- void destroyProfileSnapshot(@utf8InCpp String packageName, @utf8InCpp String codePath);
+ @utf8InCpp String profileName);
+ void destroyProfileSnapshot(@utf8InCpp String packageName, @utf8InCpp String profileName);
void idmap(@utf8InCpp String targetApkPath, @utf8InCpp String overlayApkPath, int uid);
void removeIdmap(@utf8InCpp String overlayApkPath);
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 0c836e8..0549a46 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -876,13 +876,14 @@
exit(68); /* only get here on exec failure */
}
-bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths) {
+bool dump_profiles(int32_t uid, const std::string& pkgname, const std::string& profile_name,
+ const std::string& code_path) {
std::vector<unique_fd> profile_fds;
unique_fd reference_profile_fd;
- std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname.c_str());
+ std::string out_file_name = StringPrintf("/data/misc/profman/%s-%s.txt",
+ pkgname.c_str(), profile_name.c_str());
- // TODO(calin): get the profile name as a parameter.
- open_profile_files(uid, pkgname, "primary.prof", /*is_secondary_dex*/false,
+ open_profile_files(uid, pkgname, profile_name, /*is_secondary_dex*/false,
&profile_fds, &reference_profile_fd);
const bool has_reference_profile = (reference_profile_fd.get() != -1);
@@ -896,22 +897,20 @@
unique_fd output_fd(open(out_file_name.c_str(),
O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0644));
if (fchmod(output_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
- ALOGE("installd cannot chmod '%s' dump_profile\n", out_file_name.c_str());
+ LOG(ERROR) << "installd cannot chmod file for dump_profile" << out_file_name;
return false;
}
- std::vector<std::string> code_full_paths = base::Split(code_paths, ";");
+
std::vector<std::string> dex_locations;
std::vector<unique_fd> apk_fds;
- for (const std::string& code_full_path : code_full_paths) {
- const char* full_path = code_full_path.c_str();
- unique_fd apk_fd(open(full_path, O_RDONLY | O_NOFOLLOW));
- if (apk_fd == -1) {
- ALOGE("installd cannot open '%s'\n", full_path);
- return false;
- }
- dex_locations.push_back(get_location_from_path(full_path));
- apk_fds.push_back(std::move(apk_fd));
+ unique_fd apk_fd(open(code_path.c_str(), O_RDONLY | O_NOFOLLOW));
+ if (apk_fd == -1) {
+ PLOG(ERROR) << "installd cannot open " << code_path.c_str();
+ return false;
}
+ dex_locations.push_back(get_location_from_path(code_path.c_str()));
+ apk_fds.push_back(std::move(apk_fd));
+
pid_t pid = fork();
if (pid == 0) {
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index 29312d2..b96351b 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -63,7 +63,10 @@
bool create_profile_snapshot(int32_t app_id, const std::string& package,
const std::string& profile_name);
-bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths);
+bool dump_profiles(int32_t uid,
+ const std::string& pkgname,
+ const std::string& profile_name,
+ const std::string& code_path);
bool copy_system_profile(const std::string& system_profile,
uid_t packageUid,
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 3e5e832..74dca72 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -181,6 +181,7 @@
const char* se_info;
bool downgrade;
int target_sdk_version;
+ const char* profile_name;
};
bool ReadSystemProperties() {
@@ -363,6 +364,8 @@
return ReadArgumentsV3(argc, argv);
case 4:
return ReadArgumentsV4(argc, argv);
+ case 5:
+ return ReadArgumentsV5(argc, argv);
default:
LOG(ERROR) << "Unsupported version " << version;
@@ -449,6 +452,9 @@
// conservative and may force some classes to verify at runtime.
package_parameters_.target_sdk_version = 0;
+ // Set the profile name to the primary apk profile.
+ package_parameters_.profile_name = "primary.prof";
+
if (param_index != 11) {
LOG(ERROR) << "Not enough parameters";
return false;
@@ -536,6 +542,9 @@
// conservative and may force some classes to verify at runtime.
package_parameters_.target_sdk_version = 0;
+ // Set the profile name to the primary apk profile.
+ package_parameters_.profile_name = "primary.prof";
+
if (param_index != 12) {
LOG(ERROR) << "Not enough parameters";
return false;
@@ -623,6 +632,9 @@
}
}
+ // Set the profile name to the primary apk profile.
+ package_parameters_.profile_name = "primary.prof";
+
if (param_index != 13) {
LOG(ERROR) << "Not enough parameters";
return false;
@@ -631,6 +643,99 @@
return true;
}
+ // TODO: this pattern does not scale and result in a lot of code duplication.
+ // Either find a better pattern or refactor the code to eliminate the duplication.
+ bool ReadArgumentsV5(int argc ATTRIBUTE_UNUSED, char** argv) {
+ size_t dexopt_index = 3;
+
+ // Check for "dexopt".
+ if (argv[dexopt_index] == nullptr) {
+ LOG(ERROR) << "Missing parameters";
+ return false;
+ }
+ if (std::string("dexopt").compare(argv[dexopt_index]) != 0) {
+ LOG(ERROR) << "Expected \"dexopt\"";
+ return false;
+ }
+
+ size_t param_index = 0;
+ for (;; ++param_index) {
+ const char* param = argv[dexopt_index + 1 + param_index];
+ if (param == nullptr) {
+ break;
+ }
+
+ switch (param_index) {
+ case 0:
+ package_parameters_.apk_path = param;
+ break;
+
+ case 1:
+ package_parameters_.uid = atoi(param);
+ break;
+
+ case 2:
+ package_parameters_.pkgName = param;
+ break;
+
+ case 3:
+ package_parameters_.instruction_set = param;
+ break;
+
+ case 4:
+ package_parameters_.dexopt_needed = atoi(param);
+ break;
+
+ case 5:
+ package_parameters_.oat_dir = param;
+ break;
+
+ case 6:
+ package_parameters_.dexopt_flags = atoi(param);
+ break;
+
+ case 7:
+ package_parameters_.compiler_filter = param;
+ break;
+
+ case 8:
+ package_parameters_.volume_uuid = ParseNull(param);
+ break;
+
+ case 9:
+ package_parameters_.shared_libraries = ParseNull(param);
+ break;
+
+ case 10:
+ package_parameters_.se_info = ParseNull(param);
+ break;
+
+ case 11:
+ package_parameters_.downgrade = ParseBool(param);
+ break;
+
+ case 12:
+ package_parameters_.target_sdk_version = atoi(param);
+ break;
+
+ case 13:
+ package_parameters_.profile_name = ParseNull(param);
+ break;
+
+ default:
+ LOG(ERROR) << "Too many arguments, got " << param;
+ return false;
+ }
+ }
+
+ if (param_index != 14) {
+ LOG(ERROR) << "Not enough parameters";
+ return false;
+ }
+
+ return true;
+ }
+
static int ReplaceMask(int input, int old_mask, int new_mask) {
return (input & old_mask) != 0 ? new_mask : 0;
}
@@ -738,6 +843,9 @@
// conservative and may force some classes to verify at runtime.
package_parameters_.target_sdk_version = 0;
+ // Set the profile name to the primary apk profile.
+ package_parameters_.profile_name = "primary.prof";
+
return true;
}
@@ -1028,7 +1136,7 @@
package_parameters_.se_info,
package_parameters_.downgrade,
package_parameters_.target_sdk_version,
- "primary.prof");
+ package_parameters_.profile_name);
}
int RunPreopt() {
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 4d6d234..8113542 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -259,7 +259,14 @@
std::unique_ptr<std::string> se_info_ptr(new std::string(se_info_));
bool downgrade = false;
int32_t target_sdk_version = 0; // default
+ std::unique_ptr<std::string> profile_name_ptr(new std::string("primary.prof"));
+ bool prof_result;
+ binder::Status prof_binder_result = service_->prepareAppProfile(
+ package_name_, kTestUserId, kTestAppId, *profile_name_ptr, /*code path*/ "base.apk",
+ /*dex_metadata*/ nullptr, &prof_result);
+ ASSERT_TRUE(prof_binder_result.isOk());
+ ASSERT_TRUE(prof_result);
binder::Status result = service_->dexopt(path,
uid,
package_name_ptr,
@@ -272,7 +279,8 @@
class_loader_context_ptr,
se_info_ptr,
downgrade,
- target_sdk_version);
+ target_sdk_version,
+ profile_name_ptr);
ASSERT_EQ(should_binder_call_succeed, result.isOk());
int expected_access = should_dex_be_compiled ? 0 : -1;
std::string odex = GetSecondaryDexArtifact(path, "odex");
@@ -498,10 +506,12 @@
ASSERT_TRUE(WIFEXITED(wait_child(pid)));
}
- void mergePackageProfiles(const std::string& package_name, bool expected_result) {
+ void mergePackageProfiles(const std::string& package_name,
+ const std::string& code_path,
+ bool expected_result) {
bool result;
binder::Status binder_result = service_->mergeProfiles(
- kTestAppUid, package_name, &result);
+ kTestAppUid, package_name, code_path, &result);
ASSERT_TRUE(binder_result.isOk());
ASSERT_EQ(expected_result, result);
@@ -628,7 +638,7 @@
LOG(INFO) << "ProfileMergeOk";
SetupProfiles(/*setup_ref*/ true);
- mergePackageProfiles(package_name_, /*expected_result*/ true);
+ mergePackageProfiles(package_name_, "primary.prof", /*expected_result*/ true);
}
// The reference profile is created on the fly. We need to be able to
@@ -637,14 +647,14 @@
LOG(INFO) << "ProfileMergeOkNoReference";
SetupProfiles(/*setup_ref*/ false);
- mergePackageProfiles(package_name_, /*expected_result*/ true);
+ mergePackageProfiles(package_name_, "primary.prof", /*expected_result*/ true);
}
TEST_F(ProfileTest, ProfileMergeFailWrongPackage) {
LOG(INFO) << "ProfileMergeFailWrongPackage";
SetupProfiles(/*setup_ref*/ true);
- mergePackageProfiles("not.there", /*expected_result*/ false);
+ mergePackageProfiles("not.there", "primary.prof", /*expected_result*/ false);
}
TEST_F(ProfileTest, ProfileDirOk) {
@@ -657,7 +667,6 @@
std::string ref_profile_dir = create_primary_reference_profile_package_dir_path(package_name_);
CheckFileAccess(cur_profile_dir, kTestAppUid, kTestAppUid, 0700 | S_IFDIR);
- CheckFileAccess(cur_profile_file, kTestAppUid, kTestAppUid, 0600 | S_IFREG);
CheckFileAccess(ref_profile_dir, kSystemUid, kTestAppGid, 0770 | S_IFDIR);
}
@@ -689,7 +698,6 @@
// Check the file access.
CheckFileAccess(cur_profile_dir, kTestAppUid, kTestAppUid, 0700 | S_IFDIR);
- CheckFileAccess(cur_profile_file, kTestAppUid, kTestAppUid, 0600 | S_IFREG);
CheckFileAccess(ref_profile_dir, kSystemUid, kTestAppGid, 0770 | S_IFDIR);
}