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

Commit f4578f1a authored by Josh Gao's avatar Josh Gao Committed by android-build-merger
Browse files

Merge changes I8e8e0963,I3c714f63,Id157412e,Ib7c26fbd am: 55ddb995

am: 66ca192a

Change-Id: I751dbb8fd9a5b5f79118ce38a63d2b5073bb5bf7
parents 96ab6a71 66ca192a
Loading
Loading
Loading
Loading
+0 −6
Original line number Original line Diff line number Diff line
@@ -1241,10 +1241,7 @@ void update_transport_status() {
        return true;
        return true;
    });
    });


    D("update_transport_status: transports_ready = %s", result ? "true" : "false");

    bool ready;
    bool ready;

    {
    {
        std::lock_guard<std::mutex> lock(init_mutex);
        std::lock_guard<std::mutex> lock(init_mutex);
        transports_ready = result;
        transports_ready = result;
@@ -1252,14 +1249,11 @@ void update_transport_status() {
    }
    }


    if (ready) {
    if (ready) {
        D("update_transport_status: notifying");
        init_cv.notify_all();
        init_cv.notify_all();
    }
    }
}
}


void adb_notify_device_scan_complete() {
void adb_notify_device_scan_complete() {
    D("device scan complete");

    {
    {
        std::lock_guard<std::mutex> lock(init_mutex);
        std::lock_guard<std::mutex> lock(init_mutex);
        device_scan_complete = true;
        device_scan_complete = true;
+78 −37
Original line number Original line Diff line number Diff line
@@ -151,10 +151,7 @@ struct usb_handle : public ::usb_handle {
static auto& usb_handles = *new std::unordered_map<std::string, std::unique_ptr<usb_handle>>();
static auto& usb_handles = *new std::unordered_map<std::string, std::unique_ptr<usb_handle>>();
static auto& usb_handles_mutex = *new std::mutex();
static auto& usb_handles_mutex = *new std::mutex();


static std::thread* device_poll_thread = nullptr;
static libusb_hotplug_callback_handle hotplug_handle;
static bool terminate_device_poll_thread = false;
static auto& device_poll_mutex = *new std::mutex();
static auto& device_poll_cv = *new std::condition_variable();


static std::string get_device_address(libusb_device* device) {
static std::string get_device_address(libusb_device* device) {
    return StringPrintf("usb:%d:%d", libusb_get_bus_number(device),
    return StringPrintf("usb:%d:%d", libusb_get_bus_number(device),
@@ -175,6 +172,17 @@ static std::string get_device_serial_path(libusb_device* device) {
    path += "/serial";
    path += "/serial";
    return path;
    return path;
}
}

static std::string get_device_dev_path(libusb_device* device) {
    uint8_t ports[7];
    int port_count = libusb_get_port_numbers(device, ports, 7);
    if (port_count < 0) return "";
    return StringPrintf("/dev/bus/usb/%03u/%03u", libusb_get_bus_number(device), ports[0]);
}

static bool is_device_accessible(libusb_device* device) {
    return access(get_device_dev_path(device).c_str(), R_OK | W_OK) == 0;
}
#endif
#endif


static bool endpoint_is_output(uint8_t endpoint) {
static bool endpoint_is_output(uint8_t endpoint) {
@@ -229,7 +237,7 @@ static void process_device(libusb_device* device) {
            // TODO: Is this assumption valid?
            // TODO: Is this assumption valid?
            LOG(VERBOSE) << "skipping interface with incorrect num_altsetting at " << device_address
            LOG(VERBOSE) << "skipping interface with incorrect num_altsetting at " << device_address
                         << " (interface " << interface_num << ")";
                         << " (interface " << interface_num << ")";
            return;
            continue;
        }
        }


        const libusb_interface_descriptor& interface_desc = interface.altsetting[0];
        const libusb_interface_descriptor& interface_desc = interface.altsetting[0];
@@ -237,7 +245,7 @@ static void process_device(libusb_device* device) {
                              interface_desc.bInterfaceProtocol)) {
                              interface_desc.bInterfaceProtocol)) {
            LOG(VERBOSE) << "skipping non-adb interface at " << device_address << " (interface "
            LOG(VERBOSE) << "skipping non-adb interface at " << device_address << " (interface "
                         << interface_num << ")";
                         << interface_num << ")";
            return;
            continue;
        }
        }


        LOG(VERBOSE) << "found potential adb interface at " << device_address << " (interface "
        LOG(VERBOSE) << "found potential adb interface at " << device_address << " (interface "
@@ -253,7 +261,7 @@ static void process_device(libusb_device* device) {
            const uint8_t transfer_type = endpoint_attr & LIBUSB_TRANSFER_TYPE_MASK;
            const uint8_t transfer_type = endpoint_attr & LIBUSB_TRANSFER_TYPE_MASK;


            if (transfer_type != LIBUSB_TRANSFER_TYPE_BULK) {
            if (transfer_type != LIBUSB_TRANSFER_TYPE_BULK) {
                return;
                continue;
            }
            }


            if (endpoint_is_output(endpoint_addr) && !found_out) {
            if (endpoint_is_output(endpoint_addr) && !found_out) {
@@ -371,31 +379,60 @@ static void process_device(libusb_device* device) {
    }
    }


    register_usb_transport(usb_handle_raw, device_serial.c_str(), device_address.c_str(), writable);
    register_usb_transport(usb_handle_raw, device_serial.c_str(), device_address.c_str(), writable);

    LOG(INFO) << "registered new usb device '" << device_serial << "'";
    LOG(INFO) << "registered new usb device '" << device_serial << "'";
}
}


static void poll_for_devices() {
static std::atomic<int> connecting_devices(0);
    libusb_device** list;
    adb_thread_setname("device poll");
    while (true) {
        const ssize_t device_count = libusb_get_device_list(nullptr, &list);

        LOG(VERBOSE) << "found " << device_count << " attached devices";


        for (ssize_t i = 0; i < device_count; ++i) {
static void device_connected(libusb_device* device) {
            process_device(list[i]);
#if defined(__linux__)
    // Android's host linux libusb uses netlink instead of udev for device hotplug notification,
    // which means we can get hotplug notifications before udev has updated ownership/perms on the
    // device. Since we're not going to be able to link against the system's libudev any time soon,
    // hack around this by checking for accessibility in a loop.
    ++connecting_devices;
    auto thread = std::thread([device]() {
        std::string device_path = get_device_dev_path(device);
        auto start = std::chrono::steady_clock::now();
        while (std::chrono::steady_clock::now() - start < 500ms) {
            if (is_device_accessible(device)) {
                break;
            }
            std::this_thread::sleep_for(10ms);
        }
        }


        libusb_free_device_list(list, 1);
        process_device(device);
        --connecting_devices;
    });
    thread.detach();
#else
    process_device(device);
#endif
}


        adb_notify_device_scan_complete();
static void device_disconnected(libusb_device* device) {
    std::string device_address = get_device_address(device);


        std::unique_lock<std::mutex> lock(device_poll_mutex);
    LOG(INFO) << "device disconnected: " << device_address;
        if (device_poll_cv.wait_for(lock, 500ms, []() { return terminate_device_poll_thread; })) {
    std::unique_lock<std::mutex> lock(usb_handles_mutex);
            return;
    auto it = usb_handles.find(device_address);
    if (it != usb_handles.end()) {
        if (!it->second->device_handle) {
            // If the handle is null, we were never able to open the device.
            unregister_usb_transport(it->second.get());
        }
        usb_handles.erase(it);
    }
}
}

static int hotplug_callback(libusb_context*, libusb_device* device, libusb_hotplug_event event,
                            void*) {
    if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {
        device_connected(device);
    } else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) {
        device_disconnected(device);
    }
    }
    return 0;
}
}


void usb_init() {
void usb_init() {
@@ -405,6 +442,24 @@ void usb_init() {
        LOG(FATAL) << "failed to initialize libusb: " << libusb_error_name(rc);
        LOG(FATAL) << "failed to initialize libusb: " << libusb_error_name(rc);
    }
    }


    // Register the hotplug callback.
    rc = libusb_hotplug_register_callback(
        nullptr, static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
                                                   LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
        LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
        LIBUSB_CLASS_PER_INTERFACE, hotplug_callback, nullptr, &hotplug_handle);

    if (rc != LIBUSB_SUCCESS) {
        LOG(FATAL) << "failed to register libusb hotplug callback";
    }

    // Wait for all of the connecting devices to finish.
    while (connecting_devices != 0) {
        std::this_thread::sleep_for(10ms);
    }

    adb_notify_device_scan_complete();

    // Spawn a thread for libusb_handle_events.
    // Spawn a thread for libusb_handle_events.
    std::thread([]() {
    std::thread([]() {
        adb_thread_setname("libusb");
        adb_thread_setname("libusb");
@@ -412,24 +467,10 @@ void usb_init() {
            libusb_handle_events(nullptr);
            libusb_handle_events(nullptr);
        }
        }
    }).detach();
    }).detach();

    // Spawn a thread to do device enumeration.
    // TODO: Use libusb_hotplug_* instead?
    std::unique_lock<std::mutex> lock(device_poll_mutex);
    device_poll_thread = new std::thread(poll_for_devices);
}
}


void usb_cleanup() {
void usb_cleanup() {
    {
    libusb_hotplug_deregister_callback(nullptr, hotplug_handle);
        std::unique_lock<std::mutex> lock(device_poll_mutex);
        terminate_device_poll_thread = true;

        if (!device_poll_thread) {
            return;
        }
    }
    device_poll_cv.notify_all();
    device_poll_thread->join();
}
}


// Dispatch a libusb transfer, unlock |device_lock|, and then wait for the result.
// Dispatch a libusb transfer, unlock |device_lock|, and then wait for the result.