From ffc8a8702d9e1568995ce155c648fd029909cdac Mon Sep 17 00:00:00 2001 From: Tom Marshall Date: Thu, 5 Nov 2015 21:30:40 -0800 Subject: recovery: Provide sideload cancellation Change-Id: I13f0c9ae5444652a2141442ef24258679a78d320 --- adb_install.cpp | 126 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 85 insertions(+), 41 deletions(-) (limited to 'adb_install.cpp') diff --git a/adb_install.cpp b/adb_install.cpp index 4cfcb2a..a67973d 100644 --- a/adb_install.cpp +++ b/adb_install.cpp @@ -34,6 +34,7 @@ #include "fuse_sideload.h" static RecoveryUI* ui = NULL; +static pthread_t sideload_thread; static void set_usb_driver(bool enabled) { @@ -66,69 +67,80 @@ maybe_restart_adbd() { } } +struct sideload_data { + bool* wipe_cache; + const char* install_file; + bool cancel; + int result; +}; + +static struct sideload_data sideload_data; + // How long (in seconds) we wait for the host to start sending us a // package, before timing out. #define ADB_INSTALL_TIMEOUT 300 -int -apply_from_adb(RecoveryUI* ui_, bool* wipe_cache, const char* install_file) { - modified_flash = true; - - ui = ui_; - - stop_adbd(); - set_usb_driver(true); - - ui->Print("\n\nNow send the package you want to apply\n" - "to the device with \"adb sideload \"...\n"); - +void *adb_sideload_thread(void* v) { pid_t child; if ((child = fork()) == 0) { execl("/sbin/recovery", "recovery", "--adbd", NULL); _exit(-1); } + time_t start_time = time(NULL); + time_t now = start_time; + // FUSE_SIDELOAD_HOST_PATHNAME will start to exist once the host // connects and starts serving a package. Poll for its // appearance. (Note that inotify doesn't work with FUSE.) - int result = INSTALL_ERROR; - int status; - bool waited = false; + int result = INSTALL_NONE; + int status = -1; struct stat st; - for (int i = 0; i < ADB_INSTALL_TIMEOUT; ++i) { - if (waitpid(child, &status, WNOHANG) != 0) { + while (now - start_time < ADB_INSTALL_TIMEOUT) { + /* + * Exit if either: + * - The adb child process dies, or + * - The ui tells us to cancel + */ + if (kill(child, 0) != 0) { result = INSTALL_ERROR; - waited = true; break; } - if (stat(FUSE_SIDELOAD_HOST_PATHNAME, &st) != 0) { - if (errno == ENOENT && i < ADB_INSTALL_TIMEOUT-1) { - sleep(1); - continue; - } else { - ui->Print("\nTimed out waiting for package.\n\n"); - result = INSTALL_ERROR; - kill(child, SIGKILL); - break; - } + if (sideload_data.cancel) { + break; + } + + status = stat(FUSE_SIDELOAD_HOST_PATHNAME, &st); + if (status == 0) { + break; } - result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, install_file, false); - break; + if (errno != ENOENT && errno != ENOTCONN) { + ui->Print("\nError %s waiting for package\n\n", strerror(errno)); + result = INSTALL_ERROR; + break; + } + + sleep(1); + now = time(NULL); } - if (!waited) { - // Calling stat() on this magic filename signals the minadbd - // subprocess to shut down. - stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st); + if (status == 0) { + // Signal UI thread that we can no longer cancel + ui->CancelWaitKey(); + + result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, + sideload_data.wipe_cache, + sideload_data.install_file, + false); - // TODO(dougz): there should be a way to cancel waiting for a - // package (by pushing some button combo on the device). For now - // you just have to 'adb sideload' a file that's not a valid - // package, like "/dev/null". - waitpid(child, &status, 0); + sideload_data.result = result; } + // Ensure adb exits + kill(child, SIGTERM); + waitpid(child, &status, 0); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { if (WEXITSTATUS(status) == 3) { ui->Print("\nYou need adb 1.0.32 or newer to sideload\nto this device.\n\n"); @@ -137,8 +149,40 @@ apply_from_adb(RecoveryUI* ui_, bool* wipe_cache, const char* install_file) { } } - set_usb_driver(false); + LOGI("sideload thread finished\n"); + return NULL; +} + +void +start_sideload(RecoveryUI* ui_, bool* wipe_cache, const char* install_file) { + modified_flash = true; + + ui = ui_; + + stop_adbd(); + set_usb_driver(true); + + ui->Print("\n\nNow send the package you want to apply\n" + "to the device with \"adb sideload \"...\n"); + + sideload_data.wipe_cache = wipe_cache; + sideload_data.install_file = install_file; + sideload_data.cancel = false; + sideload_data.result = INSTALL_NONE; + + pthread_create(&sideload_thread, NULL, &adb_sideload_thread, NULL); +} + +void stop_sideload() { + sideload_data.cancel = true; +} + +int wait_sideload() { + pthread_join(sideload_thread, NULL); + + ui->FlushKeys(); + maybe_restart_adbd(); - return result; + return sideload_data.result; } -- cgit v1.1