Merge "adb: add help text for USB permission errors." am: 663e949b2b
am: e37325defc
* commit 'e37325defce9078a566b070c595d5c4dd933e35d':
adb: add help text for USB permission errors.
This commit is contained in:
commit
4542b62cca
7 changed files with 107 additions and 15 deletions
|
@ -214,18 +214,23 @@ void local_init(int port);
|
|||
void local_connect(int port);
|
||||
int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* error);
|
||||
|
||||
/* usb host/client interface */
|
||||
// USB host/client interface.
|
||||
void usb_init();
|
||||
int usb_write(usb_handle *h, const void *data, int len);
|
||||
int usb_read(usb_handle *h, void *data, int len);
|
||||
int usb_close(usb_handle *h);
|
||||
void usb_kick(usb_handle *h);
|
||||
|
||||
/* used for USB device detection */
|
||||
// USB device detection.
|
||||
#if ADB_HOST
|
||||
int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol);
|
||||
#endif
|
||||
|
||||
// USB permission error help text. The short version will be one line, long may be multi-line.
|
||||
// Returns a string message to print, or an empty string if no problems could be found.
|
||||
std::string UsbNoPermissionsShortHelpText();
|
||||
std::string UsbNoPermissionsLongHelpText();
|
||||
|
||||
int adb_commandline(int argc, const char **argv);
|
||||
|
||||
ConnectionState connection_state(atransport *t);
|
||||
|
|
|
@ -674,7 +674,11 @@ atransport* acquire_one_transport(TransportType type, const char* serial,
|
|||
adb_mutex_lock(&transport_lock);
|
||||
for (const auto& t : transport_list) {
|
||||
if (t->connection_state == kCsNoPerm) {
|
||||
*error_out = "insufficient permissions for device";
|
||||
*error_out = UsbNoPermissionsLongHelpText();
|
||||
// If we couldn't figure out a reasonable help message default to something generic.
|
||||
if (error_out->empty()) {
|
||||
*error_out = "insufficient permissions for device";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -748,17 +752,20 @@ atransport* acquire_one_transport(TransportType type, const char* serial,
|
|||
return result;
|
||||
}
|
||||
|
||||
const char* atransport::connection_state_name() const {
|
||||
const std::string atransport::connection_state_name() const {
|
||||
switch (connection_state) {
|
||||
case kCsOffline: return "offline";
|
||||
case kCsBootloader: return "bootloader";
|
||||
case kCsDevice: return "device";
|
||||
case kCsHost: return "host";
|
||||
case kCsRecovery: return "recovery";
|
||||
case kCsNoPerm: return "no permissions";
|
||||
case kCsSideload: return "sideload";
|
||||
case kCsUnauthorized: return "unauthorized";
|
||||
default: return "unknown";
|
||||
case kCsOffline: return "offline";
|
||||
case kCsBootloader: return "bootloader";
|
||||
case kCsDevice: return "device";
|
||||
case kCsHost: return "host";
|
||||
case kCsRecovery: return "recovery";
|
||||
case kCsNoPerm: {
|
||||
std::string message = UsbNoPermissionsShortHelpText();
|
||||
return message.empty() ? "no permissions" : message;
|
||||
}
|
||||
case kCsSideload: return "sideload";
|
||||
case kCsUnauthorized: return "unauthorized";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -866,7 +873,8 @@ static void append_transport(const atransport* t, std::string* result,
|
|||
*result += '\t';
|
||||
*result += t->connection_state_name();
|
||||
} else {
|
||||
android::base::StringAppendF(result, "%-22s %s", serial, t->connection_state_name());
|
||||
android::base::StringAppendF(result, "%-22s %s", serial,
|
||||
t->connection_state_name().c_str());
|
||||
|
||||
append_transport_info(result, "", t->devpath, false);
|
||||
append_transport_info(result, "product:", t->product, false);
|
||||
|
|
|
@ -90,7 +90,7 @@ public:
|
|||
fdevent auth_fde;
|
||||
size_t failed_auth_attempts = 0;
|
||||
|
||||
const char* connection_state_name() const;
|
||||
const std::string connection_state_name() const;
|
||||
|
||||
void update_version(int version, size_t payload);
|
||||
int get_protocol_version() const;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usbdevice_fs.h>
|
||||
#include <linux/version.h>
|
||||
|
@ -595,3 +596,54 @@ void usb_init() {
|
|||
fatal_errno("cannot create device_poll thread");
|
||||
}
|
||||
}
|
||||
|
||||
static const char kPermissionsHelpUrl[] = "developer.android.com/tools/device.html";
|
||||
|
||||
// Returns a message describing any potential problems we find with udev, or nullptr if we can't
|
||||
// find plugdev information (i.e. udev is not installed).
|
||||
static const char* GetUdevProblem() {
|
||||
errno = 0;
|
||||
group* plugdev_group = getgrnam("plugdev");
|
||||
|
||||
if (plugdev_group == nullptr) {
|
||||
if (errno != 0) {
|
||||
D("failed to read plugdev group info: %s", strerror(errno));
|
||||
}
|
||||
// We can't give any generally useful advice here, just let the caller print the help URL.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// getgroups(2) indicates that the group_member() may not check the egid so we check it
|
||||
// additionally just to be sure.
|
||||
if (group_member(plugdev_group->gr_gid) || getegid() == plugdev_group->gr_gid) {
|
||||
// The user is in plugdev so the problem is likely with the udev rules.
|
||||
return "verify udev rules";
|
||||
}
|
||||
return "udev requires plugdev group membership";
|
||||
}
|
||||
|
||||
// Short help text must be a single line, and will look something like:
|
||||
// no permissions (reason); see <URL>
|
||||
std::string UsbNoPermissionsShortHelpText() {
|
||||
std::string help_text = "no permissions";
|
||||
|
||||
const char* problem = GetUdevProblem();
|
||||
if (problem != nullptr) {
|
||||
help_text += android::base::StringPrintf(" (%s)", problem);
|
||||
}
|
||||
|
||||
return android::base::StringPrintf("%s; see [%s]", help_text.c_str(), kPermissionsHelpUrl);
|
||||
}
|
||||
|
||||
// Long help text can span multiple lines and should provide more detailed information.
|
||||
std::string UsbNoPermissionsLongHelpText() {
|
||||
std::string header = "USB permission failure";
|
||||
|
||||
const char* problem = GetUdevProblem();
|
||||
if (problem != nullptr) {
|
||||
header += android::base::StringPrintf(": %s", problem);
|
||||
}
|
||||
|
||||
return android::base::StringPrintf("%s.\nSee [%s] for more information.",
|
||||
header.c_str(), kPermissionsHelpUrl);
|
||||
}
|
||||
|
|
|
@ -571,3 +571,12 @@ void usb_kick(usb_handle *h)
|
|||
{
|
||||
h->kick(h);
|
||||
}
|
||||
|
||||
// kCsNoPerm is a host-side issue, we can just ignore it here.
|
||||
std::string UsbNoPermissionsShortHelpText() {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string UsbNoPermissionsLongHelpText() {
|
||||
return "";
|
||||
}
|
||||
|
|
|
@ -552,3 +552,12 @@ void usb_kick(usb_handle *handle)
|
|||
handle->interface = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// kCsNoPerm is Linux-only.
|
||||
std::string UsbNoPermissionsShortHelpText() {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string UsbNoPermissionsLongHelpText() {
|
||||
return "";
|
||||
}
|
||||
|
|
|
@ -659,3 +659,12 @@ static void kick_devices() {
|
|||
}
|
||||
adb_mutex_unlock(&usb_lock);
|
||||
}
|
||||
|
||||
// kCsNoPerm is Linux-only.
|
||||
std::string UsbNoPermissionsShortHelpText() {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string UsbNoPermissionsLongHelpText() {
|
||||
return "";
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue