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

Commit efd8c328 authored by Elliott Hughes's avatar Elliott Hughes Committed by Gerrit Code Review
Browse files

Merge "Share the new adb USB diagnostic code with fastboot."

parents 9fb50475 1b708d36
Loading
Loading
Loading
Loading
+15 −0
Original line number Original line Diff line number Diff line
@@ -160,6 +160,19 @@ LOCAL_STATIC_LIBRARIES := libadbd
LOCAL_SHARED_LIBRARIES := libbase libcutils
LOCAL_SHARED_LIBRARIES := libbase libcutils
include $(BUILD_NATIVE_TEST)
include $(BUILD_NATIVE_TEST)


# libdiagnose_usb
# =========================================================

include $(CLEAR_VARS)
LOCAL_MODULE := libdiagnose_usb
LOCAL_MODULE_HOST_OS := darwin linux windows
LOCAL_CFLAGS := $(LIBADB_CFLAGS)
LOCAL_SRC_FILES := diagnose_usb.cpp
# Even though we're building a static library (and thus there's no link step for
# this to take effect), this adds the includes to our path.
LOCAL_STATIC_LIBRARIES := libbase
include $(BUILD_HOST_STATIC_LIBRARY)

# adb_test
# adb_test
# =========================================================
# =========================================================


@@ -185,6 +198,7 @@ LOCAL_STATIC_LIBRARIES := \
    libadb \
    libadb \
    libcrypto_static \
    libcrypto_static \
    libcutils \
    libcutils \
    libdiagnose_usb \


# Set entrypoint to wmain from sysdeps_win32.cpp instead of main
# Set entrypoint to wmain from sysdeps_win32.cpp instead of main
LOCAL_LDFLAGS_windows := -municode
LOCAL_LDFLAGS_windows := -municode
@@ -261,6 +275,7 @@ LOCAL_STATIC_LIBRARIES := \
    libadb \
    libadb \
    libbase \
    libbase \
    libcrypto_static \
    libcrypto_static \
    libdiagnose_usb \
    liblog \
    liblog \


# Don't use libcutils on Windows.
# Don't use libcutils on Windows.
+0 −5
Original line number Original line Diff line number Diff line
@@ -226,11 +226,6 @@ void usb_kick(usb_handle *h);
int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol);
int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol);
#endif
#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);
int adb_commandline(int argc, const char **argv);


ConnectionState connection_state(atransport *t);
ConnectionState connection_state(atransport *t);

adb/diagnose_usb.cpp

0 → 100644
+83 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "diagnose_usb.h"

#include <errno.h>
#include <unistd.h>

#include <string>

#include <android-base/stringprintf.h>

#if defined(__linux__)
#include <grp.h>
#endif

static const char kPermissionsHelpUrl[] = "http://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() {
#if defined(__linux__)
    errno = 0;
    group* plugdev_group = getgrnam("plugdev");

    if (plugdev_group == nullptr) {
        if (errno != 0) {
            perror("failed to read plugdev group info");
        }
        // 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";
#else
    return nullptr;
#endif
}

// 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 = "insufficient permissions for device";

    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);
}

adb/diagnose_usb.h

0 → 100644
+27 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __DIAGNOSE_LINUX_USB_H
#define __DIAGNOSE_LINUX_USB_H

#include <string>

// 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();

#endif
+4 −8
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@


#include "adb.h"
#include "adb.h"
#include "adb_utils.h"
#include "adb_utils.h"
#include "diagnose_usb.h"


static void transport_unref(atransport *t);
static void transport_unref(atransport *t);


@@ -674,11 +675,9 @@ atransport* acquire_one_transport(TransportType type, const char* serial,
    adb_mutex_lock(&transport_lock);
    adb_mutex_lock(&transport_lock);
    for (const auto& t : transport_list) {
    for (const auto& t : transport_list) {
        if (t->connection_state == kCsNoPerm) {
        if (t->connection_state == kCsNoPerm) {
#if ADB_HOST
            *error_out = UsbNoPermissionsLongHelpText();
            *error_out = UsbNoPermissionsLongHelpText();
            // If we couldn't figure out a reasonable help message default to something generic.
#endif
            if (error_out->empty()) {
                *error_out = "insufficient permissions for device";
            }
            continue;
            continue;
        }
        }


@@ -759,10 +758,7 @@ const std::string atransport::connection_state_name() const {
        case kCsDevice: return "device";
        case kCsDevice: return "device";
        case kCsHost: return "host";
        case kCsHost: return "host";
        case kCsRecovery: return "recovery";
        case kCsRecovery: return "recovery";
        case kCsNoPerm: {
        case kCsNoPerm: return UsbNoPermissionsShortHelpText();
            std::string message = UsbNoPermissionsShortHelpText();
            return message.empty() ? "no permissions" : message;
        }
        case kCsSideload: return "sideload";
        case kCsSideload: return "sideload";
        case kCsUnauthorized: return "unauthorized";
        case kCsUnauthorized: return "unauthorized";
        default: return "unknown";
        default: return "unknown";
Loading