Android 6.0 usb解析(二)UsbHostManager

之前在Android5.1的时候我们分析过UsbDevicemanager,现在Android6.0我们不准备分析UsbDevicemanager了,因为大致原理差不多。而UsbDeviceManager是将手机作为一个设备,比如手机连上电脑,使用adb、mtp等。而这里准备分析的UsbHostManager,是将手机作为一个host,比如手机连接usb鼠标、usb摄像头等。

UsbHostManager的初始化

UsbHostManager和UsbDeviceManager一样都是在UsbService中新建的。

  1. public UsbService(Context context) {  
  2.     mContext = context;  
  3.   
  4.     mAlsaManager = new UsbAlsaManager(context);  
  5.   
  6.     final PackageManager pm = mContext.getPackageManager();  
  7.     if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {  
  8.         mHostManager = new UsbHostManager(context, mAlsaManager);  
  9.     }  

然后在UsbService的systemReady中调用了UsbHostManager的systemReady函数。

  1. public void systemReady() {  
  2.     mAlsaManager.systemReady();  
  3.   
  4.     if (mDeviceManager != null) {  
  5.         mDeviceManager.systemReady();  
  6.     }  
  7.     if (mHostManager != null) {  
  8.         mHostManager.systemReady();  
  9.     }  
  10.     if (mPortManager != null) {  
  11.         mPortManager.systemReady();  
  12.     }  
  13. }  
UsbHostManager的构造函数就是新建一些对象,我们直接看systemReady函数。这个函数在新的线程中调用了monitorUsbHostBus函数。
  1. public void systemReady() {  
  2.     synchronized (mLock) {  
  3.         // Create a thread to call into native code to wait for USB host events.  
  4.         // This thread will call us back on usbDeviceAdded and usbDeviceRemoved.  
  5.         Runnable runnable = new Runnable() {  
  6.             public void run() {  
  7.                 monitorUsbHostBus();  
  8.             }  
  9.         };  
  10.         new Thread(null, runnable, "UsbService host thread").start();  
  11.     }  
  12. }  

而monitorUsbHostBus函数是一个JNI函数。

  1. private native void monitorUsbHostBus();  


UsbHostManager的hal层

monitorUsbHostBus对应的JNI函数是在com_android_server_UsbHostManager.cpp的android_server_UsbHostManager_monitorUsbHostBus函数,在这个函数调用了usb_host_init函数,创建了一个INotify的fd,以及创建了一个usb_host_context对象。usb_host_run函数就是循环读取INotify的fd的事件,我们把usb_device_added, usb_device_removed两个回调函数也传入了usb_host_run函数了。

  1. static void android_server_UsbHostManager_monitorUsbHostBus(JNIEnv* /* env */, jobject thiz)  
  2. {  
  3.     struct usb_host_context* context = usb_host_init();  
  4.     if (!context) {  
  5.         ALOGE("usb_host_init failed");  
  6.         return;  
  7.     }  
  8.     // this will never return so it is safe to pass thiz directly  
  9.     usb_host_run(context, usb_device_added, usb_device_removed, NULL, (void *)thiz);  
  10. }  

usb_host_init是在system\core\libusbhost\usbhost.c文件中,这个函数中新建一个usb_host_context对象,还有新建了一个INotify,并且usb_host_context的fd就是INotify的fd。

  1. struct usb_host_context *usb_host_init()  
  2. {  
  3.     struct usb_host_context *context = calloc(1, sizeof(struct usb_host_context));//新建一个usb_host_context对象  
  4.     if (!context) {  
  5.         fprintf(stderr, "out of memory in usb_host_context\n");  
  6.         return NULL;  
  7.     }  
  8.     context->fd = inotify_init();//新建一个INotify  
  9.     if (context->fd < 0) {  
  10.         fprintf(stderr, "inotify_init failed\n");  
  11.         free(context);  
  12.         return NULL;  
  13.     }  
  14.     return context;  
  15. }  
我们再来看看usb_host_run函数。先调用了usb_host_load函数,这个函数主要把add和remove的回调,放到context相应的成员变量中,然后增加了dev目录放入INotify的观察。下面循环调用usb_host_read_event函数去读取INotify fd的事件。
  1. void usb_host_run(struct usb_host_context *context,  
  2.                   usb_device_added_cb added_cb,  
  3.                   usb_device_removed_cb removed_cb,  
  4.                   usb_discovery_done_cb discovery_done_cb,  
  5.                   void *client_data)  
  6. {  
  7.     int done;  
  8.   
  9.     done = usb_host_load(context, added_cb, removed_cb, discovery_done_cb, client_data);  
  10.   
  11.     while (!done) {  
  12.   
  13.         done = usb_host_read_event(context);  
  14.     }  
  15. }  
usb_host_load函数先把add和remove的两个回调设置到usb_host_context 中,然后将dev目录放入INotify观察。然后调用watch_existing_subdirs将/dev/bus/usb下的目录都添加到INotify中观察,最后再调用find_existing_devices函数,把找到的设备调用added_cb(增加的回调函数)
  1. int usb_host_load(struct usb_host_context *context,  
  2.                   usb_device_added_cb added_cb,  
  3.                   usb_device_removed_cb removed_cb,  
  4.                   usb_discovery_done_cb discovery_done_cb,  
  5.                   void *client_data)  
  6. {  
  7.     int done = 0;  
  8.     int i;  
  9.   
  10.     context->cb_added = added_cb;//回调赋值  
  11.     context->cb_removed = removed_cb;  
  12.     context->data = client_data;  
  13.   
  14.     D("Created device discovery thread\n");  
  15.   
  16.     /* watch for files added and deleted within USB_FS_DIR */  
  17.     context->wddbus = -1;  
  18.     for (i = 0; i < MAX_USBFS_WD_COUNT; i++)  
  19.         context->wds[i] = -1;  
  20.   
  21.     /* watch the root for new subdirectories */  
  22.     context->wdd = inotify_add_watch(context->fd, DEV_DIR, IN_CREATE | IN_DELETE);//将dev目录放入INotify观察  
  23.     if (context->wdd < 0) {  
  24.         fprintf(stderr, "inotify_add_watch failed\n");  
  25.         if (discovery_done_cb)  
  26.             discovery_done_cb(client_data);  
  27.         return done;  
  28.     }  
  29.   
  30.     watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);  
  31.   
  32.     /* check for existing devices first, after we have inotify set up */  
  33.     done = find_existing_devices(added_cb, client_data);  
  34.     if (discovery_done_cb)  
  35.         done |= discovery_done_cb(client_data);  
  36.   
  37.     return done;  
  38. }   
