USB 权限申请流程

USB android授权方式

权限的控制分三块:
1:USB host端有个线程循环检测系统是否USB设备插拔,如果有就找到申请权限的APP并调用起来
2:APP运行后主动申请权限,也就是requestPermission()接口
3:APP运行后直接打开USB设备,这时候USB host端会去检测APP是否已经有控制权限了,也就是调用的hasPermission()接口

第一种方式主要是再设计app 时候,能通过系统intent filter , 进行启动某个activity
第二种方式主要是设计app已经启动,再使用usb 的使用进行动态注册,申请权限
第三中跟第二种类似,是再open device 时候进行申请权限, 可以hasPermission 授权

第一种:

systemReady -> UsbHostManager.java
  monitorUsbHostBus ->
   android_server_UsbHostManager_monitorUsbHostBus -> android_server_UsbHostManager.cpp
    usb_host_run -> Usbhost.c
      usb_host_read_event ->
        context->cb_added -> //有usb设备添加
          usb_device_added ->
            env->CallVoidMethod -> //对方方法method_endUsbDeviceAdded  --> endUsbDeviceAdded
              endUsbDeviceAdded -> UsbHostManager.java
                getCurrentSettings().deviceAttached ->
                  deviceAttached ->  UsbSettingsManager.java
                    resolveActivity ->
                      resolveActivity ->
                        mUserContext.startActivityAsUser //包名是com.android.systemui.usb.UsbConfirmActivity
                          onCreate -> UsbConfirmActivity.java
                            setupAlert //弹出权限确认对话框

第二种:

requestPermission -> UsbManager.java
  mService.requestDevicePermission ->
    requestDevicePermission -> UsbService.java
      getSettingsForUser(userId).requestPermission ->
        requestPermission -> UsbSettingsManager.java
          requestPermissionDialog ->
            mUserContext.startActivityAsUser //包名com.android.systemui.usb.UsbPermissionActivity
              onCreate -> UsbPermissionActivity.java
                setupAlert //弹出权限确认对话框

第三种:

openDevice -> UsbService.java
  mHostManager.openDevice ->
    openDevice ->  UsbHostManager.java
      getCurrentSettings().checkPermission ->
        hasPermission UsbSettingsManager.java

第一种方式问题及处理方法
APP : 设计插入启动activity, 下面是静态注册:

图片.png

动态注册:

@Override
    public void registerReceiver() {
        IntentFilter mUsbDeviceFilter = new IntentFilter();
        mUsbDeviceFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        mUsbDeviceFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        mUsbDeviceFilter.addAction(ACTION_USB_PERMISSION);
        mContext.registerReceiver(this,mUsbDeviceFilter);
    }

1-声明 为android.hardware.usb.host
2-如果你的APP想要在有USB device插入时能够被调用起来,那么必须要在xml的Activity中申请权限android.hardware.usb.action.USB_DEVICE_ATTACHED
3-如果只关心某些设备,可以通过里配置一个xml文件来做过滤

如果不想弹出权限:

diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
index 3eccccd..18130ab 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
@@ -99,6 +99,11 @@ public class UsbConfirmActivity extends AlertActivity
 
         setupAlert();
+        if (mResolveInfo.activityInfo.packageName.equals("ai.xxxx.xxx")) {
+            Log.d(TAG, "UsbConfirmActivity enable Usb permission for ai.xxxx.xxx");
+            onClick(this, AlertDialog.BUTTON_POSITIVE);
+        }
     }

第二、三种流程及问题处理方法
详细流程:

图片.png

  1. 新建activity,获取UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE)

  2. 获取所以的USB设备HashMap map = usbManager.getDeviceList()

  3. 过滤别的USB设备,拿到自己USB的USBDevice类,然后请求USB权限,usbManager.requestPermission(usbDevice, pendingIntent);并注册一个回调意图,用来判断用户是否授予权限

  4. UsbManager类的requestPermission方法会调用mService. requestDevicePermission

5.mService是IUsbManager的对象,而IUsbManager是一个AIDL接口
https://www.androidos.net.cn/android/8.0.0_r4/xref/frameworks/base/core/java/android/hardware/usb/IUsbManager.aidl
UsbService是它的实现类,所以最终是调用的UsbService的requestDevicePermission方法

  1. 在requestDevicePermission方法里面调用的getSettingsForUser(userId).requestPermission

  2. getSettingsForUser(userId)其实是去获取UsbUserSettingsManager实例,所以是调用的UsbUserSettingsManager的requestPermission方法

  3. 在requestPermission方法里面首先会进行判断是否拥有USB权限,如果有就回调广播直接return返回的。如果没有那就判断是否有相机权限,如果没有权限回调广播直接return的。注意从始至终是没有发送用户拒绝的广播的

  4. 接着会调用自身的requestPermissionDialog方法,在requestPermissionDialog方法里面又会去调用mUsbPermissionManager.requestPermissionDialog方法

10.最终在UsbPermissionManager类的requestPermissionDialog方法中调用startActivityAsUser 启动UsbPermissionActivity权限申请对话框

11.监听弹出权限对话框的onclick方法,如果点击的授权,那就在UsbPermissionActivity的onDestory里面回调最开始的广播,通知我们的应用,用户授予的权限。

实例:
如果对usb 授权,需要知道vid pid
android/frameworks/base/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java

    public boolean hasPermission(UsbDevice device) {
        synchronized (mLock) {
            int uid = Binder.getCallingUid();
            if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
                return true;
            }

+            if( vid&& pid == true) {
+                String deviceName = device.getDeviceName();
+                Slog.d(TAG, "customer uid:"+uid+"deviceName:"+deviceName);
+                SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName);
+                if (uidList == null) {
+                   uidList = new SparseBooleanArray(1);
+                   mDevicePermissionMap.put(deviceName, uidList);
+                }
+                uidList.put(uid, true);
+          }
            SparseBooleanArray uidList = mDevicePermissionMap.get(device.getDeviceName());
            if (uidList == null) {
                return false;
            }
            return uidList.get(uid);
        }
    }

REF:
https://developer.android.com/guide/topics/connectivity/usb/host.html#java

你可能感兴趣的:(USB 权限申请流程)