summaryrefslogtreecommitdiff
path: root/cmds/installd/utils.cpp
diff options
context:
space:
mode:
author Treehugger Robot <treehugger-gerrit@google.com> 2018-02-15 16:17:06 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2018-02-15 16:17:06 +0000
commiteb7ea99ab2e29a4593517d0de271ff76e044c13b (patch)
tree52152dded31881b890e312510872df59fb17faa3 /cmds/installd/utils.cpp
parent1bd06e18901ac449e90522673f9f3e1bd4e2aebc (diff)
parent0c609c25d69e57e2cf906039d2a7b69de5f78bde (diff)
Merge changes from topic "cp_calin_framework_2017"
* changes: Fix otapreopt parameters reading Fix profileSnapshot test in installd. Allow public profile compilation for primary apks [installd] Pass .dm files to dexopt Replace profman invocation for prepareAppProfiles Refactor argument parsing in ota preopt Extract the otapreopt parameters in their own class and add tests Fix profile guided compilation for secondaries and add more tests [installd] Create profile snaphots for boot image [installd] Extend profile operations to take the profile name [installd] Prepare profiles for app code paths Prepare installd to handle profiles per code path Add Installd IPC to compute the SHA256 of a seconday dex file.
Diffstat (limited to 'cmds/installd/utils.cpp')
-rw-r--r--cmds/installd/utils.cpp98
1 files changed, 86 insertions, 12 deletions
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 61c9c8ff08..a8c32ed2a5 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -26,7 +26,9 @@
#include <sys/statvfs.h>
#include <android-base/logging.h>
+#include <android-base/strings.h>
#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
#include <cutils/fs.h>
#include <cutils/properties.h>
#include <log/log.h>
@@ -40,7 +42,9 @@
#define DEBUG_XATTRS 0
+using android::base::EndsWith;
using android::base::StringPrintf;
+using android::base::unique_fd;
namespace android {
namespace installd {
@@ -235,7 +239,6 @@ std::string create_data_dalvik_cache_path() {
// Keep profile paths in sync with ActivityThread and LoadedApk.
const std::string PROFILE_EXT = ".prof";
const std::string CURRENT_PROFILE_EXT = ".cur";
-const std::string PRIMARY_PROFILE_NAME = "primary" + PROFILE_EXT;
const std::string SNAPSHOT_PROFILE_EXT = ".snapshot";
// Gets the parent directory and the file name for the given secondary dex path.
@@ -256,8 +259,8 @@ static bool get_secondary_dex_location(const std::string& dex_path,
return true;
}
-std::string create_current_profile_path(userid_t user, const std::string& location,
- bool is_secondary_dex) {
+std::string create_current_profile_path(userid_t user, const std::string& package_name,
+ const std::string& location, bool is_secondary_dex) {
if (is_secondary_dex) {
// Secondary dex current profiles are stored next to the dex files under the oat folder.
std::string dex_dir;
@@ -269,12 +272,14 @@ std::string create_current_profile_path(userid_t user, const std::string& locati
PROFILE_EXT.c_str());
} else {
// Profiles for primary apks are under /data/misc/profiles/cur.
- std::string profile_dir = create_primary_current_profile_package_dir_path(user, location);
- return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME.c_str());
+ std::string profile_dir = create_primary_current_profile_package_dir_path(
+ user, package_name);
+ return StringPrintf("%s/%s", profile_dir.c_str(), location.c_str());
}
}
-std::string create_reference_profile_path(const std::string& location, bool is_secondary_dex) {
+std::string create_reference_profile_path(const std::string& package_name,
+ const std::string& location, bool is_secondary_dex) {
if (is_secondary_dex) {
// Secondary dex reference profiles are stored next to the dex files under the oat folder.
std::string dex_dir;
@@ -285,16 +290,15 @@ std::string create_reference_profile_path(const std::string& location, bool is_s
dex_dir.c_str(), dex_name.c_str(), PROFILE_EXT.c_str());
} else {
// Reference profiles for primary apks are stored in /data/misc/profile/ref.
- std::string profile_dir = create_primary_reference_profile_package_dir_path(location);
- return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME.c_str());
+ std::string profile_dir = create_primary_reference_profile_package_dir_path(package_name);
+ return StringPrintf("%s/%s", profile_dir.c_str(), location.c_str());
}
}
std::string create_snapshot_profile_path(const std::string& package,
- const std::string& code_path ATTRIBUTE_UNUSED) {
- // TODD(calin): code_path is ignored for now. It will be used when each split gets its own
- // profile file.
- std::string ref_profile = create_reference_profile_path(package, /*is_secondary_dex*/ false);
+ const std::string& profile_name) {
+ std::string ref_profile = create_reference_profile_path(package, profile_name,
+ /*is_secondary_dex*/ false);
return ref_profile + SNAPSHOT_PROFILE_EXT;
}
@@ -984,5 +988,75 @@ int prepare_app_cache_dir(const std::string& parent, const char* name, mode_t ta
return 0;
}
+// Collect all non empty profiles from the given directory and puts then into profile_paths.
+// The profiles are identified based on PROFILE_EXT extension.
+// If a subdirectory or profile file cannot be opened the method logs a warning and moves on.
+// It returns true if there were no errors at all, and false otherwise.
+static bool collect_profiles(DIR* d,
+ const std::string& current_path,
+ std::vector<std::string>* profiles_paths) {
+ int32_t dir_fd = dirfd(d);
+ if (dir_fd < 0) {
+ return false;
+ }
+
+ bool result = true;
+ struct dirent* dir_entry;
+ while ((dir_entry = readdir(d))) {
+ std::string name = dir_entry->d_name;
+ std::string local_path = current_path + "/" + name;
+
+ if (dir_entry->d_type == DT_REG) {
+ // Check if this is a non empty profile file.
+ if (EndsWith(name, PROFILE_EXT)) {
+ struct stat st;
+ if (stat(local_path.c_str(), &st) != 0) {
+ PLOG(WARNING) << "Cannot stat local path " << local_path;
+ result = false;
+ continue;
+ } else if (st.st_size > 0) {
+ profiles_paths->push_back(local_path);
+ }
+ }
+ } else if (dir_entry->d_type == DT_DIR) {
+ // always skip "." and ".."
+ if (name == "." || name == "..") {
+ continue;
+ }
+
+ unique_fd subdir_fd(openat(dir_fd, name.c_str(),
+ O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC));
+ if (subdir_fd < 0) {
+ PLOG(WARNING) << "Could not open dir path " << local_path;
+ result = false;
+ continue;
+ }
+
+ DIR* subdir = fdopendir(subdir_fd);
+ if (subdir == NULL) {
+ PLOG(WARNING) << "Could not open dir path " << local_path;
+ result = false;
+ continue;
+ }
+ bool new_result = collect_profiles(subdir, local_path, profiles_paths);
+ result = result && new_result;
+ if (closedir(subdir) != 0) {
+ PLOG(WARNING) << "Could not close dir path " << local_path;
+ }
+ }
+ }
+
+ return result;
+}
+
+bool collect_profiles(std::vector<std::string>* profiles_paths) {
+ DIR* d = opendir(android_profiles_dir.c_str());
+ if (d == NULL) {
+ return false;
+ } else {
+ return collect_profiles(d, android_profiles_dir, profiles_paths);
+ }
+}
+
} // namespace installd
} // namespace android