diff --git a/adb/adb.h b/adb/adb.h index e2911e81e..8c37c4bb5 100644 --- a/adb/adb.h +++ b/adb/adb.h @@ -59,7 +59,7 @@ constexpr size_t LINUX_MAX_SOCKET_SIZE = 4194304; std::string adb_version(); // Increment this when we want to force users to start a new adb server. -#define ADB_SERVER_VERSION 40 +#define ADB_SERVER_VERSION 41 using TransportId = uint64_t; class atransport; diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp index 022666ff3..cf22efa8e 100644 --- a/adb/client/adb_install.cpp +++ b/adb/client/adb_install.cpp @@ -38,14 +38,22 @@ static constexpr int kFastDeployMinApi = 24; -static bool _use_legacy_install() { +static bool can_use_feature(const char* feature) { FeatureSet features; std::string error; if (!adb_get_feature_set(&features, &error)) { fprintf(stderr, "error: %s\n", error.c_str()); return true; } - return !CanUseFeature(features, kFeatureCmd); + return CanUseFeature(features, feature); +} + +static bool use_legacy_install() { + return !can_use_feature(kFeatureCmd); +} + +static bool is_apex_supported() { + return can_use_feature(kFeatureApex); } static int pm_command(int argc, const char** argv) { @@ -102,7 +110,7 @@ static int uninstall_app_legacy(int argc, const char** argv) { } int uninstall_app(int argc, const char** argv) { - if (_use_legacy_install()) { + if (use_legacy_install()) { return uninstall_app_legacy(argc, argv); } return uninstall_app_streamed(argc, argv); @@ -133,8 +141,21 @@ static int install_app_streamed(int argc, const char** argv, bool use_fastdeploy // The last argument must be the APK file const char* file = argv[argc - 1]; - if (!android::base::EndsWithIgnoreCase(file, ".apk")) { - error_exit("filename doesn't end .apk: %s", file); + if (!android::base::EndsWithIgnoreCase(file, ".apk") && + !android::base::EndsWithIgnoreCase(file, ".apex")) { + error_exit("filename doesn't end .apk or .apex: %s", file); + } + + bool is_apex = false; + if (android::base::EndsWithIgnoreCase(file, ".apex")) { + is_apex = true; + } + if (is_apex && !is_apex_supported()) { + error_exit(".apex is not supported on the target device"); + } + + if (is_apex && use_fastdeploy) { + error_exit("--fastdeploy doesn't support .apex files"); } if (use_fastdeploy == true) { @@ -177,6 +198,10 @@ static int install_app_streamed(int argc, const char** argv, bool use_fastdeploy // do last to override any user specified value cmd += " " + android::base::StringPrintf("-S %" PRIu64, static_cast(sb.st_size)); + if (is_apex) { + cmd += " --apex"; + } + int remoteFd = adb_connect(cmd, &error); if (remoteFd < 0) { fprintf(stderr, "adb: connect error for write: %s\n", error.c_str()); @@ -218,6 +243,9 @@ static int install_app_legacy(int argc, const char** argv, bool use_fastdeploy, // All other arguments passed through verbatim. int last_apk = -1; for (int i = argc - 1; i >= 0; i--) { + if (android::base::EndsWithIgnoreCase(argv[i], ".apex")) { + error_exit("APEX packages are only compatible with Streamed Install"); + } if (android::base::EndsWithIgnoreCase(argv[i], ".apk")) { last_apk = i; break; @@ -303,14 +331,14 @@ int install_app(int argc, const char** argv) { } if (installMode == INSTALL_DEFAULT) { - if (_use_legacy_install()) { + if (use_legacy_install()) { installMode = INSTALL_PUSH; } else { installMode = INSTALL_STREAM; } } - if (installMode == INSTALL_STREAM && _use_legacy_install() == true) { + if (installMode == INSTALL_STREAM && use_legacy_install() == true) { error_exit("Attempting to use streaming install on unsupported device"); } @@ -359,6 +387,9 @@ int install_multiple_app(int argc, const char** argv) { uint64_t total_size = 0; for (int i = argc - 1; i >= 0; i--) { const char* file = argv[i]; + if (android::base::EndsWithIgnoreCase(argv[i], ".apex")) { + error_exit("APEX packages are not compatible with install-multiple"); + } if (android::base::EndsWithIgnoreCase(file, ".apk") || android::base::EndsWithIgnoreCase(file, ".dm")) { @@ -373,7 +404,7 @@ int install_multiple_app(int argc, const char** argv) { if (first_apk == -1) error_exit("need APK file on command line"); std::string install_cmd; - if (_use_legacy_install()) { + if (use_legacy_install()) { install_cmd = "exec:pm"; } else { install_cmd = "exec:cmd package"; diff --git a/adb/transport.cpp b/adb/transport.cpp index 0fbeec6e1..b65d676c0 100644 --- a/adb/transport.cpp +++ b/adb/transport.cpp @@ -66,6 +66,7 @@ const char* const kFeatureCmd = "cmd"; const char* const kFeatureStat2 = "stat_v2"; const char* const kFeatureLibusb = "libusb"; const char* const kFeaturePushSync = "push_sync"; +const char* const kFeatureApex = "apex"; namespace { @@ -1008,6 +1009,9 @@ const FeatureSet& supported_features() { // Local static allocation to avoid global non-POD variables. static const FeatureSet* features = new FeatureSet{ kFeatureShell2, kFeatureCmd, kFeatureStat2, +#if ADB_HOST + kFeatureApex +#endif // 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). diff --git a/adb/transport.h b/adb/transport.h index 1350e63f6..ea97270b9 100644 --- a/adb/transport.h +++ b/adb/transport.h @@ -59,6 +59,8 @@ extern const char* const kFeatureStat2; extern const char* const kFeatureLibusb; // The server supports `push --sync`. extern const char* const kFeaturePushSync; +// The server supports installing .apex packages. +extern const char* const kFeatureApex; TransportId NextTransportId();