watch_existing_subdirs,就是将/dev/bus/usb下的设备目录(001开始到MAX_USBFS_WD_COUNT值都inotify_add_watch)都添加到INotify中去。
  1. static void watch_existing_subdirs(struct usb_host_context *context,  
  2.                                    int *wds, int wd_count)  
  3. {  
  4.     char path[100];  
  5.     int i, ret;  
  6.   
  7.     wds[0] = inotify_add_watch(context->fd, USB_FS_DIR, IN_CREATE | IN_DELETE);  
  8.     if (wds[0] < 0)  
  9.         return;  
  10.   
  11.     /* watch existing subdirectories of USB_FS_DIR */  
  12.     for (i = 1; i < wd_count; i++) {  
  13.         snprintf(path, sizeof(path), USB_FS_DIR "/%03d", i);  
  14.         ret = inotify_add_watch(context->fd, path, IN_CREATE | IN_DELETE);  
  15.         if (ret >= 0)  
  16.             wds[i] = ret;  
  17.     }  
  18. }  
然后我们再来看find_existing_devices函数,就是遍历dev/bus/usb的目录然后再调用find_existing_devices_bus函数
  1. static int find_existing_devices(usb_device_added_cb added_cb,  
  2.                                   void *client_data)  
  3. {  
  4.     char busname[32];  
  5.     DIR *busdir;  
  6.     struct dirent *de;  
  7.     int done = 0;  
  8.   
  9.     busdir = opendir(USB_FS_DIR);  
  10.     if(busdir == 0) return 0;  
  11.   
  12.     while ((de = readdir(busdir)) != 0 && !done) {  
  13.         if(badname(de->d_name)) continue;  
  14.   
  15.         snprintf(busname, sizeof(busname), USB_FS_DIR "/%s", de->d_name);  
  16.         done = find_existing_devices_bus(busname, added_cb,  
  17.                                          client_data);  
  18.     } //end of busdir while  
  19.     closedir(busdir);  
  20.   
  21.     return done;  
  22. }  
