Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fedeef6f authored by xunchang's avatar xunchang
Browse files

Support wipe command in rescue mode

Bug: 131037235
Test: unit tests pass, run `adb rescue wipe`
Change-Id: I22668f2c98fe2d9195d2561f961c28a7c08e712c
parent e645ba5a
Loading
Loading
Loading
Loading
+15 −8
Original line number Diff line number Diff line
@@ -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 <filename>\"...\n");
  } else {
    ui->Print("\n\nWaiting for rescue commands...\n");
  }
  RecoveryUI* ui = device->GetUI();

  int install_result = INSTALL_ERROR;
  std::map<MinadbdCommand, CommandFunction> 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 <filename>\"...\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
+1 −2
Original line number Diff line number Diff line
@@ -17,9 +17,8 @@
#pragma once

#include <recovery_ui/device.h>
#include <recovery_ui/ui.h>

// 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);
+40 −6
Original line number Diff line number Diff line
@@ -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:<message-size>
      std::string args(name);
      return create_service_thread("rescue-wipe",
                                   std::bind(WipeDeviceService, std::placeholders::_1, args));
    }

    return unique_fd{};
  }

+1 −1
Original line number Diff line number Diff line
@@ -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) {
+3 −1
Original line number Diff line number Diff line
@@ -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,
Loading