一)场景需求
项目中使用到了can协议控制车机功能,can 直接转串口,用USB转串口工具 cn.wch.uartlib 来实现. can 板子通过usb 插入到机器上面,那就是usb 协议了。
遇到问题:
- 插入can 板的usb 到机器上后,直接弹出授权框框。 需要默认不要弹出。这个逻辑是什么。【应用端解决】
- 在项目中请求usb 授权,后会有授权框框,其实就是1中的弹框。 如何默认授权,不让弹框。 这个逻辑是什么。【framework层解决】
如下图所示:
二)参考资料
android 10.0 去掉usb授权提示框 默认给予权限
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 版本,方法有所区别,代码逻辑有所区别。但核心原理一致,可参考修改。