Merge "Refactor profile dir creation"
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 93353bf..daa744f 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -342,6 +342,47 @@
 #endif
 }
 
+static bool prepare_app_profile_dir(const std::string& packageName, int32_t appId, int32_t userId) {
+    if (!property_get_bool("dalvik.vm.usejitprofiles", false)) {
+        return true;
+    }
+
+    int32_t uid = multiuser_get_uid(userId, appId);
+    int shared_app_gid = multiuser_get_shared_gid(userId, appId);
+    if (shared_app_gid == -1) {
+        // TODO(calin): this should no longer be possible but do not continue if we don't get
+        // a valid shared gid.
+        PLOG(WARNING) << "Invalid shared_app_gid for " << packageName;
+        return true;
+    }
+
+    const std::string profile_dir =
+            create_primary_current_profile_package_dir_path(userId, packageName);
+    // read-write-execute only for the app user.
+    if (fs_prepare_dir_strict(profile_dir.c_str(), 0700, uid, uid) != 0) {
+        PLOG(ERROR) << "Failed to prepare " << profile_dir;
+        return false;
+    }
+    const std::string profile_file = create_current_profile_path(userId, packageName,
+            /*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);
+    // dex2oat/profman runs under the shared app gid and it needs to read/write reference
+    // profiles.
+    if (fs_prepare_dir_strict(
+            ref_profile_path.c_str(), 0701, shared_app_gid, shared_app_gid) != 0) {
+        PLOG(ERROR) << "Failed to prepare " << ref_profile_path;
+        return false;
+    }
+    return true;
+}
+
 binder::Status InstalldNativeService::createAppData(const std::unique_ptr<std::string>& uuid,
         const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
         const std::string& seInfo, int32_t targetSdkVersion, int64_t* _aidl_return) {
@@ -417,28 +458,8 @@
             return error("Failed to set hard quota " + path);
         }
 
-        if (property_get_bool("dalvik.vm.usejitprofiles", false)) {
-            const std::string profile_dir =
-                    create_primary_current_profile_package_dir_path(userId, pkgname);
-            // read-write-execute only for the app user.
-            if (fs_prepare_dir_strict(profile_dir.c_str(), 0700, uid, uid) != 0) {
-                return error("Failed to prepare " + profile_dir);
-            }
-            const std::string profile_file = create_current_profile_path(userId, pkgname,
-                    /*is_secondary_dex*/false);
-            // read-write only for the app user.
-            if (fs_prepare_file_strict(profile_file.c_str(), 0600, uid, uid) != 0) {
-                return error("Failed to prepare " + profile_file);
-            }
-            const std::string ref_profile_path =
-                    create_primary_reference_profile_package_dir_path(pkgname);
-            // dex2oat/profman runs under the shared app gid and it needs to read/write reference
-            // profiles.
-            int shared_app_gid = multiuser_get_shared_gid(0, appId);
-            if ((shared_app_gid != -1) && fs_prepare_dir_strict(
-                    ref_profile_path.c_str(), 0701, shared_app_gid, shared_app_gid) != 0) {
-                return error("Failed to prepare " + ref_profile_path);
-            }
+        if (!prepare_app_profile_dir(packageName, appId, userId)) {
+            return error("Failed to prepare profiles for " + packageName);
         }
     }
     return ok();
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 19b42b5..ebeae96 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -144,10 +144,11 @@
     static constexpr uid_t kSystemGid = 1000;
     static constexpr int32_t kOSdkVersion = 25;
     static constexpr int32_t kAppDataFlags = FLAG_STORAGE_CE | FLAG_STORAGE_DE;
-    static constexpr uid_t kTestAppUid = 19999;
-    static constexpr gid_t kTestAppGid = 19999;
-    static constexpr uid_t kTestAppId = kTestAppUid;
     static constexpr int32_t kTestUserId = 0;
+    static constexpr uid_t kTestAppId = 19999;
+
+    const gid_t kTestAppUid = multiuser_get_uid(kTestUserId, kTestAppId);
+    const uid_t kTestAppGid = multiuser_get_shared_gid(kTestUserId, kTestAppId);
 
     InstalldNativeService* service_;
     std::unique_ptr<std::string> volume_uuid_;
@@ -245,7 +246,10 @@
 
     void CompileSecondaryDex(const std::string& path, int32_t dex_storage_flag,
             bool should_binder_call_succeed, bool should_dex_be_compiled = true,
-            int uid = kTestAppUid) {
+            int32_t uid = -1) {
+        if (uid == -1) {
+            uid = kTestAppUid;
+        }
         std::unique_ptr<std::string> package_name_ptr(new std::string(package_name_));
         int32_t dexopt_needed = 0;  // does not matter;
         std::unique_ptr<std::string> out_path = nullptr;  // does not matter
@@ -279,7 +283,10 @@
 
     void reconcile_secondary_dex(const std::string& path, int32_t storage_flag,
             bool should_binder_call_succeed, bool should_dex_exist, bool should_dex_be_deleted,
-            int uid = kTestAppUid, std::string* package_override = nullptr) {
+            int32_t uid = -1, std::string* package_override = nullptr) {
+        if (uid == -1) {
+            uid = kTestAppUid;
+        }
         std::vector<std::string> isas;
         isas.push_back(kRuntimeIsa);
         bool out_secondary_dex_exists = false;
@@ -556,5 +563,19 @@
     ASSERT_EQ(ENOENT, errno);
 }
 
+TEST_F(ProfileTest, ProfileDirOk) {
+    LOG(INFO) << "ProfileDirOk";
+
+    std::string cur_profile_dir = create_primary_current_profile_package_dir_path(
+            kTestUserId, package_name_);
+    std::string cur_profile_file = create_current_profile_path(kTestUserId, package_name_,
+            /*is_secondary_dex*/false);
+    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, kTestAppGid, kTestAppGid, 0701 | S_IFDIR);
+}
+
 }  // namespace installd
 }  // namespace android