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

Commit ae2a64e2 authored by Elliott Hughes's avatar Elliott Hughes Committed by Gerrit Code Review
Browse files

Merge "use new cmd command"

parents 7fc45c33 6fa848ad
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ constexpr size_t MAX_PAYLOAD = MAX_PAYLOAD_V2;
std::string adb_version();

// Increment this when we want to force users to start a new adb server.
#define ADB_SERVER_VERSION 34
#define ADB_SERVER_VERSION 35

class atransport;
struct usb_handle;
+157 −68
Original line number Diff line number Diff line
@@ -59,6 +59,8 @@
static int install_app(TransportType t, const char* serial, int argc, const char** argv);
static int install_multiple_app(TransportType t, const char* serial, int argc, const char** argv);
static int uninstall_app(TransportType t, const char* serial, int argc, const char** argv);
static int install_app_legacy(TransportType t, const char* serial, int argc, const char** argv);
static int uninstall_app_legacy(TransportType t, const char* serial, int argc, const char** argv);

static std::string gProductOutPath;
extern int gListenAll;
@@ -1622,16 +1624,24 @@ int adb_commandline(int argc, const char **argv) {
    }
    else if (!strcmp(argv[0], "install")) {
        if (argc < 2) return usage();
        FeatureSet features = GetFeatureSet(transport_type, serial);
        if (CanUseFeature(features, kFeatureCmd)) {
            return install_app(transport_type, serial, argc, argv);
        }
        return install_app_legacy(transport_type, serial, argc, argv);
    }
    else if (!strcmp(argv[0], "install-multiple")) {
        if (argc < 2) return usage();
        return install_multiple_app(transport_type, serial, argc, argv);
    }
    else if (!strcmp(argv[0], "uninstall")) {
        if (argc < 2) return usage();
        FeatureSet features = GetFeatureSet(transport_type, serial);
        if (CanUseFeature(features, kFeatureCmd)) {
            return uninstall_app(transport_type, serial, argc, argv);
        }
        return uninstall_app_legacy(transport_type, serial, argc, argv);
    }
    else if (!strcmp(argv[0], "sync")) {
        std::string src;
        bool list_only = false;
@@ -1738,86 +1748,83 @@ int adb_commandline(int argc, const char **argv) {
    return 1;
}

static int pm_command(TransportType transport, const char* serial, int argc, const char** argv) {
    std::string cmd = "pm";

    while (argc-- > 0) {
        cmd += " " + escape_arg(*argv++);
    }

    // TODO(dpursell): add command-line arguments to install/uninstall to
    // manually disable shell protocol if needed.
    return send_shell_command(transport, serial, cmd, false);
}

static int uninstall_app(TransportType transport, const char* serial, int argc, const char** argv) {
    /* if the user choose the -k option, we refuse to do it until devices are
       out with the option to uninstall the remaining data somehow (adb/ui) */
    if (argc == 3 && strcmp(argv[1], "-k") == 0)
    {
    // 'adb uninstall' takes the same arguments as 'cmd package uninstall' on device
    std::string cmd = "cmd package";
    while (argc-- > 0) {
        // deny the '-k' option until the remaining data/cache can be removed with adb/UI
        if (strcmp(*argv, "-k") == 0) {
            printf(
                "The -k option uninstalls the application while retaining the data/cache.\n"
                "At the moment, there is no way to remove the remaining data.\n"
                "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
            "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
        return -1;
                "If you truly wish to continue, execute 'adb shell cmd package uninstall -k'.\n");
            return EXIT_FAILURE;
        }

    /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
    return pm_command(transport, serial, argc, argv);
        cmd += " " + escape_arg(*argv++);
    }

static int delete_file(TransportType transport, const char* serial, const std::string& filename) {
    std::string cmd = "rm -f " + escape_arg(filename);
    return send_shell_command(transport, serial, cmd, false);
}

static int install_app(TransportType transport, const char* serial, int argc, const char** argv) {
    static const char *const DATA_DEST = "/data/local/tmp/%s";
    static const char *const SD_DEST = "/sdcard/tmp/%s";
    const char* where = DATA_DEST;
    int i;
    struct stat sb;

    for (i = 1; i < argc; i++) {
        if (!strcmp(argv[i], "-s")) {
            where = SD_DEST;
        }
    }

    // Find last APK argument.
    // All other arguments passed through verbatim.
    int last_apk = -1;
    for (i = argc - 1; i >= 0; i--) {
        const char* file = argv[i];
    // The last argument must be the APK file
    const char* file = argv[argc - 1];
    const char* dot = strrchr(file, '.');
    bool found_apk = false;
    struct stat sb;
    if (dot && !strcasecmp(dot, ".apk")) {
        if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
            fprintf(stderr, "Invalid APK file: %s\n", file);
                return -1;
            return EXIT_FAILURE;
        }
        found_apk = true;
    }

            last_apk = i;
            break;
    if (!found_apk) {
        fprintf(stderr, "Missing APK file\n");
        return EXIT_FAILURE;
    }

    int localFd = adb_open(file, O_RDONLY);
    if (localFd < 0) {
        fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
        return 1;
    }

    if (last_apk == -1) {
        fprintf(stderr, "Missing APK file\n");
        return -1;
    std::string error;
    std::string cmd = "exec:cmd package";

    // don't copy the APK name, but, copy the rest of the arguments as-is
    while (argc-- > 1) {
        cmd += " " + escape_arg(std::string(*argv++));
    }

    int result = -1;
    std::vector<const char*> apk_file = {argv[last_apk]};
    std::string apk_dest = android::base::StringPrintf(
        where, adb_basename(argv[last_apk]).c_str());
    if (!do_sync_push(apk_file, apk_dest.c_str())) goto cleanup_apk;
    argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
    result = pm_command(transport, serial, argc, argv);
    // add size parameter [required for streaming installs]
    // do last to override any user specified value
    cmd += " " + android::base::StringPrintf("-S %" PRIu64, static_cast<uint64_t>(sb.st_size));

cleanup_apk:
    delete_file(transport, serial, apk_dest);
    return result;
    int remoteFd = adb_connect(cmd, &error);
    if (remoteFd < 0) {
        fprintf(stderr, "Connect error for write: %s\n", error.c_str());
        adb_close(localFd);
        return 1;
    }

    char buf[BUFSIZ];
    copy_to_file(localFd, remoteFd);
    read_status_line(remoteFd, buf, sizeof(buf));

    adb_close(localFd);
    adb_close(remoteFd);

    if (strncmp("Success", buf, 7)) {
        fprintf(stderr, "Failed to write %s\n", file);
        fputs(buf, stderr);
        return 1;
    }
    fputs(buf, stderr);
    return 0;
}

static int install_multiple_app(TransportType transport, const char* serial, int argc,
@@ -1836,7 +1843,7 @@ static int install_multiple_app(TransportType transport, const char* serial, int
        if (dot && !strcasecmp(dot, ".apk")) {
            if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
                fprintf(stderr, "Invalid APK file: %s\n", file);
                return -1;
                return EXIT_FAILURE;
            }

            total_size += sb.st_size;
@@ -1861,7 +1868,7 @@ static int install_multiple_app(TransportType transport, const char* serial, int
    int fd = adb_connect(cmd, &error);
    if (fd < 0) {
        fprintf(stderr, "Connect error for create: %s\n", error.c_str());
        return -1;
        return EXIT_FAILURE;
    }
    char buf[BUFSIZ];
    read_status_line(fd, buf, sizeof(buf));
@@ -1879,7 +1886,7 @@ static int install_multiple_app(TransportType transport, const char* serial, int
    if (session_id < 0) {
        fprintf(stderr, "Failed to create session\n");
        fputs(buf, stderr);
        return -1;
        return EXIT_FAILURE;
    }

    // Valid session, now stream the APKs
@@ -1934,7 +1941,7 @@ finalize_session:
    fd = adb_connect(service, &error);
    if (fd < 0) {
        fprintf(stderr, "Connect error for finalize: %s\n", error.c_str());
        return -1;
        return EXIT_FAILURE;
    }
    read_status_line(fd, buf, sizeof(buf));
    adb_close(fd);
@@ -1945,6 +1952,88 @@ finalize_session:
    } else {
        fprintf(stderr, "Failed to finalize session\n");
        fputs(buf, stderr);
        return -1;
        return EXIT_FAILURE;
    }
}

static int pm_command(TransportType transport, const char* serial, int argc, const char** argv) {
    std::string cmd = "pm";

    while (argc-- > 0) {
        cmd += " " + escape_arg(*argv++);
    }

    return send_shell_command(transport, serial, cmd, false);
}

static int uninstall_app_legacy(TransportType transport, const char* serial, int argc, const char** argv) {
    /* if the user choose the -k option, we refuse to do it until devices are
       out with the option to uninstall the remaining data somehow (adb/ui) */
    int i;
    for (i = 1; i < argc; i++) {
        if (!strcmp(argv[i], "-k")) {
            printf(
                "The -k option uninstalls the application while retaining the data/cache.\n"
                "At the moment, there is no way to remove the remaining data.\n"
                "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
                "If you truly wish to continue, execute 'adb shell pm uninstall -k'\n.");
            return EXIT_FAILURE;
        }
    }

    /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
    return pm_command(transport, serial, argc, argv);
}

static int delete_file(TransportType transport, const char* serial, const std::string& filename) {
    std::string cmd = "rm -f " + escape_arg(filename);
    return send_shell_command(transport, serial, cmd, false);
}

static int install_app_legacy(TransportType transport, const char* serial, int argc, const char** argv) {
    static const char *const DATA_DEST = "/data/local/tmp/%s";
    static const char *const SD_DEST = "/sdcard/tmp/%s";
    const char* where = DATA_DEST;
    int i;
    struct stat sb;

    for (i = 1; i < argc; i++) {
        if (!strcmp(argv[i], "-s")) {
            where = SD_DEST;
        }
    }

    // Find last APK argument.
    // All other arguments passed through verbatim.
    int last_apk = -1;
    for (i = argc - 1; i >= 0; i--) {
        const char* file = argv[i];
        const char* dot = strrchr(file, '.');
        if (dot && !strcasecmp(dot, ".apk")) {
            if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
                fprintf(stderr, "Invalid APK file: %s\n", file);
                return EXIT_FAILURE;
            }

            last_apk = i;
            break;
        }
    }

    if (last_apk == -1) {
        fprintf(stderr, "Missing APK file\n");
        return EXIT_FAILURE;
    }

    int result = -1;
    std::vector<const char*> apk_file = {argv[last_apk]};
    std::string apk_dest = android::base::StringPrintf(
        where, adb_basename(argv[last_apk]).c_str());
    if (!do_sync_push(apk_file, apk_dest.c_str())) goto cleanup_apk;
    argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
    result = pm_command(transport, serial, argc, argv);

cleanup_apk:
    delete_file(transport, serial, apk_dest);
    return result;
}
+5 −1
Original line number Diff line number Diff line
@@ -42,6 +42,9 @@ static std::list<atransport*> pending_list;

ADB_MUTEX_DEFINE( transport_lock );

const char* const kFeatureShell2 = "shell_v2";
const char* const kFeatureCmd = "cmd";

static std::string dump_packet(const char* name, const char* func, apacket* p) {
    unsigned  command = p->msg.command;
    int       len     = p->msg.data_length;
@@ -780,7 +783,8 @@ constexpr char kFeatureStringDelimiter = ',';
const FeatureSet& supported_features() {
    // Local static allocation to avoid global non-POD variables.
    static const FeatureSet* features = new FeatureSet{
        kFeatureShell2
        kFeatureShell2,
        kFeatureCmd
        // Increment ADB_SERVER_VERSION whenever the feature list changes to
        // make sure that the adb client and server features stay in sync
        // (http://b/24370690).
+3 −1
Original line number Diff line number Diff line
@@ -38,7 +38,9 @@ bool CanUseFeature(const FeatureSet& feature_set, const std::string& feature);

// Do not use any of [:;=,] in feature strings, they have special meaning
// in the connection banner.
constexpr char kFeatureShell2[] = "shell_v2";
extern const char* const kFeatureShell2;
// The 'cmd' command is available
extern const char* const kFeatureCmd;

class atransport {
public: