USB 功能简介

USB OTG: USB On-The-Go的简称,是USB 2.0规定的补充标准,它可以使手机等作为USB主机,和其他USB设备连接通信,例如U盘,另外的手机,USB Hub等。

Android对Usb的支持是从3.1开始的,显然是加强Android平板的对外扩展能力。而对Usb使用更多的,是Android在工业中的使用。Android工业板子一般都会提供多个U口和多个串口,它们是连接外设的手段与桥梁。

USB OTG是通过OTG线连接通信,OTG线一头是公头连接手机USB HOST,一头母头接外设。如图一连接通信。

Android USB代码分析

在路径/frameworks/base/core/java/android/hardware/usb/下,这个包内包含了USB相关的类。

1,USBManager:定义了USB的action和参数,获取USB的状态,与连接的USB设备通信。

方法getDeviceList获取到所有连接的USB device的HashMap

方法openDevice 与USB设备通信

当有USB设备连接时,会发送广播ACTION_USB_DEVICE_ATTACHED。

public static final StringACTION_USB_DEVICE_ATTACHED =

           "android.hardware.usb.action.USB_DEVICE_ATTACHED";

当有USB设备移除时,会发送广播ACTION_USB_DEVICE_DETACHED。

 publicstatic final String ACTION_USB_DEVICE_DETACHED =

           "android.hardware.usb.action.USB_DEVICE_DETACHED";


2, UsbDevice:Usb设备的抽象,它包含一个或多个UsbInterface,而每个UsbInterface包含多个UsbEndpoint。Host与其通信,先打开UsbDeviceConnection,使用UsbRequest在一个端点(endpoint)发送和接收数据。

3,UsbInterface:定义了设备的功能集,一个UsbDevice包含多个UsbInterface,每个Interface都是独立的。

4,UsbEndpoint:endpoint是interface的通信通道。

5,UsbDeviceConnection:host与device建立的连接,并在endpoint传输数据。

 6,UsbRequest:USB 请求包。可以在UsbDeviceConnection上异步传输数据。注意是只在异步通信时才会用到它。

7,UsbConstants:USB常量的定义。


  Settings中USB界面

Settings界面代码主要由UsbModeChooserActivity和UsbBackend显示USB选项,

UsbBackend中通过方法setUsbFunction调用UsbManager中setCurrentFunction,设置不同的USB连接模式,如

       mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MTP, true);

设置USB模式为MTP,同理也可设置为PTP,MIDI等。这个方法第二参数true/false是设置是否可以通过USB连接传输数据,当为true时,就可以传输数据,当为false时,USB连接仅为充电,无法访问手机上文件。

通过方法getUsbDataMode()可以获取当前USB连接模式,UsbModeChooserActivity通过这个方法显示当前的USB连接模式。

方法isModeSupported判断这种USB模式是否支持,只有支持的模式才会在选项中显示。

UsbModeChooserActivity弹出的USB选项Dialog,包含支持的USB连接模式。



3.3 USB OTG界面

手机通过OTG线连接U盘之类的外设,会通过SystemUI中StorageNotification,添加了对Storage的监听,

