Merge "dumpsys: remove usage of String16::std_string"
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 29eb6e5..f9235e5 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -424,12 +424,11 @@
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
     std::lock_guard<std::recursive_mutex> lock(mLock);
 
-    const char* pkgname = packageName.c_str();
     binder::Status res = ok();
-    if (!clear_reference_profile(pkgname)) {
+    if (!clear_reference_profile(packageName)) {
         res = error("Failed to clear reference profile for " + packageName);
     }
-    if (!clear_current_profiles(pkgname)) {
+    if (!clear_current_profiles(packageName)) {
         res = error("Failed to clear current profiles for " + packageName);
     }
     return res;
@@ -477,7 +476,7 @@
             }
         }
         if (!only_cache) {
-            if (!clear_current_profile(pkgname, userId)) {
+            if (!clear_current_profile(packageName, userId)) {
                 res = error("Failed to clear current profile for " + packageName);
             }
         }
@@ -485,13 +484,13 @@
     return res;
 }
 
-static int destroy_app_reference_profile(const char *pkgname) {
+static int destroy_app_reference_profile(const std::string& pkgname) {
     return delete_dir_contents_and_dir(
         create_data_ref_profile_package_path(pkgname),
         /*ignore_if_missing*/ true);
 }
 
-static int destroy_app_current_profiles(const char *pkgname, userid_t userid) {
+static int destroy_app_current_profiles(const std::string& pkgname, userid_t userid) {
     return delete_dir_contents_and_dir(
         create_data_user_profile_package_path(userid, pkgname),
         /*ignore_if_missing*/ true);
@@ -502,15 +501,14 @@
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
     std::lock_guard<std::recursive_mutex> lock(mLock);
 
-    const char* pkgname = packageName.c_str();
     binder::Status res = ok();
     std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
     for (auto user : users) {
-        if (destroy_app_current_profiles(pkgname, user) != 0) {
+        if (destroy_app_current_profiles(packageName, user) != 0) {
             res = error("Failed to destroy current profiles for " + packageName);
         }
     }
-    if (destroy_app_reference_profile(pkgname) != 0) {
+    if (destroy_app_reference_profile(packageName) != 0) {
         res = error("Failed to destroy reference profile for " + packageName);
     }
     return res;
@@ -538,11 +536,11 @@
         if (delete_dir_contents_and_dir(path) != 0) {
             res = error("Failed to delete " + path);
         }
-        destroy_app_current_profiles(pkgname, userId);
+        destroy_app_current_profiles(packageName, userId);
         // TODO(calin): If the package is still installed by other users it's probably
         // beneficial to keep the reference profile around.
         // Verify if it's ok to do that.
-        destroy_app_reference_profile(pkgname);
+        destroy_app_reference_profile(packageName);
     }
     return res;
 }
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 0fb207b..58b9d2c 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -101,19 +101,19 @@
     return truncated;
 }
 
-bool clear_reference_profile(const char* pkgname) {
+bool clear_reference_profile(const std::string& pkgname) {
     std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname);
     std::string reference_profile = create_primary_profile(reference_profile_dir);
     return clear_profile(reference_profile);
 }
 
-bool clear_current_profile(const char* pkgname, userid_t user) {
+bool clear_current_profile(const std::string& pkgname, userid_t user) {
     std::string profile_dir = create_data_user_profile_package_path(user, pkgname);
     std::string profile = create_primary_profile(profile_dir);
     return clear_profile(profile);
 }
 
-bool clear_current_profiles(const char* pkgname) {
+bool clear_current_profiles(const std::string& pkgname) {
     bool success = true;
     std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
     for (auto user : users) {
@@ -512,12 +512,12 @@
     return profile_fd;
 }
 
-static fd_t open_primary_profile_file(userid_t user, const char* pkgname) {
+static fd_t open_primary_profile_file(userid_t user, const std::string& pkgname) {
     std::string profile_dir = create_data_user_profile_package_path(user, pkgname);
     return open_primary_profile_file_from_dir(profile_dir, O_RDONLY);
 }
 
-static fd_t open_reference_profile(uid_t uid, const char* pkgname, bool read_write) {
+static fd_t open_reference_profile(uid_t uid, const std::string& pkgname, bool read_write) {
     std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname);
     int flags = read_write ? O_RDWR | O_CREAT : O_RDONLY;
     fd_t fd = open_primary_profile_file_from_dir(reference_profile_dir, flags);
@@ -534,7 +534,7 @@
     return fd;
 }
 
-static void open_profile_files(uid_t uid, const char* pkgname,
+static void open_profile_files(uid_t uid, const std::string& pkgname,
             /*out*/ std::vector<fd_t>* profiles_fd, /*out*/ fd_t* reference_profile_fd) {
     // Open the reference profile in read-write mode as profman might need to save the merge.
     *reference_profile_fd = open_reference_profile(uid, pkgname, /*read_write*/ true);
@@ -614,7 +614,7 @@
 // a re-compilation of the package.
 // If the return value is true all the current profiles would have been merged into
 // the reference profiles accessible with open_reference_profile().
-bool analyse_profiles(uid_t uid, const char* pkgname) {
+bool analyse_profiles(uid_t uid, const std::string& pkgname) {
     std::vector<fd_t> profiles_fd;
     fd_t reference_profile_fd = -1;
     open_profile_files(uid, pkgname, &profiles_fd, &reference_profile_fd);
@@ -628,8 +628,6 @@
         return false;
     }
 
-    ALOGV("PROFMAN (MERGE): --- BEGIN '%s' ---\n", pkgname);
-
     pid_t pid = fork();
     if (pid == 0) {
         /* child -- drop privileges before continuing */
@@ -740,12 +738,10 @@
     }
 }
 
-bool dump_profiles(int32_t uid, const char* pkgname, const char* code_paths) {
+bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths) {
     std::vector<fd_t> profile_fds;
     fd_t reference_profile_fd = -1;
-    std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname);
-
-    ALOGV("PROFMAN (DUMP): --- BEGIN '%s' ---\n", pkgname);
+    std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname.c_str());
 
     open_profile_files(uid, pkgname, &profile_fds, &reference_profile_fd);
 
@@ -753,7 +749,7 @@
     const bool has_profiles = !profile_fds.empty();
 
     if (!has_reference_profile && !has_profiles) {
-        ALOGE("profman dump: no profiles to dump for '%s'", pkgname);
+        LOG(ERROR)  << "profman dump: no profiles to dump for " << pkgname;
         return false;
     }
 
@@ -1105,8 +1101,8 @@
 // Opens the vdex files and assigns the input fd to in_vdex_wrapper_fd and the output fd to
 // out_vdex_wrapper_fd. Returns true for success or false in case of errors.
 bool open_vdex_files(const char* apk_path, const char* out_oat_path, int dexopt_needed,
-        const char* instruction_set, bool is_public, int uid, bool is_secondary_dex,
-        Dex2oatFileWrapper* in_vdex_wrapper_fd,
+        const char* instruction_set, bool is_public, bool profile_guided,
+        int uid, bool is_secondary_dex, Dex2oatFileWrapper* in_vdex_wrapper_fd,
         Dex2oatFileWrapper* out_vdex_wrapper_fd) {
     CHECK(in_vdex_wrapper_fd != nullptr);
     CHECK(out_vdex_wrapper_fd != nullptr);
@@ -1116,7 +1112,9 @@
     int dexopt_action = abs(dexopt_needed);
     bool is_odex_location = dexopt_needed < 0;
     std::string in_vdex_path_str;
-    if (dexopt_action != DEX2OAT_FROM_SCRATCH) {
+    // Disable passing an input vdex when the compilation is profile-guided. The dexlayout
+    // optimization in dex2oat is incompatible with it. b/35872504.
+    if (dexopt_action != DEX2OAT_FROM_SCRATCH && !profile_guided) {
         // Open the possibly existing vdex. If none exist, we pass -1 to dex2oat for input-vdex-fd.
         const char* path = nullptr;
         if (is_odex_location) {
@@ -1135,7 +1133,7 @@
             return false;
         }
         if (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE) {
-            // When we dex2oat because iof boot image change, we are going to update
+            // When we dex2oat because of boot image change, we are going to update
             // in-place the vdex file.
             in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDWR, 0));
         } else {
@@ -1449,8 +1447,8 @@
     // Open vdex files.
     Dex2oatFileWrapper in_vdex_fd;
     Dex2oatFileWrapper out_vdex_fd;
-    if (!open_vdex_files(dex_path, out_oat_path, dexopt_needed, instruction_set, is_public, uid,
-            is_secondary_dex, &in_vdex_fd, &out_vdex_fd)) {
+    if (!open_vdex_files(dex_path, out_oat_path, dexopt_needed, instruction_set, is_public,
+            profile_guided, uid, is_secondary_dex, &in_vdex_fd, &out_vdex_fd)) {
         return -1;
     }
 
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index 7bb6eee..fab4d94 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -34,14 +34,14 @@
 
 typedef int fd_t;
 
-bool clear_reference_profile(const char* pkgname);
-bool clear_current_profile(const char* pkgname, userid_t user);
-bool clear_current_profiles(const char* pkgname);
+bool clear_reference_profile(const std::string& pkgname);
+bool clear_current_profile(const std::string& pkgname, userid_t user);
+bool clear_current_profiles(const std::string& pkgname);
 
 bool move_ab(const char* apk_path, const char* instruction_set, const char* output_path);
 
-bool analyse_profiles(uid_t uid, const char* pkgname);
-bool dump_profiles(int32_t uid, const char* pkgname, const char* code_paths);
+bool analyse_profiles(uid_t uid, const std::string& pkgname);
+bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths);
 
 bool delete_odex(const char* apk_path, const char* instruction_set, const char* output_path);
 
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 947cc0d..940046f 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -35,6 +35,8 @@
 #define TEST_SYSTEM_DIR1 "/system/app/"
 #define TEST_SYSTEM_DIR2 "/vendor/app/"
 
+#define TEST_PROFILE_DIR "/data/misc/profiles"
+
 #define REALLY_LONG_APP_NAME "com.example." \
         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." \
         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." \
@@ -74,6 +76,9 @@
 
         android_system_dirs.dirs[1].path = (char*) TEST_SYSTEM_DIR2;
         android_system_dirs.dirs[1].len = strlen(TEST_SYSTEM_DIR2);
+
+        android_profiles_dir.path = (char*) TEST_PROFILE_DIR;
+        android_profiles_dir.len = strlen(TEST_PROFILE_DIR);
     }
 
     virtual void TearDown() {
@@ -317,6 +322,7 @@
     size_t pkgnameSize = PKG_NAME_MAX;
     char pkgname[pkgnameSize + 1];
     memset(pkgname, 'a', pkgnameSize);
+    pkgname[1] = '.';
     pkgname[pkgnameSize] = '\0';
 
     EXPECT_EQ(0, create_pkg_path(path, pkgname, "", 0))
@@ -329,19 +335,6 @@
              << "Package path should be a really long string of a's";
 }
 
-TEST_F(UtilsTest, CreatePkgPath_LongPkgNameFail) {
-    char path[PKG_PATH_MAX];
-
-    // Create long packagename of "aaaaa..."
-    size_t pkgnameSize = PKG_NAME_MAX + 1;
-    char pkgname[pkgnameSize + 1];
-    memset(pkgname, 'a', pkgnameSize);
-    pkgname[pkgnameSize] = '\0';
-
-    EXPECT_EQ(-1, create_pkg_path(path, pkgname, "", 0))
-            << "Should return error because package name is too long.";
-}
-
 TEST_F(UtilsTest, CreatePkgPath_LongPostfixFail) {
     char path[PKG_PATH_MAX];
 
@@ -508,5 +501,50 @@
             create_data_user_ce_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example"));
 }
 
+TEST_F(UtilsTest, IsValidPackageName) {
+    EXPECT_EQ(true, is_valid_package_name("android"));
+    EXPECT_EQ(true, is_valid_package_name("com.example"));
+    EXPECT_EQ(true, is_valid_package_name("com.example-1"));
+    EXPECT_EQ(true, is_valid_package_name("com.example-1024"));
+    EXPECT_EQ(true, is_valid_package_name("com.example.foo---KiJFj4a_tePVw95pSrjg=="));
+    EXPECT_EQ(true, is_valid_package_name("really_LONG.a1234.package_name"));
+
+    EXPECT_EQ(false, is_valid_package_name("1234.package"));
+    EXPECT_EQ(false, is_valid_package_name("com.1234.package"));
+    EXPECT_EQ(false, is_valid_package_name(""));
+    EXPECT_EQ(false, is_valid_package_name("."));
+    EXPECT_EQ(false, is_valid_package_name(".."));
+    EXPECT_EQ(false, is_valid_package_name("../"));
+    EXPECT_EQ(false, is_valid_package_name("com.example/../com.evil/"));
+    EXPECT_EQ(false, is_valid_package_name("com.example-1/../com.evil/"));
+    EXPECT_EQ(false, is_valid_package_name("/com.evil"));
+}
+
+TEST_F(UtilsTest, CreateDataUserProfilePath) {
+    EXPECT_EQ("/data/misc/profiles/cur/0", create_data_user_profile_path(0));
+    EXPECT_EQ("/data/misc/profiles/cur/1", create_data_user_profile_path(1));
+}
+
+TEST_F(UtilsTest, CreateDataUserProfilePackagePath) {
+    EXPECT_EQ("/data/misc/profiles/cur/0/com.example",
+            create_data_user_profile_package_path(0, "com.example"));
+    EXPECT_EQ("/data/misc/profiles/cur/1/com.example",
+            create_data_user_profile_package_path(1, "com.example"));
+}
+
+TEST_F(UtilsTest, CreateDataRefProfilePath) {
+    EXPECT_EQ("/data/misc/profiles/ref", create_data_ref_profile_path());
+}
+
+TEST_F(UtilsTest, CreateDataRefProfilePackagePath) {
+    EXPECT_EQ("/data/misc/profiles/ref/com.example",
+        create_data_ref_profile_package_path("com.example"));
+}
+
+TEST_F(UtilsTest, CreatePrimaryProfile) {
+    EXPECT_EQ("/data/misc/profiles/ref/com.example/primary.prof",
+        create_primary_profile("/data/misc/profiles/ref/com.example"));
+}
+
 }  // namespace installd
 }  // namespace android
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 7c40ef7..a6fa656 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -217,18 +217,18 @@
     return StringPrintf("%s/cur/%u", android_profiles_dir.path, userid);
 }
 
-std::string create_data_user_profile_package_path(userid_t user, const char* package_name) {
-    check_package_name(package_name);
-    return StringPrintf("%s/%s",create_data_user_profile_path(user).c_str(), package_name);
+std::string create_data_user_profile_package_path(userid_t user, const std::string& package_name) {
+    check_package_name(package_name.c_str());
+    return StringPrintf("%s/%s",create_data_user_profile_path(user).c_str(), package_name.c_str());
 }
 
 std::string create_data_ref_profile_path() {
     return StringPrintf("%s/ref", android_profiles_dir.path);
 }
 
-std::string create_data_ref_profile_package_path(const char* package_name) {
-    check_package_name(package_name);
-    return StringPrintf("%s/ref/%s", android_profiles_dir.path, package_name);
+std::string create_data_ref_profile_package_path(const std::string& package_name) {
+    check_package_name(package_name.c_str());
+    return StringPrintf("%s/ref/%s", android_profiles_dir.path, package_name.c_str());
 }
 
 std::string create_data_dalvik_cache_path() {
@@ -346,46 +346,42 @@
  * 0 on success.
  */
 bool is_valid_package_name(const std::string& packageName) {
-    const char* pkgname = packageName.c_str();
-    const char *x = pkgname;
-    int alpha = -1;
+    // This logic is borrowed from PackageParser.java
+    bool hasSep = false;
+    bool front = true;
 
-    if (strlen(pkgname) > PKG_NAME_MAX) {
+    auto it = packageName.begin();
+    for (; it != packageName.end() && *it != '-'; it++) {
+        char c = *it;
+        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
+            front = false;
+            continue;
+        }
+        if (!front) {
+            if ((c >= '0' && c <= '9') || c == '_') {
+                continue;
+            }
+        }
+        if (c == '.') {
+            hasSep = true;
+            front = true;
+            continue;
+        }
+        LOG(WARNING) << "Bad package character " << c << " in " << packageName;
         return false;
     }
 
-    while (*x) {
-        if (isalnum(*x) || (*x == '_')) {
-                /* alphanumeric or underscore are fine */
-        } else if (*x == '.') {
-            if ((x == pkgname) || (x[1] == '.') || (x[1] == 0)) {
-                    /* periods must not be first, last, or doubled */
-                ALOGE("invalid package name '%s'\n", pkgname);
-                return false;
-            }
-        } else if (*x == '-') {
-            /* Suffix -X is fine to let versioning of packages.
-               But whatever follows should be alphanumeric.*/
-            alpha = 1;
-        } else {
-                /* anything not A-Z, a-z, 0-9, _, or . is invalid */
-            ALOGE("invalid package name '%s'\n", pkgname);
-            return false;
-        }
-
-        x++;
+    if (front) {
+        LOG(WARNING) << "Missing separator in " << packageName;
+        return false;
     }
 
-    if (alpha == 1) {
-        // Skip current character
-        x++;
-        while (*x) {
-            if (!isalnum(*x)) {
-                ALOGE("invalid package name '%s' should include only numbers after -\n", pkgname);
-                return false;
-            }
-            x++;
-        }
+    for (; it != packageName.end(); it++) {
+        char c = *it;
+        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) continue;
+        if ((c >= '0' && c <= '9') || c == '_' || c == '-' || c == '=') continue;
+        LOG(WARNING) << "Bad suffix character " << c << " in " << packageName;
+        return false;
     }
 
     return true;
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 425b675..8090b18 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -95,10 +95,10 @@
 std::string create_data_misc_legacy_path(userid_t userid);
 
 std::string create_data_user_profile_path(userid_t userid);
-std::string create_data_user_profile_package_path(userid_t user, const char* package_name);
+std::string create_data_user_profile_package_path(userid_t user, const std::string& package_name);
 
 std::string create_data_ref_profile_path();
-std::string create_data_ref_profile_package_path(const char* package_name);
+std::string create_data_ref_profile_package_path(const std::string& package_name);
 
 std::string create_data_dalvik_cache_path();