Merge "Revert "Use arm instruction set with clang 7.0 LTO""
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 9dbbb77..e9758a0 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -56,7 +56,6 @@
using std::string;
#define MAX_SYS_FILES 10
-#define MAX_PACKAGES 16
const char* k_traceTagsProperty = "debug.atrace.tags.enableflags";
@@ -588,12 +587,6 @@
static void clearAppProperties()
{
- for (int i = 0; i < MAX_PACKAGES; i++) {
- std::string key = android::base::StringPrintf(k_traceAppsPropertyTemplate, i);
- if (!android::base::SetProperty(key, "")) {
- fprintf(stderr, "failed to clear system property: %s\n", key.c_str());
- }
- }
if (!android::base::SetProperty(k_traceAppsNumberProperty, "")) {
fprintf(stderr, "failed to clear system property: %s",
k_traceAppsNumberProperty);
@@ -607,11 +600,6 @@
int i = 0;
char* start = cmdline;
while (start != NULL) {
- if (i == MAX_PACKAGES) {
- fprintf(stderr, "error: only 16 packages could be traced at once\n");
- clearAppProperties();
- return false;
- }
char* end = strchr(start, ',');
if (end != NULL) {
*end = '\0';
@@ -1049,7 +1037,7 @@
fprintf(stderr, "usage: %s [options] [categories...]\n", cmd);
fprintf(stderr, "options include:\n"
" -a appname enable app-level tracing for a comma "
- "separated list of cmdlines\n"
+ "separated list of cmdlines; * is a wildcard matching any process\n"
" -b N use a trace buffer size of N KB\n"
" -c trace into a circular buffer\n"
" -f filename use the categories written in a file as space-separated\n"
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 89ce1e5..3ec0163 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -6,6 +6,9 @@
chmod 0222 /sys/kernel/debug/tracing/trace_marker
chmod 0222 /sys/kernel/tracing/trace_marker
+# Scheduler tracepoints require schedstats=enable
+ write /proc/sys/kernel/sched_schedstats 1
+
# Grant unix world read/write permissions to kernel tracepoints.
# Access control to these files is now entirely in selinux policy.
chmod 0666 /sys/kernel/debug/tracing/trace_clock
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index a641dbb..98ad138 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -180,7 +180,7 @@
continue;
}
- if (limit_by_mtime && st.st_mtime >= thirty_minutes_ago) {
+ if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
continue;
}
@@ -1585,6 +1585,7 @@
is_remote_mode = 1;
do_fb = 0;
} else if (ds.extra_options_ == "bugreportwear") {
+ do_start_service = true;
ds.update_progress_ = true;
} else if (ds.extra_options_ == "bugreporttelephony") {
telephony_only = true;
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 7d1537a..352cf0a 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -18,6 +18,7 @@
shared_libs: [
"libbase",
"libbinder",
+ "libcrypto",
"libcutils",
"liblog",
"liblogwrap",
@@ -91,4 +92,28 @@
],
}
+//
+// Static library for otapreopt used in testing
+//
+cc_library_static {
+ name: "libotapreoptparameters",
+ cflags: [
+ "-Wall",
+ "-Werror"
+ ],
+ clang: true,
+
+ srcs: [
+ "otapreopt_parameters.cpp"],
+
+ export_include_dirs: ["."],
+
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "liblog",
+ "libutils",
+ ],
+}
+
subdirs = ["tests"]
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index 1d21b3c..a4f95da 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -23,10 +23,11 @@
LOCAL_CFLAGS += -DART_BASE_ADDRESS_MIN_DELTA=$(LOCAL_LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA)
LOCAL_CFLAGS += -DART_BASE_ADDRESS_MAX_DELTA=$(LOCAL_LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA)
-LOCAL_SRC_FILES := otapreopt.cpp globals.cpp utils.cpp dexopt.cpp
+LOCAL_SRC_FILES := otapreopt.cpp otapreopt_parameters.cpp globals.cpp utils.cpp dexopt.cpp
LOCAL_HEADER_LIBRARIES := dex2oat_headers
LOCAL_SHARED_LIBRARIES := \
libbase \
+ libcrypto \
libcutils \
liblog \
liblogwrap \
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index b0661c5..68acc69 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -103,6 +103,7 @@
}
static binder::Status exception(uint32_t code, const std::string& msg) {
+ LOG(ERROR) << msg << " (" << code << ")";
return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
}
@@ -366,13 +367,6 @@
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);
@@ -522,16 +516,17 @@
}
-binder::Status InstalldNativeService::clearAppProfiles(const std::string& packageName) {
+binder::Status InstalldNativeService::clearAppProfiles(const std::string& packageName,
+ const std::string& profileName) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
std::lock_guard<std::recursive_mutex> lock(mLock);
binder::Status res = ok();
- if (!clear_primary_reference_profile(packageName)) {
+ if (!clear_primary_reference_profile(packageName, profileName)) {
res = error("Failed to clear reference profile for " + packageName);
}
- if (!clear_primary_current_profiles(packageName)) {
+ if (!clear_primary_current_profiles(packageName, profileName)) {
res = error("Failed to clear current profiles for " + packageName);
}
return res;
@@ -581,11 +576,6 @@
res = error("Failed to delete contents of " + path);
}
}
- if (!only_cache) {
- if (!clear_primary_current_profile(packageName, userId)) {
- res = error("Failed to clear current profile for " + packageName);
- }
- }
}
return res;
}
@@ -1833,68 +1823,74 @@
// Dumps the contents of a profile file, using pkgname's dex files for pretty
// printing the result.
binder::Status InstalldNativeService::dumpProfiles(int32_t uid, const std::string& packageName,
- const std::string& codePaths, bool* _aidl_return) {
+ const std::string& profileName, const std::string& codePath, bool* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
std::lock_guard<std::recursive_mutex> lock(mLock);
- const char* pkgname = packageName.c_str();
- const char* code_paths = codePaths.c_str();
-
- *_aidl_return = dump_profiles(uid, pkgname, code_paths);
+ *_aidl_return = dump_profiles(uid, packageName, profileName, codePath);
return ok();
}
// Copy the contents of a system profile over the data profile.
binder::Status InstalldNativeService::copySystemProfile(const std::string& systemProfile,
- int32_t packageUid, const std::string& packageName, bool* _aidl_return) {
+ int32_t packageUid, const std::string& packageName, const std::string& profileName,
+ bool* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
std::lock_guard<std::recursive_mutex> lock(mLock);
- *_aidl_return = copy_system_profile(systemProfile, packageUid, packageName);
+ *_aidl_return = copy_system_profile(systemProfile, packageUid, packageName, profileName);
return ok();
}
// TODO: Consider returning error codes.
binder::Status InstalldNativeService::mergeProfiles(int32_t uid, const std::string& packageName,
- bool* _aidl_return) {
+ const std::string& profileName, bool* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
std::lock_guard<std::recursive_mutex> lock(mLock);
- *_aidl_return = analyze_primary_profiles(uid, packageName);
+ *_aidl_return = analyze_primary_profiles(uid, packageName, profileName);
return ok();
}
binder::Status InstalldNativeService::createProfileSnapshot(int32_t appId,
- const std::string& packageName, const std::string& codePath, bool* _aidl_return) {
+ const std::string& packageName, const std::string& profileName,
+ const std::string& classpath, bool* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
std::lock_guard<std::recursive_mutex> lock(mLock);
- *_aidl_return = create_profile_snapshot(appId, packageName, codePath);
+ *_aidl_return = create_profile_snapshot(appId, packageName, profileName, classpath);
return ok();
}
binder::Status InstalldNativeService::destroyProfileSnapshot(const std::string& packageName,
- const std::string& codePath) {
+ const std::string& profileName) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
std::lock_guard<std::recursive_mutex> lock(mLock);
- std::string snapshot = create_snapshot_profile_path(packageName, codePath);
+ std::string snapshot = create_snapshot_profile_path(packageName, profileName);
if ((unlink(snapshot.c_str()) != 0) && (errno != ENOENT)) {
- return error("Failed to destroy profile snapshot for " + packageName + ":" + codePath);
+ return error("Failed to destroy profile snapshot for " + packageName + ":" + profileName);
}
return ok();
}
+static const char* getCStr(const std::unique_ptr<std::string>& data,
+ const char* default_value = nullptr) {
+ return data == nullptr ? default_value : data->c_str();
+}
binder::Status InstalldNativeService::dexopt(const std::string& apkPath, int32_t uid,
const std::unique_ptr<std::string>& packageName, const std::string& instructionSet,
int32_t dexoptNeeded, const std::unique_ptr<std::string>& outputPath, int32_t dexFlags,
const std::string& compilerFilter, const std::unique_ptr<std::string>& uuid,
const std::unique_ptr<std::string>& classLoaderContext,
- const std::unique_ptr<std::string>& seInfo, bool downgrade, int32_t targetSdkVersion) {
+ const std::unique_ptr<std::string>& seInfo, bool downgrade, int32_t targetSdkVersion,
+ const std::unique_ptr<std::string>& profileName,
+ const std::unique_ptr<std::string>& dexMetadataPath,
+ const std::unique_ptr<std::string>& compilationReason) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
if (packageName && *packageName != "*") {
@@ -1903,16 +1899,19 @@
std::lock_guard<std::recursive_mutex> lock(mLock);
const char* apk_path = apkPath.c_str();
- const char* pkgname = packageName ? packageName->c_str() : "*";
+ const char* pkgname = getCStr(packageName, "*");
const char* instruction_set = instructionSet.c_str();
- const char* oat_dir = outputPath ? outputPath->c_str() : nullptr;
+ const char* oat_dir = getCStr(outputPath);
const char* compiler_filter = compilerFilter.c_str();
- const char* volume_uuid = uuid ? uuid->c_str() : nullptr;
- const char* class_loader_context = classLoaderContext ? classLoaderContext->c_str() : nullptr;
- const char* se_info = seInfo ? seInfo->c_str() : nullptr;
+ const char* volume_uuid = getCStr(uuid);
+ const char* class_loader_context = getCStr(classLoaderContext);
+ const char* se_info = getCStr(seInfo);
+ const char* profile_name = getCStr(profileName);
+ const char* dm_path = getCStr(dexMetadataPath);
+ const char* compilation_reason = getCStr(compilationReason);
int res = android::installd::dexopt(apk_path, uid, pkgname, instruction_set, dexoptNeeded,
oat_dir, dexFlags, compiler_filter, volume_uuid, class_loader_context, se_info,
- downgrade, targetSdkVersion);
+ downgrade, targetSdkVersion, profile_name, dm_path, compilation_reason);
return res ? error(res, "Failed to dexopt") : ok();
}
@@ -2379,6 +2378,22 @@
return result ? ok() : error();
}
+binder::Status InstalldNativeService::hashSecondaryDexFile(
+ const std::string& dexPath, const std::string& packageName, int32_t uid,
+ const std::unique_ptr<std::string>& volumeUuid, int32_t storageFlag,
+ std::vector<uint8_t>* _aidl_return) {
+ ENFORCE_UID(AID_SYSTEM);
+ CHECK_ARGUMENT_UUID(volumeUuid);
+ CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+
+ // mLock is not taken here since we will never modify the file system.
+ // If a file is modified just as we are reading it this may result in an
+ // anomalous hash, but that's ok.
+ bool result = android::installd::hash_secondary_dex_file(
+ dexPath, packageName, uid, volumeUuid, storageFlag, _aidl_return);
+ return result ? ok() : error();
+}
+
binder::Status InstalldNativeService::invalidateMounts() {
ENFORCE_UID(AID_SYSTEM);
std::lock_guard<std::recursive_mutex> lock(mMountsLock);
@@ -2457,5 +2472,17 @@
return ok();
}
+binder::Status InstalldNativeService::prepareAppProfile(const std::string& packageName,
+ int32_t userId, int32_t appId, const std::string& profileName, const std::string& codePath,
+ const std::unique_ptr<std::string>& dexMetadata, bool* _aidl_return) {
+ ENFORCE_UID(AID_SYSTEM);
+ CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ std::lock_guard<std::recursive_mutex> lock(mLock);
+
+ *_aidl_return = prepare_app_profile(packageName, userId, appId, profileName, codePath,
+ dexMetadata);
+ return ok();
+}
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 93b59ed..1648603 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -85,22 +85,26 @@
const std::string& compilerFilter, const std::unique_ptr<std::string>& uuid,
const std::unique_ptr<std::string>& classLoaderContext,
const std::unique_ptr<std::string>& seInfo, bool downgrade,
- int32_t targetSdkVersion);
+ int32_t targetSdkVersion, const std::unique_ptr<std::string>& profileName,
+ const std::unique_ptr<std::string>& dexMetadataPath,
+ const std::unique_ptr<std::string>& compilationReason);
binder::Status rmdex(const std::string& codePath, const std::string& instructionSet);
- binder::Status mergeProfiles(int32_t uid, const std::string& packageName, bool* _aidl_return);
+ binder::Status mergeProfiles(int32_t uid, const std::string& packageName,
+ const std::string& profileName, bool* _aidl_return);
binder::Status dumpProfiles(int32_t uid, const std::string& packageName,
- const std::string& codePaths, bool* _aidl_return);
+ const std::string& profileName, const std::string& codePath, bool* _aidl_return);
binder::Status copySystemProfile(const std::string& systemProfile,
- int32_t uid, const std::string& packageName, bool* _aidl_return);
- binder::Status clearAppProfiles(const std::string& packageName);
+ int32_t uid, const std::string& packageName, const std::string& profileName,
+ bool* _aidl_return);
+ binder::Status clearAppProfiles(const std::string& packageName, const std::string& profileName);
binder::Status destroyAppProfiles(const std::string& packageName);
binder::Status createProfileSnapshot(int32_t appId, const std::string& packageName,
- const std::string& codePath, bool* _aidl_return);
+ const std::string& profileName, const std::string& classpath, bool* _aidl_return);
binder::Status destroyProfileSnapshot(const std::string& packageName,
- const std::string& codePath);
+ const std::string& profileName);
binder::Status idmap(const std::string& targetApkPath, const std::string& overlayApkPath,
int32_t uid);
@@ -123,11 +127,19 @@
binder::Status reconcileSecondaryDexFile(const std::string& dexPath,
const std::string& packageName, int32_t uid, const std::vector<std::string>& isa,
const std::unique_ptr<std::string>& volumeUuid, int32_t storage_flag, bool* _aidl_return);
+ binder::Status hashSecondaryDexFile(const std::string& dexPath,
+ const std::string& packageName, int32_t uid, const std::unique_ptr<std::string>& volumeUuid,
+ int32_t storageFlag, std::vector<uint8_t>* _aidl_return);
binder::Status invalidateMounts();
binder::Status isQuotaSupported(const std::unique_ptr<std::string>& volumeUuid,
bool* _aidl_return);
+ binder::Status prepareAppProfile(const std::string& packageName,
+ int32_t userId, int32_t appId, const std::string& profileName,
+ const std::string& codePath, const std::unique_ptr<std::string>& dexMetadata,
+ bool* _aidl_return);
+
private:
std::recursive_mutex mLock;
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 2c9c6bd..432751f 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -51,20 +51,24 @@
@nullable @utf8InCpp String outputPath, int dexFlags,
@utf8InCpp String compilerFilter, @nullable @utf8InCpp String uuid,
@nullable @utf8InCpp String sharedLibraries,
- @nullable @utf8InCpp String seInfo, boolean downgrade, int targetSdkVersion);
+ @nullable @utf8InCpp String seInfo, boolean downgrade, int targetSdkVersion,
+ @nullable @utf8InCpp String profileName,
+ @nullable @utf8InCpp String dexMetadataPath,
+ @nullable @utf8InCpp String compilationReason);
void rmdex(@utf8InCpp String codePath, @utf8InCpp String instructionSet);
- boolean mergeProfiles(int uid, @utf8InCpp String packageName);
- boolean dumpProfiles(int uid, @utf8InCpp String packageName, @utf8InCpp String codePaths);
+ boolean mergeProfiles(int uid, @utf8InCpp String packageName, @utf8InCpp String profileName);
+ boolean dumpProfiles(int uid, @utf8InCpp String packageName, @utf8InCpp String profileName,
+ @utf8InCpp String codePath);
boolean copySystemProfile(@utf8InCpp String systemProfile, int uid,
- @utf8InCpp String packageName);
- void clearAppProfiles(@utf8InCpp String packageName);
+ @utf8InCpp String packageName, @utf8InCpp String profileName);
+ void clearAppProfiles(@utf8InCpp String packageName, @utf8InCpp String profileName);
void destroyAppProfiles(@utf8InCpp String packageName);
boolean createProfileSnapshot(int appId, @utf8InCpp String packageName,
- @utf8InCpp String codePath);
- void destroyProfileSnapshot(@utf8InCpp String packageName, @utf8InCpp String codePath);
+ @utf8InCpp String profileName, @utf8InCpp String classpath);
+ void destroyProfileSnapshot(@utf8InCpp String packageName, @utf8InCpp String profileName);
void idmap(@utf8InCpp String targetApkPath, @utf8InCpp String overlayApkPath, int uid);
void removeIdmap(@utf8InCpp String overlayApkPath);
@@ -87,6 +91,13 @@
int uid, in @utf8InCpp String[] isas, @nullable @utf8InCpp String volume_uuid,
int storage_flag);
+ byte[] hashSecondaryDexFile(@utf8InCpp String dexPath, @utf8InCpp String pkgName,
+ int uid, @nullable @utf8InCpp String volumeUuid, int storageFlag);
+
void invalidateMounts();
boolean isQuotaSupported(@nullable @utf8InCpp String uuid);
+
+ boolean prepareAppProfile(@utf8InCpp String packageName,
+ int userId, int appId, @utf8InCpp String profileName, @utf8InCpp String codePath,
+ @nullable @utf8InCpp String dexMetadata);
}
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index f281010..9f1cd45 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -15,6 +15,7 @@
*/
#define LOG_TAG "installed"
+#include <array>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
@@ -27,6 +28,7 @@
#include <sys/wait.h>
#include <unistd.h>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
@@ -36,6 +38,7 @@
#include <cutils/properties.h>
#include <cutils/sched_policy.h>
#include <log/log.h> // TODO: Move everything to base/logging.
+#include <openssl/sha.h>
#include <private/android_filesystem_config.h>
#include <selinux/android.h>
#include <system/thread_defs.h>
@@ -46,8 +49,10 @@
#include "otapreopt_utils.h"
#include "utils.h"
-using android::base::StringPrintf;
using android::base::EndsWith;
+using android::base::ReadFully;
+using android::base::StringPrintf;
+using android::base::WriteFully;
using android::base::unique_fd;
namespace android {
@@ -132,37 +137,43 @@
}
// Clear the reference profile for the given location.
-// The location is the package name for primary apks or the dex path for secondary dex files.
-static bool clear_reference_profile(const std::string& location, bool is_secondary_dex) {
- return clear_profile(create_reference_profile_path(location, is_secondary_dex));
+// The location is the profile name for primary apks or the dex path for secondary dex files.
+static bool clear_reference_profile(const std::string& package_name, const std::string& location,
+ bool is_secondary_dex) {
+ return clear_profile(create_reference_profile_path(package_name, location, is_secondary_dex));
}
// Clear the reference profile for the given location.
-// The location is the package name for primary apks or the dex path for secondary dex files.
-static bool clear_current_profile(const std::string& pkgname, userid_t user,
- bool is_secondary_dex) {
- return clear_profile(create_current_profile_path(user, pkgname, is_secondary_dex));
+// The location is the profile name for primary apks or the dex path for secondary dex files.
+static bool clear_current_profile(const std::string& package_name, const std::string& location,
+ userid_t user, bool is_secondary_dex) {
+ return clear_profile(create_current_profile_path(user, package_name, location,
+ is_secondary_dex));
}
// Clear the reference profile for the primary apk of the given package.
-bool clear_primary_reference_profile(const std::string& pkgname) {
- return clear_reference_profile(pkgname, /*is_secondary_dex*/false);
+// The location is the profile name for primary apks or the dex path for secondary dex files.
+bool clear_primary_reference_profile(const std::string& package_name,
+ const std::string& location) {
+ return clear_reference_profile(package_name, location, /*is_secondary_dex*/false);
}
// Clear all current profile for the primary apk of the given package.
-bool clear_primary_current_profiles(const std::string& pkgname) {
+// The location is the profile name for primary apks or the dex path for secondary dex files.
+bool clear_primary_current_profiles(const std::string& package_name, const std::string& location) {
bool success = true;
// For secondary dex files, we don't really need the user but we use it for sanity checks.
std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
for (auto user : users) {
- success &= clear_current_profile(pkgname, user, /*is_secondary_dex*/false);
+ success &= clear_current_profile(package_name, location, user, /*is_secondary_dex*/false);
}
return success;
}
// Clear the current profile for the primary apk of the given package and user.
-bool clear_primary_current_profile(const std::string& pkgname, userid_t user) {
- return clear_current_profile(pkgname, user, /*is_secondary_dex*/false);
+bool clear_primary_current_profile(const std::string& package_name, const std::string& location,
+ userid_t user) {
+ return clear_current_profile(package_name, location, user, /*is_secondary_dex*/false);
}
static int split_count(const char *str)
@@ -212,7 +223,8 @@
const char* input_file_name, const char* output_file_name, int swap_fd,
const char* instruction_set, const char* compiler_filter,
bool debuggable, bool post_bootcomplete, bool background_job_compile, int profile_fd,
- const char* class_loader_context, int target_sdk_version, bool disable_hidden_api_checks) {
+ const char* class_loader_context, int target_sdk_version, bool enable_hidden_api_checks,
+ int dex_metadata_fd, const char* compilation_reason) {
static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
@@ -409,6 +421,11 @@
sprintf(base_dir, "--classpath-dir=%s", apk_dir.c_str());
}
+ std::string dex_metadata_fd_arg = "--dm-fd=" + std::to_string(dex_metadata_fd);
+
+ std::string compilation_reason_arg = compilation_reason == nullptr
+ ? ""
+ : std::string("--compilation-reason=") + compilation_reason;
ALOGV("Running %s in=%s out=%s\n", dex2oat_bin, relative_input_file_name, output_file_name);
@@ -439,7 +456,9 @@
+ (disable_cdex ? 1 : 0)
+ (generate_minidebug_info ? 1 : 0)
+ (target_sdk_version != 0 ? 2 : 0)
- + (disable_hidden_api_checks ? 2 : 0)];
+ + (enable_hidden_api_checks ? 2 : 0)
+ + (dex_metadata_fd > -1 ? 1 : 0)
+ + (compilation_reason != nullptr ? 1 : 0)];
int i = 0;
argv[i++] = dex2oat_bin;
argv[i++] = zip_fd_arg;
@@ -513,11 +532,18 @@
argv[i++] = RUNTIME_ARG;
argv[i++] = target_sdk_version_arg;
}
- if (disable_hidden_api_checks) {
+ if (enable_hidden_api_checks) {
argv[i++] = RUNTIME_ARG;
- argv[i++] = "-Xno-hidden-api-checks";
+ argv[i++] = "-Xhidden-api-checks";
}
+ if (dex_metadata_fd > -1) {
+ argv[i++] = dex_metadata_fd_arg.c_str();
+ }
+
+ if(compilation_reason != nullptr) {
+ argv[i++] = compilation_reason_arg.c_str();
+ }
// Do not add after dex2oat_flags, they should override others for debugging.
argv[i] = NULL;
@@ -633,29 +659,31 @@
return fd;
}
-static unique_fd open_current_profile(uid_t uid, userid_t user, const std::string& location,
- bool is_secondary_dex) {
- std::string profile = create_current_profile_path(user, location, is_secondary_dex);
+static unique_fd open_current_profile(uid_t uid, userid_t user, const std::string& package_name,
+ const std::string& location, bool is_secondary_dex) {
+ std::string profile = create_current_profile_path(user, package_name, location,
+ is_secondary_dex);
return open_profile(uid, profile, O_RDONLY);
}
-static unique_fd open_reference_profile(uid_t uid, const std::string& location, bool read_write,
- bool is_secondary_dex) {
- std::string profile = create_reference_profile_path(location, is_secondary_dex);
+static unique_fd open_reference_profile(uid_t uid, const std::string& package_name,
+ const std::string& location, bool read_write, bool is_secondary_dex) {
+ std::string profile = create_reference_profile_path(package_name, location, is_secondary_dex);
return open_profile(uid, profile, read_write ? (O_CREAT | O_RDWR) : O_RDONLY);
}
static unique_fd open_spnashot_profile(uid_t uid, const std::string& package_name,
- const std::string& code_path) {
- std::string profile = create_snapshot_profile_path(package_name, code_path);
+ const std::string& location) {
+ std::string profile = create_snapshot_profile_path(package_name, location);
return open_profile(uid, profile, O_CREAT | O_RDWR | O_TRUNC);
}
-static void open_profile_files(uid_t uid, const std::string& location, bool is_secondary_dex,
+static void open_profile_files(uid_t uid, const std::string& package_name,
+ const std::string& location, bool is_secondary_dex,
/*out*/ std::vector<unique_fd>* profiles_fd, /*out*/ unique_fd* 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, location, /*read_write*/ true,
- is_secondary_dex);
+ *reference_profile_fd = open_reference_profile(uid, package_name, location,
+ /*read_write*/ true, is_secondary_dex);
// For secondary dex files, we don't really need the user but we use it for sanity checks.
// Note: the user owning the dex file should be the current user.
@@ -666,7 +694,8 @@
users = get_known_users(/*volume_uuid*/ nullptr);
}
for (auto user : users) {
- unique_fd profile_fd = open_current_profile(uid, user, location, is_secondary_dex);
+ unique_fd profile_fd = open_current_profile(uid, user, package_name, location,
+ is_secondary_dex);
// Add to the lists only if both fds are valid.
if (profile_fd.get() >= 0) {
profiles_fd->push_back(std::move(profile_fd));
@@ -701,28 +730,45 @@
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) {
- static const size_t MAX_INT_LEN = 32;
+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());
- char profile_buf[strlen("--profile-file-fd=") + MAX_INT_LEN];
- for (size_t k = 0; k < profiles_fd.size(); k++) {
- sprintf(profile_buf, "--profile-file-fd=%d", profiles_fd[k].get());
- profile_args[k].assign(profile_buf);
+ if (copy_and_update) {
+ CHECK_EQ(1u, profile_fds.size());
+ CHECK(apk_fds != nullptr);
+ CHECK_EQ(1u, apk_fds->size());
}
- char reference_profile_arg[strlen("--reference-profile-file-fd=") + MAX_INT_LEN];
- sprintf(reference_profile_arg, "--reference-profile-file-fd=%d", reference_profile_fd.get());
+ 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());
+
+ std::vector<std::string> apk_args;
+ if (apk_fds != nullptr) {
+ for (size_t k = 0; k < apk_fds->size(); k++) {
+ apk_args.push_back("--apk-fd=" + std::to_string((*apk_fds)[k].get()));
+ }
+ }
// program name, reference profile fd, the final NULL and the profile fds
- const char* argv[3 + profiles_fd.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;
+ argv[i++] = reference_profile_arg.c_str();
for (size_t k = 0; k < profile_args.size(); k++) {
argv[i++] = profile_args[k].c_str();
}
+ 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;
@@ -731,16 +777,37 @@
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
// worth to recompile the given location.
// If the return value is true all the current profiles would have been merged into
// the reference profiles accessible with open_reference_profile().
-static bool analyze_profiles(uid_t uid, const std::string& location, bool is_secondary_dex) {
+static bool analyze_profiles(uid_t uid, const std::string& package_name,
+ const std::string& location, bool is_secondary_dex) {
std::vector<unique_fd> profiles_fd;
unique_fd reference_profile_fd;
- open_profile_files(uid, location, is_secondary_dex, &profiles_fd, &reference_profile_fd);
+ open_profile_files(uid, package_name, location, is_secondary_dex,
+ &profiles_fd, &reference_profile_fd);
if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) {
// Skip profile guided compilation because no profiles were found.
// Or if the reference profile info couldn't be opened.
@@ -802,13 +869,14 @@
if (should_clear_current_profiles) {
if (is_secondary_dex) {
// For secondary dex files, the owning user is the current user.
- clear_current_profile(location, multiuser_get_user_id(uid), is_secondary_dex);
+ clear_current_profile(package_name, location, multiuser_get_user_id(uid),
+ is_secondary_dex);
} else {
- clear_primary_current_profiles(location);
+ clear_primary_current_profiles(package_name, location);
}
}
if (should_clear_reference_profile) {
- clear_reference_profile(location, is_secondary_dex);
+ clear_reference_profile(package_name, location, is_secondary_dex);
}
return need_to_compile;
}
@@ -819,8 +887,9 @@
// worth to recompile 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 analyze_primary_profiles(uid_t uid, const std::string& pkgname) {
- return analyze_profiles(uid, pkgname, /*is_secondary_dex*/false);
+bool analyze_primary_profiles(uid_t uid, const std::string& package_name,
+ const std::string& profile_name) {
+ return analyze_profiles(uid, package_name, profile_name, /*is_secondary_dex*/false);
}
static void run_profman_dump(const std::vector<unique_fd>& profile_fds,
@@ -858,12 +927,14 @@
exit(68); /* only get here on exec failure */
}
-bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths) {
+bool dump_profiles(int32_t uid, const std::string& pkgname, const std::string& profile_name,
+ const std::string& code_path) {
std::vector<unique_fd> profile_fds;
unique_fd reference_profile_fd;
- std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname.c_str());
+ std::string out_file_name = StringPrintf("/data/misc/profman/%s-%s.txt",
+ pkgname.c_str(), profile_name.c_str());
- open_profile_files(uid, pkgname, /*is_secondary_dex*/false,
+ open_profile_files(uid, pkgname, profile_name, /*is_secondary_dex*/false,
&profile_fds, &reference_profile_fd);
const bool has_reference_profile = (reference_profile_fd.get() != -1);
@@ -877,22 +948,20 @@
unique_fd output_fd(open(out_file_name.c_str(),
O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0644));
if (fchmod(output_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
- ALOGE("installd cannot chmod '%s' dump_profile\n", out_file_name.c_str());
+ LOG(ERROR) << "installd cannot chmod file for dump_profile" << out_file_name;
return false;
}
- std::vector<std::string> code_full_paths = base::Split(code_paths, ";");
+
std::vector<std::string> dex_locations;
std::vector<unique_fd> apk_fds;
- for (const std::string& code_full_path : code_full_paths) {
- const char* full_path = code_full_path.c_str();
- unique_fd apk_fd(open(full_path, O_RDONLY | O_NOFOLLOW));
- if (apk_fd == -1) {
- ALOGE("installd cannot open '%s'\n", full_path);
- return false;
- }
- dex_locations.push_back(get_location_from_path(full_path));
- apk_fds.push_back(std::move(apk_fd));
+ unique_fd apk_fd(open(code_path.c_str(), O_RDONLY | O_NOFOLLOW));
+ if (apk_fd == -1) {
+ PLOG(ERROR) << "installd cannot open " << code_path.c_str();
+ return false;
}
+ dex_locations.push_back(get_location_from_path(code_path.c_str()));
+ apk_fds.push_back(std::move(apk_fd));
+
pid_t pid = fork();
if (pid == 0) {
@@ -913,10 +982,11 @@
}
bool copy_system_profile(const std::string& system_profile,
- uid_t packageUid, const std::string& data_profile_location) {
+ uid_t packageUid, const std::string& package_name, const std::string& profile_name) {
unique_fd in_fd(open(system_profile.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC));
unique_fd out_fd(open_reference_profile(packageUid,
- data_profile_location,
+ package_name,
+ profile_name,
/*read_write*/ true,
/*secondary*/ false));
if (in_fd.get() < 0) {
@@ -924,7 +994,7 @@
return false;
}
if (out_fd.get() < 0) {
- PLOG(WARNING) << "Could not open profile " << data_profile_location;
+ PLOG(WARNING) << "Could not open profile " << package_name;
return false;
}
@@ -937,7 +1007,7 @@
if (flock(out_fd.get(), LOCK_EX | LOCK_NB) != 0) {
if (errno != EWOULDBLOCK) {
- PLOG(WARNING) << "Error locking profile " << data_profile_location;
+ PLOG(WARNING) << "Error locking profile " << package_name;
}
// This implies that the app owning this profile is running
// (and has acquired the lock).
@@ -945,13 +1015,13 @@
// The app never acquires the lock for the reference profiles of primary apks.
// Only dex2oat from installd will do that. Since installd is single threaded
// we should not see this case. Nevertheless be prepared for it.
- PLOG(WARNING) << "Failed to flock " << data_profile_location;
+ PLOG(WARNING) << "Failed to flock " << package_name;
return false;
}
bool truncated = ftruncate(out_fd.get(), 0) == 0;
if (!truncated) {
- PLOG(WARNING) << "Could not truncate " << data_profile_location;
+ PLOG(WARNING) << "Could not truncate " << package_name;
}
// Copy over data.
@@ -965,7 +1035,7 @@
write(out_fd.get(), buffer, bytes);
}
if (flock(out_fd.get(), LOCK_UN) != 0) {
- PLOG(WARNING) << "Error unlocking profile " << data_profile_location;
+ PLOG(WARNING) << "Error unlocking profile " << package_name;
}
// Use _exit since we don't want to run the global destructors in the child.
// b/62597429
@@ -1264,19 +1334,42 @@
// Opens the reference profiles if needed.
// Note that the reference profile might not exist so it's OK if the fd will be -1.
Dex2oatFileWrapper maybe_open_reference_profile(const std::string& pkgname,
- const std::string& dex_path, bool profile_guided, bool is_public, int uid,
- bool is_secondary_dex) {
- // Public apps should not be compiled with profile information ever. Same goes for the special
- // package '*' used for the system server.
- if (!profile_guided || is_public || (pkgname[0] == '*')) {
+ const std::string& dex_path, const char* profile_name, bool profile_guided,
+ bool is_public, int uid, bool is_secondary_dex) {
+ // If we are not profile guided compilation, or we are compiling system server
+ // do not bother to open the profiles; we won't be using them.
+ if (!profile_guided || (pkgname[0] == '*')) {
+ return Dex2oatFileWrapper();
+ }
+
+ // If this is a secondary dex path which is public do not open the profile.
+ // We cannot compile public secondary dex paths with profiles. That's because
+ // it will expose how the dex files are used by their owner.
+ //
+ // Note that the PackageManager is responsible to set the is_public flag for
+ // primary apks and we do not check it here. In some cases, e.g. when
+ // compiling with a public profile from the .dm file the PackageManager will
+ // set is_public toghether with the profile guided compilation.
+ if (is_secondary_dex && is_public) {
return Dex2oatFileWrapper();
}
// Open reference profile in read only mode as dex2oat does not get write permissions.
- const std::string location = is_secondary_dex ? dex_path : pkgname;
- unique_fd ufd = open_reference_profile(uid, location, /*read_write*/false, is_secondary_dex);
- const auto& cleanup = [location, is_secondary_dex]() {
- clear_reference_profile(location.c_str(), is_secondary_dex);
+ std::string location;
+ if (is_secondary_dex) {
+ location = dex_path;
+ } else {
+ if (profile_name == nullptr) {
+ // This path is taken for system server re-compilation lunched from ZygoteInit.
+ return Dex2oatFileWrapper();
+ } else {
+ location = profile_name;
+ }
+ }
+ unique_fd ufd = open_reference_profile(uid, pkgname, location, /*read_write*/false,
+ is_secondary_dex);
+ const auto& cleanup = [pkgname, location, is_secondary_dex]() {
+ clear_reference_profile(pkgname, location, is_secondary_dex);
};
return Dex2oatFileWrapper(ufd.release(), cleanup);
}
@@ -1732,7 +1825,8 @@
}
// Analyze profiles.
- bool profile_was_updated = analyze_profiles(uid, dex_path, /*is_secondary_dex*/true);
+ bool profile_was_updated = analyze_profiles(uid, pkgname, dex_path,
+ /*is_secondary_dex*/true);
// Run dexoptanalyzer to get dexopt_needed code. This is not expected to return.
exec_dexoptanalyzer(dex_path,
@@ -1779,7 +1873,8 @@
int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* instruction_set,
int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
const char* volume_uuid, const char* class_loader_context, const char* se_info,
- bool downgrade, int target_sdk_version) {
+ bool downgrade, int target_sdk_version, const char* profile_name,
+ const char* dex_metadata_path, const char* compilation_reason) {
CHECK(pkgname != nullptr);
CHECK(pkgname[0] != 0);
if ((dexopt_flags & ~DEXOPT_MASK) != 0) {
@@ -1801,7 +1896,7 @@
bool profile_guided = (dexopt_flags & DEXOPT_PROFILE_GUIDED) != 0;
bool is_secondary_dex = (dexopt_flags & DEXOPT_SECONDARY_DEX) != 0;
bool background_job_compile = (dexopt_flags & DEXOPT_IDLE_BACKGROUND_JOB) != 0;
- bool disable_hidden_api_checks = (dexopt_flags & DEXOPT_DISABLE_HIDDEN_API_CHECKS) != 0;
+ bool enable_hidden_api_checks = (dexopt_flags & DEXOPT_ENABLE_HIDDEN_API_CHECKS) != 0;
// Check if we're dealing with a secondary dex file and if we need to compile it.
std::string oat_dir_str;
@@ -1868,7 +1963,15 @@
// Open the reference profile if needed.
Dex2oatFileWrapper reference_profile_fd = maybe_open_reference_profile(
- pkgname, dex_path, profile_guided, is_public, uid, is_secondary_dex);
+ pkgname, dex_path, profile_name, profile_guided, is_public, uid, is_secondary_dex);
+
+ unique_fd dex_metadata_fd;
+ if (dex_metadata_path != nullptr) {
+ dex_metadata_fd.reset(TEMP_FAILURE_RETRY(open(dex_metadata_path, O_RDONLY | O_NOFOLLOW)));
+ if (dex_metadata_fd.get() < 0) {
+ PLOG(ERROR) << "Failed to open dex metadata file " << dex_metadata_path;
+ }
+ }
ALOGV("DexInv: --- BEGIN '%s' ---\n", dex_path);
@@ -1899,7 +2002,9 @@
reference_profile_fd.get(),
class_loader_context,
target_sdk_version,
- disable_hidden_api_checks);
+ enable_hidden_api_checks,
+ dex_metadata_fd.get(),
+ compilation_reason);
_exit(68); /* only get here on exec failure */
} else {
int res = wait_child(pid);
@@ -2027,9 +2132,9 @@
// Delete profiles.
std::string current_profile = create_current_profile_path(
- multiuser_get_user_id(uid), dex_path, /*is_secondary*/true);
+ multiuser_get_user_id(uid), pkgname, dex_path, /*is_secondary*/true);
std::string reference_profile = create_reference_profile_path(
- dex_path, /*is_secondary*/true);
+ pkgname, dex_path, /*is_secondary*/true);
result = unlink_if_exists(current_profile) && result;
result = unlink_if_exists(reference_profile) && result;
@@ -2081,6 +2186,90 @@
}
}
+// Compute and return the hash (SHA-256) of the secondary dex file at dex_path.
+// Returns true if all parameters are valid and the hash successfully computed and stored in
+// out_secondary_dex_hash.
+// Also returns true with an empty hash if the file does not currently exist or is not accessible to
+// the app.
+// For any other errors (e.g. if any of the parameters are invalid) returns false.
+bool hash_secondary_dex_file(const std::string& dex_path, const std::string& pkgname, int uid,
+ const std::unique_ptr<std::string>& volume_uuid, int storage_flag,
+ std::vector<uint8_t>* out_secondary_dex_hash) {
+ out_secondary_dex_hash->clear();
+
+ const char* volume_uuid_cstr = volume_uuid == nullptr ? nullptr : volume_uuid->c_str();
+
+ if (storage_flag != FLAG_STORAGE_CE && storage_flag != FLAG_STORAGE_DE) {
+ LOG(ERROR) << "hash_secondary_dex_file called with invalid storage_flag: "
+ << storage_flag;
+ return false;
+ }
+
+ // Pipe to get the hash result back from our child process.
+ unique_fd pipe_read, pipe_write;
+ if (!Pipe(&pipe_read, &pipe_write)) {
+ PLOG(ERROR) << "Failed to create pipe";
+ return false;
+ }
+
+ // Fork so that actual access to the files is done in the app's own UID, to ensure we only
+ // access data the app itself can access.
+ pid_t pid = fork();
+ if (pid == 0) {
+ // child -- drop privileges before continuing
+ drop_capabilities(uid);
+ pipe_read.reset();
+
+ if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid_cstr, uid, storage_flag)) {
+ LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
+ _exit(1);
+ }
+
+ unique_fd fd(TEMP_FAILURE_RETRY(open(dex_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW)));
+ if (fd == -1) {
+ if (errno == EACCES || errno == ENOENT) {
+ // Not treated as an error.
+ _exit(0);
+ }
+ PLOG(ERROR) << "Failed to open secondary dex " << dex_path;
+ _exit(1);
+ }
+
+ SHA256_CTX ctx;
+ SHA256_Init(&ctx);
+
+ std::vector<uint8_t> buffer(65536);
+ while (true) {
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
+ if (bytes_read == 0) {
+ break;
+ } else if (bytes_read == -1) {
+ PLOG(ERROR) << "Failed to read secondary dex " << dex_path;
+ _exit(1);
+ }
+
+ SHA256_Update(&ctx, buffer.data(), bytes_read);
+ }
+
+ std::array<uint8_t, SHA256_DIGEST_LENGTH> hash;
+ SHA256_Final(hash.data(), &ctx);
+ if (!WriteFully(pipe_write, hash.data(), hash.size())) {
+ _exit(1);
+ }
+
+ _exit(0);
+ }
+
+ // parent
+ pipe_write.reset();
+
+ out_secondary_dex_hash->resize(SHA256_DIGEST_LENGTH);
+ if (!ReadFully(pipe_read, out_secondary_dex_hash->data(), out_secondary_dex_hash->size())) {
+ out_secondary_dex_hash->clear();
+ }
+ return wait_child(pid) == 0;
+}
+
// Helper for move_ab, so that we can have common failure-case cleanup.
static bool unlink_and_rename(const char* from, const char* to) {
// Check whether "from" exists, and if so whether it's regular. If it is, unlink. Otherwise,
@@ -2336,42 +2525,206 @@
}
}
-bool create_profile_snapshot(int32_t app_id, const std::string& package_name,
- const std::string& code_path) {
+bool open_classpath_files(const std::string& classpath, std::vector<unique_fd>* apk_fds) {
+ std::vector<std::string> classpaths_elems = base::Split(classpath, ":");
+ for (const std::string& elem : classpaths_elems) {
+ unique_fd fd(TEMP_FAILURE_RETRY(open(elem.c_str(), O_RDONLY)));
+ if (fd < 0) {
+ PLOG(ERROR) << "Could not open classpath elem " << elem;
+ return false;
+ } else {
+ apk_fds->push_back(std::move(fd));
+ }
+ }
+ return true;
+}
+
+static bool create_app_profile_snapshot(int32_t app_id,
+ const std::string& package_name,
+ const std::string& profile_name,
+ const std::string& classpath) {
int app_shared_gid = multiuser_get_shared_gid(/*user_id*/ 0, app_id);
- unique_fd snapshot_fd = open_spnashot_profile(AID_SYSTEM, package_name, code_path);
+ unique_fd snapshot_fd = open_spnashot_profile(AID_SYSTEM, package_name, profile_name);
if (snapshot_fd < 0) {
return false;
}
std::vector<unique_fd> profiles_fd;
unique_fd reference_profile_fd;
- open_profile_files(app_shared_gid, package_name, /*is_secondary_dex*/ false, &profiles_fd,
- &reference_profile_fd);
+ open_profile_files(app_shared_gid, package_name, profile_name, /*is_secondary_dex*/ false,
+ &profiles_fd, &reference_profile_fd);
if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) {
return false;
}
profiles_fd.push_back(std::move(reference_profile_fd));
+ // Open the class paths elements. These will be used to filter out profile data that does
+ // not belong to the classpath during merge.
+ std::vector<unique_fd> apk_fds;
+ if (!open_classpath_files(classpath, &apk_fds)) {
+ return false;
+ }
+
pid_t pid = fork();
if (pid == 0) {
/* child -- drop privileges before continuing */
drop_capabilities(app_shared_gid);
- run_profman_merge(profiles_fd, snapshot_fd);
+ run_profman_merge(profiles_fd, snapshot_fd, &apk_fds);
exit(42); /* only get here on exec failure */
}
/* parent */
int return_code = wait_child(pid);
if (!WIFEXITED(return_code)) {
- LOG(WARNING) << "profman failed for " << package_name << ":" << code_path;
+ LOG(WARNING) << "profman failed for " << package_name << ":" << profile_name;
return false;
}
return true;
}
+static bool create_boot_image_profile_snapshot(const std::string& package_name,
+ const std::string& profile_name,
+ const std::string& classpath) {
+ // The reference profile directory for the android package might not be prepared. Do it now.
+ const std::string ref_profile_dir =
+ create_primary_reference_profile_package_dir_path(package_name);
+ if (fs_prepare_dir(ref_profile_dir.c_str(), 0770, AID_SYSTEM, AID_SYSTEM) != 0) {
+ PLOG(ERROR) << "Failed to prepare " << ref_profile_dir;
+ return false;
+ }
+
+ // Open and create the snapshot profile.
+ unique_fd snapshot_fd = open_spnashot_profile(AID_SYSTEM, package_name, profile_name);
+
+ // Collect all non empty profiles.
+ // The collection will traverse all applications profiles and find the non empty files.
+ // This has the potential of inspecting a large number of files and directories (depending
+ // on the number of applications and users). So there is a slight increase in the chance
+ // to get get occasionally I/O errors (e.g. for opening the file). When that happens do not
+ // fail the snapshot and aggregate whatever profile we could open.
+ //
+ // The profile snapshot is a best effort based on available data it's ok if some data
+ // from some apps is missing. It will be counter productive for the snapshot to fail
+ // because we could not open or read some of the files.
+ std::vector<std::string> profiles;
+ if (!collect_profiles(&profiles)) {
+ LOG(WARNING) << "There were errors while collecting the profiles for the boot image.";
+ }
+
+ // If we have no profiles return early.
+ if (profiles.empty()) {
+ return true;
+ }
+
+ // Open the classpath elements. These will be used to filter out profile data that does
+ // not belong to the classpath during merge.
+ std::vector<unique_fd> apk_fds;
+ if (!open_classpath_files(classpath, &apk_fds)) {
+ return false;
+ }
+
+ // If we could not open any files from the classpath return an error.
+ if (apk_fds.empty()) {
+ LOG(ERROR) << "Could not open any of the classpath elements.";
+ return false;
+ }
+
+ // Aggregate the profiles in batches of kAggregationBatchSize.
+ // We do this to avoid opening a huge a amount of files.
+ static constexpr size_t kAggregationBatchSize = 10;
+
+ std::vector<unique_fd> profiles_fd;
+ for (size_t i = 0; i < profiles.size(); ) {
+ for (size_t k = 0; k < kAggregationBatchSize && i < profiles.size(); k++, i++) {
+ unique_fd fd = open_profile(AID_SYSTEM, profiles[i], O_RDONLY);
+ if (fd.get() >= 0) {
+ profiles_fd.push_back(std::move(fd));
+ }
+ }
+ pid_t pid = fork();
+ if (pid == 0) {
+ /* child -- drop privileges before continuing */
+ drop_capabilities(AID_SYSTEM);
+
+ run_profman_merge(profiles_fd, snapshot_fd, &apk_fds);
+ exit(42); /* only get here on exec failure */
+ }
+
+ /* parent */
+ int return_code = wait_child(pid);
+ if (!WIFEXITED(return_code)) {
+ PLOG(WARNING) << "profman failed for " << package_name << ":" << profile_name;
+ return false;
+ }
+ return true;
+ }
+ return true;
+}
+
+bool create_profile_snapshot(int32_t app_id, const std::string& package_name,
+ const std::string& profile_name, const std::string& classpath) {
+ if (app_id == -1) {
+ return create_boot_image_profile_snapshot(package_name, profile_name, classpath);
+ } else {
+ return create_app_profile_snapshot(app_id, package_name, profile_name, classpath);
+ }
+}
+
+bool prepare_app_profile(const std::string& package_name,
+ userid_t user_id,
+ appid_t app_id,
+ const std::string& profile_name,
+ 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,
+ /*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;
+ }
+
+ // Check if we need to install the profile from the dex metadata.
+ if (dex_metadata == nullptr) {
+ return true;
+ }
+
+ // 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 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)));
+ if (apk_fd < 0) {
+ PLOG(ERROR) << "Could not open code path " << code_path;
+ return false;
+ }
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ /* child -- drop privileges before continuing */
+ gid_t app_shared_gid = multiuser_get_shared_gid(user_id, app_id);
+ drop_capabilities(app_shared_gid);
+
+ // 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 */
+ }
+
+ /* parent */
+ int return_code = wait_child(pid);
+ if (!WIFEXITED(return_code)) {
+ PLOG(WARNING) << "profman failed for " << package_name << ":" << profile_name;
+ return false;
+ }
+ return true;
+}
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index 4923a43..62f9467 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -33,24 +33,27 @@
static constexpr int DEX2OAT_FOR_FILTER = 3;
static constexpr int DEX2OAT_FOR_RELOCATION = 4;
-// Clear the reference profile for the primary apk of the given package.
-bool clear_primary_reference_profile(const std::string& pkgname);
-// Clear the current profile for the primary apk of the given package and user.
-bool clear_primary_current_profile(const std::string& pkgname, userid_t user);
-// Clear all current profile for the primary apk of the given package.
-bool clear_primary_current_profiles(const std::string& pkgname);
-
-bool move_ab(const char* apk_path, const char* instruction_set, const char* output_path);
+// Clear the reference profile identified by the given profile name.
+bool clear_primary_reference_profile(const std::string& pkgname, const std::string& profile_name);
+// Clear the current profile identified by the given profile name (for single user).
+bool clear_primary_current_profile(const std::string& pkgname, const std::string& profile_name,
+ userid_t user);
+// Clear all current profiles identified by the given profile name (all users).
+bool clear_primary_current_profiles(const std::string& pkgname, const std::string& profile_name);
// Decide if profile guided compilation is needed or not based on existing profiles.
-// The analysis is done for the primary apks (base + splits) of the given package.
+// The analysis is done for a single profile name (which corresponds to a single code path).
// Returns true if there is enough information in the current profiles that makes it
// worth to recompile 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 analyze_primary_profiles(uid_t uid, const std::string& pkgname);
+bool analyze_primary_profiles(uid_t uid,
+ const std::string& pkgname,
+ const std::string& profile_name);
-// Create a snapshot of the profile information for the given package and code path.
+// Create a snapshot of the profile information for the given package profile.
+// If appId is -1, the method creates the profile snapshot for the boot image.
+//
// The profile snapshot is the aggregation of all existing profiles (all current user
// profiles & the reference profile) and is meant to capture the all the profile information
// without performing a merge into the reference profile which might impact future dex2oat
@@ -59,14 +62,34 @@
// ownership is assigned to AID_SYSTEM.
// The snapshot location is reference_profile_location.snapshot. If a snapshot is already
// there, it will be truncated and overwritten.
-bool create_profile_snapshot(int32_t app_id, const std::string& package,
- const std::string& code_path);
+//
+// The classpath acts as filter: only profiling data belonging to elements of the classpath
+// will end up in the snapshot.
+bool create_profile_snapshot(int32_t app_id,
+ const std::string& package,
+ const std::string& profile_name,
+ const std::string& classpath);
-bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths);
+bool dump_profiles(int32_t uid,
+ const std::string& pkgname,
+ const std::string& profile_name,
+ const std::string& code_path);
bool copy_system_profile(const std::string& system_profile,
uid_t packageUid,
- const std::string& data_profile_location);
+ const std::string& pkgname,
+ const std::string& profile_name);
+
+// Prepare the app profile for the given code path:
+// - create the current profile using profile_name
+// - merge the profile from the dex metadata file (if present) into
+// the reference profile.
+bool prepare_app_profile(const std::string& package_name,
+ userid_t user_id,
+ appid_t app_id,
+ const std::string& profile_name,
+ const std::string& code_path,
+ const std::unique_ptr<std::string>& dex_metadata);
bool delete_odex(const char* apk_path, const char* instruction_set, const char* output_path);
@@ -75,10 +98,15 @@
const std::unique_ptr<std::string>& volumeUuid, int storage_flag,
/*out*/bool* out_secondary_dex_exists);
+bool hash_secondary_dex_file(const std::string& dex_path,
+ const std::string& pkgname, int uid, const std::unique_ptr<std::string>& volume_uuid,
+ int storage_flag, std::vector<uint8_t>* out_secondary_dex_hash);
+
int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set,
int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
const char* volume_uuid, const char* class_loader_context, const char* se_info,
- bool downgrade, int target_sdk_version);
+ bool downgrade, int target_sdk_version, const char* profile_name,
+ const char* dexMetadataPath, const char* compilation_reason);
bool calculate_oat_file_path_default(char path[PKG_PATH_MAX], const char *oat_dir,
const char *apk_path, const char *instruction_set);
@@ -89,6 +117,8 @@
bool create_cache_path_default(char path[PKG_PATH_MAX], const char *src,
const char *instruction_set);
+bool move_ab(const char* apk_path, const char* instruction_set, const char* output_path);
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/installd_constants.h b/cmds/installd/installd_constants.h
index 9b6714d..06c83e4 100644
--- a/cmds/installd/installd_constants.h
+++ b/cmds/installd/installd_constants.h
@@ -52,7 +52,7 @@
// Tells the compiler that it is invoked from the background service. This
// controls whether extra debugging flags can be used (taking more compile time.)
constexpr int DEXOPT_IDLE_BACKGROUND_JOB = 1 << 9;
-constexpr int DEXOPT_DISABLE_HIDDEN_API_CHECKS = 1 << 10;
+constexpr int DEXOPT_ENABLE_HIDDEN_API_CHECKS = 1 << 10;
/* all known values for dexopt flags */
constexpr int DEXOPT_MASK =
@@ -64,7 +64,7 @@
| DEXOPT_FORCE
| DEXOPT_STORAGE_CE
| DEXOPT_STORAGE_DE
- | DEXOPT_DISABLE_HIDDEN_API_CHECKS;
+ | DEXOPT_ENABLE_HIDDEN_API_CHECKS;
// NOTE: keep in sync with StorageManager
constexpr int FLAG_STORAGE_DE = 1 << 0;
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 1c78ff0..d8d5796 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -43,6 +43,7 @@
#include "globals.h"
#include "installd_constants.h"
#include "installd_deps.h" // Need to fill in requirements of commands.
+#include "otapreopt_parameters.h"
#include "otapreopt_utils.h"
#include "system_properties.h"
#include "utils.h"
@@ -78,8 +79,8 @@
static_assert(DEXOPT_FORCE == 1 << 6, "DEXOPT_FORCE unexpected.");
static_assert(DEXOPT_STORAGE_CE == 1 << 7, "DEXOPT_STORAGE_CE unexpected.");
static_assert(DEXOPT_STORAGE_DE == 1 << 8, "DEXOPT_STORAGE_DE unexpected.");
-static_assert(DEXOPT_DISABLE_HIDDEN_API_CHECKS == 1 << 10,
- "DEXOPT_DISABLE_HIDDEN_API_CHECKS unexpected");
+static_assert(DEXOPT_ENABLE_HIDDEN_API_CHECKS == 1 << 10,
+ "DEXOPT_ENABLE_HIDDEN_API_CHECKS unexpected");
static_assert(DEXOPT_MASK == 0x5fe, "DEXOPT_MASK unexpected.");
@@ -158,31 +159,15 @@
}
std::string GetOTADataDirectory() const {
- return StringPrintf("%s/%s", GetOtaDirectoryPrefix().c_str(), target_slot_.c_str());
+ return StringPrintf("%s/%s", GetOtaDirectoryPrefix().c_str(), GetTargetSlot().c_str());
}
const std::string& GetTargetSlot() const {
- return target_slot_;
+ return parameters_.target_slot;
}
private:
- struct Parameters {
- const char *apk_path;
- uid_t uid;
- const char *pkgName;
- const char *instruction_set;
- int dexopt_needed;
- const char* oat_dir;
- int dexopt_flags;
- const char* compiler_filter;
- const char* volume_uuid;
- const char* shared_libraries;
- const char* se_info;
- bool downgrade;
- int target_sdk_version;
- };
-
bool ReadSystemProperties() {
static constexpr const char* kPropertyFiles[] = {
"/default.prop", "/system/build.prop"
@@ -306,439 +291,7 @@
}
bool ReadArguments(int argc, char** argv) {
- // Expected command line:
- // target-slot [version] dexopt {DEXOPT_PARAMETERS}
-
- const char* target_slot_arg = argv[1];
- if (target_slot_arg == nullptr) {
- LOG(ERROR) << "Missing parameters";
- return false;
- }
- // Sanitize value. Only allow (a-zA-Z0-9_)+.
- target_slot_ = target_slot_arg;
- if (!ValidateTargetSlotSuffix(target_slot_)) {
- LOG(ERROR) << "Target slot suffix not legal: " << target_slot_;
- return false;
- }
-
- // Check for version or "dexopt" next.
- if (argv[2] == nullptr) {
- LOG(ERROR) << "Missing parameters";
- return false;
- }
-
- if (std::string("dexopt").compare(argv[2]) == 0) {
- // This is version 1 (N) or pre-versioning version 2.
- constexpr int kV2ArgCount = 1 // "otapreopt"
- + 1 // slot
- + 1 // "dexopt"
- + 1 // apk_path
- + 1 // uid
- + 1 // pkg
- + 1 // isa
- + 1 // dexopt_needed
- + 1 // oat_dir
- + 1 // dexopt_flags
- + 1 // filter
- + 1 // volume
- + 1 // libs
- + 1; // seinfo
- if (argc == kV2ArgCount) {
- return ReadArgumentsV2(argc, argv, false);
- } else {
- return ReadArgumentsV1(argc, argv);
- }
- }
-
- uint32_t version;
- if (!ParseUInt(argv[2], &version)) {
- LOG(ERROR) << "Could not parse version: " << argv[2];
- return false;
- }
-
- switch (version) {
- case 2:
- return ReadArgumentsV2(argc, argv, true);
- case 3:
- return ReadArgumentsV3(argc, argv);
- case 4:
- return ReadArgumentsV4(argc, argv);
-
- default:
- LOG(ERROR) << "Unsupported version " << version;
- return false;
- }
- }
-
- bool ReadArgumentsV2(int argc ATTRIBUTE_UNUSED, char** argv, bool versioned) {
- size_t dexopt_index = versioned ? 3 : 2;
-
- // Check for "dexopt".
- if (argv[dexopt_index] == nullptr) {
- LOG(ERROR) << "Missing parameters";
- return false;
- }
- if (std::string("dexopt").compare(argv[dexopt_index]) != 0) {
- LOG(ERROR) << "Expected \"dexopt\"";
- return false;
- }
-
- size_t param_index = 0;
- for (;; ++param_index) {
- const char* param = argv[dexopt_index + 1 + param_index];
- if (param == nullptr) {
- break;
- }
-
- switch (param_index) {
- case 0:
- package_parameters_.apk_path = param;
- break;
-
- case 1:
- package_parameters_.uid = atoi(param);
- break;
-
- case 2:
- package_parameters_.pkgName = param;
- break;
-
- case 3:
- package_parameters_.instruction_set = param;
- break;
-
- case 4:
- package_parameters_.dexopt_needed = atoi(param);
- break;
-
- case 5:
- package_parameters_.oat_dir = param;
- break;
-
- case 6:
- package_parameters_.dexopt_flags = atoi(param);
- break;
-
- case 7:
- package_parameters_.compiler_filter = param;
- break;
-
- case 8:
- package_parameters_.volume_uuid = ParseNull(param);
- break;
-
- case 9:
- package_parameters_.shared_libraries = ParseNull(param);
- break;
-
- case 10:
- package_parameters_.se_info = ParseNull(param);
- break;
-
- default:
- LOG(ERROR) << "Too many arguments, got " << param;
- return false;
- }
- }
-
- // Set downgrade to false. It is only relevant when downgrading compiler
- // filter, which is not the case during ota.
- package_parameters_.downgrade = false;
-
- // Set target_sdk_version to 0, ie the platform SDK version. This is
- // conservative and may force some classes to verify at runtime.
- package_parameters_.target_sdk_version = 0;
-
- if (param_index != 11) {
- LOG(ERROR) << "Not enough parameters";
- return false;
- }
-
- return true;
- }
-
- bool ReadArgumentsV3(int argc ATTRIBUTE_UNUSED, char** argv) {
- size_t dexopt_index = 3;
-
- // Check for "dexopt".
- if (argv[dexopt_index] == nullptr) {
- LOG(ERROR) << "Missing parameters";
- return false;
- }
- if (std::string("dexopt").compare(argv[dexopt_index]) != 0) {
- LOG(ERROR) << "Expected \"dexopt\"";
- return false;
- }
-
- size_t param_index = 0;
- for (;; ++param_index) {
- const char* param = argv[dexopt_index + 1 + param_index];
- if (param == nullptr) {
- break;
- }
-
- switch (param_index) {
- case 0:
- package_parameters_.apk_path = param;
- break;
-
- case 1:
- package_parameters_.uid = atoi(param);
- break;
-
- case 2:
- package_parameters_.pkgName = param;
- break;
-
- case 3:
- package_parameters_.instruction_set = param;
- break;
-
- case 4:
- package_parameters_.dexopt_needed = atoi(param);
- break;
-
- case 5:
- package_parameters_.oat_dir = param;
- break;
-
- case 6:
- package_parameters_.dexopt_flags = atoi(param);
- break;
-
- case 7:
- package_parameters_.compiler_filter = param;
- break;
-
- case 8:
- package_parameters_.volume_uuid = ParseNull(param);
- break;
-
- case 9:
- package_parameters_.shared_libraries = ParseNull(param);
- break;
-
- case 10:
- package_parameters_.se_info = ParseNull(param);
- break;
-
- case 11:
- package_parameters_.downgrade = ParseBool(param);
- break;
-
- default:
- LOG(ERROR) << "Too many arguments, got " << param;
- return false;
- }
- }
-
- // Set target_sdk_version to 0, ie the platform SDK version. This is
- // conservative and may force some classes to verify at runtime.
- package_parameters_.target_sdk_version = 0;
-
- if (param_index != 12) {
- LOG(ERROR) << "Not enough parameters";
- return false;
- }
-
- return true;
- }
-
- bool ReadArgumentsV4(int argc ATTRIBUTE_UNUSED, char** argv) {
- size_t dexopt_index = 3;
-
- // Check for "dexopt".
- if (argv[dexopt_index] == nullptr) {
- LOG(ERROR) << "Missing parameters";
- return false;
- }
- if (std::string("dexopt").compare(argv[dexopt_index]) != 0) {
- LOG(ERROR) << "Expected \"dexopt\"";
- return false;
- }
-
- size_t param_index = 0;
- for (;; ++param_index) {
- const char* param = argv[dexopt_index + 1 + param_index];
- if (param == nullptr) {
- break;
- }
-
- switch (param_index) {
- case 0:
- package_parameters_.apk_path = param;
- break;
-
- case 1:
- package_parameters_.uid = atoi(param);
- break;
-
- case 2:
- package_parameters_.pkgName = param;
- break;
-
- case 3:
- package_parameters_.instruction_set = param;
- break;
-
- case 4:
- package_parameters_.dexopt_needed = atoi(param);
- break;
-
- case 5:
- package_parameters_.oat_dir = param;
- break;
-
- case 6:
- package_parameters_.dexopt_flags = atoi(param);
- break;
-
- case 7:
- package_parameters_.compiler_filter = param;
- break;
-
- case 8:
- package_parameters_.volume_uuid = ParseNull(param);
- break;
-
- case 9:
- package_parameters_.shared_libraries = ParseNull(param);
- break;
-
- case 10:
- package_parameters_.se_info = ParseNull(param);
- break;
-
- case 11:
- package_parameters_.downgrade = ParseBool(param);
- break;
-
- case 12:
- package_parameters_.target_sdk_version = atoi(param);
- break;
-
- default:
- LOG(ERROR) << "Too many arguments, got " << param;
- return false;
- }
- }
-
- if (param_index != 13) {
- LOG(ERROR) << "Not enough parameters";
- return false;
- }
-
- return true;
- }
-
- static int ReplaceMask(int input, int old_mask, int new_mask) {
- return (input & old_mask) != 0 ? new_mask : 0;
- }
-
- bool ReadArgumentsV1(int argc ATTRIBUTE_UNUSED, char** argv) {
- // Check for "dexopt".
- if (argv[2] == nullptr) {
- LOG(ERROR) << "Missing parameters";
- return false;
- }
- if (std::string("dexopt").compare(argv[2]) != 0) {
- LOG(ERROR) << "Expected \"dexopt\"";
- return false;
- }
-
- size_t param_index = 0;
- for (;; ++param_index) {
- const char* param = argv[3 + param_index];
- if (param == nullptr) {
- break;
- }
-
- switch (param_index) {
- case 0:
- package_parameters_.apk_path = param;
- break;
-
- case 1:
- package_parameters_.uid = atoi(param);
- break;
-
- case 2:
- package_parameters_.pkgName = param;
- break;
-
- case 3:
- package_parameters_.instruction_set = param;
- break;
-
- case 4: {
- // Version 1 had:
- // DEXOPT_DEX2OAT_NEEDED = 1
- // DEXOPT_PATCHOAT_NEEDED = 2
- // DEXOPT_SELF_PATCHOAT_NEEDED = 3
- // We will simply use DEX2OAT_FROM_SCRATCH.
- package_parameters_.dexopt_needed = DEX2OAT_FROM_SCRATCH;
- break;
- }
-
- case 5:
- package_parameters_.oat_dir = param;
- break;
-
- case 6: {
- // Version 1 had:
- constexpr int OLD_DEXOPT_PUBLIC = 1 << 1;
- // Note: DEXOPT_SAFEMODE has been removed.
- // constexpr int OLD_DEXOPT_SAFEMODE = 1 << 2;
- constexpr int OLD_DEXOPT_DEBUGGABLE = 1 << 3;
- constexpr int OLD_DEXOPT_BOOTCOMPLETE = 1 << 4;
- constexpr int OLD_DEXOPT_PROFILE_GUIDED = 1 << 5;
- constexpr int OLD_DEXOPT_OTA = 1 << 6;
- int input = atoi(param);
- package_parameters_.dexopt_flags =
- ReplaceMask(input, OLD_DEXOPT_PUBLIC, DEXOPT_PUBLIC) |
- ReplaceMask(input, OLD_DEXOPT_DEBUGGABLE, DEXOPT_DEBUGGABLE) |
- ReplaceMask(input, OLD_DEXOPT_BOOTCOMPLETE, DEXOPT_BOOTCOMPLETE) |
- ReplaceMask(input, OLD_DEXOPT_PROFILE_GUIDED, DEXOPT_PROFILE_GUIDED) |
- ReplaceMask(input, OLD_DEXOPT_OTA, 0);
- break;
- }
-
- case 7:
- package_parameters_.compiler_filter = param;
- break;
-
- case 8:
- package_parameters_.volume_uuid = ParseNull(param);
- break;
-
- case 9:
- package_parameters_.shared_libraries = ParseNull(param);
- break;
-
- default:
- LOG(ERROR) << "Too many arguments, got " << param;
- return false;
- }
- }
-
- if (param_index != 10) {
- LOG(ERROR) << "Not enough parameters";
- return false;
- }
-
- // Set se_info to null. It is only relevant for secondary dex files, which we won't
- // receive from a v1 A side.
- package_parameters_.se_info = nullptr;
-
- // Set downgrade to false. It is only relevant when downgrading compiler
- // filter, which is not the case during ota.
- package_parameters_.downgrade = false;
-
- // Set target_sdk_version to 0, ie the platform SDK version. This is
- // conservative and may force some classes to verify at runtime.
- package_parameters_.target_sdk_version = 0;
-
- return true;
+ return parameters_.ReadArguments(argc, const_cast<const char**>(argv));
}
void PrepareEnvironment() {
@@ -754,11 +307,11 @@
// Ensure that we have the right boot image. The first time any app is
// compiled, we'll try to generate it.
bool PrepareBootImage(bool force) const {
- if (package_parameters_.instruction_set == nullptr) {
+ if (parameters_.instruction_set == nullptr) {
LOG(ERROR) << "Instruction set missing.";
return false;
}
- const char* isa = package_parameters_.instruction_set;
+ const char* isa = parameters_.instruction_set;
// Check whether the file exists where expected.
std::string dalvik_cache = GetOTADataDirectory() + "/" + DALVIK_CACHE;
@@ -799,7 +352,7 @@
std::string preopted_boot_art_path = StringPrintf("/system/framework/%s/boot.art", isa);
if (access(preopted_boot_art_path.c_str(), F_OK) == 0) {
- return PatchoatBootImage(art_path, isa);
+ return PatchoatBootImage(isa_path, isa);
} else {
// No preopted boot image. Try to compile.
return Dex2oatBootImage(boot_classpath_, art_path, oat_path, isa);
@@ -868,14 +421,14 @@
CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory.";
}
- bool PatchoatBootImage(const std::string& art_path, const char* isa) const {
+ bool PatchoatBootImage(const std::string& output_dir, const char* isa) const {
// This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
std::vector<std::string> cmd;
cmd.push_back("/system/bin/patchoat");
cmd.push_back("--input-image-location=/system/framework/boot.art");
- cmd.push_back(StringPrintf("--output-image-file=%s", art_path.c_str()));
+ cmd.push_back(StringPrintf("--output-image-directory=%s", output_dir.c_str()));
cmd.push_back(StringPrintf("--instruction-set=%s", isa));
@@ -982,9 +535,9 @@
// jar content must be exactly the same).
// (This is ugly as it's the only thing where we need to understand the contents
- // of package_parameters_, but it beats postponing the decision or using the call-
+ // of parameters_, but it beats postponing the decision or using the call-
// backs to do weird things.)
- const char* apk_path = package_parameters_.apk_path;
+ const char* apk_path = parameters_.apk_path;
CHECK(apk_path != nullptr);
if (StartsWith(apk_path, android_root_)) {
const char* last_slash = strrchr(apk_path, '/');
@@ -1011,21 +564,25 @@
return false;
}
- // Run dexopt with the parameters of package_parameters_.
+ // Run dexopt with the parameters of parameters_.
+ // TODO(calin): embed the profile name in the parameters.
int Dexopt() {
- return dexopt(package_parameters_.apk_path,
- package_parameters_.uid,
- package_parameters_.pkgName,
- package_parameters_.instruction_set,
- package_parameters_.dexopt_needed,
- package_parameters_.oat_dir,
- package_parameters_.dexopt_flags,
- package_parameters_.compiler_filter,
- package_parameters_.volume_uuid,
- package_parameters_.shared_libraries,
- package_parameters_.se_info,
- package_parameters_.downgrade,
- package_parameters_.target_sdk_version);
+ return dexopt(parameters_.apk_path,
+ parameters_.uid,
+ parameters_.pkgName,
+ parameters_.instruction_set,
+ parameters_.dexopt_needed,
+ parameters_.oat_dir,
+ parameters_.dexopt_flags,
+ parameters_.compiler_filter,
+ parameters_.volume_uuid,
+ parameters_.shared_libraries,
+ parameters_.se_info,
+ parameters_.downgrade,
+ parameters_.target_sdk_version,
+ parameters_.profile_name,
+ parameters_.dex_metadata_path,
+ parameters_.compilation_reason);
}
int RunPreopt() {
@@ -1056,12 +613,12 @@
// If this was a profile-guided run, we may have profile version issues. Try to downgrade,
// if possible.
- if ((package_parameters_.dexopt_flags & DEXOPT_PROFILE_GUIDED) == 0) {
+ if ((parameters_.dexopt_flags & DEXOPT_PROFILE_GUIDED) == 0) {
return dexopt_result;
}
LOG(WARNING) << "Downgrading compiler filter in an attempt to progress compilation";
- package_parameters_.dexopt_flags &= ~DEXOPT_PROFILE_GUIDED;
+ parameters_.dexopt_flags &= ~DEXOPT_PROFILE_GUIDED;
return Dexopt();
}
@@ -1186,13 +743,12 @@
SystemProperties system_properties_;
// Some select properties that are always needed.
- std::string target_slot_;
std::string android_root_;
std::string android_data_;
std::string boot_classpath_;
std::string asec_mountpoint_;
- Parameters package_parameters_;
+ OTAPreoptParameters parameters_;
// Store environment values we need to set.
std::vector<std::string> environ_;
diff --git a/cmds/installd/otapreopt_parameters.cpp b/cmds/installd/otapreopt_parameters.cpp
new file mode 100644
index 0000000..802d5d7
--- /dev/null
+++ b/cmds/installd/otapreopt_parameters.cpp
@@ -0,0 +1,355 @@
+/*
+ ** Copyright 2016, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include "otapreopt_parameters.h"
+
+#include <android-base/logging.h>
+
+#include "dexopt.h"
+#include "installd_constants.h"
+#include "otapreopt_utils.h"
+
+#ifndef LOG_TAG
+#define LOG_TAG "otapreopt"
+#endif
+
+namespace android {
+namespace installd {
+
+static bool ParseBool(const char* in) {
+ if (strcmp(in, "true") == 0) {
+ return true;
+ }
+ return false;
+}
+
+static const char* ParseNull(const char* arg) {
+ return (strcmp(arg, "!") == 0) ? nullptr : arg;
+}
+
+static bool ParseUInt(const char* in, uint32_t* out) {
+ char* end;
+ long long int result = strtoll(in, &end, 0);
+ if (in == end || *end != '\0') {
+ return false;
+ }
+ if (result < std::numeric_limits<uint32_t>::min() ||
+ std::numeric_limits<uint32_t>::max() < result) {
+ return false;
+ }
+ *out = static_cast<uint32_t>(result);
+ return true;
+}
+
+bool OTAPreoptParameters::ReadArguments(int argc, const char** argv) {
+ // Expected command line:
+ // target-slot [version] dexopt {DEXOPT_PARAMETERS}
+
+ const char* target_slot_arg = argv[1];
+ if (target_slot_arg == nullptr) {
+ LOG(ERROR) << "Missing parameters";
+ return false;
+ }
+ // Sanitize value. Only allow (a-zA-Z0-9_)+.
+ target_slot = target_slot_arg;
+ if (!ValidateTargetSlotSuffix(target_slot)) {
+ LOG(ERROR) << "Target slot suffix not legal: " << target_slot;
+ return false;
+ }
+
+ // Check for version or "dexopt" next.
+ if (argv[2] == nullptr) {
+ LOG(ERROR) << "Missing parameters";
+ return false;
+ }
+
+ if (std::string("dexopt").compare(argv[2]) == 0) {
+ // This is version 1 (N) or pre-versioning version 2.
+ constexpr int kV2ArgCount = 1 // "otapreopt"
+ + 1 // slot
+ + 1 // "dexopt"
+ + 1 // apk_path
+ + 1 // uid
+ + 1 // pkg
+ + 1 // isa
+ + 1 // dexopt_needed
+ + 1 // oat_dir
+ + 1 // dexopt_flags
+ + 1 // filter
+ + 1 // volume
+ + 1 // libs
+ + 1; // seinfo
+ if (argc == kV2ArgCount) {
+ return ReadArgumentsPostV1(2, argv, false);
+ } else {
+ return ReadArgumentsV1(argv);
+ }
+ }
+
+ uint32_t version;
+ if (!ParseUInt(argv[2], &version)) {
+ LOG(ERROR) << "Could not parse version: " << argv[2];
+ return false;
+ }
+
+ return ReadArgumentsPostV1(version, argv, true);
+}
+
+static int ReplaceMask(int input, int old_mask, int new_mask) {
+ return (input & old_mask) != 0 ? new_mask : 0;
+}
+
+void OTAPreoptParameters::SetDefaultsForPostV1Arguments() {
+ // Set se_info to null. It is only relevant for secondary dex files, which we won't
+ // receive from a v1 A side.
+ se_info = nullptr;
+
+ // Set downgrade to false. It is only relevant when downgrading compiler
+ // filter, which is not the case during ota.
+ downgrade = false;
+
+ // Set target_sdk_version to 0, ie the platform SDK version. This is
+ // conservative and may force some classes to verify at runtime.
+ target_sdk_version = 0;
+
+ // Set the profile name to the primary apk profile.
+ profile_name = "primary.prof";
+
+ // By default we don't have a dex metadata file.
+ dex_metadata_path = nullptr;
+
+ // The compilation reason is ab-ota (match the system property pm.dexopt.ab-ota)
+ compilation_reason = "ab-ota";
+}
+
+bool OTAPreoptParameters::ReadArgumentsV1(const char** argv) {
+ // Check for "dexopt".
+ if (argv[2] == nullptr) {
+ LOG(ERROR) << "Missing parameters";
+ return false;
+ }
+ if (std::string("dexopt").compare(argv[2]) != 0) {
+ LOG(ERROR) << "Expected \"dexopt\" but found: " << argv[2];
+ return false;
+ }
+
+ size_t param_index = 0;
+ for (;; ++param_index) {
+ const char* param = argv[3 + param_index];
+ if (param == nullptr) {
+ break;
+ }
+
+ switch (param_index) {
+ case 0:
+ apk_path = param;
+ break;
+
+ case 1:
+ uid = atoi(param);
+ break;
+
+ case 2:
+ pkgName = param;
+ break;
+
+ case 3:
+ instruction_set = param;
+ break;
+
+ case 4: {
+ // Version 1 had:
+ // DEXOPT_DEX2OAT_NEEDED = 1
+ // DEXOPT_PATCHOAT_NEEDED = 2
+ // DEXOPT_SELF_PATCHOAT_NEEDED = 3
+ // We will simply use DEX2OAT_FROM_SCRATCH.
+ dexopt_needed = DEX2OAT_FROM_SCRATCH;
+ break;
+ }
+
+ case 5:
+ oat_dir = param;
+ break;
+
+ case 6: {
+ // Version 1 had:
+ constexpr int OLD_DEXOPT_PUBLIC = 1 << 1;
+ // Note: DEXOPT_SAFEMODE has been removed.
+ // constexpr int OLD_DEXOPT_SAFEMODE = 1 << 2;
+ constexpr int OLD_DEXOPT_DEBUGGABLE = 1 << 3;
+ constexpr int OLD_DEXOPT_BOOTCOMPLETE = 1 << 4;
+ constexpr int OLD_DEXOPT_PROFILE_GUIDED = 1 << 5;
+ constexpr int OLD_DEXOPT_OTA = 1 << 6;
+ int input = atoi(param);
+ dexopt_flags =
+ ReplaceMask(input, OLD_DEXOPT_PUBLIC, DEXOPT_PUBLIC) |
+ ReplaceMask(input, OLD_DEXOPT_DEBUGGABLE, DEXOPT_DEBUGGABLE) |
+ ReplaceMask(input, OLD_DEXOPT_BOOTCOMPLETE, DEXOPT_BOOTCOMPLETE) |
+ ReplaceMask(input, OLD_DEXOPT_PROFILE_GUIDED, DEXOPT_PROFILE_GUIDED) |
+ ReplaceMask(input, OLD_DEXOPT_OTA, 0);
+ break;
+ }
+
+ case 7:
+ compiler_filter = param;
+ break;
+
+ case 8:
+ volume_uuid = ParseNull(param);
+ break;
+
+ case 9:
+ shared_libraries = ParseNull(param);
+ break;
+
+ default:
+ LOG(ERROR) << "Too many arguments, got " << param;
+ return false;
+ }
+ }
+
+ if (param_index != 10) {
+ LOG(ERROR) << "Not enough parameters";
+ return false;
+ }
+
+ SetDefaultsForPostV1Arguments();
+
+ return true;
+}
+
+bool OTAPreoptParameters::ReadArgumentsPostV1(uint32_t version, const char** argv, bool versioned) {
+ size_t num_args_expected = 0;
+ switch (version) {
+ case 2: num_args_expected = 11; break;
+ case 3: num_args_expected = 12; break;
+ case 4: num_args_expected = 13; break;
+ case 5: num_args_expected = 14; break;
+ case 6: num_args_expected = 15; break;
+ case 7: num_args_expected = 16; break;
+ default:
+ LOG(ERROR) << "Don't know how to read arguments for version " << version;
+ return false;
+ }
+ size_t dexopt_index = versioned ? 3 : 2;
+
+ // Check for "dexopt".
+ if (argv[dexopt_index] == nullptr) {
+ LOG(ERROR) << "Missing parameters";
+ return false;
+ }
+ if (std::string("dexopt").compare(argv[dexopt_index]) != 0) {
+ LOG(ERROR) << "Expected \"dexopt\" but found: " << argv[dexopt_index];
+ return false;
+ }
+
+ // Validate the number of arguments.
+ size_t num_args_actual = 0;
+ while (argv[dexopt_index + 1 + num_args_actual] != nullptr) {
+ num_args_actual++;
+ }
+
+ if (num_args_actual != num_args_expected) {
+ LOG(ERROR) << "Invalid number of arguments. expected="
+ << num_args_expected << " actual=" << num_args_actual;
+ return false;
+ }
+
+ // The number of arguments is OK.
+ // Configure the default values for the parameters that were added after V1.
+ // The default values will be overwritten in case they are passed as arguments.
+ SetDefaultsForPostV1Arguments();
+
+ for (size_t param_index = 0; param_index < num_args_actual; ++param_index) {
+ const char* param = argv[dexopt_index + 1 + param_index];
+ switch (param_index) {
+ case 0:
+ apk_path = param;
+ break;
+
+ case 1:
+ uid = atoi(param);
+ break;
+
+ case 2:
+ pkgName = param;
+ break;
+
+ case 3:
+ instruction_set = param;
+ break;
+
+ case 4:
+ dexopt_needed = atoi(param);
+ break;
+
+ case 5:
+ oat_dir = param;
+ break;
+
+ case 6:
+ dexopt_flags = atoi(param);
+ break;
+
+ case 7:
+ compiler_filter = param;
+ break;
+
+ case 8:
+ volume_uuid = ParseNull(param);
+ break;
+
+ case 9:
+ shared_libraries = ParseNull(param);
+ break;
+
+ case 10:
+ se_info = ParseNull(param);
+ break;
+
+ case 11:
+ downgrade = ParseBool(param);
+ break;
+
+ case 12:
+ target_sdk_version = atoi(param);
+ break;
+
+ case 13:
+ profile_name = ParseNull(param);
+ break;
+
+ case 14:
+ dex_metadata_path = ParseNull(param);
+ break;
+
+ case 15:
+ compilation_reason = ParseNull(param);
+ break;
+
+ default:
+ LOG(FATAL) << "Should not get here. Did you call ReadArguments "
+ << "with the right expectation? index=" << param_index
+ << " num_args=" << num_args_actual;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/otapreopt_parameters.h b/cmds/installd/otapreopt_parameters.h
new file mode 100644
index 0000000..a2f6e44
--- /dev/null
+++ b/cmds/installd/otapreopt_parameters.h
@@ -0,0 +1,61 @@
+/*
+ ** Copyright 2018, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#ifndef OTAPREOPT_PARAMETERS_H_
+#define OTAPREOPT_PARAMETERS_H_
+
+#include <string>
+#include <sys/types.h>
+
+namespace android {
+namespace installd {
+
+class OTAPreoptParameters {
+ public:
+ bool ReadArguments(int argc, const char** argv);
+
+ private:
+ bool ReadArgumentsV1(const char** argv);
+ bool ReadArgumentsPostV1(uint32_t version, const char** argv, bool versioned);
+
+ void SetDefaultsForPostV1Arguments();
+ const char* apk_path;
+ uid_t uid;
+ const char* pkgName;
+ const char* instruction_set;
+ int dexopt_needed;
+ const char* oat_dir;
+ int dexopt_flags;
+ const char* compiler_filter;
+ const char* volume_uuid;
+ const char* shared_libraries;
+ const char* se_info;
+ bool downgrade;
+ int target_sdk_version;
+ const char* profile_name;
+ const char* dex_metadata_path;
+ const char* compilation_reason;
+
+ std::string target_slot;
+
+ friend class OTAPreoptService;
+ friend class OTAPreoptTest;
+};
+
+} // namespace installd
+} // namespace android
+
+#endif // OTAPREOPT_PARAMETERS_H_
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index 1a22992..7438d3d 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -24,6 +24,7 @@
shared_libs: [
"libbase",
"libbinder",
+ "libcrypto",
"libcutils",
"libselinux",
"libutils",
@@ -44,6 +45,7 @@
shared_libs: [
"libbase",
"libbinder",
+ "libcrypto",
"libcutils",
"libselinux",
"libutils",
@@ -64,6 +66,7 @@
shared_libs: [
"libbase",
"libbinder",
+ "libcrypto",
"libcutils",
"libselinux",
"libutils",
@@ -75,3 +78,20 @@
"liblogwrap",
],
}
+
+cc_test {
+ name: "installd_otapreopt_test",
+ clang: true,
+ srcs: ["installd_otapreopt_test.cpp"],
+ cflags: ["-Wall", "-Werror"],
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "libutils",
+ ],
+ static_libs: [
+ "liblog",
+ "libotapreoptparameters"
+ ],
+}
+
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index ff29506..d640558 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <cstdlib>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
@@ -153,10 +154,12 @@
InstalldNativeService* service_;
std::unique_ptr<std::string> volume_uuid_;
std::string package_name_;
+ std::string apk_path_;
std::string app_apk_dir_;
std::string app_private_dir_ce_;
std::string app_private_dir_de_;
std::string se_info_;
+ std::string app_oat_dir_;
int64_t ce_data_inode_;
@@ -197,13 +200,13 @@
void create_mock_app() {
// Create the oat dir.
- std::string app_oat_dir = app_apk_dir_ + "/oat";
+ app_oat_dir_ = app_apk_dir_ + "/oat";
mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755);
- service_->createOatDir(app_oat_dir, kRuntimeIsa);
+ service_->createOatDir(app_oat_dir_, kRuntimeIsa);
// Copy the primary apk.
- std::string apk_path = app_apk_dir_ + "/base.jar";
- ASSERT_TRUE(WriteBase64ToFile(kDexFile, apk_path, kSystemUid, kSystemGid, 0644));
+ apk_path_ = app_apk_dir_ + "/base.jar";
+ ASSERT_TRUE(WriteBase64ToFile(kDexFile, apk_path_, kSystemUid, kSystemGid, 0644));
// Create the app user data.
ASSERT_TRUE(service_->createAppData(
@@ -259,6 +262,9 @@
std::unique_ptr<std::string> se_info_ptr(new std::string(se_info_));
bool downgrade = false;
int32_t target_sdk_version = 0; // default
+ std::unique_ptr<std::string> profile_name_ptr = nullptr;
+ std::unique_ptr<std::string> dm_path_ptr = nullptr;
+ std::unique_ptr<std::string> compilation_reason_ptr = nullptr;
binder::Status result = service_->dexopt(path,
uid,
@@ -272,8 +278,11 @@
class_loader_context_ptr,
se_info_ptr,
downgrade,
- target_sdk_version);
- ASSERT_EQ(should_binder_call_succeed, result.isOk());
+ target_sdk_version,
+ profile_name_ptr,
+ dm_path_ptr,
+ compilation_reason_ptr);
+ ASSERT_EQ(should_binder_call_succeed, result.isOk()) << result.toString8().c_str();
int expected_access = should_dex_be_compiled ? 0 : -1;
std::string odex = GetSecondaryDexArtifact(path, "odex");
std::string vdex = GetSecondaryDexArtifact(path, "vdex");
@@ -301,7 +310,7 @@
storage_flag,
&out_secondary_dex_exists);
- ASSERT_EQ(should_binder_call_succeed, result.isOk());
+ ASSERT_EQ(should_binder_call_succeed, result.isOk()) << result.toString8().c_str();
ASSERT_EQ(should_dex_exist, out_secondary_dex_exists);
int expected_access = should_dex_be_deleted ? -1 : 0;
@@ -320,6 +329,115 @@
ASSERT_EQ(gid, st.st_gid);
ASSERT_EQ(mode, st.st_mode);
}
+
+ void CompilePrimaryDexOk(std::string compiler_filter,
+ int32_t dex_flags,
+ const char* oat_dir,
+ int32_t uid,
+ int32_t dexopt_needed,
+ const char* dm_path = nullptr,
+ bool downgrade = false) {
+ return CompilePrimaryDex(
+ compiler_filter, dex_flags, oat_dir, uid, dexopt_needed, dm_path, downgrade, true);
+ }
+
+ void CompilePrimaryDexFail(std::string compiler_filter,
+ int32_t dex_flags,
+ const char* oat_dir,
+ int32_t uid,
+ int32_t dexopt_needed,
+ const char* dm_path = nullptr,
+ bool downgrade = false) {
+ return CompilePrimaryDex(
+ compiler_filter, dex_flags, oat_dir, uid, dexopt_needed, dm_path, downgrade, false);
+ }
+
+ void CompilePrimaryDex(std::string compiler_filter,
+ int32_t dex_flags,
+ const char* oat_dir,
+ int32_t uid,
+ int32_t dexopt_needed,
+ const char* dm_path,
+ bool downgrade,
+ bool should_binder_call_succeed) {
+ std::unique_ptr<std::string> package_name_ptr(new std::string(package_name_));
+ std::unique_ptr<std::string> out_path(
+ oat_dir == nullptr ? nullptr : new std::string(oat_dir));
+ std::unique_ptr<std::string> class_loader_context_ptr(new std::string("&"));
+ std::unique_ptr<std::string> se_info_ptr(new std::string(se_info_));
+ int32_t target_sdk_version = 0; // default
+ std::unique_ptr<std::string> profile_name_ptr(new std::string("primary.prof"));
+ std::unique_ptr<std::string> dm_path_ptr = nullptr;
+ if (dm_path != nullptr) {
+ dm_path_ptr.reset(new std::string(dm_path));
+ }
+ std::unique_ptr<std::string> compilation_reason_ptr(new std::string("test-reason"));
+
+ bool prof_result;
+ binder::Status prof_binder_result = service_->prepareAppProfile(
+ package_name_, kTestUserId, kTestAppId, *profile_name_ptr, apk_path_,
+ /*dex_metadata*/ nullptr, &prof_result);
+
+ ASSERT_TRUE(prof_binder_result.isOk()) << prof_binder_result.toString8().c_str();
+ ASSERT_TRUE(prof_result);
+
+ binder::Status result = service_->dexopt(apk_path_,
+ uid,
+ package_name_ptr,
+ kRuntimeIsa,
+ dexopt_needed,
+ out_path,
+ dex_flags,
+ compiler_filter,
+ volume_uuid_,
+ class_loader_context_ptr,
+ se_info_ptr,
+ downgrade,
+ target_sdk_version,
+ profile_name_ptr,
+ dm_path_ptr,
+ compilation_reason_ptr);
+ ASSERT_EQ(should_binder_call_succeed, result.isOk()) << result.toString8().c_str();
+
+ if (!should_binder_call_succeed) {
+ return;
+ }
+ // Check the access to the compiler output.
+ // - speed-profile artifacts are not world-wide readable.
+ // - files are owned by the system uid.
+ std::string odex = GetPrimaryDexArtifact(oat_dir, apk_path_, "odex");
+ std::string vdex = GetPrimaryDexArtifact(oat_dir, apk_path_, "vdex");
+ std::string art = GetPrimaryDexArtifact(oat_dir, apk_path_, "art");
+
+ bool is_public = (dex_flags & DEXOPT_PUBLIC) != 0;
+ mode_t mode = S_IFREG | (is_public ? 0644 : 0640);
+ CheckFileAccess(odex, kSystemUid, uid, mode);
+ CheckFileAccess(vdex, kSystemUid, uid, mode);
+
+ if (compiler_filter == "speed-profile") {
+ CheckFileAccess(art, kSystemUid, uid, mode);
+ }
+ }
+
+ std::string GetPrimaryDexArtifact(const char* oat_dir,
+ const std::string& dex_path,
+ const std::string& type) {
+ if (oat_dir == nullptr) {
+ std::string path = dex_path;
+ for (auto it = path.begin() + 1; it < path.end(); ++it) {
+ if (*it == '/') {
+ *it = '@';
+ }
+ }
+ return android_data_dir + DALVIK_CACHE + '/' + kRuntimeIsa + "/" + path
+ + "@classes.dex";
+ } else {
+ std::string::size_type name_end = dex_path.rfind('.');
+ std::string::size_type name_start = dex_path.rfind('/');
+ return std::string(oat_dir) + "/" + kRuntimeIsa + "/" +
+ dex_path.substr(name_start + 1, name_end - name_start) + type;
+ }
+ }
};
@@ -366,6 +484,87 @@
/*binder_ok*/ false, /*compile_ok*/ false, kSystemUid);
}
+TEST_F(DexoptTest, DexoptPrimaryPublic) {
+ LOG(INFO) << "DexoptPrimaryPublic";
+ CompilePrimaryDexOk("verify",
+ DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC,
+ app_oat_dir_.c_str(),
+ kTestAppGid,
+ DEX2OAT_FROM_SCRATCH);
+}
+
+TEST_F(DexoptTest, DexoptPrimaryFailedInvalidFilter) {
+ LOG(INFO) << "DexoptPrimaryFailedInvalidFilter";
+ CompilePrimaryDexFail("awesome-filter",
+ DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PUBLIC,
+ app_oat_dir_.c_str(),
+ kTestAppGid,
+ DEX2OAT_FROM_SCRATCH);
+}
+
+TEST_F(DexoptTest, DexoptPrimaryProfileNonPublic) {
+ LOG(INFO) << "DexoptPrimaryProfileNonPublic";
+ CompilePrimaryDexOk("speed-profile",
+ DEXOPT_BOOTCOMPLETE | DEXOPT_PROFILE_GUIDED,
+ app_oat_dir_.c_str(),
+ kTestAppGid,
+ DEX2OAT_FROM_SCRATCH);
+}
+
+TEST_F(DexoptTest, DexoptPrimaryProfilePublic) {
+ LOG(INFO) << "DexoptPrimaryProfilePublic";
+ CompilePrimaryDexOk("speed-profile",
+ DEXOPT_BOOTCOMPLETE | DEXOPT_PROFILE_GUIDED | DEXOPT_PUBLIC,
+ app_oat_dir_.c_str(),
+ kTestAppGid,
+ DEX2OAT_FROM_SCRATCH);
+}
+
+TEST_F(DexoptTest, DexoptPrimaryBackgroundOk) {
+ LOG(INFO) << "DexoptPrimaryBackgroundOk";
+ CompilePrimaryDexOk("speed-profile",
+ DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PROFILE_GUIDED,
+ app_oat_dir_.c_str(),
+ kTestAppGid,
+ DEX2OAT_FROM_SCRATCH);
+}
+
+class PrimaryDexReCompilationTest : public DexoptTest {
+ public:
+ virtual void SetUp() {
+ DexoptTest::SetUp();
+ CompilePrimaryDexOk("verify",
+ DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC,
+ app_oat_dir_.c_str(),
+ kTestAppGid,
+ DEX2OAT_FROM_SCRATCH);
+ std::string odex = GetSecondaryDexArtifact(apk_path_, "odex");
+ std::string vdex = GetSecondaryDexArtifact(apk_path_, "vdex");
+
+ first_compilation_odex_fd_.reset(open(odex.c_str(), O_RDONLY));
+ first_compilation_vdex_fd_.reset(open(vdex.c_str(), O_RDONLY));
+ }
+
+ virtual void TearDown() {
+ first_compilation_odex_fd_.reset(-1);
+ first_compilation_vdex_fd_.reset(-1);
+ DexoptTest::TearDown();
+ }
+
+ protected:
+ unique_fd first_compilation_odex_fd_;
+ unique_fd first_compilation_vdex_fd_;
+};
+
+TEST_F(PrimaryDexReCompilationTest, DexoptPrimaryUpdateInPlaceVdex) {
+ LOG(INFO) << "DexoptPrimaryUpdateInPlaceVdex";
+
+ CompilePrimaryDexOk("verify",
+ DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PUBLIC,
+ app_oat_dir_.c_str(),
+ kTestAppGid,
+ DEX2OAT_FOR_BOOT_IMAGE);
+}
class ReconcileTest : public DexoptTest {
virtual void SetUp() {
@@ -431,17 +630,22 @@
std::string ref_profile_;
std::string snap_profile_;
+ static constexpr const char* kPrimaryProfile = "primary.prof";
+
virtual void SetUp() {
DexoptTest::SetUp();
cur_profile_ = create_current_profile_path(
- kTestUserId, package_name_, /*is_secondary_dex*/ false);
- ref_profile_ = create_reference_profile_path(package_name_, /*is_secondary_dex*/ false);
- snap_profile_ = create_snapshot_profile_path(package_name_, "base.jar");
+ kTestUserId, package_name_, kPrimaryProfile, /*is_secondary_dex*/ false);
+ ref_profile_ = create_reference_profile_path(package_name_, kPrimaryProfile,
+ /*is_secondary_dex*/ false);
+ snap_profile_ = create_snapshot_profile_path(package_name_, kPrimaryProfile);
}
- void SetupProfile(const std::string& path, uid_t uid, gid_t gid, mode_t mode, int32_t seed) {
- run_cmd("profman --generate-test-profile-seed=" + std::to_string(seed) +
- " --generate-test-profile-num-dex=2 --generate-test-profile=" + path);
+ void SetupProfile(const std::string& path, uid_t uid, gid_t gid, mode_t mode,
+ int32_t num_dex) {
+ run_cmd("profman --generate-test-profile-seed=" + std::to_string(num_dex) +
+ " --generate-test-profile-num-dex=" + std::to_string(num_dex) +
+ " --generate-test-profile=" + path);
::chmod(path.c_str(), mode);
::chown(path.c_str(), uid, gid);
}
@@ -449,7 +653,7 @@
void SetupProfiles(bool setup_ref) {
SetupProfile(cur_profile_, kTestAppUid, kTestAppGid, 0600, 1);
if (setup_ref) {
- SetupProfile(ref_profile_, kTestAppUid, kTestAppGid, 0060, 2);
+ SetupProfile(ref_profile_, kTestAppUid, kTestAppGid, 0600, 2);
}
}
@@ -457,8 +661,8 @@
bool expected_result) {
bool result;
binder::Status binder_result = service_->createProfileSnapshot(
- appid, package_name, "base.jar", &result);
- ASSERT_TRUE(binder_result.isOk());
+ appid, package_name, kPrimaryProfile, apk_path_, &result);
+ ASSERT_TRUE(binder_result.isOk()) << binder_result.toString8().c_str();
ASSERT_EQ(expected_result, result);
if (!expected_result) {
@@ -475,7 +679,8 @@
run_cmd("touch " + expected_profile_content);
run_cmd("profman --profile-file=" + cur_profile_ +
" --profile-file=" + ref_profile_ +
- " --reference-profile-file=" + expected_profile_content);
+ " --reference-profile-file=" + expected_profile_content +
+ " --apk=" + apk_path_);
ASSERT_TRUE(AreFilesEqual(expected_profile_content, snap_profile_));
@@ -493,7 +698,62 @@
ASSERT_TRUE(WIFEXITED(wait_child(pid)));
}
- private:
+ void mergePackageProfiles(const std::string& package_name,
+ const std::string& code_path,
+ bool expected_result) {
+ bool result;
+ binder::Status binder_result = service_->mergeProfiles(
+ kTestAppUid, package_name, code_path, &result);
+ ASSERT_TRUE(binder_result.isOk()) << binder_result.toString8().c_str();
+ ASSERT_EQ(expected_result, result);
+
+ if (!expected_result) {
+ // Do not check the files if we expect to fail.
+ return;
+ }
+
+ // Check that the snapshot was created witht he expected acess flags.
+ CheckFileAccess(ref_profile_, kTestAppUid, kTestAppUid, 0600 | S_IFREG);
+
+ // The snapshot should be equivalent to the merge of profiles.
+ std::string ref_profile_content = ref_profile_ + ".expected";
+ run_cmd("rm -f " + ref_profile_content);
+ run_cmd("touch " + ref_profile_content);
+ run_cmd("profman --profile-file=" + cur_profile_ +
+ " --profile-file=" + ref_profile_ +
+ " --reference-profile-file=" + ref_profile_content);
+
+ ASSERT_TRUE(AreFilesEqual(ref_profile_content, ref_profile_));
+ }
+
+ // TODO(calin): add dex metadata tests once the ART change is merged.
+ void preparePackageProfile(const std::string& package_name, const std::string& profile_name,
+ bool expected_result) {
+ bool result;
+ binder::Status binder_result = service_->prepareAppProfile(
+ package_name, kTestUserId, kTestAppId, profile_name, apk_path_,
+ /*dex_metadata*/ nullptr, &result);
+ ASSERT_TRUE(binder_result.isOk()) << binder_result.toString8().c_str();
+ ASSERT_EQ(expected_result, result);
+
+ if (!expected_result) {
+ // Do not check the files if we expect to fail.
+ return;
+ }
+
+ std::string code_path_cur_prof = create_current_profile_path(
+ kTestUserId, package_name, profile_name, /*is_secondary_dex*/ false);
+ std::string code_path_ref_profile = create_reference_profile_path(package_name,
+ profile_name, /*is_secondary_dex*/ false);
+
+ // Check that we created the current profile.
+ CheckFileAccess(code_path_cur_prof, kTestAppUid, kTestAppUid, 0600 | S_IFREG);
+
+ // Without dex metadata we don't generate a reference profile.
+ ASSERT_EQ(-1, access(code_path_ref_profile.c_str(), R_OK));
+ }
+
+ protected:
void TransitionToSystemServer() {
ASSERT_TRUE(DropCapabilities(kSystemUid, kSystemGid));
int32_t res = selinux_android_setcontext(
@@ -559,24 +819,46 @@
SetupProfiles(/*setup_ref*/ true);
createProfileSnapshot(kTestAppId, package_name_, /*expected_result*/ true);
- binder::Status binder_result = service_->destroyProfileSnapshot(package_name_, "base.jar");
- ASSERT_TRUE(binder_result.isOk());
+ binder::Status binder_result = service_->destroyProfileSnapshot(package_name_, kPrimaryProfile);
+ ASSERT_TRUE(binder_result.isOk()) << binder_result.toString8().c_str();
struct stat st;
ASSERT_EQ(-1, stat(snap_profile_.c_str(), &st));
ASSERT_EQ(ENOENT, errno);
}
+TEST_F(ProfileTest, ProfileMergeOk) {
+ LOG(INFO) << "ProfileMergeOk";
+
+ SetupProfiles(/*setup_ref*/ true);
+ mergePackageProfiles(package_name_, "primary.prof", /*expected_result*/ true);
+}
+
+// The reference profile is created on the fly. We need to be able to
+// merge without one.
+TEST_F(ProfileTest, ProfileMergeOkNoReference) {
+ LOG(INFO) << "ProfileMergeOkNoReference";
+
+ SetupProfiles(/*setup_ref*/ false);
+ mergePackageProfiles(package_name_, "primary.prof", /*expected_result*/ true);
+}
+
+TEST_F(ProfileTest, ProfileMergeFailWrongPackage) {
+ LOG(INFO) << "ProfileMergeFailWrongPackage";
+
+ SetupProfiles(/*setup_ref*/ true);
+ mergePackageProfiles("not.there", "primary.prof", /*expected_result*/ false);
+}
+
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);
+ kPrimaryProfile, /*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, kSystemUid, kTestAppGid, 0770 | S_IFDIR);
}
@@ -588,7 +870,7 @@
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);
+ kPrimaryProfile, /*is_secondary_dex*/false);
std::string ref_profile_dir = create_primary_reference_profile_package_dir_path(package_name_);
// Simulate a pre-P setup by changing the owner to kTestAppGid and permissions to 0700.
@@ -608,9 +890,132 @@
// Check the file access.
CheckFileAccess(cur_profile_dir, kTestAppUid, kTestAppUid, 0700 | S_IFDIR);
- CheckFileAccess(cur_profile_file, kTestAppUid, kTestAppUid, 0600 | S_IFREG);
CheckFileAccess(ref_profile_dir, kSystemUid, kTestAppGid, 0770 | S_IFDIR);
}
+TEST_F(ProfileTest, ProfilePrepareOk) {
+ LOG(INFO) << "ProfilePrepareOk";
+ preparePackageProfile(package_name_, "split.prof", /*expected_result*/ true);
+}
+
+TEST_F(ProfileTest, ProfilePrepareFailInvalidPackage) {
+ LOG(INFO) << "ProfilePrepareFailInvalidPackage";
+ preparePackageProfile("not.there.package", "split.prof", /*expected_result*/ false);
+}
+
+TEST_F(ProfileTest, ProfilePrepareFailProfileChangedUid) {
+ LOG(INFO) << "ProfilePrepareFailProfileChangedUid";
+ SetupProfiles(/*setup_ref*/ false);
+ // Change the uid on the profile to trigger a failure.
+ ::chown(cur_profile_.c_str(), kTestAppUid + 1, kTestAppGid + 1);
+ preparePackageProfile(package_name_, "primary.prof", /*expected_result*/ false);
+}
+
+
+class BootProfileTest : public ProfileTest {
+ public:
+ virtual void setup() {
+ ProfileTest::SetUp();
+ intial_android_profiles_dir = android_profiles_dir;
+ }
+
+ virtual void TearDown() {
+ android_profiles_dir = intial_android_profiles_dir;
+ ProfileTest::TearDown();
+ }
+
+ void UpdateAndroidProfilesDir(const std::string& profile_dir) {
+ android_profiles_dir = profile_dir;
+ // We need to create the reference profile directory in the new profile dir.
+ run_cmd("mkdir -p " + profile_dir + "/ref");
+ }
+
+ void createBootImageProfileSnapshot(const std::string& classpath, bool expected_result) {
+ bool result;
+ binder::Status binder_result = service_->createProfileSnapshot(
+ -1, "android", "android.prof", classpath, &result);
+ ASSERT_TRUE(binder_result.isOk());
+ ASSERT_EQ(expected_result, result);
+
+ if (!expected_result) {
+ // Do not check the files if we expect to fail.
+ return;
+ }
+
+ // Check that the snapshot was created with he expected access flags.
+ const std::string boot_profile = create_snapshot_profile_path("android", "android.prof");
+ CheckFileAccess(boot_profile, kSystemUid, kSystemGid, 0600 | S_IFREG);
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ /* child */
+ TransitionToSystemServer();
+
+ // System server should be able to open the snapshot.
+ unique_fd fd(open(boot_profile.c_str(), O_RDONLY));
+ ASSERT_TRUE(fd > -1) << "Failed to open profile as kSystemUid: " << strerror(errno);
+ _exit(0);
+ }
+ /* parent */
+ ASSERT_TRUE(WIFEXITED(wait_child(pid)));
+ }
+ protected:
+ std::string intial_android_profiles_dir;
+};
+
+TEST_F(BootProfileTest, BootProfileSnapshotOk) {
+ LOG(INFO) << "BootProfileSnapshotOk";
+ char* boot_classpath = getenv("BOOTCLASSPATH");
+ ASSERT_TRUE(boot_classpath != nullptr);
+ createBootImageProfileSnapshot(boot_classpath, /*expected_result*/ true);
+}
+
+TEST_F(BootProfileTest, BootProfileSnapshotFailEmptyClasspath) {
+ LOG(INFO) << "BootProfileSnapshotFailEmptyClasspath";
+
+ createBootImageProfileSnapshot(/*boot_classpath*/ "", /*expected_result*/ false);
+}
+
+TEST_F(BootProfileTest, BootProfileSnapshotOkNoProfiles) {
+ LOG(INFO) << "BootProfileSnapshotOkNoProfiles";
+ char* boot_classpath = getenv("BOOTCLASSPATH");
+ ASSERT_TRUE(boot_classpath != nullptr);
+
+ // The app_apk_dir has no profiles. So we shouldn't be able to merge anything.
+ // Still, this is not a failure case.
+ UpdateAndroidProfilesDir(app_apk_dir_);
+ createBootImageProfileSnapshot(boot_classpath, /*expected_result*/ true);
+}
+
+// Verify that profile collection.
+TEST_F(BootProfileTest, CollectProfiles) {
+ LOG(INFO) << "CollectProfiles";
+
+ // Create some profile directories mimicking the real profile structure.
+ run_cmd("mkdir -p " + app_private_dir_de_ + "/profiles/ref");
+ run_cmd("mkdir -p " + app_private_dir_de_ + "/profiles/cur/0/");
+ run_cmd("mkdir -p " + app_private_dir_de_ + "/profiles/cur/1/");
+ // Create an empty profile.
+ run_cmd("touch " + app_private_dir_de_ + "/profiles/cur/1/primary.prof");
+ // Create a random file.
+ run_cmd("touch " + app_private_dir_de_ + "/profiles/cur/0/non.profile.file");
+
+ // Create some non-empty profiles.
+ std::string current_prof = app_private_dir_de_ + "/profiles/cur/0/primary.prof";
+ run_cmd("echo 1 > " + current_prof);
+ std::string ref_prof = app_private_dir_de_ + "/profiles/ref/primary.prof";
+ run_cmd("echo 1 > " + ref_prof);
+
+ UpdateAndroidProfilesDir(app_private_dir_de_ + "/profiles");
+
+ std::vector<std::string> profiles;
+ collect_profiles(&profiles);
+
+ // Only two profiles should be in the output.
+ ASSERT_EQ(2u, profiles.size());
+ ASSERT_TRUE(std::find(profiles.begin(), profiles.end(), current_prof) != profiles.end());
+ ASSERT_TRUE(std::find(profiles.begin(), profiles.end(), ref_prof) != profiles.end());
+}
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/tests/installd_otapreopt_test.cpp b/cmds/installd/tests/installd_otapreopt_test.cpp
new file mode 100644
index 0000000..82bf932
--- /dev/null
+++ b/cmds/installd/tests/installd_otapreopt_test.cpp
@@ -0,0 +1,223 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <android-base/logging.h>
+#include <gtest/gtest.h>
+
+#include "otapreopt_parameters.h"
+
+namespace android {
+namespace installd {
+
+static bool ParseBool(const char* in) {
+ if (strcmp(in, "true") == 0) {
+ return true;
+ }
+ return false;
+}
+
+static const char* ParseNull(const char* arg) {
+ return (strcmp(arg, "!") == 0) ? nullptr : arg;
+}
+
+class OTAPreoptTest : public testing::Test {
+protected:
+ virtual void SetUp() {
+ setenv("ANDROID_LOG_TAGS", "*:f", 1);
+ android::base::InitLogging(nullptr, android::base::StderrLogger);
+ }
+
+ void verifyPackageParameters(const OTAPreoptParameters& params,
+ uint32_t version,
+ bool versioned,
+ const char** args) {
+ // otapreopt target-slot [version] dexopt {DEXOPT_PARAMETERS}
+ int i = 0;
+ if (version > 2 || (version == 2 && versioned)) {
+ i += 4;
+ } else {
+ i += 3;
+ }
+ ASSERT_STREQ(params.target_slot.c_str(), args[1]);
+ ASSERT_STREQ(params.apk_path, args[i++]);
+ ASSERT_EQ(params.uid, static_cast<uid_t>(atoi(args[i++])));
+ ASSERT_STREQ(params.pkgName, args[i++]);
+ ASSERT_STREQ(params.instruction_set, args[i++]);
+ ASSERT_EQ(params.dexopt_needed, atoi(args[i++]));
+ ASSERT_STREQ(params.oat_dir, args[i++]);
+ ASSERT_EQ(params.dexopt_flags, atoi(args[i++]));
+ ASSERT_STREQ(params.compiler_filter, args[i++]);
+ ASSERT_STREQ(params.volume_uuid, ParseNull(args[i++]));
+ ASSERT_STREQ(params.shared_libraries, ParseNull(args[i++]));
+ if (version > 1) {
+ ASSERT_STREQ(params.se_info, ParseNull(args[i++]));
+ } else {
+ ASSERT_EQ(params.se_info, nullptr);
+ }
+ if (version > 2) {
+ ASSERT_EQ(params.downgrade, ParseBool(args[i++]));
+ } else {
+ ASSERT_FALSE(params.downgrade);
+ }
+ if (version > 3) {
+ ASSERT_EQ(params.target_sdk_version, atoi(args[i++]));
+ } else {
+ ASSERT_EQ(params.target_sdk_version, 0);
+ }
+ if (version > 4) {
+ ASSERT_STREQ(params.profile_name, ParseNull(args[i++]));
+ } else {
+ ASSERT_STREQ(params.profile_name, "primary.prof");
+ }
+ if (version > 5) {
+ ASSERT_STREQ(params.dex_metadata_path, ParseNull(args[i++]));
+ } else {
+ ASSERT_EQ(params.dex_metadata_path, nullptr);
+ }
+ if (version > 6) {
+ ASSERT_STREQ(params.compilation_reason, ParseNull(args[i++]));
+ } else {
+ ASSERT_STREQ(params.compilation_reason, "ab-ota");
+ }
+ }
+
+ const char* getVersionCStr(uint32_t version) {
+ switch (version) {
+ case 1: return "1";
+ case 2: return "2";
+ case 3: return "3";
+ case 4: return "4";
+ case 5: return "5";
+ case 6: return "6";
+ case 7: return "7";
+ }
+ return nullptr;
+ }
+
+ std::vector<const char*> getArgs(uint32_t version, bool versioned) {
+ std::vector<const char*> args;
+ args.push_back("otapreopt"); // "otapreopt"
+ args.push_back("a"); // slot
+ if (versioned) {
+ args.push_back(getVersionCStr(version));
+ }
+ args.push_back("dexopt"); // "dexopt"
+ args.push_back("foo.apk"); // apk_path
+ args.push_back("123"); // uid
+ args.push_back("pkgname"); // pkg
+ args.push_back("arm"); // isa
+ args.push_back("1"); // dexopt_needed (DEX2OAT_FROM_SCRATCH)
+ args.push_back("oat_dir"); // oat_dir
+ args.push_back("0"); // dexopt_flags
+ args.push_back("speed"); // filter
+ args.push_back("!"); // volume
+ args.push_back("shared.lib"); // libs
+
+ if (version > 1) {
+ args.push_back("!"); // seinfo
+ }
+ if (version > 2) {
+ args.push_back("true"); // downgrade
+ }
+ if (version > 3) {
+ args.push_back("28"); // sdk_version
+ }
+ if (version > 4) {
+ args.push_back("split_a.prof"); // profile_name
+ }
+ if (version > 5) {
+ args.push_back("dex_metadata.dm"); // dex_metadata_path
+ }
+ if (version > 6) {
+ args.push_back("ab-ota-test"); // compilation_reason
+ }
+ args.push_back(nullptr); // we have to end with null.
+ return args;
+ }
+
+ void VerifyReadArguments(uint32_t version, bool versioned) {
+ OTAPreoptParameters params;
+ std::vector<const char*> args = getArgs(version, versioned);
+ ASSERT_TRUE(params.ReadArguments(args.size() - 1, args.data()));
+ verifyPackageParameters(params, version, versioned, args.data());
+ }
+};
+
+TEST_F(OTAPreoptTest, ReadArgumentsV1) {
+ VerifyReadArguments(1, false);
+}
+
+TEST_F(OTAPreoptTest, ReadArgumentsV2Unversioned) {
+ VerifyReadArguments(2, false);
+}
+
+TEST_F(OTAPreoptTest, ReadArgumentsV2) {
+ VerifyReadArguments(2, true);
+}
+
+TEST_F(OTAPreoptTest, ReadArgumentsV3) {
+ VerifyReadArguments(3, true);
+}
+
+TEST_F(OTAPreoptTest, ReadArgumentsV4) {
+ VerifyReadArguments(4, true);
+}
+
+TEST_F(OTAPreoptTest, ReadArgumentsV5) {
+ VerifyReadArguments(5, true);
+}
+
+TEST_F(OTAPreoptTest, ReadArgumentsV6) {
+ VerifyReadArguments(6, true);
+}
+
+TEST_F(OTAPreoptTest, ReadArgumentsV7) {
+ VerifyReadArguments(7, true);
+}
+
+TEST_F(OTAPreoptTest, ReadArgumentsFailToManyArgs) {
+ OTAPreoptParameters params;
+ std::vector<const char*> args = getArgs(5, true);
+ args[2] = "3"; // pretend it's version 3. It should fail since there are too many args.
+ ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data()));
+}
+
+TEST_F(OTAPreoptTest, ReadArgumentsFailInsufficientArgs) {
+ OTAPreoptParameters params;
+ std::vector<const char*> args = getArgs(4, true);
+ args[2] = "5"; // pretend it's version 5. It should fail since there are insufficient args.
+ ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data()));
+}
+
+TEST_F(OTAPreoptTest, ReadArgumentsFailInvalidDexopt) {
+ OTAPreoptParameters params;
+ std::vector<const char*> args = getArgs(4, true);
+ args[3] = "dexopt-invalid";
+ ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data()));
+}
+
+TEST_F(OTAPreoptTest, ReadArgumentsFailInvalidSlot) {
+ OTAPreoptParameters params;
+ std::vector<const char*> args = getArgs(3, true);
+ args[1] = "invalid-slot???";
+ ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data()));
+}
+
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index ca812bd..a5af5d7 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <sys/statvfs.h>
@@ -56,16 +57,19 @@
return create_cache_path_default(path, src, instruction_set);
}
+static std::string get_full_path(const char* path) {
+ return StringPrintf("/data/local/tmp/user/0/%s", path);
+}
+
static void mkdir(const char* path, uid_t owner, gid_t group, mode_t mode) {
- const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
- ::mkdir(fullPath, mode);
- ::chown(fullPath, owner, group);
- ::chmod(fullPath, mode);
+ const std::string fullPath = get_full_path(path);
+ ::mkdir(fullPath.c_str(), mode);
+ ::chown(fullPath.c_str(), owner, group);
+ ::chmod(fullPath.c_str(), mode);
}
static void touch(const char* path, uid_t owner, gid_t group, mode_t mode) {
- int fd = ::open(StringPrintf("/data/local/tmp/user/0/%s", path).c_str(),
- O_RDWR | O_CREAT, mode);
+ int fd = ::open(get_full_path(path).c_str(), O_RDWR | O_CREAT, mode);
::fchown(fd, owner, group);
::fchmod(fd, mode);
::close(fd);
@@ -73,13 +77,13 @@
static int stat_gid(const char* path) {
struct stat buf;
- ::stat(StringPrintf("/data/local/tmp/user/0/%s", path).c_str(), &buf);
+ ::stat(get_full_path(path).c_str(), &buf);
return buf.st_gid;
}
static int stat_mode(const char* path) {
struct stat buf;
- ::stat(StringPrintf("/data/local/tmp/user/0/%s", path).c_str(), &buf);
+ ::stat(get_full_path(path).c_str(), &buf);
return buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISGID);
}
@@ -149,6 +153,69 @@
EXPECT_EQ(10000, stat_gid("com.example/bar/file"));
}
+TEST_F(ServiceTest, HashSecondaryDex) {
+ LOG(INFO) << "HashSecondaryDex";
+
+ mkdir("com.example", 10000, 10000, 0700);
+ mkdir("com.example/foo", 10000, 10000, 0700);
+ touch("com.example/foo/file", 10000, 20000, 0700);
+
+ std::vector<uint8_t> result;
+ std::string dexPath = get_full_path("com.example/foo/file");
+ EXPECT_TRUE(service->hashSecondaryDexFile(
+ dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+
+ EXPECT_EQ(result.size(), 32U);
+
+ std::ostringstream output;
+ output << std::hex << std::setfill('0');
+ for (auto b : result) {
+ output << std::setw(2) << +b;
+ }
+
+ // This is the SHA256 of an empty string (sha256sum /dev/null)
+ EXPECT_EQ(output.str(), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
+}
+
+TEST_F(ServiceTest, HashSecondaryDex_NoSuch) {
+ LOG(INFO) << "HashSecondaryDex_NoSuch";
+
+ std::vector<uint8_t> result;
+ std::string dexPath = get_full_path("com.example/foo/file");
+ EXPECT_TRUE(service->hashSecondaryDexFile(
+ dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+
+ EXPECT_EQ(result.size(), 0U);
+}
+
+TEST_F(ServiceTest, HashSecondaryDex_Unreadable) {
+ LOG(INFO) << "HashSecondaryDex_Unreadable";
+
+ mkdir("com.example", 10000, 10000, 0700);
+ mkdir("com.example/foo", 10000, 10000, 0700);
+ touch("com.example/foo/file", 10000, 20000, 0300);
+
+ std::vector<uint8_t> result;
+ std::string dexPath = get_full_path("com.example/foo/file");
+ EXPECT_TRUE(service->hashSecondaryDexFile(
+ dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+
+ EXPECT_EQ(result.size(), 0U);
+}
+
+TEST_F(ServiceTest, HashSecondaryDex_WrongApp) {
+ LOG(INFO) << "HashSecondaryDex_WrongApp";
+
+ mkdir("com.example", 10000, 10000, 0700);
+ mkdir("com.example/foo", 10000, 10000, 0700);
+ touch("com.example/foo/file", 10000, 20000, 0700);
+
+ std::vector<uint8_t> result;
+ std::string dexPath = get_full_path("com.example/foo/file");
+ EXPECT_FALSE(service->hashSecondaryDexFile(
+ dexPath, "com.wrong", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+}
+
TEST_F(ServiceTest, CalculateOat) {
char buf[PKG_PATH_MAX];
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 49da85d..bbff6fb 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -337,34 +337,50 @@
}
TEST_F(UtilsTest, CreatePrimaryCurrentProfile) {
- std::string expected =
+ std::string expected_base =
create_primary_current_profile_package_dir_path(0, "com.example") + "/primary.prof";
- EXPECT_EQ(expected,
- create_current_profile_path(/*user*/0, "com.example", /*is_secondary*/false));
+ EXPECT_EQ(expected_base,
+ create_current_profile_path(/*user*/0, "com.example", "primary.prof",
+ /*is_secondary*/false));
+
+ std::string expected_split =
+ create_primary_current_profile_package_dir_path(0, "com.example") + "/split.prof";
+ EXPECT_EQ(expected_split,
+ create_current_profile_path(/*user*/0, "com.example", "split.prof",
+ /*is_secondary*/false));
}
TEST_F(UtilsTest, CreatePrimaryReferenceProfile) {
- std::string expected =
+ std::string expected_base =
create_primary_reference_profile_package_dir_path("com.example") + "/primary.prof";
- EXPECT_EQ(expected,
- create_reference_profile_path("com.example", /*is_secondary*/false));
+ EXPECT_EQ(expected_base,
+ create_reference_profile_path("com.example", "primary.prof", /*is_secondary*/false));
+
+ std::string expected_split =
+ create_primary_reference_profile_package_dir_path("com.example") + "/split.prof";
+ EXPECT_EQ(expected_split,
+ create_reference_profile_path("com.example", "split.prof", /*is_secondary*/false));
}
TEST_F(UtilsTest, CreateProfileSnapshot) {
- std::string expected =
+ std::string expected_base =
create_primary_reference_profile_package_dir_path("com.example") + "/primary.prof.snapshot";
- EXPECT_EQ(expected, create_snapshot_profile_path("com.example", "base.apk"));
+ EXPECT_EQ(expected_base, create_snapshot_profile_path("com.example", "primary.prof"));
+
+ std::string expected_split =
+ create_primary_reference_profile_package_dir_path("com.example") + "/split.prof.snapshot";
+ EXPECT_EQ(expected_split, create_snapshot_profile_path("com.example", "split.prof"));
}
TEST_F(UtilsTest, CreateSecondaryCurrentProfile) {
EXPECT_EQ("/data/user/0/com.example/oat/secondary.dex.cur.prof",
- create_current_profile_path(/*user*/0,
+ create_current_profile_path(/*user*/0, "com.example",
"/data/user/0/com.example/secondary.dex", /*is_secondary*/true));
}
TEST_F(UtilsTest, CreateSecondaryReferenceProfile) {
EXPECT_EQ("/data/user/0/com.example/oat/secondary.dex.prof",
- create_reference_profile_path(
+ create_reference_profile_path("com.example",
"/data/user/0/com.example/secondary.dex", /*is_secondary*/true));
}
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 61c9c8f..a8c32ed 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 @@
// 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 @@
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 @@
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 @@
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 @@
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
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 5391061..b74073c 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -80,10 +80,17 @@
std::string create_primary_reference_profile_package_dir_path(const std::string& package_name);
std::string create_current_profile_path(
- userid_t user, const std::string& package_name, bool is_secondary_dex);
+ userid_t user,
+ const std::string& package_name,
+ const std::string& location,
+ bool is_secondary_dex);
std::string create_reference_profile_path(
- const std::string& package_name, bool is_secondary_dex);
-std::string create_snapshot_profile_path(const std::string& package, const std::string& code_path);
+ const std::string& package_name,
+ const std::string& location,
+ bool is_secondary_dex);
+std::string create_snapshot_profile_path(
+ const std::string& package,
+ const std::string& profile_name);
std::vector<userid_t> get_known_users(const char* volume_uuid);
@@ -129,6 +136,12 @@
int prepare_app_cache_dir(const std::string& parent, const char* name, mode_t target_mode,
uid_t uid, gid_t gid);
+// Collect all non empty profiles from the global profile directory and
+// put 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.
+bool collect_profiles(std::vector<std::string>* profiles_paths);
+
} // namespace installd
} // namespace android
diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
index a2443c0..30e70b0 100644
--- a/libs/binder/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -17,11 +17,11 @@
#include <binder/BufferedTextOutput.h>
#include <binder/Debug.h>
-#include <utils/Atomic.h>
+#include <cutils/atomic.h>
+#include <cutils/threads.h>
#include <utils/Log.h>
#include <utils/RefBase.h>
#include <utils/Vector.h>
-#include <cutils/threads.h>
#include <private/binder/Static.h>
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index da806aa..8606129 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -18,12 +18,12 @@
#include <binder/ProcessState.h>
-#include <utils/Atomic.h>
#include <binder/BpBinder.h>
#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <cutils/atomic.h>
#include <utils/Log.h>
#include <utils/String8.h>
-#include <binder/IServiceManager.h>
#include <utils/String8.h>
#include <utils/threads.h>
diff --git a/libs/vr/libpdx/service_tests.cpp b/libs/vr/libpdx/service_tests.cpp
index c7412b7..e623abf 100644
--- a/libs/vr/libpdx/service_tests.cpp
+++ b/libs/vr/libpdx/service_tests.cpp
@@ -180,8 +180,8 @@
EXPECT_EQ(kTestTid, message.GetThreadId());
EXPECT_EQ(kTestCid, message.GetChannelId());
EXPECT_EQ(kTestMid, message.GetMessageId());
- EXPECT_EQ(kTestEuid, message.GetEffectiveUserId());
- EXPECT_EQ(kTestEgid, message.GetEffectiveGroupId());
+ EXPECT_EQ((unsigned) kTestEuid, message.GetEffectiveUserId());
+ EXPECT_EQ((unsigned) kTestEgid, message.GetEffectiveGroupId());
EXPECT_EQ(kTestOp, message.GetOp());
EXPECT_EQ(service_, message.GetService());
EXPECT_EQ(test_channel, message.GetChannel());
diff --git a/opengl/libagl/BufferObjectManager.cpp b/opengl/libagl/BufferObjectManager.cpp
index 6bf28ee..3d93c19 100644
--- a/opengl/libagl/BufferObjectManager.cpp
+++ b/opengl/libagl/BufferObjectManager.cpp
@@ -18,7 +18,7 @@
#include <stddef.h>
#include <sys/types.h>
-#include <utils/Atomic.h>
+#include <cutils/atomic.h>
#include <utils/RefBase.h>
#include <utils/KeyedVector.h>
#include <utils/Errors.h>
diff --git a/opengl/libagl/TextureObjectManager.h b/opengl/libagl/TextureObjectManager.h
index de9e03e..9cf8771 100644
--- a/opengl/libagl/TextureObjectManager.h
+++ b/opengl/libagl/TextureObjectManager.h
@@ -21,7 +21,7 @@
#include <stddef.h>
#include <sys/types.h>
-#include <utils/Atomic.h>
+#include <cutils/atomic.h>
#include <utils/threads.h>
#include <utils/RefBase.h>
#include <utils/KeyedVector.h>
diff --git a/opengl/tests/gl2_java/Android.mk b/opengl/tests/gl2_java/Android.mk
index 34f4aee..71aa5a0 100644
--- a/opengl/tests/gl2_java/Android.mk
+++ b/opengl/tests/gl2_java/Android.mk
@@ -14,5 +14,6 @@
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := GL2Java
+LOCAL_SDK_VERSION := current
include $(BUILD_PACKAGE)
diff --git a/opengl/tests/gl2_jni/Android.mk b/opengl/tests/gl2_jni/Android.mk
index 409bd73..af65b5f 100644
--- a/opengl/tests/gl2_jni/Android.mk
+++ b/opengl/tests/gl2_jni/Android.mk
@@ -14,6 +14,7 @@
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := GL2JNI
+LOCAL_SDK_VERSION := current
LOCAL_JNI_SHARED_LIBRARIES := libgl2jni
diff --git a/opengl/tests/gl_jni/Android.mk b/opengl/tests/gl_jni/Android.mk
index 11b4c8b..570ae2b 100644
--- a/opengl/tests/gl_jni/Android.mk
+++ b/opengl/tests/gl_jni/Android.mk
@@ -14,6 +14,7 @@
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := GLJNI
+LOCAL_SDK_VERSION := current
LOCAL_JNI_SHARED_LIBRARIES := libgljni
diff --git a/opengl/tests/gldual/Android.mk b/opengl/tests/gldual/Android.mk
index 1991ed9..dc265b6 100644
--- a/opengl/tests/gldual/Android.mk
+++ b/opengl/tests/gldual/Android.mk
@@ -14,6 +14,7 @@
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := GLDual
+LOCAL_SDK_VERSION := current
LOCAL_JNI_SHARED_LIBRARIES := libgldualjni
diff --git a/opengl/tests/lighting1709/Android.mk b/opengl/tests/lighting1709/Android.mk
index 9563e61..0047231 100644
--- a/opengl/tests/lighting1709/Android.mk
+++ b/opengl/tests/lighting1709/Android.mk
@@ -6,6 +6,7 @@
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := LightingTest
+LOCAL_SDK_VERSION := current
LOCAL_CERTIFICATE := platform
include $(BUILD_PACKAGE)
diff --git a/opengl/tests/testFramerate/Android.mk b/opengl/tests/testFramerate/Android.mk
index 500abf3..2864fcf 100644
--- a/opengl/tests/testFramerate/Android.mk
+++ b/opengl/tests/testFramerate/Android.mk
@@ -15,5 +15,6 @@
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := TestFramerate
+LOCAL_PRIVATE_PLATFORM_APIS := true
include $(BUILD_PACKAGE)
diff --git a/opengl/tests/testPauseResume/Android.mk b/opengl/tests/testPauseResume/Android.mk
index cf8bdc3..dda5424 100644
--- a/opengl/tests/testPauseResume/Android.mk
+++ b/opengl/tests/testPauseResume/Android.mk
@@ -14,5 +14,6 @@
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := TestEGL
+LOCAL_SDK_VERSION := current
include $(BUILD_PACKAGE)
diff --git a/services/sensorservice/BatteryService.cpp b/services/sensorservice/BatteryService.cpp
index 330861d..d8e5b29 100644
--- a/services/sensorservice/BatteryService.cpp
+++ b/services/sensorservice/BatteryService.cpp
@@ -18,7 +18,7 @@
#include <math.h>
#include <sys/types.h>
-#include <utils/Atomic.h>
+#include <cutils/atomic.h>
#include <utils/Errors.h>
#include <utils/Singleton.h>
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 535d0db..4daae4d 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -18,7 +18,7 @@
#include <android-base/logging.h>
#include <sensors/convert.h>
-#include <utils/Atomic.h>
+#include <cutils/atomic.h>
#include <utils/Errors.h>
#include <utils/Singleton.h>
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 1b77aaf..821e15c8 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -28,8 +28,8 @@
*/
#include <cutils/compiler.h>
+#include <cutils/atomic.h>
-#include <utils/Atomic.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>