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

Commit a80bca7d authored by Paul Mclean's avatar Paul Mclean Committed by Android (Google) Code Review
Browse files

Merge "Revert "Revert "Eliminate native/JNI/callback USB Descriptor parsing mechanism"""

parents e75c145f 9d84fee2
Loading
Loading
Loading
Loading
+39 −5
Original line number Diff line number Diff line
@@ -17,16 +17,18 @@
#define LOG_TAG "UsbHostManagerJNI"
#include "utils/Log.h"

#include <stdlib.h>

#include "jni.h"
#include <nativehelper/JNIHelp.h>

#include <usbhost/usbhost.h>

#define MAX_DESCRIPTORS_LENGTH 16384
#define MAX_DESCRIPTORS_LENGTH 4096

// com.android.server.usb.descriptors
extern "C" {
jbyteArray JNICALL Java_com_android_server_usb_descriptors_UsbDescriptorParser_getRawDescriptors(
jbyteArray JNICALL Java_com_android_server_usb_descriptors_UsbDescriptorParser_getRawDescriptors_1native(
        JNIEnv* env, jobject thiz, jstring deviceAddr) {
    const char *deviceAddrStr = env->GetStringUTFChars(deviceAddr, NULL);
    struct usb_device* device = usb_device_open(deviceAddrStr);
@@ -39,6 +41,7 @@ jbyteArray JNICALL Java_com_android_server_usb_descriptors_UsbDescriptorParser_g

    int fd = usb_device_get_fd(device);
    if (fd < 0) {
        usb_device_close(device);
        return NULL;
    }

@@ -46,17 +49,48 @@ jbyteArray JNICALL Java_com_android_server_usb_descriptors_UsbDescriptorParser_g
    jbyte buffer[MAX_DESCRIPTORS_LENGTH];
    lseek(fd, 0, SEEK_SET);
    int numBytes = read(fd, buffer, sizeof(buffer));

    jbyteArray ret = NULL;
    usb_device_close(device);

    jbyteArray ret = NULL;
    if (numBytes != 0) {
    if (numBytes > 0) {
        ret = env->NewByteArray(numBytes);
        env->SetByteArrayRegion(ret, 0, numBytes, buffer);
    } else {
        ALOGE("error reading descriptors\n");
    }

    return ret;
}

jstring JNICALL Java_com_android_server_usb_descriptors_UsbDescriptorParser_getDescriptorString_1native(
        JNIEnv* env, jobject thiz, jstring deviceAddr, jint stringId) {

    const char *deviceAddrStr = env->GetStringUTFChars(deviceAddr, NULL);
    struct usb_device* device = usb_device_open(deviceAddrStr);
    env->ReleaseStringUTFChars(deviceAddr, deviceAddrStr);

    if (!device) {
        ALOGE("usb_device_open failed");
        return NULL;
    }

    int fd = usb_device_get_fd(device);
    if (fd < 0) {
        ALOGE("usb_device_get_fd failed");
        usb_device_close(device);
        return NULL;
    }

    char* c_str = usb_device_get_string(device, stringId, 0 /*timeout*/);

    jstring j_str = env->NewStringUTF(c_str);

    free(c_str);
    usb_device_close(device);

    return j_str;
}

} // extern "C"

+52 −116
Original line number Diff line number Diff line
@@ -22,8 +22,6 @@
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/Log.h"

#include <usbhost/usbhost.h>

#include <stdio.h>
#include <asm/byteorder.h>
#include <sys/types.h>
@@ -31,22 +29,20 @@
#include <fcntl.h>
#include <sys/ioctl.h>

#include <usbhost/usbhost.h>

#define MAX_DESCRIPTORS_LENGTH 4096

namespace android
{

static const int USB_CONTROL_TRANSFER_TIMEOUT_MS = 200;

static struct parcel_file_descriptor_offsets_t
{
    jclass mClass;
    jmethodID mConstructor;
} gParcelFileDescriptorOffsets;

static jmethodID method_beginUsbDeviceAdded;
static jmethodID method_addUsbConfiguration;
static jmethodID method_addUsbInterface;
static jmethodID method_addUsbEndpoint;
static jmethodID method_endUsbDeviceAdded;
static jmethodID method_usbDeviceAdded;
static jmethodID method_usbDeviceRemoved;

static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
@@ -57,101 +53,63 @@ static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodNa
    }
}

static int usb_device_added(const char *devname, void* client_data) {
    struct usb_descriptor_header* desc;
    struct usb_descriptor_iter iter;

    struct usb_device *device = usb_device_open(devname);
static int usb_device_added(const char *devAddress, void* clientData) {
    struct usb_device *device = usb_device_open(devAddress);
    if (!device) {
        ALOGE("usb_device_open failed\n");
        return 0;
    }

    JNIEnv* env = AndroidRuntime::getJNIEnv();
    jobject thiz = (jobject)client_data;
    const usb_device_descriptor* deviceDesc = usb_device_get_device_descriptor(device);
    int classID = deviceDesc->bDeviceClass;
    int subClassID = deviceDesc->bDeviceSubClass;

    char *manufacturer = usb_device_get_manufacturer_name(device,
            USB_CONTROL_TRANSFER_TIMEOUT_MS);
    char *product = usb_device_get_product_name(device,
            USB_CONTROL_TRANSFER_TIMEOUT_MS);
    int version = usb_device_get_version(device);
    char *serial = usb_device_get_serial(device,
            USB_CONTROL_TRANSFER_TIMEOUT_MS);

    jstring deviceName = env->NewStringUTF(devname);
    jstring manufacturerName = AndroidRuntime::NewStringLatin1(env, manufacturer);
    jstring productName = AndroidRuntime::NewStringLatin1(env, product);
    jstring serialNumber = AndroidRuntime::NewStringLatin1(env, serial);

    jboolean result = env->CallBooleanMethod(thiz, method_beginUsbDeviceAdded,
            deviceName, usb_device_get_vendor_id(device), usb_device_get_product_id(device),
            deviceDesc->bDeviceClass, deviceDesc->bDeviceSubClass, deviceDesc->bDeviceProtocol,
            manufacturerName, productName, version, serialNumber);

    env->DeleteLocalRef(serialNumber);
    env->DeleteLocalRef(productName);
    env->DeleteLocalRef(manufacturerName);
    env->DeleteLocalRef(deviceName);
    free(manufacturer);
    free(product);
    free(serial);

    if (!result) goto fail;

    usb_descriptor_iter_init(device, &iter);

    while ((desc = usb_descriptor_iter_next(&iter)) != NULL) {
        if (desc->bDescriptorType == USB_DT_CONFIG) {
            struct usb_config_descriptor *config = (struct usb_config_descriptor *)desc;
            char *name = usb_device_get_string(device, config->iConfiguration,
                    USB_CONTROL_TRANSFER_TIMEOUT_MS);
            jstring configName = AndroidRuntime::NewStringLatin1(env, name);

            env->CallVoidMethod(thiz, method_addUsbConfiguration,
                    config->bConfigurationValue, configName, config->bmAttributes,
                    config->bMaxPower);

            env->DeleteLocalRef(configName);
            free(name);
        } else if (desc->bDescriptorType == USB_DT_INTERFACE) {
            struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)desc;
            char *name = usb_device_get_string(device, interface->iInterface,
                    USB_CONTROL_TRANSFER_TIMEOUT_MS);
            jstring interfaceName = AndroidRuntime::NewStringLatin1(env, name);

            env->CallVoidMethod(thiz, method_addUsbInterface,
                    interface->bInterfaceNumber, interfaceName, interface->bAlternateSetting,
                    interface->bInterfaceClass, interface->bInterfaceSubClass,
                    interface->bInterfaceProtocol);

            env->DeleteLocalRef(interfaceName);
            free(name);
        } else if (desc->bDescriptorType == USB_DT_ENDPOINT) {
            struct usb_endpoint_descriptor *endpoint = (struct usb_endpoint_descriptor *)desc;

            env->CallVoidMethod(thiz, method_addUsbEndpoint,
                    endpoint->bEndpointAddress, endpoint->bmAttributes,
                    __le16_to_cpu(endpoint->wMaxPacketSize), endpoint->bInterval);
        }
    // get the raw descriptors
    int fd = usb_device_get_fd(device);
    if (fd < 0) {
        ALOGE("usb_device_get_fd failed\n");
        usb_device_close(device);
        // TODO return an error code here?
        return 0;
    }

    env->CallVoidMethod(thiz, method_endUsbDeviceAdded);
    // from android_hardware_UsbDeviceConnection_get_desc()
    jbyte rawdescriptors[MAX_DESCRIPTORS_LENGTH];
    lseek(fd, 0, SEEK_SET);
    int numBytes = read(fd, rawdescriptors, sizeof(rawdescriptors));

fail:
    usb_device_close(device);

    if (numBytes > 0) {
        JNIEnv* env = AndroidRuntime::getJNIEnv();
        jobject thiz = (jobject)clientData;
        jstring deviceAddress = env->NewStringUTF(devAddress);

        jbyteArray descriptorsArray = env->NewByteArray(numBytes);
        env->SetByteArrayRegion(descriptorsArray, 0, numBytes, rawdescriptors);

        env->CallBooleanMethod(thiz, method_usbDeviceAdded,
                deviceAddress, classID, subClassID, descriptorsArray);

        env->DeleteLocalRef(descriptorsArray);
        env->DeleteLocalRef(deviceAddress);

        checkAndClearExceptionFromCallback(env, __FUNCTION__);
    } else {
        // TODO return an error code here?
        ALOGE("error reading descriptors\n");
    }

    return 0;
}

static int usb_device_removed(const char *devname, void* client_data) {
static int usb_device_removed(const char *devAddress, void* clientData) {
    JNIEnv* env = AndroidRuntime::getJNIEnv();
    jobject thiz = (jobject)client_data;
    jobject thiz = (jobject)clientData;

    jstring deviceName = env->NewStringUTF(devname);
    env->CallVoidMethod(thiz, method_usbDeviceRemoved, deviceName);
    env->DeleteLocalRef(deviceName);
    jstring deviceAddress = env->NewStringUTF(devAddress);
    env->CallVoidMethod(thiz, method_usbDeviceRemoved, deviceAddress);
    env->DeleteLocalRef(deviceAddress);
    checkAndClearExceptionFromCallback(env, __FUNCTION__);
    return 0;
}
@@ -168,11 +126,11 @@ static void android_server_UsbHostManager_monitorUsbHostBus(JNIEnv* /* env */, j
}

static jobject android_server_UsbHostManager_openDevice(JNIEnv *env, jobject /* thiz */,
                                                        jstring deviceName)
                                                        jstring deviceAddress)
{
    const char *deviceNameStr = env->GetStringUTFChars(deviceName, NULL);
    struct usb_device* device = usb_device_open(deviceNameStr);
    env->ReleaseStringUTFChars(deviceName, deviceNameStr);
    const char *deviceAddressStr = env->GetStringUTFChars(deviceAddress, NULL);
    struct usb_device* device = usb_device_open(deviceAddressStr);
    env->ReleaseStringUTFChars(deviceAddress, deviceAddressStr);

    if (!device)
        return NULL;
@@ -206,34 +164,12 @@ int register_android_server_UsbHostManager(JNIEnv *env)
        ALOGE("Can't find com/android/server/usb/UsbHostManager");
        return -1;
    }
    method_beginUsbDeviceAdded = env->GetMethodID(clazz, "beginUsbDeviceAdded",
            "(Ljava/lang/String;IIIIILjava/lang/String;Ljava/lang/String;ILjava/lang/String;)Z");
    if (method_beginUsbDeviceAdded == NULL) {
    method_usbDeviceAdded =
            env->GetMethodID(clazz, "usbDeviceAdded", "(Ljava/lang/String;II[B)Z");
    if (method_usbDeviceAdded == NULL) {
        ALOGE("Can't find beginUsbDeviceAdded");
        return -1;
    }
    method_addUsbConfiguration = env->GetMethodID(clazz, "addUsbConfiguration",
            "(ILjava/lang/String;II)V");
    if (method_addUsbConfiguration == NULL) {
        ALOGE("Can't find addUsbConfiguration");
        return -1;
    }
    method_addUsbInterface = env->GetMethodID(clazz, "addUsbInterface",
            "(ILjava/lang/String;IIII)V");
    if (method_addUsbInterface == NULL) {
        ALOGE("Can't find addUsbInterface");
        return -1;
    }
    method_addUsbEndpoint = env->GetMethodID(clazz, "addUsbEndpoint", "(IIII)V");
    if (method_addUsbEndpoint == NULL) {
        ALOGE("Can't find addUsbEndpoint");
        return -1;
    }
    method_endUsbDeviceAdded = env->GetMethodID(clazz, "endUsbDeviceAdded", "()V");
    if (method_endUsbDeviceAdded == NULL) {
        ALOGE("Can't find endUsbDeviceAdded");
        return -1;
    }
    method_usbDeviceRemoved = env->GetMethodID(clazz, "usbDeviceRemoved",
            "(Ljava/lang/String;)V");
    if (method_usbDeviceRemoved == NULL) {
+1 −0
Original line number Diff line number Diff line
@@ -255,6 +255,7 @@ public final class UsbAlsaManager {
    }

    private void alsaFileAdded(String name) {
        Slog.i(TAG, "alsaFileAdded(" + name + ")");
        int type = AlsaDevice.TYPE_UNKNOWN;
        int card = -1, device = -1;

+68 −174

File changed.

Preview size limit exceeded, changes collapsed.

+24 −0
Original line number Diff line number Diff line
@@ -15,8 +15,13 @@
 */
package com.android.server.usb.descriptors;

import android.hardware.usb.UsbConfiguration;
import android.hardware.usb.UsbInterface;

import com.android.server.usb.descriptors.report.ReportCanvas;

import java.util.ArrayList;

/**
 * @hide
 * An USB Config Descriptor.
@@ -35,6 +40,9 @@ public final class UsbConfigDescriptor extends UsbDescriptor {
                                //     D4..0 Reserved, set to 0.
    private byte mMaxPower;     // 8:1 Maximum Power Consumption in 2mA units

    private ArrayList<UsbInterfaceDescriptor> mInterfaceDescriptors =
            new ArrayList<UsbInterfaceDescriptor>();

    UsbConfigDescriptor(int length, byte type) {
        super(length, type);
        mHierarchyLevel = 2;
@@ -64,6 +72,22 @@ public final class UsbConfigDescriptor extends UsbDescriptor {
        return mMaxPower;
    }

    void addInterfaceDescriptor(UsbInterfaceDescriptor interfaceDesc) {
        mInterfaceDescriptors.add(interfaceDesc);
    }

    UsbConfiguration toAndroid(UsbDescriptorParser parser) {
        String name = parser.getDescriptorString(mConfigIndex);
        UsbConfiguration config = new
                UsbConfiguration(mConfigValue, name, mAttribs, mMaxPower);
        UsbInterface[] interfaces = new UsbInterface[mInterfaceDescriptors.size()];
        for (int index = 0; index < mInterfaceDescriptors.size(); index++) {
            interfaces[index] = mInterfaceDescriptors.get(index).toAndroid(parser);
        }
        config.setInterfaces(interfaces);
        return config;
    }

    @Override
    public int parseRawDescriptors(ByteStream stream) {
        mTotalLength = stream.unpackUsbShort();
Loading