Merge "installd_service_test: fix ServiceTest.CreateAppDataSnapshot_ClearsCache"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 15cea83..a91eafe 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -981,6 +981,8 @@
AddAnrTraceDir(add_to_zip, anr_traces_dir);
+ RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
+
// Slow traces for slow operations.
struct stat st;
int i = 0;
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 65743d9..9d3a234 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -229,16 +229,16 @@
}
// OTA slot script
-cc_prebuilt_binary {
+sh_binary {
name: "otapreopt_slot",
- srcs: ["otapreopt_slot.sh"],
+ src: "otapreopt_slot.sh",
init_rc: ["otapreopt.rc"],
}
// OTA postinstall script
-cc_prebuilt_binary {
+sh_binary {
name: "otapreopt_script",
- srcs: ["otapreopt_script.sh"],
+ src: "otapreopt_script.sh",
// Let this depend on otapreopt, the chroot tool and the slot script,
// so we just have to mention one in a configuration.
required: [
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 940ba79..a639951 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -314,9 +314,15 @@
bool skip_compilation = vold_decrypt == "trigger_restart_min_framework" ||
vold_decrypt == "1";
- const std::string resolve_startup_string_arg =
+ std::string resolve_startup_string_arg =
+ MapPropertyToArg("persist.device_config.runtime.dex2oat_resolve_startup_strings",
+ "--resolve-startup-const-strings=%s");
+ if (resolve_startup_string_arg.empty()) {
+ // If empty, fall back to system property.
+ resolve_startup_string_arg =
MapPropertyToArg("dalvik.vm.dex2oat-resolve-startup-strings",
"--resolve-startup-const-strings=%s");
+ }
const std::string image_block_size_arg =
MapPropertyToArg("dalvik.vm.dex2oat-max-image-block-size",
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index c0f8e91..609ddaf 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -41,6 +41,23 @@
namespace android {
namespace installd {
+// Configuration for bind-mounted Bionic artifacts.
+
+static constexpr const char* kLinkerMountPoint = "/bionic/bin/linker";
+static constexpr const char* kRuntimeLinkerPath = "/apex/com.android.runtime/bin/linker";
+
+static constexpr const char* kBionicLibsMountPointDir = "/bionic/lib/";
+static constexpr const char* kRuntimeBionicLibsDir = "/apex/com.android.runtime/lib/bionic/";
+
+static constexpr const char* kLinkerMountPoint64 = "/bionic/bin/linker64";
+static constexpr const char* kRuntimeLinkerPath64 = "/apex/com.android.runtime/bin/linker64";
+
+static constexpr const char* kBionicLibsMountPointDir64 = "/bionic/lib64/";
+static constexpr const char* kRuntimeBionicLibsDir64 = "/apex/com.android.runtime/lib64/bionic/";
+
+static const std::vector<std::string> kBionicLibFileNames = {"libc.so", "libm.so", "libdl.so"};
+
+
static void CloseDescriptor(int fd) {
if (fd >= 0) {
int result = close(fd);
@@ -58,6 +75,64 @@
}
}
+static std::vector<apex::ApexFile> ActivateApexPackages() {
+ // The logic here is (partially) copied and adapted from
+ // system/apex/apexd/apexd_main.cpp.
+ //
+ // Only scan the APEX directory under /system (within the chroot dir).
+ // Note that this leaves around the loop devices created and used by
+ // libapexd's code, but this is fine, as we expect to reboot soon after.
+ apex::scanPackagesDirAndActivate(apex::kApexPackageSystemDir);
+ return apex::getActivePackages();
+}
+
+static void DeactivateApexPackages(const std::vector<apex::ApexFile>& active_packages) {
+ for (const apex::ApexFile& apex_file : active_packages) {
+ const std::string& package_path = apex_file.GetPath();
+ apex::Status status = apex::deactivatePackage(package_path);
+ if (!status.Ok()) {
+ LOG(ERROR) << "Failed to deactivate " << package_path << ": " << status.ErrorMessage();
+ }
+ }
+}
+
+// Copied from system/core/init/mount_namespace.cpp.
+static bool BindMount(const std::string& source, const std::string& mount_point,
+ bool recursive = false) {
+ unsigned long mountflags = MS_BIND;
+ if (recursive) {
+ mountflags |= MS_REC;
+ }
+ if (mount(source.c_str(), mount_point.c_str(), nullptr, mountflags, nullptr) == -1) {
+ PLOG(ERROR) << "Could not bind-mount " << source << " to " << mount_point;
+ return false;
+ }
+ return true;
+}
+
+// Copied from system/core/init/mount_namespace.cpp and and adjusted (bind
+// mounts are not made private, as the /postinstall is already private (see
+// `android::installd::otapreopt_chroot`).
+static bool BindMountBionic(const std::string& linker_source, const std::string& lib_dir_source,
+ const std::string& linker_mount_point,
+ const std::string& lib_mount_dir) {
+ if (access(linker_source.c_str(), F_OK) != 0) {
+ PLOG(INFO) << linker_source << " does not exist. Skipping mounting Bionic there.";
+ return true;
+ }
+ if (!BindMount(linker_source, linker_mount_point)) {
+ return false;
+ }
+ for (const auto& libname : kBionicLibFileNames) {
+ std::string mount_point = lib_mount_dir + libname;
+ std::string source = lib_dir_source + libname;
+ if (!BindMount(source, mount_point)) {
+ return false;
+ }
+ }
+ return true;
+}
+
// Entry for otapreopt_chroot. Expected parameters are:
// [cmd] [status-fd] [target-slot] "dexopt" [dexopt-params]
// The file descriptor denoted by status-fd will be closed. The rest of the parameters will
@@ -199,15 +274,24 @@
// Try to mount APEX packages in "/apex" in the chroot dir. We need at least
// the Android Runtime APEX, as it is required by otapreopt to run dex2oat.
- // The logic here is (partially) copied and adapted from
- // system/apex/apexd/apexd_main.cpp.
- //
- // Only scan the APEX directory under /system (within the chroot dir).
- // Note that this leaves around the loop devices created and used by
- // libapexd's code, but this is fine, as we expect to reboot soon after.
- apex::scanPackagesDirAndActivate(apex::kApexPackageSystemDir);
- // Collect activated packages.
- std::vector<apex::ApexFile> active_packages = apex::getActivePackages();
+ std::vector<apex::ApexFile> active_packages = ActivateApexPackages();
+
+ // Bind-mount Bionic artifacts from the Runtime APEX.
+ // This logic is copied and adapted from system/core/init/mount_namespace.cpp.
+ if (!BindMountBionic(kRuntimeLinkerPath, kRuntimeBionicLibsDir, kLinkerMountPoint,
+ kBionicLibsMountPointDir)) {
+ LOG(ERROR) << "Failed to mount 32-bit Bionic artifacts from the Runtime APEX.";
+ // Clean up and exit.
+ DeactivateApexPackages(active_packages);
+ exit(215);
+ }
+ if (!BindMountBionic(kRuntimeLinkerPath64, kRuntimeBionicLibsDir64, kLinkerMountPoint64,
+ kBionicLibsMountPointDir64)) {
+ LOG(ERROR) << "Failed to mount 64-bit Bionic artifacts from the Runtime APEX.";
+ // Clean up and exit.
+ DeactivateApexPackages(active_packages);
+ exit(216);
+ }
// Now go on and run otapreopt.
@@ -229,14 +313,8 @@
LOG(ERROR) << "Running otapreopt failed: " << error_msg;
}
- // Tear down the work down by the apexd logic above (i.e. deactivate packages).
- for (const apex::ApexFile& apex_file : active_packages) {
- const std::string& package_path = apex_file.GetPath();
- apex::Status status = apex::deactivatePackage(package_path);
- if (!status.Ok()) {
- LOG(ERROR) << "Failed to deactivate " << package_path << ": " << status.ErrorMessage();
- }
- }
+ // Tear down the work down by the apexd logic. (i.e. deactivate packages).
+ DeactivateApexPackages(active_packages);
if (!exec_result) {
exit(213);
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index e2afe1d..78edce0 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -23,6 +23,8 @@
#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/scopeguard.h>
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
#include <binder/Status.h>
@@ -85,6 +87,23 @@
system(cmd.c_str());
}
+template <typename Visitor>
+static void run_cmd_and_process_output(const std::string& cmd, const Visitor& visitor) {
+ FILE* file = popen(cmd.c_str(), "r");
+ CHECK(file != nullptr) << "Failed to ptrace " << cmd;
+ char* line = nullptr;
+ while (true) {
+ size_t n = 0u;
+ ssize_t value = getline(&line, &n, file);
+ if (value == -1) {
+ break;
+ }
+ visitor(line);
+ }
+ free(line);
+ fclose(file);
+}
+
static int mkdir(const std::string& path, uid_t owner, gid_t group, mode_t mode) {
int ret = ::mkdir(path.c_str(), mode);
if (ret != 0) {
@@ -222,7 +241,8 @@
::testing::AssertionResult create_mock_app() {
// Create the oat dir.
app_oat_dir_ = app_apk_dir_ + "/oat";
- if (mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755) != 0) {
+ // For debug mode, the directory might already exist. Avoid erroring out.
+ if (mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755) != 0 && !kDebug) {
return ::testing::AssertionFailure() << "Could not create app dir " << app_apk_dir_
<< " : " << strerror(errno);
}
@@ -628,6 +648,50 @@
DEX2OAT_FROM_SCRATCH);
}
+TEST_F(DexoptTest, ResolveStartupConstStrings) {
+ LOG(INFO) << "DexoptDex2oatResolveStartupStrings";
+ const std::string property = "persist.device_config.runtime.dex2oat_resolve_startup_strings";
+ const std::string previous_value = android::base::GetProperty(property, "");
+ auto restore_property = android::base::make_scope_guard([=]() {
+ android::base::SetProperty(property, previous_value);
+ });
+ std::string odex = GetPrimaryDexArtifact(app_oat_dir_.c_str(), apk_path_, "odex");
+ // Disable the property to start.
+ bool found_disable = false;
+ ASSERT_TRUE(android::base::SetProperty(property, "false")) << property;
+ CompilePrimaryDexOk("speed-profile",
+ DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PROFILE_GUIDED |
+ DEXOPT_GENERATE_APP_IMAGE,
+ app_oat_dir_.c_str(),
+ kTestAppGid,
+ DEX2OAT_FROM_SCRATCH);
+ run_cmd_and_process_output(
+ "oatdump --header-only --oat-file=" + odex,
+ [&](const std::string& line) {
+ if (line.find("--resolve-startup-const-strings=false") != std::string::npos) {
+ found_disable = true;
+ }
+ });
+ EXPECT_TRUE(found_disable);
+ // Enable the property and inspect that .art artifact is larger.
+ bool found_enable = false;
+ ASSERT_TRUE(android::base::SetProperty(property, "true")) << property;
+ CompilePrimaryDexOk("speed-profile",
+ DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PROFILE_GUIDED |
+ DEXOPT_GENERATE_APP_IMAGE,
+ app_oat_dir_.c_str(),
+ kTestAppGid,
+ DEX2OAT_FROM_SCRATCH);
+ run_cmd_and_process_output(
+ "oatdump --header-only --oat-file=" + odex,
+ [&](const std::string& line) {
+ if (line.find("--resolve-startup-const-strings=true") != std::string::npos) {
+ found_enable = true;
+ }
+ });
+ EXPECT_TRUE(found_enable);
+}
+
class PrimaryDexReCompilationTest : public DexoptTest {
public:
virtual void SetUp() {