之前在Android5.1的时候我们分析过UsbDevicemanager,现在Android6.0我们不准备分析UsbDevicemanager了,因为大致原理差不多。而UsbDeviceManager是将手机作为一个设备,比如手机连上电脑,使用adb、mtp等。而这里准备分析的UsbHostManager,是将手机作为一个host,比如手机连接usb鼠标、usb摄像头等。
UsbHostManager的初始化
UsbHostManager和UsbDeviceManager一样都是在UsbService中新建的。
- public UsbService(Context context) {
- mContext = context;
- mAlsaManager = new UsbAlsaManager(context);
- final PackageManager pm = mContext.getPackageManager();
- if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
- mHostManager = new UsbHostManager(context, mAlsaManager);
- }
然后在UsbService的systemReady中调用了UsbHostManager的systemReady函数。
- public void systemReady() {
- mAlsaManager.systemReady();
- if (mDeviceManager != null) {
- mDeviceManager.systemReady();
- }
- if (mHostManager != null) {
- mHostManager.systemReady();
- }
- if (mPortManager != null) {
- mPortManager.systemReady();
- }
- }
- public void systemReady() {
- synchronized (mLock) {
- // Create a thread to call into native code to wait for USB host events.
- // This thread will call us back on usbDeviceAdded and usbDeviceRemoved.
- Runnable runnable = new Runnable() {
- public void run() {
- monitorUsbHostBus();
- }
- };
- new Thread(null, runnable, "UsbService host thread").start();
- }
- }
而monitorUsbHostBus函数是一个JNI函数。
- 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函数了。
- 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);
- }
usb_host_init是在system\core\libusbhost\usbhost.c文件中,这个函数中新建一个usb_host_context对象,还有新建了一个INotify,并且usb_host_context的fd就是INotify的fd。
- struct usb_host_context *usb_host_init()
- {
- struct usb_host_context *context = calloc(1, sizeof(struct usb_host_context));//新建一个usb_host_context对象
- if (!context) {
- fprintf(stderr, "out of memory in usb_host_context\n");
- return NULL;
- }
- context->fd = inotify_init();//新建一个INotify
- 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);
- }
- }
- 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);//将dev目录放入INotify观察
- 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;
- }
- 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;
- }
- }
- 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;
- }
然后我们再来看看usb_host_read_event函数,这个函数就是去INotify中的fd读取相关的事件。具体分析我们就看注释,有一点我们要注意了,除了增加bus目录失败返回的done是1,其他的返回的done都是0.也就是我们的usb_host_run函数会在while循环中一直循环。
- int usb_host_read_event(struct usb_host_context *context)
- {
- struct inotify_event* event;
- char event_buf[512];
- char path[100];
- int i, ret, done = 0;
- int offset = 0;
- int wd;
- ret = read(context->fd, event_buf, sizeof(event_buf));
- if (ret >= (int)sizeof(struct inotify_event)) {
- while (offset < ret && !done) {
- event = (struct inotify_event*)&event_buf[offset];
- done = 0;
- wd = event->wd;
- if (wd == context->wdd) {
- if ((event->mask & IN_CREATE) && !strcmp(event->name, "bus")) {//增加bus目录,并且将bus目录也增加到watch中
- context->wddbus = inotify_add_watch(context->fd, DEV_BUS_DIR, IN_CREATE | IN_DELETE);
- if (context->wddbus < 0) {
- done = 1;//增加bus目录失败
- } else {
- watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);
- done = find_existing_devices(context->cb_added, context->data);
- }
- }
- } else if (wd == context->wddbus) {
- if ((event->mask & IN_CREATE) && !strcmp(event->name, "usb")) {//如果是dev/bus目录的事件
- watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);//将dev/bus/usb目录再增加到watch
- done = find_existing_devices(context->cb_added, context->data);//然后再看看usb下面时候有设备,有就调用添加函数
- } else if ((event->mask & IN_DELETE) && !strcmp(event->name, "usb")) {
- for (i = 0; i < MAX_USBFS_WD_COUNT; i++) {
- if (context->wds[i] >= 0) {
- inotify_rm_watch(context->fd, context->wds[i]);//是删除事件,就把这个watch删除了
- context->wds[i] = -1;
- }
- }
- }
- } else if (wd == context->wds[0]) {//是第一个wds,也就是dev/bus/usb目录的事件
- i = atoi(event->name);
- snprintf(path, sizeof(path), USB_FS_DIR "/%s", event->name);
- D("%s subdirectory %s: index: %d\n", (event->mask & IN_CREATE) ?
- "new" : "gone", path, i);
- if (i > 0 && i < MAX_USBFS_WD_COUNT) {
- int local_ret = 0;
- if (event->mask & IN_CREATE) {
- local_ret = inotify_add_watch(context->fd, path,//我们需要把usb下新增的目录也增加到watch中
- IN_CREATE | IN_DELETE);
- if (local_ret >= 0)
- context->wds[i] = local_ret;
- done = find_existing_devices_bus(path, context->cb_added,//然后再看看是否有已经存在的设备
- context->data);
- } else if (event->mask & IN_DELETE) {
- inotify_rm_watch(context->fd, context->wds[i]);
- context->wds[i] = -1;
- }
- }
- } else {
- for (i = 1; (i < MAX_USBFS_WD_COUNT) && !done; i++) {//最后剩下的肯定是dev/bus/usb下目录的事件
- if (wd == context->wds[i]) {
- snprintf(path, sizeof(path), USB_FS_DIR "/%03d/%s", i, event->name);
- if (event->mask == IN_CREATE) {//这里就直接调用增加设备或者删除设备的回调函数。
- D("new device %s\n", path);
- done = context->cb_added(path, context->data);
- } else if (event->mask == IN_DELETE) {
- D("gone device %s\n", path);
- done = context->cb_removed(path, context->data);
- }
- }
- }
- }
- offset += sizeof(struct inotify_event) + event->len;//读取的字节数增加
- }
- }
- return done;
- }
usb_device_added函数会调用UsbHostManager的beginUsbDeviceAdded和endUsbDeviceAdded函数,在UsbHostManager中会新建一个UsbDevice,然后放入mDevices中。
- 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;
- const usb_device_descriptor* deviceDesc = usb_device_get_device_descriptor(device);
- char *manufacturer = usb_device_get_manufacturer_name(device);
- char *product = usb_device_get_product_name(device);
- int version = usb_device_get_version(device);
- char *serial = usb_device_get_serial(device);
- 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);
- 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);
- 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);
- }
- }
- env->CallVoidMethod(thiz, method_endUsbDeviceAdded);
- fail:
- usb_device_close(device);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
- return 0;
- }
去除函数,也会调用UsbHostManager的usbDeviceRemoved函数,注意这个函数返回就是0
- static int usb_device_removed(const char *devname, void* client_data) {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- jobject thiz = (jobject)client_data;
- jstring deviceName = env->NewStringUTF(devname);
- env->CallVoidMethod(thiz, method_usbDeviceRemoved, deviceName);
- env->DeleteLocalRef(deviceName);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
- return 0;
- }
UsbHostManager的usbDeviceRemoved函数,会把mDevices相关的设备去除。
- private void usbDeviceRemoved(String deviceName) {
- synchronized (mLock) {
- UsbDevice device = mDevices.remove(deviceName);
- if (device != null) {
- mUsbAlsaManager.usbDeviceRemoved(device);
- getCurrentSettings().deviceDetached(device);
- }
- }
- }
UsbManager中调用usb设备
我们来看USBManager中关于获取Usb设备,以及使用它们的函数。getDeviceList可以得到一个设备名,以及对应的UsbDevice。而openDevice会得到一个UsbDeviceConnection对象。
- public HashMap<String,UsbDevice> getDeviceList() {
- Bundle bundle = new Bundle();
- try {
- mService.getDeviceList(bundle);
- HashMap<String,UsbDevice> result = new HashMap<String,UsbDevice>();
- for (String name : bundle.keySet()) {
- result.put(name, (UsbDevice)bundle.get(name));
- }
- return result;
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException in getDeviceList", e);
- return null;
- }
- }
- /**
- * Opens the device so it can be used to send and receive
- * data using {@link android.hardware.usb.UsbRequest}.
- *
- * @param device the device to open
- * @return a {@link UsbDeviceConnection}, or {@code null} if open failed
- */
- public UsbDeviceConnection openDevice(UsbDevice device) {
- try {
- String deviceName = device.getDeviceName();
- ParcelFileDescriptor pfd = mService.openDevice(deviceName);
- if (pfd != null) {
- UsbDeviceConnection connection = new UsbDeviceConnection(device);
- boolean result = connection.open(deviceName, pfd);
- pfd.close();
- if (result) {
- return connection;
- }
- }
- } catch (Exception e) {
- Log.e(TAG, "exception in UsbManager.openDevice", e);
- }
- return null;
- }
UsbHostManager的getDeviceList函数,就是把mDevices中的数据返回,然后是通过Bundle对象来传输的。
- public void getDeviceList(Bundle devices) {
- synchronized (mLock) {
- for (String name : mDevices.keySet()) {
- devices.putParcelable(name, mDevices.get(name));
- }
- }
- }
而当用户进程通过UsbManger获取到设备名后,可以通过openDevice来获取ParcelFileDescriptor ,在UsbManager中又会新建一个UsbDeviceConnection,然后把ParcelFileDescriptor 作为参数调用这个UsbDeviceConnection的open函数。
- public ParcelFileDescriptor openDevice(String deviceName) {
- synchronized (mLock) {
- if (isBlackListed(deviceName)) {
- throw new SecurityException("USB device is on a restricted bus");
- }
- UsbDevice device = mDevices.get(deviceName);
- if (device == null) {
- // if it is not in mDevices, it either does not exist or is blacklisted
- throw new IllegalArgumentException(
- "device " + deviceName + " does not exist or is restricted");
- }
- getCurrentSettings().checkPermission(device);
- return nativeOpenDevice(deviceName);
- }
- }
我们来看下UsbHostManager的openDevice函数,最后也是调用了JNI函数nativeOpenDevice
- public ParcelFileDescriptor openDevice(String deviceName) {
- synchronized (mLock) {
- if (isBlackListed(deviceName)) {
- throw new SecurityException("USB device is on a restricted bus");
- }
- UsbDevice device = mDevices.get(deviceName);
- if (device == null) {
- // if it is not in mDevices, it either does not exist or is blacklisted
- throw new IllegalArgumentException(
- "device " + deviceName + " does not exist or is restricted");
- }
- getCurrentSettings().checkPermission(device);
- return nativeOpenDevice(deviceName);
- }
- }
android_server_UsbHostManager_openDevice就是对应的JNI函数,这里主要调用了usb_device_open函数,并且返回一个usb_device,最后我们通过usb_device来获取其fd,并且把它封装在Java层ParcelFileDescriptor类中。
- static jobject android_server_UsbHostManager_openDevice(JNIEnv *env, jobject /* thiz */,
- jstring deviceName)
- {
- const char *deviceNameStr = env->GetStringUTFChars(deviceName, NULL);
- struct usb_device* device = usb_device_open(deviceNameStr);
- env->ReleaseStringUTFChars(deviceName, deviceNameStr);
- if (!device)
- return NULL;
- int fd = usb_device_get_fd(device);
- if (fd < 0) {
- usb_device_close(device);
- return NULL;
- }
- int newFD = dup(fd);
- usb_device_close(device);
- jobject fileDescriptor = jniCreateFileDescriptor(env, newFD);
- if (fileDescriptor == NULL) {
- return NULL;
- }
- return env->NewObject(gParcelFileDescriptorOffsets.mClass,
- gParcelFileDescriptorOffsets.mConstructor, fileDescriptor);
- }
usb_device_open函数就是打开对应的设备
- struct usb_device *usb_device_open(const char *dev_name)
- {
- int fd, did_retry = 0, writeable = 1;
- D("usb_device_open %s\n", dev_name);
- retry:
- fd = open(dev_name, O_RDWR);
- if (fd < 0) {
- /* if we fail, see if have read-only access */
- fd = open(dev_name, O_RDONLY);
- D("usb_device_open open returned %d errno %d\n", fd, errno);
- if (fd < 0 && (errno == EACCES || errno == ENOENT) && !did_retry) {
- /* work around race condition between inotify and permissions management */
- sleep(1);
- did_retry = 1;
- goto retry;
- }
- if (fd < 0)
- return NULL;
- writeable = 0;
- D("[ usb open read-only %s fd = %d]\n", dev_name, fd);
- }
- struct usb_device* result = usb_device_new(dev_name, fd);
- if (result)
- result->writeable = writeable;
- return result;
- }
然后我们再来看看UsbManager的openDevice使用的UsbDeviceConnection对象。
- public UsbDeviceConnection openDevice(UsbDevice device) {
- try {
- String deviceName = device.getDeviceName();
- ParcelFileDescriptor pfd = mService.openDevice(deviceName);
- if (pfd != null) {
- UsbDeviceConnection connection = new UsbDeviceConnection(device);
- boolean result = connection.open(deviceName, pfd);
- pfd.close();
- if (result) {
- return connection;
- }
- }
- } catch (Exception e) {
- Log.e(TAG, "exception in UsbManager.openDevice", e);
- }
- return null;
- }
- public UsbDeviceConnection(UsbDevice device) {
- mDevice = device;
- }
- /* package */ boolean open(String name, ParcelFileDescriptor pfd) {
- return native_open(name, pfd.getFileDescriptor());
- }
native_open函数是JNI函数,对应函数如下。根据之前打开设备的fd新建了一个usb_device,然后保存在了UsbDeviceConnection的mNativeContext对象中了。
- static jboolean
- android_hardware_UsbDeviceConnection_open(JNIEnv *env, jobject thiz, jstring deviceName,
- jobject fileDescriptor)
- {
- int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
- // duplicate the file descriptor, since ParcelFileDescriptor will eventually close its copy
- fd = dup(fd);
- if (fd < 0)
- return JNI_FALSE;
- const char *deviceNameStr = env->GetStringUTFChars(deviceName, NULL);
- struct usb_device* device = usb_device_new(deviceNameStr, fd);
- if (device) {
- env->SetLongField(thiz, field_context, (jlong)device);
- } else {
- ALOGE("usb_device_open failed for %s", deviceNameStr);
- close(fd);
- }
- env->ReleaseStringUTFChars(deviceName, deviceNameStr);
- return (device != NULL) ? JNI_TRUE : JNI_FALSE;
- }
最后用户进程获取的对象就是UsbDeviceConnection,我们可以调用其getFileDescriptor,来获取设备的fd。我们直接看下这个函数
- public int getFileDescriptor() {
- return native_get_fd();
- }
- static jint
- android_hardware_UsbDeviceConnection_get_fd(JNIEnv *env, jobject thiz)
- {
- struct usb_device* device = get_device_from_object(env, thiz);
- if (!device) {
- ALOGE("device is closed in native_get_fd");
- return -1;
- }
- return usb_device_get_fd(device);
- }
- struct usb_device* get_device_from_object(JNIEnv* env, jobject connection)
- {
- return (struct usb_device*)env->GetLongField(connection, field_context);
- }
这样通过UsbDeviceConnection的getFileDescriptor函数,用户进程拿到了自己需要的usb设备的fd了。
时序图参考:https://blog.csdn.net/q1183345443/article/details/80989438