find_existing_devices_bus函数,就是将dev/bus/usb下的目录比如001,然后001目录里面的文件,作为一个设备(组成一个devname),再调用added_cb(增加设备的回调函数)
  1. static int find_existing_devices_bus(char *busname,  
  2.                                      usb_device_added_cb added_cb,  
  3.                                      void *client_data)  
  4. {  
  5.     char devname[32];  
  6.     DIR *devdir;  
  7.     struct dirent *de;  
  8.     int done = 0;  
  9.   
  10.     devdir = opendir(busname);  
  11.     if(devdir == 0) return 0;  
  12.   
  13.     while ((de = readdir(devdir)) && !done) {  
  14.         if(badname(de->d_name)) continue;  
  15.   
  16.         snprintf(devname, sizeof(devname), "%s/%s", busname, de->d_name);  
  17.         done = added_cb(devname, client_data);  
  18.     } // end of devdir while  
  19.     closedir(devdir);  
  20.   
  21.     return done;  
  22. }  
因此总结下usb_host_load函数就是把增加、去除设备的回调赋值到usb_host_context 的相关变量中,然后增加相关目录的观察,最后查找已经存在的设备调用added_cb(增加设备的回调函数)。

然后我们再来看看usb_host_read_event函数,这个函数就是去INotify中的fd读取相关的事件。具体分析我们就看注释,有一点我们要注意了,除了增加bus目录失败返回的done是1,其他的返回的done都是0.也就是我们的usb_host_run函数会在while循环中一直循环。

  1. int usb_host_read_event(struct usb_host_context *context)  
  2. {  
  3.     struct inotify_event* event;  
  4.     char event_buf[512];  
  5.     char path[100];  
  6.     int i, ret, done = 0;  
  7.     int offset = 0;  
  8.     int wd;  
  9.   
  10.     ret = read(context->fd, event_buf, sizeof(event_buf));  
  11.     if (ret >= (int)sizeof(struct inotify_event)) {  
  12.         while (offset < ret && !done) {  
  13.             event = (struct inotify_event*)&event_buf[offset];  
  14.             done = 0;  
  15.             wd = event->wd;  
  16.             if (wd == context->wdd) {  
  17.                 if ((event->mask & IN_CREATE) && !strcmp(event->name, "bus")) {//增加bus目录,并且将bus目录也增加到watch中  
  18.                     context->wddbus = inotify_add_watch(context->fd, DEV_BUS_DIR, IN_CREATE | IN_DELETE);  
  19.                     if (context->wddbus < 0) {  
  20.                         done = 1;//增加bus目录失败  
  21.                     } else {  
  22.                         watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);  
  23.                         done = find_existing_devices(context->cb_added, context->data);  
  24.                     }  
  25.                 }  
  26.             } else if (wd == context->wddbus) {  
  27.                 if ((event->mask & IN_CREATE) && !strcmp(event->name, "usb")) {//如果是dev/bus目录的事件  
  28.                     watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);//将dev/bus/usb目录再增加到watch  
  29.                     done = find_existing_devices(context->cb_added, context->data);//然后再看看usb下面时候有设备,有就调用添加函数  
  30.                 } else if ((event->mask & IN_DELETE) && !strcmp(event->name, "usb")) {  
  31.                     for (i = 0; i < MAX_USBFS_WD_COUNT; i++) {  
  32.                         if (context->wds[i] >= 0) {  
  33.                             inotify_rm_watch(context->fd, context->wds[i]);//是删除事件,就把这个watch删除了  
  34.                             context->wds[i] = -1;  
  35.                         }  
  36.                     }  
  37.                 }  
  38.             } else if (wd == context->wds[0]) {//是第一个wds,也就是dev/bus/usb目录的事件  
  39.                 i = atoi(event->name);  
  40.                 snprintf(path, sizeof(path), USB_FS_DIR "/%s", event->name);  
  41.                 D("%s subdirectory %s: index: %d\n", (event->mask & IN_CREATE) ?  
  42.                         "new" : "gone", path, i);  
  43.                 if (i > 0 && i < MAX_USBFS_WD_COUNT) {  
  44.                     int local_ret = 0;  
  45.                     if (event->mask & IN_CREATE) {  
  46.                         local_ret = inotify_add_watch(context->fd, path,//我们需要把usb下新增的目录也增加到watch中  
  47.                                 IN_CREATE | IN_DELETE);  
  48.                         if (local_ret >= 0)  
  49.                             context->wds[i] = local_ret;  
  50.                         done = find_existing_devices_bus(path, context->cb_added,//然后再看看是否有已经存在的设备  
  51.                                 context->data);  
  52.                     } else if (event->mask & IN_DELETE) {  
  53.                         inotify_rm_watch(context->fd, context->wds[i]);  
  54.                         context->wds[i] = -1;  
  55.                     }  
  56.                 }  
  57.             } else {  
  58.                 for (i = 1; (i < MAX_USBFS_WD_COUNT) && !done; i++) {//最后剩下的肯定是dev/bus/usb下目录的事件  
  59.                     if (wd == context->wds[i]) {  
  60.                         snprintf(path, sizeof(path), USB_FS_DIR "/%03d/%s", i, event->name);  
  61.                         if (event->mask == IN_CREATE) {//这里就直接调用增加设备或者删除设备的回调函数。  
  62.                             D("new device %s\n", path);  
  63.                             done = context->cb_added(path, context->data);  
  64.                         } else if (event->mask == IN_DELETE) {  
  65.                             D("gone device %s\n", path);  
  66.                             done = context->cb_removed(path, context->data);  
  67.                         }  
  68.                     }  
  69.                 }  
  70.             }  
  71.   
  72.             offset += sizeof(struct inotify_event) + event->len;//读取的字节数增加  
  73.         }  
  74.     }  
  75.   
  76.     return done;  
  77. }   


usb_device_added函数会调用UsbHostManager的beginUsbDeviceAdded和endUsbDeviceAdded函数,在UsbHostManager中会新建一个UsbDevice,然后放入mDevices中。

  1. static int usb_device_added(const char *devname, void* client_data) {  
  2.     struct usb_descriptor_header* desc;  
  3.     struct usb_descriptor_iter iter;  
  4.   
  5.     struct usb_device *device = usb_device_open(devname);  
  6.     if (!device) {  
  7.         ALOGE("usb_device_open failed\n");  
  8.         return 0;  
  9.     }  
  10.   
  11.     JNIEnv* env = AndroidRuntime::getJNIEnv();  
  12.     jobject thiz = (jobject)client_data;  
  13.     const usb_device_descriptor* deviceDesc = usb_device_get_device_descriptor(device);  
  14.   
  15.     char *manufacturer = usb_device_get_manufacturer_name(device);  
  16.     char *product = usb_device_get_product_name(device);  
  17.     int version = usb_device_get_version(device);  
  18.     char *serial = usb_device_get_serial(device);  
  19.   
  20.     jstring deviceName = env->NewStringUTF(devname);  
  21.     jstring manufacturerName = AndroidRuntime::NewStringLatin1(env, manufacturer);  
  22.     jstring productName = AndroidRuntime::NewStringLatin1(env, product);  
  23.     jstring serialNumber = AndroidRuntime::NewStringLatin1(env, serial);  
  24.   
  25.     jboolean result = env->CallBooleanMethod(thiz, method_beginUsbDeviceAdded,  
  26.             deviceName, usb_device_get_vendor_id(device), usb_device_get_product_id(device),  
  27.             deviceDesc->bDeviceClass, deviceDesc->bDeviceSubClass, deviceDesc->bDeviceProtocol,  
  28.             manufacturerName, productName, version, serialNumber);  
  29.   
  30.     env->DeleteLocalRef(serialNumber);  
  31.     env->DeleteLocalRef(productName);  
  32.     env->DeleteLocalRef(manufacturerName);  
  33.     env->DeleteLocalRef(deviceName);  
  34.     free(manufacturer);  
  35.     free(product);  
  36.     free(serial);  
  37.   
  38.     if (!result) goto fail;  
  39.   
  40.     usb_descriptor_iter_init(device, &iter);  
  41.   
  42.     while ((desc = usb_descriptor_iter_next(&iter)) != NULL) {  
  43.         if (desc->bDescriptorType == USB_DT_CONFIG) {  
  44.             struct usb_config_descriptor *config = (struct usb_config_descriptor *)desc;  
  45.             char *name = usb_device_get_string(device, config->iConfiguration);  
  46.             jstring configName = AndroidRuntime::NewStringLatin1(env, name);  
  47.   
  48.             env->CallVoidMethod(thiz, method_addUsbConfiguration,  
  49.                     config->bConfigurationValue, configName, config->bmAttributes,  
  50.                     config->bMaxPower);  
  51.   
  52.             env->DeleteLocalRef(configName);  
  53.             free(name);  
  54.         } else if (desc->bDescriptorType == USB_DT_INTERFACE) {  
  55.             struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)desc;  
  56.             char *name = usb_device_get_string(device, interface->iInterface);  
  57.             jstring interfaceName = AndroidRuntime::NewStringLatin1(env, name);  
  58.   
  59.             env->CallVoidMethod(thiz, method_addUsbInterface,  
  60.                     interface->bInterfaceNumber, interfaceName, interface->bAlternateSetting,  
  61.                     interface->bInterfaceClass, interface->bInterfaceSubClass,  
  62.                     interface->bInterfaceProtocol);  
  63.   
  64.             env->DeleteLocalRef(interfaceName);  
  65.             free(name);  
  66.         } else if (desc->bDescriptorType == USB_DT_ENDPOINT) {  
  67.             struct usb_endpoint_descriptor *endpoint = (struct usb_endpoint_descriptor *)desc;  
  68.   
  69.             env->CallVoidMethod(thiz, method_addUsbEndpoint,  
  70.                     endpoint->bEndpointAddress, endpoint->bmAttributes,  
  71.                     __le16_to_cpu(endpoint->wMaxPacketSize), endpoint->bInterval);  
  72.         }  
  73.     }  
  74.   
  75.     env->CallVoidMethod(thiz, method_endUsbDeviceAdded);  
  76.   
  77. fail:  
  78.     usb_device_close(device);  
  79.     checkAndClearExceptionFromCallback(env, __FUNCTION__);  
  80.   
  81.     return 0;  
  82. }  

去除函数,也会调用UsbHostManager的usbDeviceRemoved函数,注意这个函数返回就是0

  1. static int usb_device_removed(const char *devname, void* client_data) {  
  2.     JNIEnv* env = AndroidRuntime::getJNIEnv();  
  3.     jobject thiz = (jobject)client_data;  
  4.   
  5.     jstring deviceName = env->NewStringUTF(devname);  
  6.     env->CallVoidMethod(thiz, method_usbDeviceRemoved, deviceName);  
  7.     env->DeleteLocalRef(deviceName);  
  8.     checkAndClearExceptionFromCallback(env, __FUNCTION__);  
  9.     return 0;  
  10. }  

UsbHostManager的usbDeviceRemoved函数,会把mDevices相关的设备去除。

  1. private void usbDeviceRemoved(String deviceName) {  
  2.     synchronized (mLock) {  
  3.         UsbDevice device = mDevices.remove(deviceName);  
  4.         if (device != null) {  
  5.             mUsbAlsaManager.usbDeviceRemoved(device);  
  6.             getCurrentSettings().deviceDetached(device);  
  7.         }  
  8.     }  
  9. }  


UsbManager中调用usb设备

我们来看USBManager中关于获取Usb设备,以及使用它们的函数。getDeviceList可以得到一个设备名,以及对应的UsbDevice。而openDevice会得到一个UsbDeviceConnection对象。

  1. public HashMap<String,UsbDevice> getDeviceList() {  
  2.     Bundle bundle = new Bundle();  
  3.     try {  
  4.         mService.getDeviceList(bundle);  
  5.         HashMap<String,UsbDevice> result = new HashMap<String,UsbDevice>();  
  6.         for (String name : bundle.keySet()) {  
  7.             result.put(name, (UsbDevice)bundle.get(name));  
  8.         }  
  9.         return result;  
  10.     } catch (RemoteException e) {  
  11.         Log.e(TAG, "RemoteException in getDeviceList", e);  
  12.         return null;  
  13.     }  
  14. }  
  15.   
  16. /** 
  17.  * Opens the device so it can be used to send and receive 
  18.  * data using {@link android.hardware.usb.UsbRequest}. 
  19.  * 
  20.  * @param device the device to open 
  21.  * @return a {@link UsbDeviceConnection}, or {@code null} if open failed 
  22.  */  
  23. public UsbDeviceConnection openDevice(UsbDevice device) {  
  24.     try {  
  25.         String deviceName = device.getDeviceName();  
  26.         ParcelFileDescriptor pfd = mService.openDevice(deviceName);  
  27.         if (pfd != null) {  
  28.             UsbDeviceConnection connection = new UsbDeviceConnection(device);  
  29.             boolean result = connection.open(deviceName, pfd);  
  30.             pfd.close();  
  31.             if (result) {  
  32.                 return connection;  
  33.             }  
  34.         }  
  35.     } catch (Exception e) {  
  36.         Log.e(TAG, "exception in UsbManager.openDevice", e);  
  37.     }  
  38.     return null;  
  39. }  

