在Android系统日常开发中,曾遇见公司多媒体兼容RK系列Android7.1以上系统时,无法在U盘目录里面删除或者创建目录或文件的现象,于是我检查了下源码,发现源码里面已经放开了大部分权限了,如下:
涉及目录:
\frameworks\base\data\etc\platform.xml
\frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java
private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace,
String packageOfInterest) {
// IMPORTANT: There are two types of permissions: install and runtime.
// Install time permissions are granted when the app is installed to
// all device users and users added in the future. Runtime permissions
// are granted at runtime explicitly to specific users. Normal and signature
// protected permissions are install time permissions. Dangerous permissions
// are install permissions if the app's target SDK is Lollipop MR1 or older,
// otherwise they are runtime permissions. This function does not manage
// runtime permissions except for the case an app targeting Lollipop MR1
// being upgraded to target a newer SDK, in which case dangerous permissions
// are transformed from install time to runtime ones.
final PackageSetting ps = (PackageSetting) pkg.mExtras;
if (ps == null) {
return;
}
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "grantPermissions");
PermissionsState permissionsState = ps.getPermissionsState();
PermissionsState origPermissions = permissionsState;
final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
boolean runtimePermissionsRevoked = false;
int[] changedRuntimePermissionUserIds = EMPTY_INT_ARRAY;
boolean changedInstallPermission = false;
if (replace) {
ps.installPermissionsFixed = false;
if (!ps.isSharedUser()) {
origPermissions = new PermissionsState(permissionsState);
permissionsState.reset();
} else {
// We need to know only about runtime permission changes since the
// calling code always writes the install permissions state but
// the runtime ones are written only if changed. The only cases of
// changed runtime permissions here are promotion of an install to
// runtime and revocation of a runtime from a shared user.
changedRuntimePermissionUserIds = revokeUnusedSharedUserPermissionsLPw(
ps.sharedUser, UserManagerService.getInstance().getUserIds());
if (!ArrayUtils.isEmpty(changedRuntimePermissionUserIds)) {
runtimePermissionsRevoked = true;
}
}
}
permissionsState.setGlobalGids(mGlobalGids);
final int N = pkg.requestedPermissions.size();
for (int i=0; i<N; i++) {
final String name = pkg.requestedPermissions.get(i);
final BasePermission bp = mSettings.mPermissions.get(name);
if (DEBUG_INSTALL) {
Log.i(TAG, "Package " + pkg.packageName + " checking " + name + ": " + bp);
}
if (bp == null || bp.packageSetting == null) {
if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) {
Slog.w(TAG, "Unknown permission " + name
+ " in package " + pkg.packageName);
}
continue;
}
final String perm = bp.name;
boolean allowedSig = false;
int grant = GRANT_DENIED;
// Keep track of app op permissions.
if ((bp.protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
ArraySet<String> pkgs = mAppOpPermissionPackages.get(bp.name);
if (pkgs == null) {
pkgs = new ArraySet<>();
mAppOpPermissionPackages.put(bp.name, pkgs);
}
pkgs.add(pkg.packageName);
}
final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
final boolean appSupportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion
>= Build.VERSION_CODES.M;
switch (level) {
case PermissionInfo.PROTECTION_NORMAL: {
// For all apps normal permissions are install time ones.
grant = GRANT_INSTALL;
} break;
case PermissionInfo.PROTECTION_DANGEROUS: {
// If a permission review is required for legacy apps we represent
// their permissions as always granted runtime ones since we need
// to keep the review required permission flag per user while an
// install permission's state is shared across all users.
if ((!appSupportsRuntimePermissions && !mPermissionReviewRequired
&& !Build.PERMISSIONS_REVIEW_REQUIRED) ||
name.equals("android.permission.WRITE_EXTERNAL_STORAGE")) {
// For legacy apps dangerous permissions are install time ones.
grant = GRANT_INSTALL;
} else if (origPermissions.hasInstallPermission(bp.name)) {
// For legacy apps that became modern, install becomes runtime.
grant = GRANT_UPGRADE;
} else if (mPromoteSystemApps
&& isSystemApp(ps)
&& mExistingSystemPackages.contains(ps.name)) {
// For legacy system apps, install becomes runtime.
// We cannot check hasInstallPermission() for system apps since those
// permissions were granted implicitly and not persisted pre-M.
grant = GRANT_UPGRADE;
} else {
// For modern apps keep runtime permissions unchanged.
//grant = GRANT_RUNTIME;
grant = GRANT_INSTALL;
}
} break;
case PermissionInfo.PROTECTION_SIGNATURE: {
// For all apps signature permissions are install time ones.
allowedSig = grantSignaturePermission(perm, pkg, bp, origPermissions);
if (allowedSig || name.equals("android.permission.WRITE_MEDIA_STORAGE")) {
grant = GRANT_INSTALL;
}
} break;
}
if (DEBUG_INSTALL) {
Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
}
if (grant != GRANT_DENIED) {
if (!isSystemApp(ps) && ps.installPermissionsFixed) {
// If this is an existing, non-system package, then
// we can't add any new permissions to it.
if (!allowedSig && !origPermissions.hasInstallPermission(perm)) {
// Except... if this is a permission that was added
// to the platform (note: need to only do this when
// updating the platform).
if (!isNewPlatformPermissionForPackage(perm, pkg)) {
grant = GRANT_DENIED;
}
}
}
但是还是不行,不过我们在源码权限文件platform.xml发现了这个权限
<permission name="android.permission.WRITE_MEDIA_STORAGE" >
<group gid="media_rw" />
<group gid="sdcard_rw" />
</permission>
我们加入这个权限后,多媒体应用就可以在U盘或者sd卡目录下面创建和删除文件了,由上面可以看出这个就是media和dscard的管理权限
权限如下:
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE"
tools:ignore="ProtectedPermissions" />