Prepare installd to handle profiles per code path

Transform each profile operation to accept the pair
(package_name, profile_name). This will allow installd to get the profile
name from the PackageManager instead of assuming a predefined name. The
PackageManager will compute and assign unique profile names for each code
path.

The end goal is to support installation and extraction of profiles per
code path.

Also, add a few extra tests for merging the profiles.

Test: installd_dexopt_test, installd_utils_test
Bug: 30934496
Change-Id: I580f037d9d3e5537032e815dc803b9ddeff343cb
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index f787887..1694233 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -99,6 +99,10 @@
 
 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();
 }
@@ -370,8 +374,9 @@
         PLOG(ERROR) << "Failed to prepare " << profile_dir;
         return false;
     }
+
     const std::string profile_file = create_current_profile_path(userId, packageName,
-            /*is_secondary_dex*/false);
+            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;
@@ -532,10 +537,10 @@
     std::lock_guard<std::recursive_mutex> lock(mLock);
 
     binder::Status res = ok();
-    if (!clear_primary_reference_profile(packageName)) {
+    if (!clear_primary_reference_profile(packageName, kPrimaryProfileName)) {
         res = error("Failed to clear reference profile for " + packageName);
     }
-    if (!clear_primary_current_profiles(packageName)) {
+    if (!clear_primary_current_profiles(packageName, kPrimaryProfileName)) {
         res = error("Failed to clear current profiles for " + packageName);
     }
     return res;
@@ -586,7 +591,7 @@
             }
         }
         if (!only_cache) {
-            if (!clear_primary_current_profile(packageName, userId)) {
+            if (!clear_primary_current_profile(packageName, kPrimaryProfileName, userId)) {
                 res = error("Failed to clear current profile for " + packageName);
             }
         }
@@ -1855,7 +1860,8 @@
     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);
+    *_aidl_return = copy_system_profile(systemProfile, packageUid, packageName,
+            kPrimaryProfileName);
     return ok();
 }
 
@@ -1866,29 +1872,29 @@
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
     std::lock_guard<std::recursive_mutex> lock(mLock);
 
-    *_aidl_return = analyze_primary_profiles(uid, packageName);
+    *_aidl_return = analyze_primary_profiles(uid, packageName, kPrimaryProfileName);
     return ok();
 }
 
 binder::Status InstalldNativeService::createProfileSnapshot(int32_t appId,
-        const std::string& packageName, const std::string& codePath, bool* _aidl_return) {
+        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 = create_profile_snapshot(appId, packageName, codePath);
+    *_aidl_return = create_profile_snapshot(appId, packageName, profileName);
     return ok();
 }
 
 binder::Status InstalldNativeService::destroyProfileSnapshot(const std::string& packageName,
-        const std::string& codePath) {
+        const std::string& profileName) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
     std::lock_guard<std::recursive_mutex> lock(mLock);
 
-    std::string snapshot = create_snapshot_profile_path(packageName, codePath);
+    std::string snapshot = create_snapshot_profile_path(packageName, profileName);
     if ((unlink(snapshot.c_str()) != 0) && (errno != ENOENT)) {
-        return error("Failed to destroy profile snapshot for " + packageName + ":" + codePath);
+        return error("Failed to destroy profile snapshot for " + packageName + ":" + profileName);
     }
     return ok();
 }
@@ -1914,9 +1920,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;
+
     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);
+            downgrade, targetSdkVersion, kPrimaryProfileName);
     return res ? error(res, "Failed to dexopt") : ok();
 }