UsbHostManager的getDeviceList函数,就是把mDevices中的数据返回,然后是通过Bundle对象来传输的。

  1. public void getDeviceList(Bundle devices) {  
  2.     synchronized (mLock) {  
  3.         for (String name : mDevices.keySet()) {  
  4.             devices.putParcelable(name, mDevices.get(name));  
  5.         }  
  6.     }  
  7. }  

而当用户进程通过UsbManger获取到设备名后,可以通过openDevice来获取ParcelFileDescriptor ,在UsbManager中又会新建一个UsbDeviceConnection,然后把ParcelFileDescriptor 作为参数调用这个UsbDeviceConnection的open函数。

  1. public ParcelFileDescriptor openDevice(String deviceName) {  
  2.     synchronized (mLock) {  
  3.         if (isBlackListed(deviceName)) {  
  4.             throw new SecurityException("USB device is on a restricted bus");  
  5.         }  
  6.         UsbDevice device = mDevices.get(deviceName);  
  7.         if (device == null) {  
  8.             // if it is not in mDevices, it either does not exist or is blacklisted  
  9.             throw new IllegalArgumentException(  
  10.                     "device " + deviceName + " does not exist or is restricted");  
  11.         }  
  12.         getCurrentSettings().checkPermission(device);  
  13.         return nativeOpenDevice(deviceName);  
  14.     }  
  15. }  

我们来看下UsbHostManager的openDevice函数,最后也是调用了JNI函数nativeOpenDevice

  1. public ParcelFileDescriptor openDevice(String deviceName) {  
  2.     synchronized (mLock) {  
  3.         if (isBlackListed(deviceName)) {  
  4.             throw new SecurityException("USB device is on a restricted bus");  
  5.         }  
  6.         UsbDevice device = mDevices.get(deviceName);  
  7.         if (device == null) {  
  8.             // if it is not in mDevices, it either does not exist or is blacklisted  
  9.             throw new IllegalArgumentException(  
  10.                     "device " + deviceName + " does not exist or is restricted");  
  11.         }  
  12.         getCurrentSettings().checkPermission(device);  
  13.         return nativeOpenDevice(deviceName);  
  14.     }  
  15. }  

android_server_UsbHostManager_openDevice就是对应的JNI函数,这里主要调用了usb_device_open函数,并且返回一个usb_device,最后我们通过usb_device来获取其fd,并且把它封装在Java层ParcelFileDescriptor类中。

  1. static jobject android_server_UsbHostManager_openDevice(JNIEnv *env, jobject /* thiz */,  
  2.                                                         jstring deviceName)  
  3. {  
  4.     const char *deviceNameStr = env->GetStringUTFChars(deviceName, NULL);  
  5.     struct usb_device* device = usb_device_open(deviceNameStr);  
  6.     env->ReleaseStringUTFChars(deviceName, deviceNameStr);  
  7.   
  8.     if (!device)  
  9.         return NULL;  
  10.   
  11.     int fd = usb_device_get_fd(device);  
  12.     if (fd < 0) {  
  13.         usb_device_close(device);  
  14.         return NULL;  
  15.     }  
  16.     int newFD = dup(fd);  
  17.     usb_device_close(device);  
  18.   
  19.     jobject fileDescriptor = jniCreateFileDescriptor(env, newFD);  
  20.     if (fileDescriptor == NULL) {  
  21.         return NULL;  
  22.     }  
  23.     return env->NewObject(gParcelFileDescriptorOffsets.mClass,  
  24.         gParcelFileDescriptorOffsets.mConstructor, fileDescriptor);  
  25. }  

usb_device_open函数就是打开对应的设备

  1. struct usb_device *usb_device_open(const char *dev_name)  
  2. {  
  3.     int fd, did_retry = 0, writeable = 1;  
  4.   
  5.     D("usb_device_open %s\n", dev_name);  
  6.   
  7. retry:  
  8.     fd = open(dev_name, O_RDWR);  
  9.     if (fd < 0) {  
  10.         /* if we fail, see if have read-only access */  
  11.         fd = open(dev_name, O_RDONLY);  
  12.         D("usb_device_open open returned %d errno %d\n", fd, errno);  
  13.         if (fd < 0 && (errno == EACCES || errno == ENOENT) && !did_retry) {  
  14.             /* work around race condition between inotify and permissions management */  
  15.             sleep(1);  
  16.             did_retry = 1;  
  17.             goto retry;  
  18.         }  
  19.   
  20.         if (fd < 0)  
  21.             return NULL;  
  22.         writeable = 0;  
  23.         D("[ usb open read-only %s fd = %d]\n", dev_name, fd);  
  24.     }  
  25.   
  26.     struct usb_device* result = usb_device_new(dev_name, fd);  
  27.     if (result)  
  28.         result->writeable = writeable;  
  29.     return result;  
  30. }  


