From 175b7bbfb4d935e1867a1d6df14e6ef94f2db2f4 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Sun, 29 Mar 2015 11:22:34 -0700 Subject: [PATCH] adb: Add option to reboot into sideload mode in recovery Currently it requires manual key press to enter the sideload mode. This CL adds 'adb reboot sideload' to reboot the device into sideload mode directly with text display on. With 'adb reboot sideload-auto-reboot', it will reboot after the sideload regardless of the installation result, unless interrupted by user. Since it needs to write to /cache/recovery/command file, 'adb root' is required before calling 'adb reboot sideload' and the one with '-auto-reboot'. Also it requires the matching CL in bootable/recovery. Change-Id: Ib7bd4e216a1efc01e64460659c97c6005bbaec1b --- adb/Android.mk | 3 +- adb/commandline.cpp | 41 +++++++++++++------------- adb/services.cpp | 70 ++++++++++++++++++++++++++++++++++++--------- 3 files changed, 79 insertions(+), 35 deletions(-) diff --git a/adb/Android.mk b/adb/Android.mk index 8d38077f2..4f19d4783 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -208,10 +208,11 @@ LOCAL_MODULE := adbd LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN) LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED) -LOCAL_C_INCLUDES += system/extras/ext4_utils system/core/fs_mgr/include +LOCAL_C_INCLUDES += system/extras/ext4_utils LOCAL_STATIC_LIBRARIES := \ libadbd \ + libbase \ libfs_mgr \ liblog \ libcutils \ diff --git a/adb/commandline.cpp b/adb/commandline.cpp index 3330baa64..f9ca5edb0 100644 --- a/adb/commandline.cpp +++ b/adb/commandline.cpp @@ -209,7 +209,11 @@ void help() " adb get-devpath - prints: \n" " adb status-window - continuously print device status for a specified device\n" " adb remount - remounts the /system, /vendor (if present) and /oem (if present) partitions on the device read-write\n" - " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n" + " adb reboot [bootloader|recovery]\n" + " - reboots the device, optionally into the bootloader or recovery program.\n" + " adb reboot sideload - reboots the device into the sideload mode in recovery program (adb root required).\n" + " adb reboot sideload-auto-reboot\n" + " - reboots into the sideload mode, then reboots automatically after the sideload regardless of the result.\n" " adb reboot-bootloader - reboots the device into the bootloader\n" " adb root - restarts the adbd daemon with root permissions\n" " adb unroot - restarts the adbd daemon without root permissions\n" @@ -1126,6 +1130,17 @@ static void parse_push_pull_args(const char **arg, int narg, char const **path1, } } +static int adb_connect_command(const char* command) { + int fd = adb_connect(command); + if (fd != -1) { + read_and_dump(fd); + adb_close(fd); + return 0; + } + fprintf(stderr, "Error: %s\n", adb_error()); + return 1; +} + int adb_commandline(int argc, const char **argv) { char buf[4096]; @@ -1475,20 +1490,14 @@ int adb_commandline(int argc, const char **argv) !strcmp(argv[0], "disable-verity") || !strcmp(argv[0], "enable-verity")) { char command[100]; - if (!strcmp(argv[0], "reboot-bootloader")) + if (!strcmp(argv[0], "reboot-bootloader")) { snprintf(command, sizeof(command), "reboot:bootloader"); - else if (argc > 1) + } else if (argc > 1) { snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]); - else + } else { snprintf(command, sizeof(command), "%s:", argv[0]); - int fd = adb_connect(command); - if (fd >= 0) { - read_and_dump(fd); - adb_close(fd); - return 0; } - fprintf(stderr,"error: %s\n", adb_error()); - return 1; + return adb_connect_command(command); } else if (!strcmp(argv[0], "bugreport")) { if (argc != 1) return usage(); @@ -1713,15 +1722,7 @@ int adb_commandline(int argc, const char **argv) return adb_auth_keygen(argv[1]); } else if (!strcmp(argv[0], "jdwp")) { - int fd = adb_connect("jdwp"); - if (fd >= 0) { - read_and_dump(fd); - adb_close(fd); - return 0; - } else { - fprintf(stderr, "error: %s\n", adb_error()); - return -1; - } + return adb_connect_command("jdwp"); } /* "adb /?" is a common idiom under Windows */ else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) { diff --git a/adb/services.cpp b/adb/services.cpp index abf8ea572..12eb406ff 100644 --- a/adb/services.cpp +++ b/adb/services.cpp @@ -32,6 +32,7 @@ #endif #if !ADB_HOST +#include "base/file.h" #include "cutils/android_reboot.h" #include "cutils/properties.h" #endif @@ -132,31 +133,72 @@ void restart_usb_service(int fd, void *cookie) adb_close(fd); } -void reboot_service(int fd, void *arg) -{ +static bool reboot_service_impl(int fd, const char* arg) { + const char* reboot_arg = arg; + bool auto_reboot = false; + + if (strcmp(reboot_arg, "sideload-auto-reboot") == 0) { + auto_reboot = true; + reboot_arg = "sideload"; + } + char buf[100]; - char property_val[PROPERTY_VALUE_MAX]; - int ret; + // It reboots into sideload mode by setting "--sideload" or "--sideload_auto_reboot" + // in the command file. + if (strcmp(reboot_arg, "sideload") == 0) { + if (getuid() != 0) { + snprintf(buf, sizeof(buf), "'adb root' is required for 'adb reboot sideload'.\n"); + WriteStringFully(fd, buf); + return false; + } + + const char* const recovery_dir = "/cache/recovery"; + const char* const command_file = "/cache/recovery/command"; + // Ensure /cache/recovery exists. + if (adb_mkdir(recovery_dir, 0770) == -1 && errno != EEXIST) { + D("Failed to create directory '%s': %s\n", recovery_dir, strerror(errno)); + return false; + } + + bool write_status = android::base::WriteStringToFile( + auto_reboot ? "--sideload_auto_reboot" : "--sideload", command_file); + if (!write_status) { + return false; + } + + reboot_arg = "recovery"; + } sync(); - ret = snprintf(property_val, sizeof(property_val), "reboot,%s", (char *) arg); - if (ret >= (int) sizeof(property_val)) { + char property_val[PROPERTY_VALUE_MAX]; + int ret = snprintf(property_val, sizeof(property_val), "reboot,%s", reboot_arg); + if (ret >= static_cast(sizeof(property_val))) { snprintf(buf, sizeof(buf), "reboot string too long. length=%d\n", ret); - WriteFdExactly(fd, buf, strlen(buf)); - goto cleanup; + WriteStringFully(fd, buf); + return false; } ret = property_set(ANDROID_RB_PROPERTY, property_val); if (ret < 0) { snprintf(buf, sizeof(buf), "reboot failed: %d\n", ret); - WriteFdExactly(fd, buf, strlen(buf)); - goto cleanup; + WriteStringFully(fd, buf); + return false; } - // Don't return early. Give the reboot command time to take effect - // to avoid messing up scripts which do "adb reboot && adb wait-for-device" - while(1) { pause(); } -cleanup: + + return true; +} + +void reboot_service(int fd, void* arg) +{ + if (reboot_service_impl(fd, static_cast(arg))) { + // Don't return early. Give the reboot command time to take effect + // to avoid messing up scripts which do "adb reboot && adb wait-for-device" + while (1) { + pause(); + } + } + free(arg); adb_close(fd); }