diff options
Diffstat (limited to '')
-rw-r--r-- | adb_install.cpp | 170 |
1 files changed, 123 insertions, 47 deletions
diff --git a/adb_install.cpp b/adb_install.cpp index ac0130651..291708c69 100644 --- a/adb_install.cpp +++ b/adb_install.cpp @@ -16,6 +16,7 @@ #include "adb_install.h" +#include <dirent.h> #include <errno.h> #include <fcntl.h> #include <signal.h> @@ -24,115 +25,190 @@ #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> +#include <sys/stat.h> +#include <signal.h> +#include <fcntl.h> +#include <stdio.h> #include <unistd.h> -#include <android-base/file.h> -#include <android-base/logging.h> -#include <android-base/properties.h> -#include <android-base/unique_fd.h> +#include "ui.h" +#include "cutils/properties.h" #include "common.h" #include "fuse_sideload.h" -#include "install.h" -#include "ui.h" +#ifdef USE_OLD_VERIFIER +#include "verifier24/verifier.h" +#else +#include "verifier.h" +#endif static void set_usb_driver(bool enabled) { - // USB configfs doesn't use /s/c/a/a/enable. - if (android::base::GetBoolProperty("sys.usb.configfs", false)) { + char configfs[PROPERTY_VALUE_MAX]; + property_get("sys.usb.configfs", configfs, "false"); + if (strcmp(configfs, "false") == 0 || strcmp(configfs, "0") == 0) return; - } - static constexpr const char* USB_DRIVER_CONTROL = "/sys/class/android_usb/android0/enable"; - android::base::unique_fd fd(open(USB_DRIVER_CONTROL, O_WRONLY)); - if (fd == -1) { - PLOG(ERROR) << "Failed to open driver control"; + int fd = open("/sys/class/android_usb/android0/enable", O_WRONLY); + if (fd < 0) { +/* These error messages show when built in older Android branches (e.g. Gingerbread) + It's not a critical error so we're disabling the error messages. + ui->Print("failed to open driver control: %s\n", strerror(errno)); +*/ + printf("failed to open driver control: %s\n", strerror(errno)); return; } - // Not using android::base::WriteStringToFile since that will open with O_CREAT and give EPERM - // when USB_DRIVER_CONTROL doesn't exist. When it gives EPERM, we don't know whether that's due - // to non-existent USB_DRIVER_CONTROL or indeed a permission issue. - if (!android::base::WriteStringToFd(enabled ? "1" : "0", fd)) { - PLOG(ERROR) << "Failed to set driver control"; + + if (TEMP_FAILURE_RETRY(write(fd, enabled ? "1" : "0", 1)) == -1) { +/* + ui->Print("failed to set driver control: %s\n", strerror(errno)); +*/ + printf("failed to set driver control: %s\n", strerror(errno)); + } + if (close(fd) < 0) { +/* + ui->Print("failed to close driver control: %s\n", strerror(errno)); +*/ + printf("failed to close driver control: %s\n", strerror(errno)); + } +} + +// On Android 8.0 for some reason init can't seem to completely stop adbd +// so we have to kill it too if it doesn't die on its own. +static void kill_adbd() { + DIR* dir = opendir("/proc"); + if (dir) { + struct dirent* de = 0; + + while ((de = readdir(dir)) != 0) { + if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) + continue; + + int pid = -1; + int ret = sscanf(de->d_name, "%d", &pid); + + if (ret == 1) { + char cmdpath[PATH_MAX]; + sprintf(cmdpath, "/proc/%d/cmdline", pid); + + FILE* file = fopen(cmdpath, "r"); + size_t task_size = PATH_MAX; + char task[PATH_MAX]; + char* p = task; + if (getline(&p, &task_size, file) > 0) { + if (strstr(task, "adbd") != 0) { + printf("adbd pid %d found, sending kill.\n", pid); + kill(pid, SIGINT); + usleep(5000); + kill(pid, SIGKILL); + } + } + fclose(file); + } + } + closedir(dir); } } static void stop_adbd() { - ui->Print("Stopping adbd...\n"); - android::base::SetProperty("ctl.stop", "adbd"); + printf("Stopping adbd...\n"); + property_set("ctl.stop", "adbd"); + usleep(5000); + kill_adbd(); set_usb_driver(false); } +static bool is_ro_debuggable() { + char value[PROPERTY_VALUE_MAX+1]; + return (property_get("ro.debuggable", value, NULL) == 1 && value[0] == '1'); +} + static void maybe_restart_adbd() { if (is_ro_debuggable()) { - ui->Print("Restarting adbd...\n"); + printf("Restarting adbd...\n"); set_usb_driver(true); - android::base::SetProperty("ctl.start", "adbd"); + property_set("ctl.start", "adbd"); } } -int apply_from_adb(bool* wipe_cache, const char* install_file) { - modified_flash = true; +// 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(const char* install_file, pid_t* child_pid) { stop_adbd(); set_usb_driver(true); +/* +int apply_from_adb(RecoveryUI* ui, bool* wipe_cache, const char* install_file) { + modified_flash = true; - ui->Print( - "\n\nNow send the package you want to apply\n" - "to the device with \"adb sideload <filename>\"...\n"); + stop_adbd(ui); + set_usb_driver(ui, true); + ui->Print("\n\nNow send the package you want to apply\n" + "to the device with \"adb sideload <filename>\"...\n"); +*/ pid_t child; if ((child = fork()) == 0) { - execl("/sbin/recovery", "recovery", "--adbd", nullptr); - _exit(EXIT_FAILURE); + execl("/sbin/recovery", "recovery", "--adbd", install_file, NULL); + _exit(-1); } - // How long (in seconds) we wait for the host to start sending us a package, before timing out. - static constexpr int ADB_INSTALL_TIMEOUT = 300; + *child_pid = child; + // caller can now kill the child thread from another thread - // 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.) + // 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; + struct stat st; for (int i = 0; i < ADB_INSTALL_TIMEOUT; ++i) { if (waitpid(child, &status, WNOHANG) != 0) { - result = INSTALL_ERROR; + result = -1; waited = true; break; } - struct stat st; if (stat(FUSE_SIDELOAD_HOST_PATHNAME, &st) != 0) { - if (errno == ENOENT && i < ADB_INSTALL_TIMEOUT - 1) { + if (errno == ENOENT && i < ADB_INSTALL_TIMEOUT-1) { sleep(1); continue; } else { - ui->Print("\nTimed out waiting for package.\n\n"); - result = INSTALL_ERROR; + printf("\nTimed out waiting for package: %s\n\n", strerror(errno)); + result = -1; kill(child, SIGKILL); break; } } - result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, install_file, false, 0); - break; + // Install is handled elsewhere in TWRP + //install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, install_file, false); + return 0; } + // if we got here, something failed + *child_pid = 0; + if (!waited) { - // Calling stat() on this magic filename signals the minadbd subprocess to shut down. - struct stat st; + // Calling stat() on this magic filename signals the minadbd + // subprocess to shut down. stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st); - // TODO: 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". + // 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); } 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"); + printf("\nYou need adb 1.0.32 or newer to sideload\nto this device.\n\n"); + result = -2; } else if (!WIFSIGNALED(status)) { - ui->Print("\n(adbd status %d)\n", WEXITSTATUS(status)); + printf("adbd status %d\n", WEXITSTATUS(status)); } } |