Loading adb/adb.h +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading adb/commandline.cpp +157 −68 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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, Loading @@ -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; Loading @@ -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)); Loading @@ -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 Loading Loading @@ -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); Loading @@ -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; } adb/transport.cpp +5 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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). Loading adb/transport.h +3 −1 Original line number Diff line number Diff line Loading @@ -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: Loading Loading
adb/adb.h +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading
adb/commandline.cpp +157 −68 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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, Loading @@ -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; Loading @@ -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)); Loading @@ -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 Loading Loading @@ -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); Loading @@ -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; }
adb/transport.cpp +5 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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). Loading
adb/transport.h +3 −1 Original line number Diff line number Diff line Loading @@ -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: Loading