最近在Android4.4上调试一个Usb指纹模块,记录下系统默认权限修改.
Usb Device具体操作流程这里就不写了,网上有很多例子,
正常流程:首先是UsbManager申请权限,这时会出现一个提示框,如下图:
勾选默认情况下用于该设备后,点击确定。这时会在/data/system/users/0/目录下生成一个xml文件
usb_device_manager.xml
内容如下:
会保存package应用程序的包名,设备vid,pid,以及相关协议.
知道这些后,开始跟踪代码找相关函数.
UsbManager的requestPermission最后是调用Usbservice的requestDevicePermission函数然后到UsbSettingsManager里的requestPermission函数,这个最后的requestPermissionDialog就是调用Systemui的UsbPermissionActivity弹出的第一个申请权限的对话框.
由于我要在裁剪过的系统里进行修改,这里面已经删除了SystemUi所以,只能在requestPermissionDialog之前进行处理.
查看Systemui中UsbPermissionActivity申请权限点击后主要作了两件事
intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED);
intent.putExtra(UsbManager.EXTRA_DEVICE, mDevice);
// grant permission for the device
service.grantDevicePermission(mDevice, uid);
// set or clear default setting
if (alwaysUse) {
service.setDevicePackage(
mDevice, mResolveInfo.activityInfo.packageName, userId);
} else {
service.setDevicePackage(mDevice, null, userId);
}
首先调用UsbService的grantDevicePermission,然后调用了setDevicePackage
对应查看UsbSettingsManager的两个函数,然后对UsbSettingsManager进行了如下修改
修改构造函数
public UsbSettingsManager(Context context, UserHandle user) {
if (DEBUG) Slog.v(TAG, "Creating settings for " + user);
try {
mUserContext = context.createPackageContextAsUser("android", 0, user);
} catch (NameNotFoundException e) {
throw new RuntimeException("Missing android package");
}
mContext = context;
mPackageManager = mUserContext.getPackageManager();
mUser = user;
mSettingsFile = new AtomicFile(new File(
Environment.getUserSystemDirectory(user.getIdentifier()),
"usb_device_manager.xml"));
synchronized (mLock) {
if (UserHandle.OWNER.equals(user)) {
upgradeSingleUserLocked();
}
readSettingsLocked();
}
//add by hclydao
DeviceFilter myfilter = new DeviceFilter(pid, vid,0, 0, 0);
String pak = mDevicePreferenceMap.get(myfilter);
if(pak == null) {
mDevicePreferenceMap.put(myfilter, mypakname);//mypakname是应用程序包名 String类型
writeSettingsLocked();
}
//add end
mPackageMonitor.register(mUserContext, null, true);
}
其中pid,vid在之前测试的usb_device_manager.xml中可以找到,一般产家都会直接提供,这里的操作是直接启动后,直接将相关信息写到usb_device_manager.xml文件中,这里相当于调用了一次setDevicePackage.
然后修改requestPermission函数
public void requestPermission(UsbDevice device, String packageName, PendingIntent pi) {
Intent intent = new Intent();
// respond immediately if permission has already been granted
if (hasPermission(device)) {
intent.putExtra(UsbManager.EXTRA_DEVICE, device);
intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
try {
pi.send(mUserContext, 0, intent);
} catch (PendingIntent.CanceledException e) {
if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled");
}
return;
}
//hclydao
if(packageName.equals(mypakname)) {
int uid = Binder.getCallingUid();
SparseBooleanArray uidList = new SparseBooleanArray(1);
mDevicePermissionMap.put(device.getDeviceName(), uidList);
uidList.put(uid, true);
intent.putExtra(UsbManager.EXTRA_DEVICE, device);
intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
try {
pi.send(mUserContext, 0, intent);
} catch (PendingIntent.CanceledException e) {
if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled");
}
return;
}
// start UsbPermissionActivity so user can choose an activity
intent.putExtra(UsbManager.EXTRA_DEVICE, device);
requestPermissionDialog(intent, packageName, pi);
}
如果当前申请权限的包名与默认设置的包名一致就直接给权限返回.直接相当于调用了一次grantDevicePermission
修改完成后,编译系统更新,解决问题.
======================================
作者:hclydao
http://blog.csdn.net/hclydao
版权没有,但是转载请保留此段声明
===========================================