Merge "adb: fix feature sets on devices that don't have them." am: 10f8f5e363
Change-Id: Ieebf1b914d0ef08be0b5bb16698d05cf72001109
This commit is contained in:
commit
da03311c3f
5 changed files with 64 additions and 52 deletions
|
|
@ -416,14 +416,18 @@ std::string format_host_command(const char* command) {
|
|||
return android::base::StringPrintf("%s:%s", prefix, command);
|
||||
}
|
||||
|
||||
const FeatureSet& adb_get_feature_set() {
|
||||
static const android::base::NoDestructor<FeatureSet> features([] {
|
||||
std::string result;
|
||||
if (!adb_query(format_host_command("features"), &result, &result)) {
|
||||
fprintf(stderr, "failed to get feature set: %s\n", result.c_str());
|
||||
return FeatureSet{};
|
||||
}
|
||||
return StringToFeatureSet(result);
|
||||
}());
|
||||
return *features;
|
||||
const std::optional<FeatureSet>& adb_get_feature_set(std::string* error) {
|
||||
static std::string cached_error [[clang::no_destroy]];
|
||||
static const std::optional<FeatureSet> features
|
||||
[[clang::no_destroy]] ([]() -> std::optional<FeatureSet> {
|
||||
std::string result;
|
||||
if (adb_query(format_host_command("features"), &result, &cached_error)) {
|
||||
return StringToFeatureSet(result);
|
||||
}
|
||||
return std::nullopt;
|
||||
}());
|
||||
if (!features && error) {
|
||||
*error = cached_error;
|
||||
}
|
||||
return features;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ bool adb_status(borrowed_fd fd, std::string* _Nonnull error);
|
|||
std::string format_host_command(const char* _Nonnull command);
|
||||
|
||||
// Get the feature set of the current preferred transport.
|
||||
const FeatureSet& adb_get_feature_set();
|
||||
const std::optional<FeatureSet>& adb_get_feature_set(std::string* _Nullable error);
|
||||
|
||||
#if defined(__linux__)
|
||||
// Get the path of a file containing the path to the server executable, if the socket spec set via
|
||||
|
|
|
|||
|
|
@ -57,11 +57,12 @@ enum class CmdlineOption { None, Enable, Disable };
|
|||
}
|
||||
|
||||
static bool can_use_feature(const char* feature) {
|
||||
auto&& features = adb_get_feature_set();
|
||||
if (features.empty()) {
|
||||
// We ignore errors here, if the device is missing, we'll notice when we try to push install.
|
||||
auto&& features = adb_get_feature_set(nullptr);
|
||||
if (!features) {
|
||||
return false;
|
||||
}
|
||||
return CanUseFeature(features, feature);
|
||||
return CanUseFeature(*features, feature);
|
||||
}
|
||||
|
||||
static InstallMode best_install_mode() {
|
||||
|
|
|
|||
|
|
@ -672,16 +672,17 @@ static int RemoteShell(bool use_shell_protocol, const std::string& type_arg, cha
|
|||
}
|
||||
|
||||
static int adb_shell(int argc, const char** argv) {
|
||||
auto&& features = adb_get_feature_set();
|
||||
if (features.empty()) {
|
||||
return 1;
|
||||
std::string error;
|
||||
auto&& features = adb_get_feature_set(&error);
|
||||
if (!features) {
|
||||
error_exit("%s", error.c_str());
|
||||
}
|
||||
|
||||
enum PtyAllocationMode { kPtyAuto, kPtyNo, kPtyYes, kPtyDefinitely };
|
||||
|
||||
// Defaults.
|
||||
char escape_char = '~'; // -e
|
||||
bool use_shell_protocol = CanUseFeature(features, kFeatureShell2); // -x
|
||||
char escape_char = '~'; // -e
|
||||
bool use_shell_protocol = CanUseFeature(*features, kFeatureShell2); // -x
|
||||
PtyAllocationMode tty = use_shell_protocol ? kPtyAuto : kPtyDefinitely; // -t/-T
|
||||
|
||||
// Parse shell-specific command-line options.
|
||||
|
|
@ -757,7 +758,7 @@ static int adb_shell(int argc, const char** argv) {
|
|||
if (!use_shell_protocol) {
|
||||
if (shell_type_arg != kShellServiceArgPty) {
|
||||
fprintf(stderr, "error: %s only supports allocating a pty\n",
|
||||
!CanUseFeature(features, kFeatureShell2) ? "device" : "-x");
|
||||
!CanUseFeature(*features, kFeatureShell2) ? "device" : "-x");
|
||||
return 1;
|
||||
} else {
|
||||
// If we're not using the shell protocol, the type argument must be empty.
|
||||
|
|
@ -777,11 +778,13 @@ static int adb_shell(int argc, const char** argv) {
|
|||
}
|
||||
|
||||
static int adb_abb(int argc, const char** argv) {
|
||||
auto&& features = adb_get_feature_set();
|
||||
if (features.empty()) {
|
||||
std::string error;
|
||||
auto&& features = adb_get_feature_set(&error);
|
||||
if (!features) {
|
||||
error_exit("%s", error.c_str());
|
||||
return 1;
|
||||
}
|
||||
if (!CanUseFeature(features, kFeatureAbb)) {
|
||||
if (!CanUseFeature(*features, kFeatureAbb)) {
|
||||
error_exit("abb is not supported by the device");
|
||||
}
|
||||
|
||||
|
|
@ -1159,9 +1162,9 @@ int send_shell_command(const std::string& command, bool disable_shell_protocol,
|
|||
// Use shell protocol if it's supported and the caller doesn't explicitly
|
||||
// disable it.
|
||||
if (!disable_shell_protocol) {
|
||||
auto&& features = adb_get_feature_set();
|
||||
if (!features.empty()) {
|
||||
use_shell_protocol = CanUseFeature(features, kFeatureShell2);
|
||||
auto&& features = adb_get_feature_set(nullptr);
|
||||
if (features) {
|
||||
use_shell_protocol = CanUseFeature(*features, kFeatureShell2);
|
||||
} else {
|
||||
// Device was unreachable.
|
||||
attempt_connection = false;
|
||||
|
|
@ -1810,12 +1813,13 @@ int adb_commandline(int argc, const char** argv) {
|
|||
}
|
||||
return adb_connect_command(android::base::StringPrintf("tcpip:%d", port));
|
||||
} else if (!strcmp(argv[0], "remount")) {
|
||||
auto&& features = adb_get_feature_set();
|
||||
if (features.empty()) {
|
||||
return 1;
|
||||
std::string error;
|
||||
auto&& features = adb_get_feature_set(&error);
|
||||
if (!features) {
|
||||
error_exit("%s", error.c_str());
|
||||
}
|
||||
|
||||
if (CanUseFeature(features, kFeatureRemountShell)) {
|
||||
if (CanUseFeature(*features, kFeatureRemountShell)) {
|
||||
std::vector<const char*> args = {"shell"};
|
||||
args.insert(args.cend(), argv, argv + argc);
|
||||
return adb_shell_noinput(args.size(), args.data());
|
||||
|
|
@ -2034,11 +2038,12 @@ int adb_commandline(int argc, const char** argv) {
|
|||
} else if (!strcmp(argv[0], "track-jdwp")) {
|
||||
return adb_connect_command("track-jdwp");
|
||||
} else if (!strcmp(argv[0], "track-app")) {
|
||||
auto&& features = adb_get_feature_set();
|
||||
if (features.empty()) {
|
||||
return 1;
|
||||
std::string error;
|
||||
auto&& features = adb_get_feature_set(&error);
|
||||
if (!features) {
|
||||
error_exit("%s", error.c_str());
|
||||
}
|
||||
if (!CanUseFeature(features, kFeatureTrackApp)) {
|
||||
if (!CanUseFeature(*features, kFeatureTrackApp)) {
|
||||
error_exit("track-app is not supported by the device");
|
||||
}
|
||||
TrackAppStreamsCallback callback;
|
||||
|
|
@ -2064,13 +2069,14 @@ int adb_commandline(int argc, const char** argv) {
|
|||
return 0;
|
||||
} else if (!strcmp(argv[0], "features")) {
|
||||
// Only list the features common to both the adb client and the device.
|
||||
auto&& features = adb_get_feature_set();
|
||||
if (features.empty()) {
|
||||
return 1;
|
||||
std::string error;
|
||||
auto&& features = adb_get_feature_set(&error);
|
||||
if (!features) {
|
||||
error_exit("%s", error.c_str());
|
||||
}
|
||||
|
||||
for (const std::string& name : features) {
|
||||
if (CanUseFeature(features, name)) {
|
||||
for (const std::string& name : *features) {
|
||||
if (CanUseFeature(*features, name)) {
|
||||
printf("%s\n", name.c_str());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -225,21 +225,22 @@ struct TransferLedger {
|
|||
|
||||
class SyncConnection {
|
||||
public:
|
||||
SyncConnection()
|
||||
: acknowledgement_buffer_(sizeof(sync_status) + SYNC_DATA_MAX),
|
||||
features_(adb_get_feature_set()) {
|
||||
SyncConnection() : acknowledgement_buffer_(sizeof(sync_status) + SYNC_DATA_MAX) {
|
||||
acknowledgement_buffer_.resize(0);
|
||||
max = SYNC_DATA_MAX; // TODO: decide at runtime.
|
||||
|
||||
if (features_.empty()) {
|
||||
Error("failed to get feature set");
|
||||
std::string error;
|
||||
auto&& features = adb_get_feature_set(&error);
|
||||
if (!features) {
|
||||
Error("failed to get feature set: %s", error.c_str());
|
||||
} else {
|
||||
have_stat_v2_ = CanUseFeature(features_, kFeatureStat2);
|
||||
have_ls_v2_ = CanUseFeature(features_, kFeatureLs2);
|
||||
have_sendrecv_v2_ = CanUseFeature(features_, kFeatureSendRecv2);
|
||||
have_sendrecv_v2_brotli_ = CanUseFeature(features_, kFeatureSendRecv2Brotli);
|
||||
have_sendrecv_v2_lz4_ = CanUseFeature(features_, kFeatureSendRecv2LZ4);
|
||||
have_sendrecv_v2_dry_run_send_ = CanUseFeature(features_, kFeatureSendRecv2DryRunSend);
|
||||
features_ = &*features;
|
||||
have_stat_v2_ = CanUseFeature(*features, kFeatureStat2);
|
||||
have_ls_v2_ = CanUseFeature(*features, kFeatureLs2);
|
||||
have_sendrecv_v2_ = CanUseFeature(*features, kFeatureSendRecv2);
|
||||
have_sendrecv_v2_brotli_ = CanUseFeature(*features, kFeatureSendRecv2Brotli);
|
||||
have_sendrecv_v2_lz4_ = CanUseFeature(*features, kFeatureSendRecv2LZ4);
|
||||
have_sendrecv_v2_dry_run_send_ = CanUseFeature(*features, kFeatureSendRecv2DryRunSend);
|
||||
std::string error;
|
||||
fd.reset(adb_connect("sync:", &error));
|
||||
if (fd < 0) {
|
||||
|
|
@ -283,7 +284,7 @@ class SyncConnection {
|
|||
return compression;
|
||||
}
|
||||
|
||||
const FeatureSet& Features() const { return features_; }
|
||||
const FeatureSet& Features() const { return *features_; }
|
||||
|
||||
bool IsValid() { return fd >= 0; }
|
||||
|
||||
|
|
@ -921,7 +922,7 @@ class SyncConnection {
|
|||
private:
|
||||
std::deque<std::pair<std::string, std::string>> deferred_acknowledgements_;
|
||||
Block acknowledgement_buffer_;
|
||||
const FeatureSet& features_;
|
||||
const FeatureSet* features_ = nullptr;
|
||||
bool have_stat_v2_;
|
||||
bool have_ls_v2_;
|
||||
bool have_sendrecv_v2_;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue