Replace profman invocation for prepareAppProfiles

Instead of using the default merging path, use the dedicated
copy_and_update_profile_key path which will also update the
profile key to the actual apk path.

(cherry picked from commit b7eecae060ac625c38dd56b064a44391a569dcf6)

Test: installd_dexopt_test
Bug: 30934496

Merged-In: Ib268be534e3832598d55cacf0aad1c723772cc6c
Change-Id: Ib268be534e3832598d55cacf0aad1c723772cc6c
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 4cd05b2..9c9567e 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -715,13 +715,20 @@
 static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3;
 static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4;
 
-static void run_profman_merge(const std::vector<unique_fd>& profiles_fd,
-        const unique_fd& reference_profile_fd, const std::vector<unique_fd>* apk_fds = nullptr) {
+static void run_profman(const std::vector<unique_fd>& profile_fds,
+                        const unique_fd& reference_profile_fd,
+                        const std::vector<unique_fd>* apk_fds,
+                        bool copy_and_update) {
     const char* profman_bin = is_debug_runtime() ? "/system/bin/profmand" : "/system/bin/profman";
 
-    std::vector<std::string> profile_args(profiles_fd.size());
-    for (size_t k = 0; k < profiles_fd.size(); k++) {
-        profile_args[k] = "--profile-file-fd=" + std::to_string(profiles_fd[k].get());
+    if (copy_and_update) {
+        CHECK_EQ(1u, profile_fds.size());
+        CHECK(apk_fds != nullptr);
+        CHECK_EQ(1u, apk_fds->size());
+    }
+    std::vector<std::string> profile_args(profile_fds.size());
+    for (size_t k = 0; k < profile_fds.size(); k++) {
+        profile_args[k] = "--profile-file-fd=" + std::to_string(profile_fds[k].get());
     }
     std::string reference_profile_arg = "--reference-profile-file-fd="
             + std::to_string(reference_profile_fd.get());
@@ -734,7 +741,7 @@
     }
 
     // program name, reference profile fd, the final NULL and the profile fds
-    const char* argv[3 + profile_args.size() + apk_args.size()];
+    const char* argv[3 + profile_args.size() + apk_args.size() + (copy_and_update ? 1 : 0)];
     int i = 0;
     argv[i++] = profman_bin;
     argv[i++] = reference_profile_arg.c_str();
@@ -744,6 +751,9 @@
     for (size_t k = 0; k < apk_args.size(); k++) {
         argv[i++] = apk_args[k].c_str();
     }
+    if (copy_and_update) {
+        argv[i++] = "--copy-and-update-profile-key";
+    }
     // Do not add after dex2oat_flags, they should override others for debugging.
     argv[i] = NULL;
 
@@ -752,6 +762,25 @@
     exit(68);   /* only get here on exec failure */
 }
 
+
+static void run_profman_merge(const std::vector<unique_fd>& profiles_fd,
+                              const unique_fd& reference_profile_fd,
+                              const std::vector<unique_fd>* apk_fds = nullptr) {
+    run_profman(profiles_fd, reference_profile_fd, apk_fds, /*copy_and_update*/false);
+}
+
+
+static void run_profman_copy_and_update(unique_fd&& profile_fd,
+                                        unique_fd&& reference_profile_fd,
+                                        unique_fd&& apk_fd) {
+    std::vector<unique_fd> profiles_fd;
+    profiles_fd.push_back(std::move(profile_fd));
+    std::vector<unique_fd> apk_fds;
+    apk_fds.push_back(std::move(apk_fd));
+
+    run_profman(profiles_fd, reference_profile_fd, &apk_fds, /*copy_and_update*/true);
+}
+
 // Decides if profile guided compilation is needed or not based on existing profiles.
 // The location is the package name for primary apks or the dex path for secondary dex files.
 // Returns true if there is enough information in the current profiles that makes it
@@ -2610,7 +2639,7 @@
                          userid_t user_id,
                          appid_t app_id,
                          const std::string& profile_name,
-                         const std::string& code_path ATTRIBUTE_UNUSED,
+                         const std::string& code_path,
                          const std::unique_ptr<std::string>& dex_metadata) {
     // Prepare the current profile.
     std::string cur_profile  = create_current_profile_path(user_id, package_name, profile_name,
@@ -2631,8 +2660,11 @@
             /*read_write*/ true, /*is_secondary_dex*/ false);
     unique_fd dex_metadata_fd(TEMP_FAILURE_RETRY(
             open(dex_metadata->c_str(), O_RDONLY | O_NOFOLLOW)));
-    std::vector<unique_fd> profiles_fd;
-    profiles_fd.push_back(std::move(dex_metadata_fd));
+    unique_fd apk_fd(TEMP_FAILURE_RETRY(open(code_path.c_str(), O_RDONLY | O_NOFOLLOW)));
+    if (apk_fd < 0) {
+        PLOG(ERROR) << "Could not open code path " << code_path;
+        return false;
+    }
 
     pid_t pid = fork();
     if (pid == 0) {
@@ -2640,10 +2672,10 @@
         gid_t app_shared_gid = multiuser_get_shared_gid(user_id, app_id);
         drop_capabilities(app_shared_gid);
 
-        // TODO(calin): the dex metadata profile might embed different names for the
-        // same code path (e.g. YouTube.apk or base.apk, depending on how the initial
-        // profile was captured). We should pass the code path to adjust the names in the profile.
-        run_profman_merge(profiles_fd, ref_profile_fd);
+        // The copy and update takes ownership over the fds.
+        run_profman_copy_and_update(std::move(dex_metadata_fd),
+                                    std::move(ref_profile_fd),
+                                    std::move(apk_fd));
         exit(42);   /* only get here on exec failure */
     }