当volume状态发生变化时,会在onVolumeStateChangedInternal做对应提示。

   private final StorageEventListener mListener = newStorageEventListener() {

        @Override

        public void onVolumeStateChanged(VolumeInfo

vol, int oldState, intnewState) {

            onVolumeStateChangedInternal(vol);

        }


 刚通过OTG线连接U盘,调用onVolumeChecking显示checking U盘的提示。

   privateNotificationonVolumeChecking(VolumeInfo vol) {

        finalDiskInfo disk = vol.getDisk();

        final CharSequence title = mContext.getString(

                R.string.ext_media_checking_notification_title, disk.getDescription());

        final CharSequence text = mContext.getString(

                R.string.ext_media_checking_notification_message, disk.getDescription());


        returnbuildNotificationBuilder(vol, title, text)

                .setCategory(Notification.CATEGORY_PROGRESS)

                .setOngoing(true)

                .build();

   }

 当U盘状态为MOUNTED时,调用onVolumeMounted更新U盘提示,当U盘移除时,调用onVolumeRemoved或者onVolumeBadRemoval,提示已经移除U盘。

 这个通过OTG线连接U盘,显示的提示和插入SD卡类似,都可以点击Notification进入DocumentsUI,浏览和操作U盘中的文件。


手机通过OTG线与另外手机连接时,在MtpDocumentsProvider这个应用中有ReceiverActivity有监听

android.hardware.usb.action.USB_DEVICE_ATTACHED 这个广播,当主机通过OTG线连接另一台手机时,

接收到这个广播,从广播中获取到连接设备信息,创建相应的Uri,把Uri传给启动DocumentsUI的intent,

在启动DocumentsUI后,另外一台手机的USB连接模式未MTP,PTP时,主机就能查看和操作从机的文件。当是charging only状态,主机无法访问从机文件。

public class ReceiverActivity extends Activity {

   @Override

   protected voidonCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        if(UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(getIntent().getAction())) {

            final UsbDevice device = getIntent().getParcelableExtra(UsbManager.EXTRA_DEVICE);

            try{

                finalMtpDocumentsProvider provider =MtpDocumentsProvider.getInstance();

                provider.openDevice(device.getDeviceId());

                finalString deviceRootId =provider.getDeviceDocumentId(device.getDeviceId());

                finalUri uri = DocumentsContract.buildRootUri(

                        MtpDocumentsProvider.AUTHORITY,deviceRootId);


                final Intent intent = newIntent(Intent.ACTION_VIEW);

                intent.setDataAndType(uri,DocumentsContract.Root.MIME_TYPE_ITEM);

                intent.addCategory(Intent.CATEGORY_DEFAULT);

                this.startActivity(intent);

            }catch(IOException exception) {

                Log.e(MtpDocumentsProvider.TAG,"Failed to open

device", exception);

            }

        }

        finish();

   }

}

 同时也是在MtpDocumentsProvider的UsbIntentReceiver,这个receiver会监听OTG插拔两个广播

android.hardware.usb.action.USB_DEVICE_ATTACHED和android.hardware.usb.action.USB_DEVICE_DETACHED。


public class UsbIntentReceiver extendsBroadcastReceiver {

   @Override

   public voidonReceive(Context context, Intent intent) {

        final UsbDevice device = intent.getExtras().getParcelable(UsbManager.EXTRA_DEVICE);

        switch(intent.getAction()) {

            case UsbManager.ACTION_USB_DEVICE_ATTACHED:

                MtpDocumentsProvider.getInstance().resumeRootScanner();

                break;

            case UsbManager.ACTION_USB_DEVICE_DETACHED:

                try{

                    MtpDocumentsProvider.getInstance().closeDevice(device.getDeviceId());

                }catch(IOException | InterruptedException e) {

                    Log.e(MtpDocumentsProvider.TAG,"Failed to close

device", e);

                }

                break;

        }

   }

}

 通过在MtpDocumentsProvider中初始化ServiceIntentSender,通过调用sendUpdateNotificationIntent显示手机连接的提示。


USB和底层交互

在android中很多地方使用到了UEvent机制,如图:像HDMI,Battery,USB相关等;当我们需要接受底层的UEvent的时候,我们就需要注册一个UEventObserver。Kernel层和framework层交互通过UeventObserver。在USB插拔时,在UsbDeviceManager中有注册UEventObserver,监听USB的uevent,当有uevent事件上传,获取对应的USB状态,和连接的设备之类。


    /*

     * Listensfor uevent messages from the kernel to monitor the USB state

     */

    private final UEventObserver mUEventObserver = newUEventObserver() {

        @Override

        public voidonUEvent(UEventObserver.UEvent event) {

            if (DEBUG) Slog.v(TAG, "USB UEVENT:

" + event.toString());


            Stringstate = event.get("USB_STATE");

            Stringaccessory = event.get("ACCESSORY");

            if (state != null) {

                mHandler.updateState(state);

            }else if ("START".equals(accessory)) {

                if (DEBUG) Slog.d(TAG, "got

accessory start");

                startAccessoryMode();

            }

        }

    };


mUEventObserver通过 startObserving加入想要监听的uevent,当对应事件上传,就会在对应onUEvent作出对应处理。

                // Watch for USB configuration

changes

                mUEventObserver.startObserving(USB_STATE_MATCH);

                mUEventObserver.startObserving(ACCESSORY_START_MATCH);

startObserving这个方法转到UEventThread中,UEventThread是UeventObserver的内部类,run中一个死循环,不断监听底层的uevent,然后发送uevent。

        @Override

        public voidrun() {

            nativeSetup();


            while (true) {

                Stringmessage =nativeWaitForNextEvent();

                if (message != null) {

                   if (DEBUG) {

                       Log.d(TAG, message);

                   }

                   sendEvent(message);

                }

            }

        }


USB插拔的后续处理就根据uevent上传的状态在updateState方法中赋值connected,configured,通过Handler发送Message:MSG_UPDATE_STATE,包含connected,configured,在UsbHandler中handleMessage中更新USB,adb的Notification,上层界面显示。

        public void  updateState(String state){

            int connected, configured;


            if ("DISCONNECTED".equals(state)) {

                connected= 0;

                configured= 0;

            }else if ("CONNECTED".equals(state)) {

                connected= 1;

                configured= 0;

            }else if ("CONFIGURED".equals(state)) {

                connected= 1;

                configured= 1;

            }else{

                Slog.e(TAG, "unknown

state "+ state);

                return;

            }

            removeMessages(MSG_UPDATE_STATE);

            Messagemsg = Message.obtain(this, MSG_UPDATE_STATE);

            msg.arg1= connected;

            msg.arg2= configured;

            // debounce disconnects to avoid

problems bringing up USB tethering

            sendMessageDelayed(msg,(connected == 0) ?UPDATE_DELAY: 0);

        }

UsbHostManager中从jni回调beginUsbDeviceAdded-》addUsbConfiguration-》addUsbInterface-》addUsbEndpoint-》endUsbDeviceAdded

通过这些方法把USB OTG device挂载上,手机当成USB主机,可以通过USB连接模式,传输数据等。

你可能感兴趣的:(USB 功能简介)