SystemServer.java在服务启动时会启动UsbService(frameworks/base/services/java/com/android/server/usb/UsbService.java),UsbService会构造UsbHostManager和UsbDeviceManager
frameworks/base/services/jni/com_android_server_UsbHostManager.cpp
static void android_server_UsbHostManager_monitorUsbHostBus(JNIEnv *env, jobject thiz) { struct usb_host_context* context = usb_host_init(); if (!context) { ALOGE("usb_host_init failed"); return; } // this will never return so it is safe to pass thiz directly usb_host_run(context, usb_device_added, usb_device_removed, NULL, (void *)thiz); }
system/core/libusbhost/usbhost.c
#define DEV_DIR "/dev" #define DEV_BUS_DIR DEV_DIR "/bus" #define USB_FS_DIR DEV_BUS_DIR "/usb" #define USB_FS_ID_SCANNER USB_FS_DIR "/%d/%d" #define USB_FS_ID_FORMAT USB_FS_DIR "/%03d/%03d" #define MAX_USBFS_WD_COUNT 10 struct usb_host_context { int fd; usb_device_added_cb cb_added; usb_device_removed_cb cb_removed; void *data; int wds[MAX_USBFS_WD_COUNT]; int wdd; int wddbus; }; struct usb_device { char dev_name[64]; unsigned char desc[4096]; int desc_length; int fd; int writeable; }; struct usb_host_context *usb_host_init() { struct usb_host_context *context = calloc(1, sizeof(struct usb_host_context)); if (!context) { fprintf(stderr, "out of memory in usb_host_context\n"); return NULL; } context->fd = inotify_init(); if (context->fd < 0) { fprintf(stderr, "inotify_init failed\n"); free(context); return NULL; } return context; } void usb_host_run(struct usb_host_context *context, usb_device_added_cb added_cb, usb_device_removed_cb removed_cb, usb_discovery_done_cb discovery_done_cb, void *client_data) { int done; done = usb_host_load(context, added_cb, removed_cb, discovery_done_cb, client_data); while (!done) { done = usb_host_read_event(context); } } /* usb_host_run() */ int usb_host_load(struct usb_host_context *context, usb_device_added_cb added_cb, usb_device_removed_cb removed_cb, usb_discovery_done_cb discovery_done_cb, void *client_data) { int done = 0; int i; context->cb_added = added_cb; context->cb_removed = removed_cb; context->data = client_data; D("Created device discovery thread\n"); /* watch for files added and deleted within USB_FS_DIR */ context->wddbus = -1; for (i = 0; i < MAX_USBFS_WD_COUNT; i++) context->wds[i] = -1; /* watch the root for new subdirectories */ context->wdd = inotify_add_watch(context->fd, DEV_DIR, IN_CREATE | IN_DELETE); if (context->wdd < 0) { fprintf(stderr, "inotify_add_watch failed\n"); if (discovery_done_cb) discovery_done_cb(client_data); return done; } watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT); /* check for existing devices first, after we have inotify set up */ done = find_existing_devices(added_cb, client_data); if (discovery_done_cb) done |= discovery_done_cb(client_data); return done; } /* usb_host_load() */ static void watch_existing_subdirs(struct usb_host_context *context, int *wds, int wd_count) { char path[100]; int i, ret; wds[0] = inotify_add_watch(context->fd, USB_FS_DIR, IN_CREATE | IN_DELETE); if (wds[0] < 0) return; /* watch existing subdirectories of USB_FS_DIR */ for (i = 1; i < wd_count; i++) { snprintf(path, sizeof(path), USB_FS_DIR "/%03d", i); ret = inotify_add_watch(context->fd, path, IN_CREATE | IN_DELETE); if (ret >= 0) wds[i] = ret; } } /* returns true if one of the callbacks indicates we are done */ static int find_existing_devices(usb_device_added_cb added_cb, void *client_data) { char busname[32]; DIR *busdir; struct dirent *de; int done = 0; busdir = opendir(USB_FS_DIR); if(busdir == 0) return 0; while ((de = readdir(busdir)) != 0 && !done) { if(badname(de->d_name)) continue; snprintf(busname, sizeof(busname), USB_FS_DIR "/%s", de->d_name); done = find_existing_devices_bus(busname, added_cb, client_data); } //end of busdir while closedir(busdir); return done; } static int find_existing_devices_bus(char *busname, usb_device_added_cb added_cb, void *client_data) { char devname[32]; DIR *devdir; struct dirent *de; int done = 0; devdir = opendir(busname); if(devdir == 0) return 0; while ((de = readdir(devdir)) && !done) { if(badname(de->d_name)) continue; snprintf(devname, sizeof(devname), "%s/%s", busname, de->d_name); done = added_cb(devname, client_data); } // end of devdir while closedir(devdir); return done; }
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); if (!device) { ALOGE("usb_device_open failed\n"); return 0; } JNIEnv* env = AndroidRuntime::getJNIEnv(); jobject thiz = (jobject)client_data; Vector<int> interfaceValues; Vector<int> endpointValues; const usb_device_descriptor* deviceDesc = usb_device_get_device_descriptor(device); uint16_t vendorId = usb_device_get_vendor_id(device); uint16_t productId = usb_device_get_product_id(device); uint8_t deviceClass = deviceDesc->bDeviceClass; uint8_t deviceSubClass = deviceDesc->bDeviceSubClass; uint8_t protocol = deviceDesc->bDeviceProtocol; usb_descriptor_iter_init(device, &iter); while ((desc = usb_descriptor_iter_next(&iter)) != NULL) { if (desc->bDescriptorType == USB_DT_INTERFACE) { struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)desc; // push class, subclass, protocol and number of endpoints into interfaceValues vector interfaceValues.add(interface->bInterfaceNumber); interfaceValues.add(interface->bInterfaceClass); interfaceValues.add(interface->bInterfaceSubClass); interfaceValues.add(interface->bInterfaceProtocol); interfaceValues.add(interface->bNumEndpoints); } else if (desc->bDescriptorType == USB_DT_ENDPOINT) { struct usb_endpoint_descriptor *endpoint = (struct usb_endpoint_descriptor *)desc; // push address, attributes, max packet size and interval into endpointValues vector endpointValues.add(endpoint->bEndpointAddress); endpointValues.add(endpoint->bmAttributes); endpointValues.add(__le16_to_cpu(endpoint->wMaxPacketSize)); endpointValues.add(endpoint->bInterval); } } usb_device_close(device); // handle generic device notification int length = interfaceValues.size(); jintArray interfaceArray = env->NewIntArray(length); env->SetIntArrayRegion(interfaceArray, 0, length, interfaceValues.array()); length = endpointValues.size(); jintArray endpointArray = env->NewIntArray(length); env->SetIntArrayRegion(endpointArray, 0, length, endpointValues.array()); jstring deviceName = env->NewStringUTF(devname); env->CallVoidMethod(thiz, method_usbDeviceAdded, deviceName, vendorId, productId, deviceClass, deviceSubClass, protocol, interfaceArray, endpointArray); env->DeleteLocalRef(interfaceArray); env->DeleteLocalRef(endpointArray); env->DeleteLocalRef(deviceName); checkAndClearExceptionFromCallback(env, __FUNCTION__); return 0; }
frameworks/base/services/java/com/android/server/usb/UsbHostManager.java
/* Called from JNI in monitorUsbHostBus() to report new USB devices */ private void usbDeviceAdded(String deviceName, int vendorID, int productID, int deviceClass, int deviceSubclass, int deviceProtocol, /* array of quintuples containing id, class, subclass, protocol and number of endpoints for each interface */ int[] interfaceValues, /* array of quadruples containing address, attributes, max packet size and interval for each endpoint */ int[] endpointValues) { if (isBlackListed(deviceName) || isBlackListed(deviceClass, deviceSubclass, deviceProtocol)) { return; } synchronized (mLock) { if (mDevices.get(deviceName) != null) { Slog.w(TAG, "device already on mDevices list: " + deviceName); return; } int numInterfaces = interfaceValues.length / 5; Parcelable[] interfaces = new UsbInterface[numInterfaces]; try { // repackage interfaceValues as an array of UsbInterface int intf, endp, ival = 0, eval = 0; for (intf = 0; intf < numInterfaces; intf++) { int interfaceId = interfaceValues[ival++]; int interfaceClass = interfaceValues[ival++]; int interfaceSubclass = interfaceValues[ival++]; int interfaceProtocol = interfaceValues[ival++]; int numEndpoints = interfaceValues[ival++]; Parcelable[] endpoints = new UsbEndpoint[numEndpoints]; for (endp = 0; endp < numEndpoints; endp++) { int address = endpointValues[eval++]; int attributes = endpointValues[eval++]; int maxPacketSize = endpointValues[eval++]; int interval = endpointValues[eval++]; endpoints[endp] = new UsbEndpoint(address, attributes, maxPacketSize, interval); } // don't allow if any interfaces are blacklisted if (isBlackListed(interfaceClass, interfaceSubclass, interfaceProtocol)) { return; } interfaces[intf] = new UsbInterface(interfaceId, interfaceClass, interfaceSubclass, interfaceProtocol, endpoints); } } catch (Exception e) { // beware of index out of bound exceptions, which might happen if // a device does not set bNumEndpoints correctly Slog.e(TAG, "error parsing USB descriptors", e); return; } UsbDevice device = new UsbDevice(deviceName, vendorID, productID, deviceClass, deviceSubclass, deviceProtocol, interfaces); mDevices.put(deviceName, device); getCurrentSettings().deviceAttached(device); } }
frameworks/base/services/java/com/android/server/usb/UsbSettingsManager.java
public void deviceAttached(UsbDevice device) { Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED); intent.putExtra(UsbManager.EXTRA_DEVICE, device); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ArrayList<ResolveInfo> matches; String defaultPackage; synchronized (mLock) { matches = getDeviceMatchesLocked(device, intent); // Launch our default activity directly, if we have one. // Otherwise we will start the UsbResolverActivity to allow the user to choose. defaultPackage = mDevicePreferenceMap.get(new DeviceFilter(device)); } // Send broadcast to running activity with registered intent mUserContext.sendBroadcast(intent); // Start activity with registered intent resolveActivity(intent, matches, defaultPackage, device, null); }