minadbd: Support `adb reboot` under sideload/rescue modes.

Bug: 128415917
Test: Run the following commands under sideload and rescue modes
      respectively.
$ adb reboot
$ adb reboot bootloader
$ adb reboot recovery
$ adb reboot rescue
$ adb reboot invalid
Change-Id: I84daf63e3360b7b4a0af5e055149a4f54e10ba90
diff --git a/minadbd/minadbd_services.cpp b/minadbd/minadbd_services.cpp
index f6aff71..9b1999d 100644
--- a/minadbd/minadbd_services.cpp
+++ b/minadbd/minadbd_services.cpp
@@ -64,7 +64,7 @@
   sideload_mount_point = path;
 }
 
-static bool WriteCommandToFd(MinadbdCommands cmd, int fd) {
+static bool WriteCommandToFd(MinadbdCommand cmd, int fd) {
   char message[kMinadbdMessageSize];
   memcpy(message, kMinadbdCommandPrefix, strlen(kMinadbdStatusPrefix));
   android::base::put_unaligned(message + strlen(kMinadbdStatusPrefix), cmd);
@@ -109,7 +109,7 @@
 
   LOG(INFO) << "sideload-host file size " << file_size << ", block size " << block_size;
 
-  if (!WriteCommandToFd(MinadbdCommands::kInstall, minadbd_socket)) {
+  if (!WriteCommandToFd(MinadbdCommand::kInstall, minadbd_socket)) {
     return kMinadbdSocketIOError;
   }
 
@@ -175,7 +175,45 @@
   }
 }
 
+// Reboots into the given target. We don't reboot directly from minadbd, but going through recovery
+// instead. This allows recovery to finish all the pending works (clear BCB, save logs etc) before
+// the reboot.
+static void RebootHostService(unique_fd /* sfd */, const std::string& target) {
+  MinadbdCommand command;
+  if (target == "bootloader") {
+    command = MinadbdCommand::kRebootBootloader;
+  } else if (target == "rescue") {
+    command = MinadbdCommand::kRebootRescue;
+  } else if (target == "recovery") {
+    command = MinadbdCommand::kRebootRecovery;
+  } else if (target == "fastboot") {
+    command = MinadbdCommand::kRebootFastboot;
+  } else {
+    command = MinadbdCommand::kRebootAndroid;
+  }
+  if (!WriteCommandToFd(command, minadbd_socket)) {
+    exit(kMinadbdSocketIOError);
+  }
+  MinadbdCommandStatus status;
+  if (!WaitForCommandStatus(minadbd_socket, &status)) {
+    exit(kMinadbdMessageFormatError);
+  }
+}
+
 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:")) {
+    // "reboot:<target>", where target must be one of the following.
+    std::string args(name);
+    if (args.empty() || args == "bootloader" || args == "rescue" || args == "recovery" ||
+        args == "fastboot") {
+      return create_service_thread("reboot",
+                                   std::bind(RebootHostService, std::placeholders::_1, args));
+    }
+    return unique_fd{};
+  }
+
+  // Rescue-specific services.
   if (rescue_mode) {
     if (ConsumePrefix(&name, "rescue-install:")) {
       // rescue-install:<file-size>:<block-size>
@@ -191,6 +229,7 @@
     return unique_fd{};
   }
 
+  // Sideload-specific services.
   if (name.starts_with("sideload:")) {
     // This exit status causes recovery to print a special error message saying to use a newer adb
     // (that supports sideload-host).