Loading cmds/installd/Android.bp +4 −0 Original line number Original line Diff line number Diff line Loading @@ -191,6 +191,10 @@ cc_binary { "libbase", "libbase", "liblog", "liblog", "libutils", "libutils", "libbinder", ], static_libs: [ "ota_dexopt_aidl_interface-cpp", ], ], required: [ required: [ "apexd" "apexd" Loading cmds/installd/otapreopt_chroot.cpp +93 −30 Original line number Original line Diff line number Diff line Loading @@ -21,15 +21,21 @@ #include <sys/wait.h> #include <sys/wait.h> #include <array> #include <array> #include <chrono> #include <fstream> #include <fstream> #include <sstream> #include <sstream> #include <thread> #include <android-base/file.h> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/logging.h> #include <android-base/macros.h> #include <android-base/macros.h> #include <android-base/parseint.h> #include <android-base/scopeguard.h> #include <android-base/scopeguard.h> #include <android-base/stringprintf.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/unique_fd.h> #include <android-base/unique_fd.h> #include <android/content/pm/IOtaDexopt.h> #include <binder/IServiceManager.h> #include <libdm/dm.h> #include <libdm/dm.h> #include <selinux/android.h> #include <selinux/android.h> Loading @@ -45,6 +51,8 @@ using android::base::StringPrintf; namespace android { namespace android { namespace installd { namespace installd { using namespace std::literals::chrono_literals; static void CloseDescriptor(int fd) { static void CloseDescriptor(int fd) { if (fd >= 0) { if (fd >= 0) { int result = close(fd); int result = close(fd); Loading @@ -53,15 +61,6 @@ static void CloseDescriptor(int fd) { } } } } static void CloseDescriptor(const char* descriptor_string) { int fd = -1; std::istringstream stream(descriptor_string); stream >> fd; if (!stream.fail()) { CloseDescriptor(fd); } } static void ActivateApexPackages() { static void ActivateApexPackages() { std::vector<std::string> apexd_cmd{"/system/bin/apexd", "--otachroot-bootstrap"}; std::vector<std::string> apexd_cmd{"/system/bin/apexd", "--otachroot-bootstrap"}; std::string apexd_error_msg; std::string apexd_error_msg; Loading Loading @@ -113,6 +112,38 @@ static void TryExtraMount(const char* name, const char* slot, const char* target UNUSED(mount_result); UNUSED(mount_result); } } static android::sp<android::content::pm::IOtaDexopt> GetDexoptService() { auto binder = android::defaultServiceManager()->getService(android::String16("otadexopt")); if (binder == nullptr) { return nullptr; } return android::interface_cast<android::content::pm::IOtaDexopt>(binder); } static bool RunDexoptCommand(int argc, char **arg, const std::string& dexopt_cmd) { // Incoming: cmd + status-fd + target-slot + cmd... | Incoming | = argc // Outgoing: cmd + target-slot + cmd... | Outgoing | = argc - 1 std::vector<std::string> cmd; cmd.reserve(argc); cmd.push_back("/system/bin/otapreopt"); // The first parameter is the status file descriptor, skip. for (size_t i = 2; i < static_cast<size_t>(argc); ++i) { cmd.push_back(arg[i]); } for (const std::string& part : android::base::Split(dexopt_cmd, " ")) { cmd.push_back(part); } // Fork and execute otapreopt in its own process. std::string error_msg; bool exec_result = Exec(cmd, &error_msg); if (!exec_result) { LOG(ERROR) << "Running otapreopt failed: " << error_msg; } return exec_result; } // Entry for otapreopt_chroot. Expected parameters are: // Entry for otapreopt_chroot. Expected parameters are: // [cmd] [status-fd] [target-slot] "dexopt" [dexopt-params] // [cmd] [status-fd] [target-slot] "dexopt" [dexopt-params] // The file descriptor denoted by status-fd will be closed. The rest of the parameters will // The file descriptor denoted by status-fd will be closed. The rest of the parameters will Loading @@ -130,8 +161,18 @@ static int otapreopt_chroot(const int argc, char **arg) { CloseDescriptor(STDIN_FILENO); CloseDescriptor(STDIN_FILENO); CloseDescriptor(STDOUT_FILENO); CloseDescriptor(STDOUT_FILENO); CloseDescriptor(STDERR_FILENO); CloseDescriptor(STDERR_FILENO); // 2) The status channel. CloseDescriptor(arg[1]); int fd; if (!android::base::ParseInt(arg[1], &fd)) { LOG(ERROR) << "Failed to parse " << arg[1]; exit(225); } // Add O_CLOEXEC to status channel, since we don't want to pass it across fork/exec, but we need // to keep it open in otapreopt_chroot to report progress if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { PLOG(ERROR) << "Failed to set O_CLOEXEC on " << fd; exit(226); } // We need to run the otapreopt tool from the postinstall partition. As such, set up a // We need to run the otapreopt tool from the postinstall partition. As such, set up a // mount namespace and change root. // mount namespace and change root. Loading Loading @@ -313,28 +354,50 @@ static int otapreopt_chroot(const int argc, char **arg) { exit(218); exit(218); } } // Now go on and run otapreopt. android::sp<android::content::pm::IOtaDexopt> dexopt = GetDexoptService(); if (dexopt == nullptr) { // Incoming: cmd + status-fd + target-slot + cmd... | Incoming | = argc LOG(ERROR) << "Failed to find otadexopt service"; // Outgoing: cmd + target-slot + cmd... | Outgoing | = argc - 1 exit(222); std::vector<std::string> cmd; } cmd.reserve(argc); cmd.push_back("/system/bin/otapreopt"); // The first parameter is the status file descriptor, skip. android::base::borrowed_fd status_fd(fd); for (size_t i = 2; i < static_cast<size_t>(argc); ++i) { // Now go on and run otapreopt. cmd.push_back(arg[i]); constexpr const int kMaximumPackages = 1000; for (int iter = 0; iter < kMaximumPackages; iter++) { android::String16 cmd; android::binder::Status status = dexopt->nextDexoptCommand(&cmd); if (!status.isOk()) { LOG(ERROR) << "Failed to retrieve next dexopt command"; // Should we fail instead? exit(224); } if (!RunDexoptCommand(argc, arg, android::String8(cmd).string())) { exit(213); } } // Fork and execute otapreopt in its own process. float progress; std::string error_msg; status = dexopt->getProgress(&progress); bool exec_result = Exec(cmd, &error_msg); if (!status.isOk()) { if (!exec_result) { LOG(ERROR) << "Failed to retrieve dexopt progress"; LOG(ERROR) << "Running otapreopt failed: " << error_msg; continue; } LOG(VERBOSE) << "Progress: " << progress; std::string progress_str = StringPrintf("global_progress %.2f\n", progress); if (!android::base::WriteStringToFd(progress_str, status_fd)) { PLOG(ERROR) << "Failed to write '" << progress_str << "' to " << status_fd.get(); } } if (!exec_result) { bool done; exit(213); status = dexopt->isDone(&done); if (!status.isOk()) { LOG(WARNING) << "Failed to check if dexopt is done"; continue; } if (done) { LOG(INFO) << "dexopt is done"; break; } std::this_thread::sleep_for(1s); } } return 0; return 0; Loading cmds/installd/otapreopt_script.sh +1 −17 Original line number Original line Diff line number Diff line Loading @@ -58,24 +58,8 @@ PREPARE=$(cmd otadexopt prepare) PROGRESS=$(cmd otadexopt progress) PROGRESS=$(cmd otadexopt progress) print -u${STATUS_FD} "global_progress $PROGRESS" print -u${STATUS_FD} "global_progress $PROGRESS" i=0 while ((i<MAXIMUM_PACKAGES)) ; do DEXOPT_PARAMS=$(cmd otadexopt next) /system/bin/otapreopt_chroot $STATUS_FD $TARGET_SLOT_SUFFIX $DEXOPT_PARAMS >&- 2>&- /system/bin/otapreopt_chroot $STATUS_FD $TARGET_SLOT_SUFFIX $DEXOPT_PARAMS >&- 2>&- PROGRESS=$(cmd otadexopt progress) print -u${STATUS_FD} "global_progress $PROGRESS" DONE=$(cmd otadexopt done) if [ "$DONE" = "OTA incomplete." ] ; then sleep 1 i=$((i+1)) continue fi break done DONE=$(cmd otadexopt done) DONE=$(cmd otadexopt done) if [ "$DONE" = "OTA incomplete." ] ; then if [ "$DONE" = "OTA incomplete." ] ; then echo "Incomplete." echo "Incomplete." Loading Loading
cmds/installd/Android.bp +4 −0 Original line number Original line Diff line number Diff line Loading @@ -191,6 +191,10 @@ cc_binary { "libbase", "libbase", "liblog", "liblog", "libutils", "libutils", "libbinder", ], static_libs: [ "ota_dexopt_aidl_interface-cpp", ], ], required: [ required: [ "apexd" "apexd" Loading
cmds/installd/otapreopt_chroot.cpp +93 −30 Original line number Original line Diff line number Diff line Loading @@ -21,15 +21,21 @@ #include <sys/wait.h> #include <sys/wait.h> #include <array> #include <array> #include <chrono> #include <fstream> #include <fstream> #include <sstream> #include <sstream> #include <thread> #include <android-base/file.h> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/logging.h> #include <android-base/macros.h> #include <android-base/macros.h> #include <android-base/parseint.h> #include <android-base/scopeguard.h> #include <android-base/scopeguard.h> #include <android-base/stringprintf.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/unique_fd.h> #include <android-base/unique_fd.h> #include <android/content/pm/IOtaDexopt.h> #include <binder/IServiceManager.h> #include <libdm/dm.h> #include <libdm/dm.h> #include <selinux/android.h> #include <selinux/android.h> Loading @@ -45,6 +51,8 @@ using android::base::StringPrintf; namespace android { namespace android { namespace installd { namespace installd { using namespace std::literals::chrono_literals; static void CloseDescriptor(int fd) { static void CloseDescriptor(int fd) { if (fd >= 0) { if (fd >= 0) { int result = close(fd); int result = close(fd); Loading @@ -53,15 +61,6 @@ static void CloseDescriptor(int fd) { } } } } static void CloseDescriptor(const char* descriptor_string) { int fd = -1; std::istringstream stream(descriptor_string); stream >> fd; if (!stream.fail()) { CloseDescriptor(fd); } } static void ActivateApexPackages() { static void ActivateApexPackages() { std::vector<std::string> apexd_cmd{"/system/bin/apexd", "--otachroot-bootstrap"}; std::vector<std::string> apexd_cmd{"/system/bin/apexd", "--otachroot-bootstrap"}; std::string apexd_error_msg; std::string apexd_error_msg; Loading Loading @@ -113,6 +112,38 @@ static void TryExtraMount(const char* name, const char* slot, const char* target UNUSED(mount_result); UNUSED(mount_result); } } static android::sp<android::content::pm::IOtaDexopt> GetDexoptService() { auto binder = android::defaultServiceManager()->getService(android::String16("otadexopt")); if (binder == nullptr) { return nullptr; } return android::interface_cast<android::content::pm::IOtaDexopt>(binder); } static bool RunDexoptCommand(int argc, char **arg, const std::string& dexopt_cmd) { // Incoming: cmd + status-fd + target-slot + cmd... | Incoming | = argc // Outgoing: cmd + target-slot + cmd... | Outgoing | = argc - 1 std::vector<std::string> cmd; cmd.reserve(argc); cmd.push_back("/system/bin/otapreopt"); // The first parameter is the status file descriptor, skip. for (size_t i = 2; i < static_cast<size_t>(argc); ++i) { cmd.push_back(arg[i]); } for (const std::string& part : android::base::Split(dexopt_cmd, " ")) { cmd.push_back(part); } // Fork and execute otapreopt in its own process. std::string error_msg; bool exec_result = Exec(cmd, &error_msg); if (!exec_result) { LOG(ERROR) << "Running otapreopt failed: " << error_msg; } return exec_result; } // Entry for otapreopt_chroot. Expected parameters are: // Entry for otapreopt_chroot. Expected parameters are: // [cmd] [status-fd] [target-slot] "dexopt" [dexopt-params] // [cmd] [status-fd] [target-slot] "dexopt" [dexopt-params] // The file descriptor denoted by status-fd will be closed. The rest of the parameters will // The file descriptor denoted by status-fd will be closed. The rest of the parameters will Loading @@ -130,8 +161,18 @@ static int otapreopt_chroot(const int argc, char **arg) { CloseDescriptor(STDIN_FILENO); CloseDescriptor(STDIN_FILENO); CloseDescriptor(STDOUT_FILENO); CloseDescriptor(STDOUT_FILENO); CloseDescriptor(STDERR_FILENO); CloseDescriptor(STDERR_FILENO); // 2) The status channel. CloseDescriptor(arg[1]); int fd; if (!android::base::ParseInt(arg[1], &fd)) { LOG(ERROR) << "Failed to parse " << arg[1]; exit(225); } // Add O_CLOEXEC to status channel, since we don't want to pass it across fork/exec, but we need // to keep it open in otapreopt_chroot to report progress if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { PLOG(ERROR) << "Failed to set O_CLOEXEC on " << fd; exit(226); } // We need to run the otapreopt tool from the postinstall partition. As such, set up a // We need to run the otapreopt tool from the postinstall partition. As such, set up a // mount namespace and change root. // mount namespace and change root. Loading Loading @@ -313,28 +354,50 @@ static int otapreopt_chroot(const int argc, char **arg) { exit(218); exit(218); } } // Now go on and run otapreopt. android::sp<android::content::pm::IOtaDexopt> dexopt = GetDexoptService(); if (dexopt == nullptr) { // Incoming: cmd + status-fd + target-slot + cmd... | Incoming | = argc LOG(ERROR) << "Failed to find otadexopt service"; // Outgoing: cmd + target-slot + cmd... | Outgoing | = argc - 1 exit(222); std::vector<std::string> cmd; } cmd.reserve(argc); cmd.push_back("/system/bin/otapreopt"); // The first parameter is the status file descriptor, skip. android::base::borrowed_fd status_fd(fd); for (size_t i = 2; i < static_cast<size_t>(argc); ++i) { // Now go on and run otapreopt. cmd.push_back(arg[i]); constexpr const int kMaximumPackages = 1000; for (int iter = 0; iter < kMaximumPackages; iter++) { android::String16 cmd; android::binder::Status status = dexopt->nextDexoptCommand(&cmd); if (!status.isOk()) { LOG(ERROR) << "Failed to retrieve next dexopt command"; // Should we fail instead? exit(224); } if (!RunDexoptCommand(argc, arg, android::String8(cmd).string())) { exit(213); } } // Fork and execute otapreopt in its own process. float progress; std::string error_msg; status = dexopt->getProgress(&progress); bool exec_result = Exec(cmd, &error_msg); if (!status.isOk()) { if (!exec_result) { LOG(ERROR) << "Failed to retrieve dexopt progress"; LOG(ERROR) << "Running otapreopt failed: " << error_msg; continue; } LOG(VERBOSE) << "Progress: " << progress; std::string progress_str = StringPrintf("global_progress %.2f\n", progress); if (!android::base::WriteStringToFd(progress_str, status_fd)) { PLOG(ERROR) << "Failed to write '" << progress_str << "' to " << status_fd.get(); } } if (!exec_result) { bool done; exit(213); status = dexopt->isDone(&done); if (!status.isOk()) { LOG(WARNING) << "Failed to check if dexopt is done"; continue; } if (done) { LOG(INFO) << "dexopt is done"; break; } std::this_thread::sleep_for(1s); } } return 0; return 0; Loading
cmds/installd/otapreopt_script.sh +1 −17 Original line number Original line Diff line number Diff line Loading @@ -58,24 +58,8 @@ PREPARE=$(cmd otadexopt prepare) PROGRESS=$(cmd otadexopt progress) PROGRESS=$(cmd otadexopt progress) print -u${STATUS_FD} "global_progress $PROGRESS" print -u${STATUS_FD} "global_progress $PROGRESS" i=0 while ((i<MAXIMUM_PACKAGES)) ; do DEXOPT_PARAMS=$(cmd otadexopt next) /system/bin/otapreopt_chroot $STATUS_FD $TARGET_SLOT_SUFFIX $DEXOPT_PARAMS >&- 2>&- /system/bin/otapreopt_chroot $STATUS_FD $TARGET_SLOT_SUFFIX $DEXOPT_PARAMS >&- 2>&- PROGRESS=$(cmd otadexopt progress) print -u${STATUS_FD} "global_progress $PROGRESS" DONE=$(cmd otadexopt done) if [ "$DONE" = "OTA incomplete." ] ; then sleep 1 i=$((i+1)) continue fi break done DONE=$(cmd otadexopt done) DONE=$(cmd otadexopt done) if [ "$DONE" = "OTA incomplete." ] ; then if [ "$DONE" = "OTA incomplete." ] ; then echo "Incomplete." echo "Incomplete." Loading