android usb解析(二)UsbHostManager(and6.0)

之前在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();
        }
    }
UsbHostManager的构造函数就是新建一些对象,我们直接看systemReady函数。这个函数在新的线程中调用了monitorUsbHostBus函数。

    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;
}
我们再来看看usb_host_run函数。先调用了usb_host_load函数,这个函数主要把add和remove的回调,放到context相应的成员变量中,然后增加了dev目录放入INotify的观察。下面循环调用usb_host_read_event函数去读取INotify fd的事件。

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_load函数先把add和remove的两个回调设置到usb_host_context 中,然后将dev目录放入INotify观察。然后调用watch_existing_subdirs将/dev/bus/usb下的目录都添加到INotify中观察,最后再调用find_existing_devices函数,把找到的设备调用added_cb(增加的回调函数)
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;
    }

  
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值