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

Commit 663e949b authored by David Pursell's avatar David Pursell Committed by Gerrit Code Review
Browse files

Merge "adb: add help text for USB permission errors."

parents 5986d9f2 d2acbd19
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -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);
+20 −12
Original line number Diff line number Diff line
@@ -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 = 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,14 +752,17 @@ 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 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);
+1 −1
Original line number Diff line number Diff line
@@ -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;
+52 −0
Original line number Diff line number Diff line
@@ -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);
}
+9 −0
Original line number Diff line number Diff line
@@ -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 "";
}
Loading