From fedeef6f6d1f7b8f1e5a8b9e77f8dc21ef6b3c95 Mon Sep 17 00:00:00 2001 From: xunchang Date: Mon, 22 Apr 2019 12:18:14 -0700 Subject: Support wipe command in rescue mode Bug: 131037235 Test: unit tests pass, run `adb rescue wipe` Change-Id: I22668f2c98fe2d9195d2561f961c28a7c08e712c --- install/adb_install.cpp | 23 ++++++++++++------ install/include/install/adb_install.h | 3 +-- minadbd/minadbd_services.cpp | 46 ++++++++++++++++++++++++++++++----- minadbd/minadbd_services_test.cpp | 2 +- minadbd/minadbd_types.h | 4 ++- recovery.cpp | 8 +++--- 6 files changed, 64 insertions(+), 22 deletions(-) diff --git a/install/adb_install.cpp b/install/adb_install.cpp index 9dfe0407f..4dd1f1b09 100644 --- a/install/adb_install.cpp +++ b/install/adb_install.cpp @@ -43,6 +43,7 @@ #include "fuse_sideload.h" #include "install/install.h" +#include "install/wipe_data.h" #include "minadbd_types.h" #include "otautil/sysutil.h" #include "recovery_ui/device.h" @@ -330,7 +331,7 @@ static void CreateMinadbdServiceAndExecuteCommands( signal(SIGPIPE, SIG_DFL); } -int ApplyFromAdb(RecoveryUI* ui, bool rescue_mode, Device::BuiltinAction* reboot_action) { +int ApplyFromAdb(Device* device, bool rescue_mode, Device::BuiltinAction* reboot_action) { // Save the usb state to restore after the sideload operation. std::string usb_state = android::base::GetProperty("sys.usb.state", "none"); // Clean up state and stop adbd. @@ -339,13 +340,7 @@ int ApplyFromAdb(RecoveryUI* ui, bool rescue_mode, Device::BuiltinAction* reboot return INSTALL_ERROR; } - if (!rescue_mode) { - ui->Print( - "\n\nNow send the package you want to apply\n" - "to the device with \"adb sideload \"...\n"); - } else { - ui->Print("\n\nWaiting for rescue commands...\n"); - } + RecoveryUI* ui = device->GetUI(); int install_result = INSTALL_ERROR; std::map command_map{ @@ -363,6 +358,18 @@ int ApplyFromAdb(RecoveryUI* ui, bool rescue_mode, Device::BuiltinAction* reboot std::bind(&AdbRebootHandler, MinadbdCommand::kRebootRescue, &install_result, reboot_action) }, }; + if (!rescue_mode) { + ui->Print( + "\n\nNow send the package you want to apply\n" + "to the device with \"adb sideload \"...\n"); + } else { + ui->Print("\n\nWaiting for rescue commands...\n"); + command_map.emplace(MinadbdCommand::kWipeData, [&device]() { + bool result = WipeData(device, false); + return std::make_pair(result, true); + }); + } + CreateMinadbdServiceAndExecuteCommands(ui, command_map, rescue_mode); // Clean up before switching to the older state, for example setting the state diff --git a/install/include/install/adb_install.h b/install/include/install/adb_install.h index 49b32b54f..3a0a81747 100644 --- a/install/include/install/adb_install.h +++ b/install/include/install/adb_install.h @@ -17,9 +17,8 @@ #pragma once #include -#include // Applies a package via `adb sideload` or `adb rescue`. Returns the install result (in `enum // InstallResult`). When a reboot has been requested, INSTALL_REBOOT will be the return value, with // the reboot target set in reboot_action. -int ApplyFromAdb(RecoveryUI* ui, bool rescue_mode, Device::BuiltinAction* reboot_action); +int ApplyFromAdb(Device* device, bool rescue_mode, Device::BuiltinAction* reboot_action); diff --git a/minadbd/minadbd_services.cpp b/minadbd/minadbd_services.cpp index 9b1999d90..1c4c0f494 100644 --- a/minadbd/minadbd_services.cpp +++ b/minadbd/minadbd_services.cpp @@ -104,7 +104,7 @@ static MinadbdErrorCode RunAdbFuseSideload(int sfd, const std::string& args, if (pieces.size() != 2 || !android::base::ParseInt(pieces[0], &file_size) || file_size <= 0 || !android::base::ParseInt(pieces[1], &block_size) || block_size <= 0) { LOG(ERROR) << "bad sideload-host arguments: " << args; - return kMinadbdPackageSizeError; + return kMinadbdHostCommandArgumentError; } LOG(INFO) << "sideload-host file size " << file_size << ", block size " << block_size; @@ -124,17 +124,17 @@ static MinadbdErrorCode RunAdbFuseSideload(int sfd, const std::string& args, return kMinadbdMessageFormatError; } - // Signal host-side adb to stop. For sideload mode, we always send kSideloadServiceExitSuccess + // Signal host-side adb to stop. For sideload mode, we always send kMinadbdServicesExitSuccess // (i.e. "DONEDONE") regardless of the install result. For rescue mode, we send failure message on // install error. if (!rescue_mode || *status == MinadbdCommandStatus::kSuccess) { - if (!android::base::WriteFully(sfd, kSideloadServiceExitSuccess, - strlen(kSideloadServiceExitSuccess))) { + if (!android::base::WriteFully(sfd, kMinadbdServicesExitSuccess, + strlen(kMinadbdServicesExitSuccess))) { return kMinadbdHostSocketIOError; } } else { - if (!android::base::WriteFully(sfd, kSideloadServiceExitFailure, - strlen(kSideloadServiceExitFailure))) { + if (!android::base::WriteFully(sfd, kMinadbdServicesExitFailure, + strlen(kMinadbdServicesExitFailure))) { return kMinadbdHostSocketIOError; } } @@ -200,6 +200,34 @@ static void RebootHostService(unique_fd /* sfd */, const std::string& target) { } } +static void WipeDeviceService(unique_fd fd, const std::string& args) { + auto pieces = android::base::Split(args, ":"); + if (pieces.size() != 2 || pieces[0] != "userdata") { + LOG(ERROR) << "Failed to parse wipe device command arguments " << args; + exit(kMinadbdHostCommandArgumentError); + } + + size_t message_size; + if (!android::base::ParseUint(pieces[1], &message_size) || + message_size < strlen(kMinadbdServicesExitSuccess)) { + LOG(ERROR) << "Failed to parse wipe device message size in " << args; + exit(kMinadbdHostCommandArgumentError); + } + + WriteCommandToFd(MinadbdCommand::kWipeData, minadbd_socket); + MinadbdCommandStatus status; + if (!WaitForCommandStatus(minadbd_socket, &status)) { + exit(kMinadbdMessageFormatError); + } + + std::string response = (status == MinadbdCommandStatus::kSuccess) ? kMinadbdServicesExitSuccess + : kMinadbdServicesExitFailure; + response += std::string(message_size - response.size(), '\0'); + if (!android::base::WriteFully(fd, response.c_str(), response.size())) { + exit(kMinadbdHostSocketIOError); + } +} + unique_fd daemon_service_to_fd(std::string_view name, atransport* /* transport */) { // Common services that are supported both in sideload and rescue modes. if (ConsumePrefix(&name, "reboot:")) { @@ -225,7 +253,13 @@ unique_fd daemon_service_to_fd(std::string_view name, atransport* /* transport * std::string args(name); return create_service_thread( "rescue-getprop", std::bind(RescueGetpropHostService, std::placeholders::_1, args)); + } else if (ConsumePrefix(&name, "rescue-wipe:")) { + // rescue-wipe:target: + std::string args(name); + return create_service_thread("rescue-wipe", + std::bind(WipeDeviceService, std::placeholders::_1, args)); } + return unique_fd{}; } diff --git a/minadbd/minadbd_services_test.cpp b/minadbd/minadbd_services_test.cpp index 593180bb3..f87873792 100644 --- a/minadbd/minadbd_services_test.cpp +++ b/minadbd/minadbd_services_test.cpp @@ -122,7 +122,7 @@ class MinadbdServicesTest : public ::testing::Test { TEST_F(MinadbdServicesTest, SideloadHostService_wrong_size_argument) { ASSERT_EXIT(ExecuteCommandAndWaitForExit("sideload-host:abc:4096"), - ::testing::ExitedWithCode(kMinadbdPackageSizeError), ""); + ::testing::ExitedWithCode(kMinadbdHostCommandArgumentError), ""); } TEST_F(MinadbdServicesTest, SideloadHostService_wrong_block_size) { diff --git a/minadbd/minadbd_types.h b/minadbd/minadbd_types.h index b370b7952..99fd45e83 100644 --- a/minadbd/minadbd_types.h +++ b/minadbd/minadbd_types.h @@ -30,7 +30,7 @@ enum MinadbdErrorCode : int { kMinadbdSocketIOError = 2, kMinadbdMessageFormatError = 3, kMinadbdAdbVersionError = 4, - kMinadbdPackageSizeError = 5, + kMinadbdHostCommandArgumentError = 5, kMinadbdFuseStartError = 6, kMinadbdUnsupportedCommandError = 7, kMinadbdCommandExecutionError = 8, @@ -51,6 +51,8 @@ enum class MinadbdCommand : uint32_t { kRebootFastboot = 4, kRebootRecovery = 5, kRebootRescue = 6, + kWipeCache = 7, + kWipeData = 8, // Last but invalid command. kError, diff --git a/recovery.cpp b/recovery.cpp index f9b3bfc0b..5fc673ec2 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -551,9 +551,9 @@ static Device::BuiltinAction prompt_and_wait(Device* device, int status) { if (chosen_action == Device::ENTER_RESCUE) { // Switch to graphics screen. ui->ShowText(false); - status = ApplyFromAdb(ui, true /* rescue_mode */, &reboot_action); + status = ApplyFromAdb(device, true /* rescue_mode */, &reboot_action); } else if (chosen_action == Device::APPLY_ADB_SIDELOAD) { - status = ApplyFromAdb(ui, false /* rescue_mode */, &reboot_action); + status = ApplyFromAdb(device, false /* rescue_mode */, &reboot_action); } else { adb = false; status = ApplyFromSdcard(device, ui); @@ -946,7 +946,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vectorShowText(true); } - status = ApplyFromAdb(ui, false /* rescue_mode */, &next_action); + status = ApplyFromAdb(device, false /* rescue_mode */, &next_action); ui->Print("\nInstall from ADB complete (status: %d).\n", status); if (sideload_auto_reboot) { status = INSTALL_REBOOT; @@ -954,7 +954,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vectorPrint("\nInstall from ADB complete (status: %d).\n", status); } else if (fsck_unshare_blocks) { if (!do_fsck_unshare_blocks()) { -- cgit v1.2.3