具体错误如下:
java.lang.SecurityException: Permission Denial: getTaskThumbnails() from pid=2881, uid=10077 requires android.permission.READ_FRAME_BUFFER
意思就是应用没有android.permission.READ_FRAME_BUFFER,但是我已经在AndroidManifest.xml中赋予了该权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <uses-permission android:name="android.permission.GET_TASKS"/> <uses-permission android:name="android.permission.READ_FRAME_BUFFER"/>还是不行,就只能跟踪源码了,首先我们可以差点在调用getTaskThumbnails的时候,在ActivityManagerService中的getTaskThumbnails会进行权限检测,调用enforceCallingPermission,enforceCallingPermission又调用checkComponentPermission,最终会调用PackageManagerService的checkUidPermission
public int checkUidPermission(String permName, int uid) { synchronized (mPackages) { Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid)); if (obj != null) { GrantedPermissions gp = (GrantedPermissions)obj; if (gp.grantedPermissions.contains(permName)) { return PackageManager.PERMISSION_GRANTED; } } else { HashSet<String> perms = mSystemPermissions.get(uid); if (perms != null && perms.contains(permName)) { return PackageManager.PERMISSION_GRANTED; } } } return PackageManager.PERMISSION_DENIED; }
我们跟踪代码的时候,发现这里面没有请求的权限android.permission.READ_FRAME_BUFFER,这是为什么呢,原因可能是安装的时候,解析AndroidManifest.xml的时候没有给他赋予这个权限,添加权限在grantPermissionsLPw函数里面,如下代码获取应用需要的权限对应的等级:
final BasePermission bp = mSettings.mPermissions.get(name); if (DEBUG_INSTALL) { if (gp != ps) { Log.i(TAG, "Package " + pkg.packageName + " checking " + name + ": " + bp); } } if (bp == null || bp.packageSetting == null) { Slog.w(TAG, "Unknown permission " + name + " in package " + pkg.packageName); continue; } final String perm = bp.name; boolean allowed; boolean allowedSig = false; final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
Android里面共有6个权限等级,定义在PermissionInfo文件。
/** * Dangerous value for {@link #protectionLevel}, corresponding * to the <code>dangerous</code> value of * {@link android.R.attr#protectionLevel}. */ public static final int PROTECTION_DANGEROUS = 1; /** * System-level value for {@link #protectionLevel}, corresponding * to the <code>signature</code> value of * {@link android.R.attr#protectionLevel}. */ public static final int PROTECTION_SIGNATURE = 2; /** * System-level value for {@link #protectionLevel}, corresponding * to the <code>signatureOrSystem</code> value of * {@link android.R.attr#protectionLevel}. */ public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3; /** * Additional flag for {@link #protectionLevel}, corresponding * to the <code>system</code> value of * {@link android.R.attr#protectionLevel}. */ public static final int PROTECTION_FLAG_SYSTEM = 0x10; /** * Additional flag for {@link #protectionLevel}, corresponding * to the <code>development</code> value of * {@link android.R.attr#protectionLevel}. */ public static final int PROTECTION_FLAG_DEVELOPMENT = 0x20;android的权限大部分定义在framework-res.apk里面,部分如下所示:
<permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" android:label="@string/permlab_changeComponentState" android:description="@string/permdesc_changeComponentState" android:protectionLevel="signature|system" /> <!-- @hide Allows an application to grant or revoke specific permissions. --> <permission android:name="android.permission.GRANT_REVOKE_PERMISSIONS" android:label="@string/permlab_grantRevokePermissions" android:description="@string/permdesc_grantRevokePermissions" android:protectionLevel="signature" /> <!-- Allows an application to use SurfaceFlinger's low level features. <p>Not for use by third-party applications. --> <permission android:name="android.permission.ACCESS_SURFACE_FLINGER" android:label="@string/permlab_accessSurfaceFlinger" android:description="@string/permdesc_accessSurfaceFlinger" android:protectionLevel="signature" /> <!-- Allows an application to take screen shots and more generally get access to the frame buffer data. <p>Not for use by third-party applications. --> <permission android:name="android.permission.READ_FRAME_BUFFER" android:label="@string/permlab_readFrameBuffer" android:description="@string/permdesc_readFrameBuffer" android:protectionLevel="signature|system" />
<item name="android.permission.BROADCAST_STICKY" package="android" /> <item name="android.permission.GRANT_REVOKE_PERMISSIONS" package="android" protection="2" /> <item name="android.permission.WRITE_USER_DICTIONARY" package="android" /> <item name="android.permission.READ_FRAME_BUFFER" package="android" protection="18" />言归正传,我们看安装时候对权限的解析,通过如下
if (level == PermissionInfo.PROTECTION_NORMAL || level == PermissionInfo.PROTECTION_DANGEROUS) { // We grant a normal or dangerous permission if any of the following // are true: // 1) The permission is required // 2) The permission is optional, but was granted in the past // 3) The permission is optional, but was requested by an // app in /system (not /data) // // Otherwise, reject the permission. allowed = (required || origPermissions.contains(perm) || (isSystemApp(ps) && !isUpdatedSystemApp(ps))); } else if (bp.packageSetting == null) { // This permission is invalid; skip it. allowed = false; } else if (level == PermissionInfo.PROTECTION_SIGNATURE) { allowed = grantSignaturePermission(perm, pkg, bp, origPermissions); if (allowed) { allowedSig = true; } } else { allowed = false; }如果允许,则添加到该apk拥有的权限列表里面:
if (allowed) { if (!gp.grantedPermissions.contains(perm)) { changedPermission = true; gp.grantedPermissions.add(perm); gp.gids = appendInts(gp.gids, bp.gids); } else if (!ps.haveGids) { gp.gids = appendInts(gp.gids, bp.gids); } }
跟踪代码我们可以发现,虽然apk请求了android.permission.READ_FRAME_BUFFER权限,但并没有赋予他,原因是签名不一致(签名需要跟定义权限的apk一致),这里获取到的level=PROTECTION_SIGNATURE,调用grantSignaturePermission判断是否获取权限。
修改对策:
1、修改apk签名
2、修改android.permission.READ_FRAME_BUFFER等级