然后我们再来看看UsbManager的openDevice使用的UsbDeviceConnection对象。

  1. public UsbDeviceConnection openDevice(UsbDevice device) {  
  2.     try {  
  3.         String deviceName = device.getDeviceName();  
  4.         ParcelFileDescriptor pfd = mService.openDevice(deviceName);  
  5.         if (pfd != null) {  
  6.             UsbDeviceConnection connection = new UsbDeviceConnection(device);  
  7.             boolean result = connection.open(deviceName, pfd);  
  8.             pfd.close();  
  9.             if (result) {  
  10.                 return connection;  
  11.             }  
  12.         }  
  13.     } catch (Exception e) {  
  14.         Log.e(TAG, "exception in UsbManager.openDevice", e);  
  15.     }  
  16.     return null;  
  17. }  
UsbDeviceConnection的构造函数就是把UsbDevice保存到mDevice,然后调用了native_open函数
  1. public UsbDeviceConnection(UsbDevice device) {  
  2.     mDevice = device;  
  3. }  
  4.   
  5. /* package */ boolean open(String name, ParcelFileDescriptor pfd) {  
  6.     return native_open(name, pfd.getFileDescriptor());  
  7. }  

native_open函数是JNI函数,对应函数如下。根据之前打开设备的fd新建了一个usb_device,然后保存在了UsbDeviceConnection的mNativeContext对象中了。

  1. static jboolean  
  2. android_hardware_UsbDeviceConnection_open(JNIEnv *env, jobject thiz, jstring deviceName,  
  3.         jobject fileDescriptor)  
  4. {  
  5.     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);  
  6.     // duplicate the file descriptor, since ParcelFileDescriptor will eventually close its copy  
  7.     fd = dup(fd);  
  8.     if (fd < 0)  
  9.         return JNI_FALSE;  
  10.   
  11.     const char *deviceNameStr = env->GetStringUTFChars(deviceName, NULL);  
  12.     struct usb_device* device = usb_device_new(deviceNameStr, fd);  
  13.     if (device) {  
  14.         env->SetLongField(thiz, field_context, (jlong)device);  
  15.     } else {  
  16.         ALOGE("usb_device_open failed for %s", deviceNameStr);  
  17.         close(fd);  
  18.     }  
  19.   
  20.     env->ReleaseStringUTFChars(deviceName, deviceNameStr);  
  21.     return (device != NULL) ? JNI_TRUE : JNI_FALSE;  
  22. }  

最后用户进程获取的对象就是UsbDeviceConnection,我们可以调用其getFileDescriptor,来获取设备的fd。我们直接看下这个函数

  1. public int getFileDescriptor() {  
  2.     return native_get_fd();  
  3. }  
而这个函数就是一个JNI函数,最后就是通过之前保存在UsbDeviceConnection的mNativeContext,把它变成一个usb_device,然后再获取其fd。
  1. static jint  
  2. android_hardware_UsbDeviceConnection_get_fd(JNIEnv *env, jobject thiz)  
  3. {  
  4.     struct usb_device* device = get_device_from_object(env, thiz);  
  5.     if (!device) {  
  6.         ALOGE("device is closed in native_get_fd");  
  7.         return -1;  
  8.     }  
  9.     return usb_device_get_fd(device);  
  10. }  
get_device_from_object就是获取UsbDeviceConnection的mNativeContext对象(实际是之前保存的usb_device对象)
  1. struct usb_device* get_device_from_object(JNIEnv* env, jobject connection)  
  2. {  
  3.     return (struct usb_device*)env->GetLongField(connection, field_context);  
  4. }  

这样通过UsbDeviceConnection的getFileDescriptor函数,用户进程拿到了自己需要的usb设备的fd了。

时序图参考:https://blog.csdn.net/q1183345443/article/details/80989438

转载http://blog.csdn.net/kc58236582/article/details/54691334

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值