Use speed-profile with the cloud profile for apks loaded by other apps.

- Add `getOdexVisibility`, which returns the visibility of the odex file
  of an APK.
- Change `prepareAppProfile` to accept `userId` being `USER_NULL`. This
  is needed by the corresponding change in framework/base, which passes
  `USER_NULL` as `userId` to indicate that the current profile should
  remain unchanged.

Bug: 175039995
Test: atest CtsCompilationTestCases
Ignore-AOSP-First: Merge conflicts.
Change-Id: I6a9a1077cee6a6d6d02ac2375da55c4a10b11861
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 9647865..894c7d3 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -2773,13 +2773,23 @@
                          const std::string& profile_name,
                          const std::string& code_path,
                          const std::optional<std::string>& dex_metadata) {
-    // Prepare the current profile.
-    std::string cur_profile  = create_current_profile_path(user_id, package_name, profile_name,
-            /*is_secondary_dex*/ false);
-    uid_t uid = multiuser_get_uid(user_id, app_id);
-    if (fs_prepare_file_strict(cur_profile.c_str(), 0600, uid, uid) != 0) {
-        PLOG(ERROR) << "Failed to prepare " << cur_profile;
-        return false;
+    if (user_id != USER_NULL) {
+        if (user_id < 0) {
+            LOG(ERROR) << "Unexpected user ID " << user_id;
+            return false;
+        }
+
+        // Prepare the current profile.
+        std::string cur_profile = create_current_profile_path(user_id, package_name, profile_name,
+                                                              /*is_secondary_dex*/ false);
+        uid_t uid = multiuser_get_uid(user_id, app_id);
+        if (fs_prepare_file_strict(cur_profile.c_str(), 0600, uid, uid) != 0) {
+            PLOG(ERROR) << "Failed to prepare " << cur_profile;
+            return false;
+        }
+    } else {
+        // Prepare the reference profile as the system user.
+        user_id = USER_SYSTEM;
     }
 
     // Check if we need to install the profile from the dex metadata.
@@ -2788,8 +2798,9 @@
     }
 
     // We have a dex metdata. Merge the profile into the reference profile.
-    unique_fd ref_profile_fd = open_reference_profile(uid, package_name, profile_name,
-            /*read_write*/ true, /*is_secondary_dex*/ false);
+    unique_fd ref_profile_fd =
+            open_reference_profile(multiuser_get_uid(user_id, app_id), package_name, profile_name,
+                                   /*read_write*/ true, /*is_secondary_dex*/ false);
     unique_fd dex_metadata_fd(TEMP_FAILURE_RETRY(
             open(dex_metadata->c_str(), O_RDONLY | O_NOFOLLOW)));
     unique_fd apk_fd(TEMP_FAILURE_RETRY(open(code_path.c_str(), O_RDONLY | O_NOFOLLOW)));
@@ -2823,5 +2834,22 @@
     return true;
 }
 
+int get_odex_visibility(const char* apk_path, const char* instruction_set, const char* oat_dir) {
+    char oat_path[PKG_PATH_MAX];
+    if (!create_oat_out_path(apk_path, instruction_set, oat_dir, /*is_secondary_dex=*/false,
+                             oat_path)) {
+        return -1;
+    }
+    struct stat st;
+    if (stat(oat_path, &st) == -1) {
+        if (errno == ENOENT) {
+            return ODEX_NOT_FOUND;
+        }
+        PLOG(ERROR) << "Could not stat " << oat_path;
+        return -1;
+    }
+    return (st.st_mode & S_IROTH) ? ODEX_IS_PUBLIC : ODEX_IS_PRIVATE;
+}
+
 }  // namespace installd
 }  // namespace android