diff options
-rw-r--r-- | Android.bp | 1 | ||||
-rw-r--r-- | fsck_unshare_blocks.cpp | 151 | ||||
-rw-r--r-- | fsck_unshare_blocks.h | 22 | ||||
-rw-r--r-- | recovery.cpp | 76 |
4 files changed, 64 insertions, 186 deletions
diff --git a/Android.bp b/Android.bp index c5225cc8b..8e29dc8fd 100644 --- a/Android.bp +++ b/Android.bp @@ -91,7 +91,6 @@ cc_library_static { ], srcs: [ - "fsck_unshare_blocks.cpp", "recovery.cpp", ], diff --git a/fsck_unshare_blocks.cpp b/fsck_unshare_blocks.cpp deleted file mode 100644 index e0b2d966b..000000000 --- a/fsck_unshare_blocks.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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 "fsck_unshare_blocks.h" - -#include <errno.h> -#include <fcntl.h> -#include <spawn.h> -#include <string.h> -#include <sys/mount.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> - -#include <algorithm> -#include <memory> -#include <string> -#include <vector> - -#include <android-base/logging.h> -#include <android-base/properties.h> -#include <android-base/unique_fd.h> -#include <fs_mgr/roots.h> - -#include "recovery_utils/roots.h" - -static constexpr const char* SYSTEM_E2FSCK_BIN = "/system/bin/e2fsck_static"; -static constexpr const char* TMP_E2FSCK_BIN = "/tmp/e2fsck.bin"; - -static bool copy_file(const char* source, const char* dest) { - android::base::unique_fd source_fd(open(source, O_RDONLY)); - if (source_fd < 0) { - PLOG(ERROR) << "open %s failed" << source; - return false; - } - - android::base::unique_fd dest_fd(open(dest, O_CREAT | O_WRONLY, S_IRWXU)); - if (dest_fd < 0) { - PLOG(ERROR) << "open %s failed" << dest; - return false; - } - - for (;;) { - char buf[4096]; - ssize_t rv = read(source_fd, buf, sizeof(buf)); - if (rv < 0) { - PLOG(ERROR) << "read failed"; - return false; - } - if (rv == 0) { - break; - } - if (write(dest_fd, buf, rv) != rv) { - PLOG(ERROR) << "write failed"; - return false; - } - } - return true; -} - -static bool run_e2fsck(const std::string& partition) { - Volume* volume = volume_for_mount_point(partition); - if (!volume) { - LOG(INFO) << "No fstab entry for " << partition << ", skipping."; - return true; - } - - LOG(INFO) << "Running e2fsck on device " << volume->blk_device; - - std::vector<std::string> args = { TMP_E2FSCK_BIN, "-p", "-E", "unshare_blocks", - volume->blk_device }; - std::vector<char*> argv(args.size()); - std::transform(args.cbegin(), args.cend(), argv.begin(), - [](const std::string& arg) { return const_cast<char*>(arg.c_str()); }); - argv.push_back(nullptr); - - pid_t child; - char* env[] = { nullptr }; - if (posix_spawn(&child, argv[0], nullptr, nullptr, argv.data(), env)) { - PLOG(ERROR) << "posix_spawn failed"; - return false; - } - - int status = 0; - int ret = TEMP_FAILURE_RETRY(waitpid(child, &status, 0)); - if (ret < 0) { - PLOG(ERROR) << "waitpid failed"; - return false; - } - if (!WIFEXITED(status)) { - LOG(ERROR) << "e2fsck exited abnormally: " << status; - return false; - } - int return_code = WEXITSTATUS(status); - if (return_code >= 8) { - LOG(ERROR) << "e2fsck could not unshare blocks: " << return_code; - return false; - } - - LOG(INFO) << "Successfully unshared blocks on " << partition; - return true; -} - -bool do_fsck_unshare_blocks() { - // List of partitions we will try to e2fsck -E unshare_blocks. - std::vector<std::string> partitions = { "/odm", "/oem", "/product", "/vendor" }; - - // Temporarily mount system so we can copy e2fsck_static. - auto system_root = android::fs_mgr::GetSystemRoot(); - bool mounted = ensure_path_mounted_at(system_root, "/mnt/system") != -1; - partitions.push_back(system_root); - - if (!mounted) { - LOG(ERROR) << "Failed to mount system image."; - return false; - } - if (!copy_file(SYSTEM_E2FSCK_BIN, TMP_E2FSCK_BIN)) { - LOG(ERROR) << "Could not copy e2fsck to /tmp."; - return false; - } - if (umount("/mnt/system") < 0) { - PLOG(ERROR) << "umount failed"; - return false; - } - - bool ok = true; - for (const auto& partition : partitions) { - ok &= run_e2fsck(partition); - } - - if (ok) { - LOG(INFO) << "Finished running e2fsck."; - } else { - LOG(ERROR) << "Finished running e2fsck, but not all partitions succceeded."; - } - return ok; -} diff --git a/fsck_unshare_blocks.h b/fsck_unshare_blocks.h deleted file mode 100644 index 9de8ef9a3..000000000 --- a/fsck_unshare_blocks.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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. - */ - -#ifndef _FILESYSTEM_CMDS_H -#define _FILESYSTEM_CMDS_H - -bool do_fsck_unshare_blocks(); - -#endif // _FILESYSTEM_CMDS_H diff --git a/recovery.cpp b/recovery.cpp index 582ca48a5..c3976aa9c 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -45,7 +45,6 @@ #include <ziparchive/zip_archive.h> #include "bootloader_message/bootloader_message.h" -#include "fsck_unshare_blocks.h" #include "install/adb_install.h" #include "install/fuse_install.h" #include "install/install.h" @@ -311,6 +310,62 @@ static void run_graphics_test(RecoveryUI* ui) { ui->ShowText(true); } +static bool AskToReboot(Device* device, Device::BuiltinAction chosen_action, InstallResult status) { + switch (status) { + case INSTALL_SUCCESS: + case INSTALL_NONE: + case INSTALL_SKIPPED: + case INSTALL_RETRY: + case INSTALL_KEY_INTERRUPTED: + // okay to reboot; no need to ask. + return true; + case INSTALL_ERROR: + case INSTALL_CORRUPT: + // need to ask + break; + case INSTALL_REBOOT: + // All the reboots should have been handled prior to entering AskToReboot() or immediately + // after installing a package. + LOG(FATAL) << "Invalid status code of INSTALL_REBOOT"; + break; + } + + bool is_non_ab = android::base::GetProperty("ro.boot.slot_suffix", "").empty(); + bool is_virtual_ab = android::base::GetBoolProperty("ro.virtual_ab.enabled", false); + if (!is_non_ab && !is_virtual_ab) { + // Only prompt for non-A/B or Virtual A/B devices. + return true; + } + + std::string header_text; + std::string item_text; + switch (chosen_action) { + case Device::REBOOT: + header_text = "reboot"; + item_text = " Reboot system now"; + break; + case Device::SHUTDOWN: + header_text = "power off"; + item_text = " Power off"; + break; + default: + LOG(FATAL) << "Invalid chosen action " << chosen_action; + break; + } + + std::vector<std::string> headers{ "Previous installation has failed.", + " Your device may fail to boot if you " + header_text + + " now.", + " Confirm reboot?" }; + std::vector<std::string> items{ " Cancel", item_text }; + + size_t chosen_item = device->GetUI()->ShowMenu( + headers, items, 0, true /* menu_only */, + std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2)); + + return (chosen_item == 1); +} + // Shows the recovery UI and waits for user input. Returns one of the device builtin actions, such // as REBOOT, SHUTDOWN, or REBOOT_BOOTLOADER. Returning NO_ACTION means to take the default, which // is to reboot or shutdown depending on if the --shutdown_after flag was passed to recovery. @@ -362,14 +417,19 @@ static Device::BuiltinAction PromptAndWait(Device* device, InstallResult status) case Device::ENTER_FASTBOOT: case Device::ENTER_RECOVERY: - case Device::REBOOT: case Device::REBOOT_BOOTLOADER: case Device::REBOOT_FASTBOOT: case Device::REBOOT_RECOVERY: case Device::REBOOT_RESCUE: - case Device::SHUTDOWN: return chosen_action; + case Device::REBOOT: + case Device::SHUTDOWN: + if (!ui->IsTextVisible() || AskToReboot(device, chosen_action, status)) { + return Device::REBOOT; + } + break; + case Device::WIPE_DATA: save_current_log = true; if (ui->IsTextVisible()) { @@ -524,7 +584,6 @@ static void log_failure_code(ErrorCode code, const std::string& update_package) Device::BuiltinAction start_recovery(Device* device, const std::vector<std::string>& args) { static constexpr struct option OPTIONS[] = { { "fastboot", no_argument, nullptr, 0 }, - { "fsck_unshare_blocks", no_argument, nullptr, 0 }, { "install_with_fuse", no_argument, nullptr, 0 }, { "just_exit", no_argument, nullptr, 'x' }, { "locale", required_argument, nullptr, 0 }, @@ -557,7 +616,6 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri bool rescue = false; bool just_exit = false; bool shutdown_after = false; - bool fsck_unshare_blocks = false; int retry_count = 0; bool security_update = false; std::string locale; @@ -580,9 +638,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri break; case 0: { std::string option = OPTIONS[option_index].name; - if (option == "fsck_unshare_blocks") { - fsck_unshare_blocks = true; - } else if (option == "install_with_fuse") { + if (option == "install_with_fuse") { install_with_fuse = true; } else if (option == "locale" || option == "fastboot" || option == "reason") { // Handled in recovery_main.cpp @@ -777,10 +833,6 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri save_current_log = true; status = ApplyFromAdb(device, true /* rescue_mode */, &next_action); ui->Print("\nInstall from ADB complete (status: %d).\n", status); - } else if (fsck_unshare_blocks) { - if (!do_fsck_unshare_blocks()) { - status = INSTALL_ERROR; - } } else if (!just_exit) { // If this is an eng or userdebug build, automatically turn on the text display if no command // is specified. Note that this should be called before setting the background to avoid |