Android13 USB 串口默认授权

一)场景需求

项目中使用到了can协议控制车机功能,can 直接转串口,用USB转串口工具 cn.wch.uartlib 来实现. can 板子通过usb 插入到机器上面,那就是usb 协议了。

遇到问题:

  • 插入can 板的usb 到机器上后,直接弹出授权框框。 需要默认不要弹出。这个逻辑是什么。【应用端解决】
  • 在项目中请求usb 授权,后会有授权框框,其实就是1中的弹框。 如何默认授权,不让弹框。 这个逻辑是什么。【framework层解决】
    如下图所示:

二)参考资料

android 10.0 去掉usb授权提示框 默认给予权限

USBService源码分析(一)

USBService源码分析之Usb权限(二)
在线源码查看平台 xref

三)解决方案和源码分析

对于插入USB直接弹出弹框授权申请,如果允许就跳转到对应的app。

解决方案:

去掉应用中 USB_DEVICE_ATTCHED 的过滤器,它会直接跳转到对应的app 。 不符合需求。 故 不在热插拔逻辑的确认框.

java 复制代码
           <intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>
            </intent-filter>
            <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
                android:resource="@xml/device_filter" />

热插拔确认框:

java 复制代码
/vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java

修改文件

java 复制代码
/vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
 

备注:为什么要改这里,解决问题思路:当弹出确认框的时候,去dump 确认一下当前到底是哪个activity。

在热插拔时候 弹出的是UsbConfirmActivity.java 在应用逻辑去申请请求权限的时候,弹出的是 UsbPermissionActivity.java

解决方案

在UsbPermissionActivity 界面中,默认授权, 然后结束掉自己。

java 复制代码
  //wangfangchen add 
        //setupAlert();
		 Log.d(TAG,"22222 mo ren usb  quanbu shouquan... ");
		 mDialogHelper.grantUidAccessPermission();
	     mDialogHelper.setDefaultPackage();
		 mPermissionGranted = true;
         finish();
		//wangfangchen end 

git 记录如下:

java 复制代码
+
+//wangfangchen add 
+import android.util.Log; 
+//wangfangchen end  
+
+
 /**
  * Dialog shown when a package requests access to a USB device or accessory.
  */
 public class UsbPermissionActivity extends UsbDialogActivity {
 
+    private static final String TAG = "UsbPermissionActivity";
+
     private boolean mPermissionGranted = false;
     private UsbAudioWarningDialogMessage mUsbPermissionMessageHandler;
 
@@ -61,7 +69,14 @@ public class UsbPermissionActivity extends UsbDialogActivity {
         if (!useRecordWarning && mDialogHelper.canBeDefault()) {
             addAlwaysUseCheckbox();
         }
-        setupAlert();
+           //wangfangchen add 
+        //setupAlert();
+                Log.d(TAG,"22222 mo ren usb  quanbu shouquan... ");
+                mDialogHelper.grantUidAccessPermission();
+            mDialogHelper.setDefaultPackage();
+               mPermissionGranted = true;
+        finish();
+     
 

源码分析及思路

**思路:**在弹出界面的情况下默认选中复选框并点击确认,这些步骤默认执行即可。 实际操作中发开机后每次都会弹框,这是系统机制检测的远呀,固无法从根本上来解决这个问题,那么就只能在弹框界面默认选中执行。

Framework层源码分析

UsbPermissionActivity 从哪里而来。 dumps Activity 界面是 UsbPermissionActivity,从何而来。

第一种方案,grep 大法搜索,找到使用地方和配置。这里暂延伸讨论。

可以看到一个配置路径 config 里面的配置

java 复制代码
   frameworks/base/core/res/res/values/config.xml:2890:            >com.android.systemui/com.android.systemui.usb.UsbPermissionActivity</string>

第二种方案

USB 相关的一定有USB相关服务,就去源码里面搜一下,相关的。

这里有个方法

java 复制代码
 @Override
    public void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) {
        final int uid = Binder.getCallingUid();
        final int pid = Binder.getCallingPid();
        final int userId = UserHandle.getUserId(uid);

        final long token = Binder.clearCallingIdentity();
        try {
            getPermissionsForUser(userId).requestPermission(device, packageName, pi, pid, uid);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

点击进去:

UserService 里面,getPermissionsForUser(userId).requestPermission 方法中的getPermissionsForUser 那就对应应该是 UsbUserPermissionManager.java 对象类了吧。

requestPermissionDialog 查看代码,其实就是跳转了

这里不就找到了跳转到SystemUI 里面去了吗? 从Framework 层 UsbService 响应到SystemUI 显示UI和业务逻辑了。

SystemUI层源码分析

1) 查看UsbPermissionActivity.java , UsbPermissionActivity extends UsbDialogActivity

onResume 方法中,setupAlert() 方法,看着像一个弹框,onConfirm 看着像确认框,在确认框里面有grantUidAccessPermission 授权方法。 并结束掉当前 Activity . 所以,模拟这个过程,不让弹框弹出不就可以了吗。

2)追踪UsbDialogActivity.java UsbDialogActivity extends AlertActivity

java 复制代码
70      @Override
71      public void onClick(DialogInterface dialog, int which) {
72          if (which == AlertDialog.BUTTON_POSITIVE) {
73              onConfirm();
74          } else {
75              finish();
76          }
77      }


  abstract void onConfirm();

onClick onConfirm 不就是回到了 UserPermissionActivity 里面了嘛 。

3)追踪 AlertActivity.java 回到了Framework 层的对话框

java 复制代码
abstract class AlertActivity extends Activity implements DialogInterface

里面有个方法setupAlert

4)追踪 AlertController.java 追踪installContent 方法。

这样由UserPermissionActivity 中的弹出对话框 setupAlert 方法链路就形成了闭环。

对于真正实现授权的业务逻辑,可以跟踪业务方法,这里暂不讨论。

java 复制代码
  mDialogHelper.grantUidAccessPermission();
  mDialogHelper.setDefaultPackage();
  mPermissionGranted = true;

备注:

本方案只是针对Android13 版本,其它Android12 /Android14 版本,方法有所区别,代码逻辑有所区别。但核心原理一致,可参考修改。