Move permission flag methods

Bug: 135279435
Test: atest android.content.pm.cts.PackageManagerTest
Test: atest android.permission2.cts.RestrictedPermissionsTest
Change-Id: I3a5a7d8d3a3ba9d0b3e0e62d178a18903a94ec26
This commit is contained in:
Todd Kennedy
2019-07-03 13:06:35 -07:00
parent 95eab8ae45
commit 230c0a7e60
10 changed files with 363 additions and 321 deletions

View File

@@ -722,31 +722,32 @@ public class ApplicationPackageManager extends PackageManager {
}
@Override
public int getPermissionFlags(String permissionName, String packageName, UserHandle user) {
public int getPermissionFlags(String permName, String packageName, UserHandle user) {
try {
return mPM.getPermissionFlags(permissionName, packageName, user.getIdentifier());
return mPermissionManager
.getPermissionFlags(permName, packageName, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
@Override
public void updatePermissionFlags(String permissionName, String packageName,
public void updatePermissionFlags(String permName, String packageName,
int flagMask, int flagValues, UserHandle user) {
if (DEBUG_TRACE_GRANTS
&& shouldTraceGrant(packageName, permissionName, user.getIdentifier())) {
&& shouldTraceGrant(packageName, permName, user.getIdentifier())) {
Log.i(TAG, "App " + mContext.getPackageName() + " is updating flags for "
+ permissionName + " for user " + user.getIdentifier() + ": "
+ permName + " for user " + user.getIdentifier() + ": "
+ DebugUtils.flagsToString(PackageManager.class, "FLAG_PERMISSION_", flagMask)
+ " := " + DebugUtils.flagsToString(
PackageManager.class, "FLAG_PERMISSION_", flagValues),
new RuntimeException());
}
try {
mPM.updatePermissionFlags(permissionName, packageName, flagMask,
flagValues,
mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q,
user.getIdentifier());
final boolean checkAdjustPolicyFlagPermission =
mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q;
mPermissionManager.updatePermissionFlags(permName, packageName, flagMask,
flagValues, checkAdjustPolicyFlagPermission, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}

View File

@@ -108,13 +108,6 @@ interface IPackageManager {
void resetRuntimePermissions();
int getPermissionFlags(String permissionName, String packageName, int userId);
void updatePermissionFlags(String permissionName, String packageName, int flagMask,
int flagValues, boolean checkAdjustPolicyFlagPermission, int userId);
void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId);
List<String> getWhitelistedRestrictedPermissions(String packageName, int flags,
int userId);

View File

@@ -742,17 +742,6 @@ public abstract class PackageManagerInternal {
public abstract boolean filterAppAccess(
@Nullable PackageParser.Package pkg, int callingUid, int userId);
/*
* NOTE: The following methods are temporary until permissions are extracted from
* the package manager into a component specifically for handling permissions.
*/
/** Returns the flags for the given permission. */
public abstract @Nullable int getPermissionFlagsTEMP(@NonNull String permName,
@NonNull String packageName, int userId);
/** Updates the flags for the given permission. */
public abstract void updatePermissionFlagsTEMP(@NonNull String permName,
@NonNull String packageName, int flagMask, int flagValues, int userId);
/** Returns whether the given package was signed by the platform */
public abstract boolean isPlatformSigned(String pkg);
@@ -1006,4 +995,22 @@ public abstract class PackageManagerInternal {
* the settings have been written.
*/
public abstract void writeSettings(boolean async);
/**
* Writes all permission settings for the given set of users to disk. If {@code async}
* is {@code true}, the settings are written at some point in the future. Otherwise,
* the call blocks until the settings have been written.
*/
public abstract void writePermissionSettings(@NonNull @UserIdInt int[] userIds, boolean async);
/**
* Returns the target SDK for the given UID. Will return {@code 0} if there is no
* package associated with the UID or if the package has not been installed for
* the user. Will return the highest target SDK if the UID references packages with
* a shared user id.
*/
public abstract int getTargetSdk(int uid);
/** HACK. Remove when listeners move to the permission manager */
public abstract void onPermissionsChangedTEMP(int uid);
}

View File

@@ -39,4 +39,11 @@ interface IPermissionManager {
boolean addPermission(in PermissionInfo info, boolean async);
void removePermission(String name);
int getPermissionFlags(String permName, String packageName, int userId);
void updatePermissionFlags(String permName, String packageName, int flagMask,
int flagValues, boolean checkAdjustPolicyFlagPermission, int userId);
void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId);
}

View File

@@ -4569,55 +4569,6 @@ public class PackageManagerService extends IPackageManager.Stub
return -1;
}
/**
* Check if any package sharing/holding a uid has a low enough target SDK.
*
* @param uid The uid of the packages
* @param higherTargetSDK The target SDK that might be higher than the searched package
*
* @return {@code true} if there is a package sharing/holding the uid with
* {@code package.targetSDK < higherTargetSDK}
*/
private boolean hasTargetSdkInUidLowerThan(int uid, int higherTargetSDK) {
int userId = UserHandle.getUserId(uid);
synchronized (mPackages) {
Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid));
if (obj == null) {
return false;
}
if (obj instanceof PackageSetting) {
final PackageSetting ps = (PackageSetting) obj;
if (!ps.getInstalled(userId)) {
return false;
}
return ps.pkg.applicationInfo.targetSdkVersion < higherTargetSDK;
} else if (obj instanceof SharedUserSetting) {
final SharedUserSetting sus = (SharedUserSetting) obj;
final int numPkgs = sus.packages.size();
for (int i = 0; i < numPkgs; i++) {
final PackageSetting ps = sus.packages.valueAt(i);
if (!ps.getInstalled(userId)) {
continue;
}
if (ps.pkg.applicationInfo.targetSdkVersion < higherTargetSDK) {
return true;
}
}
return false;
} else {
return false;
}
}
}
@Override
public int[] getPackageGids(String packageName, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
@@ -5695,7 +5646,8 @@ public class PackageManagerService extends IPackageManager.Stub
final long identity = Binder.clearCallingIdentity();
try {
final int flags = getPermissionFlags(permission, packageName, userId);
final int flags = mPermissionManager
.getPermissionFlags(permission, packageName, Binder.getCallingUid(), userId);
return (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0;
} finally {
Binder.restoreCallingIdentity(identity);
@@ -5798,63 +5750,6 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
@Override
public int getPermissionFlags(String permName, String packageName, int userId) {
return mPermissionManager.getPermissionFlags(
permName, packageName, getCallingUid(), userId);
}
@Override
public void updatePermissionFlags(String permName, String packageName, int flagMask,
int flagValues, boolean checkAdjustPolicyFlagPermission, int userId) {
int callingUid = getCallingUid();
boolean overridePolicy = false;
if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID) {
long callingIdentity = Binder.clearCallingIdentity();
try {
if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0) {
if (checkAdjustPolicyFlagPermission) {
mContext.enforceCallingOrSelfPermission(
Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
"Need " + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY
+ " to change policy flags");
} else if (!hasTargetSdkInUidLowerThan(callingUid, Build.VERSION_CODES.Q)) {
throw new IllegalArgumentException(
Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY + " needs "
+ " to be checked for packages targeting "
+ Build.VERSION_CODES.Q + " or later when changing policy "
+ "flags");
}
overridePolicy = true;
}
} finally {
Binder.restoreCallingIdentity(callingIdentity);
}
}
mPermissionManager.updatePermissionFlags(
permName, packageName, flagMask, flagValues, callingUid, userId,
overridePolicy, mPermissionCallback);
}
/**
* Update the permission flags for all packages and runtime permissions of a user in order
* to allow device or profile owner to remove POLICY_FIXED.
*/
@Override
public void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId) {
synchronized (mPackages) {
final boolean changed = mPermissionManager.updatePermissionFlagsForAllApps(
flagMask, flagValues, getCallingUid(), userId, mPackages.values(),
mPermissionCallback);
if (changed) {
mSettings.writeRuntimePermissionsForUserLPr(userId, false);
}
}
}
@Override
public @Nullable List<String> getWhitelistedRestrictedPermissions(@NonNull String packageName,
@PermissionWhitelistFlags int whitelistFlags, @UserIdInt int userId) {
@@ -6078,7 +5973,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
@Override
public boolean shouldShowRequestPermissionRationale(String permissionName,
public boolean shouldShowRequestPermissionRationale(String permName,
String packageName, int userId) {
if (UserHandle.getCallingUserId() != userId) {
mContext.enforceCallingPermission(
@@ -6091,7 +5986,7 @@ public class PackageManagerService extends IPackageManager.Stub
return false;
}
if (checkPermission(permissionName, packageName, userId)
if (checkPermission(permName, packageName, userId)
== PackageManager.PERMISSION_GRANTED) {
return false;
}
@@ -6100,8 +5995,8 @@ public class PackageManagerService extends IPackageManager.Stub
final long identity = Binder.clearCallingIdentity();
try {
flags = getPermissionFlags(permissionName,
packageName, userId);
flags = mPermissionManager
.getPermissionFlags(permName, packageName, Binder.getCallingUid(), userId);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -24170,13 +24065,6 @@ public class PackageManagerService extends IPackageManager.Stub
}
private class PackageManagerInternalImpl extends PackageManagerInternal {
@Override
public void updatePermissionFlagsTEMP(String permName, String packageName, int flagMask,
int flagValues, int userId) {
PackageManagerService.this.updatePermissionFlags(
permName, packageName, flagMask, flagValues, true, userId);
}
@Override
public List<ApplicationInfo> getInstalledApplications(int flags, int userId,
int callingUid) {
@@ -24257,11 +24145,6 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
@Override
public int getPermissionFlagsTEMP(String permName, String packageName, int userId) {
return PackageManagerService.this.getPermissionFlags(permName, packageName, userId);
}
@Override
public boolean isInstantApp(String packageName, int userId) {
return PackageManagerService.this.isInstantApp(packageName, userId);
@@ -25036,6 +24919,52 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
}
@Override
public void writePermissionSettings(int[] userIds, boolean async) {
synchronized (mPackages) {
for (int userId : userIds) {
mSettings.writeRuntimePermissionsForUserLPr(userId, !async);
}
}
}
@Override
public void onPermissionsChangedTEMP(int uid) {
mOnPermissionChangeListeners.onPermissionsChanged(uid);
}
@Override
public int getTargetSdk(int uid) {
int userId = UserHandle.getUserId(uid);
synchronized (mPackages) {
final Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid));
if (obj instanceof PackageSetting) {
final PackageSetting ps = (PackageSetting) obj;
if (!ps.getInstalled(userId)) {
return 0;
}
return ps.pkg.applicationInfo.targetSdkVersion;
} else if (obj instanceof SharedUserSetting) {
int maxTargetSdk = 0;
final SharedUserSetting sus = (SharedUserSetting) obj;
final int numPkgs = sus.packages.size();
for (int i = 0; i < numPkgs; i++) {
final PackageSetting ps = sus.packages.valueAt(i);
if (!ps.getInstalled(userId)) {
continue;
}
if (ps.pkg.applicationInfo.targetSdkVersion < maxTargetSdk) {
continue;
}
maxTargetSdk = ps.pkg.applicationInfo.targetSdkVersion;
}
return maxTargetSdk;
}
return 0;
}
}
}
@GuardedBy("mPackages")

View File

@@ -123,6 +123,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
/**
* Manages all permissions and handles permissions related tasks.
@@ -229,6 +230,56 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final private ArrayList<OnRuntimePermissionStateChangedListener>
mRuntimePermissionStateChangedListeners = new ArrayList<>();
// TODO: Take a look at the methods defined in the callback.
// The callback was initially created to support the split between permission
// manager and the package manager. However, it's started to be used for other
// purposes. It may make sense to keep as an abstraction, but, the methods
// necessary to be overridden may be different than what was initially needed
// for the split.
private PermissionCallback mDefaultPermissionCallback = new PermissionCallback() {
@Override
public void onGidsChanged(int appId, int userId) {
// TODO: implement when methods have been fully migrated
}
@Override
public void onPermissionGranted(int uid, int userId) {
// TODO: implement when methods have been fully migrated
}
@Override
public void onInstallPermissionGranted() {
mPackageManagerInt.writeSettings(true);
}
@Override
public void onPermissionRevoked(int uid, int userId) {
// TODO: implement when methods have been fully migrated
}
@Override
public void onInstallPermissionRevoked() {
mPackageManagerInt.writeSettings(true);
}
@Override
public void onPermissionUpdated(int[] userIds, boolean sync) {
mPackageManagerInt.writePermissionSettings(userIds, !sync);
}
@Override
public void onInstallPermissionUpdated() {
mPackageManagerInt.writeSettings(true);
}
@Override
public void onPermissionRemoved() {
mPackageManagerInt.writeSettings(false);
}
public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds, boolean sync,
int uid) {
onPermissionUpdated(updatedUserIds, sync);
mPackageManagerInt.onPermissionsChangedTEMP(uid);
}
public void onInstallPermissionUpdatedNotifyListener(int uid) {
onInstallPermissionUpdated();
mPackageManagerInt.onPermissionsChangedTEMP(uid);
}
};
PermissionManagerService(Context context,
@NonNull Object externalLock) {
mContext = context;
@@ -456,6 +507,209 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
@Override
public int getPermissionFlags(String permName, String packageName, int userId) {
final int callingUid = getCallingUid();
return getPermissionFlagsInternal(permName, packageName, callingUid, userId);
}
private int getPermissionFlagsInternal(
String permName, String packageName, int callingUid, int userId) {
if (!mUserManagerInt.exists(userId)) {
return 0;
}
enforceGrantRevokeGetRuntimePermissionPermissions("getPermissionFlags");
enforceCrossUserPermission(callingUid, userId,
true, // requireFullPermission
false, // checkShell
false, // requirePermissionWhenSameUser
"getPermissionFlags");
final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
if (pkg == null || pkg.mExtras == null) {
return 0;
}
synchronized (mLock) {
if (mSettings.getPermissionLocked(permName) == null) {
return 0;
}
}
if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
return 0;
}
final PackageSetting ps = (PackageSetting) pkg.mExtras;
PermissionsState permissionsState = ps.getPermissionsState();
return permissionsState.getPermissionFlags(permName, userId);
}
@Override
public void updatePermissionFlags(String permName, String packageName, int flagMask,
int flagValues, boolean checkAdjustPolicyFlagPermission, int userId) {
final int callingUid = getCallingUid();
boolean overridePolicy = false;
if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID) {
long callingIdentity = Binder.clearCallingIdentity();
try {
if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0) {
if (checkAdjustPolicyFlagPermission) {
mContext.enforceCallingOrSelfPermission(
Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
"Need " + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY
+ " to change policy flags");
} else if (mPackageManagerInt.getTargetSdk(callingUid)
>= Build.VERSION_CODES.Q) {
throw new IllegalArgumentException(
Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY + " needs "
+ " to be checked for packages targeting "
+ Build.VERSION_CODES.Q + " or later when changing policy "
+ "flags");
}
overridePolicy = true;
}
} finally {
Binder.restoreCallingIdentity(callingIdentity);
}
}
updatePermissionFlagsInternal(
permName, packageName, flagMask, flagValues, callingUid, userId,
overridePolicy, mDefaultPermissionCallback);
}
private void updatePermissionFlagsInternal(String permName, String packageName, int flagMask,
int flagValues, int callingUid, int userId, boolean overridePolicy,
PermissionCallback callback) {
if (ApplicationPackageManager.DEBUG_TRACE_GRANTS
&& ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
Log.i(TAG, "System is updating flags for "
+ permName + " for user " + userId + " "
+ DebugUtils.flagsToString(
PackageManager.class, "FLAG_PERMISSION_", flagMask)
+ " := "
+ DebugUtils.flagsToString(
PackageManager.class, "FLAG_PERMISSION_", flagValues)
+ " on behalf of uid " + callingUid
+ " " + mPackageManagerInt.getNameForUid(callingUid),
new RuntimeException());
}
if (!mUserManagerInt.exists(userId)) {
return;
}
enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
enforceCrossUserPermission(callingUid, userId,
true, // requireFullPermission
true, // checkShell
false, // requirePermissionWhenSameUser
"updatePermissionFlags");
if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0 && !overridePolicy) {
throw new SecurityException("updatePermissionFlags requires "
+ Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY);
}
// Only the system can change these flags and nothing else.
if (callingUid != Process.SYSTEM_UID) {
flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
flagMask &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
flagValues &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
flagValues &= ~PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
}
final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
if (pkg == null || pkg.mExtras == null) {
Log.e(TAG, "Unknown package: " + packageName);
return;
}
if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
final BasePermission bp;
synchronized (mLock) {
bp = mSettings.getPermissionLocked(permName);
}
if (bp == null) {
throw new IllegalArgumentException("Unknown permission: " + permName);
}
final PackageSetting ps = (PackageSetting) pkg.mExtras;
final PermissionsState permissionsState = ps.getPermissionsState();
final boolean hadState =
permissionsState.getRuntimePermissionState(permName, userId) != null;
final boolean permissionUpdated =
permissionsState.updatePermissionFlags(bp, userId, flagMask, flagValues);
if (permissionUpdated && bp.isRuntime()) {
notifyRuntimePermissionStateChanged(packageName, userId);
}
if (permissionUpdated && callback != null) {
// Install and runtime permissions are stored in different places,
// so figure out what permission changed and persist the change.
if (permissionsState.getInstallPermissionState(permName) != null) {
callback.onInstallPermissionUpdatedNotifyListener(pkg.applicationInfo.uid);
} else if (permissionsState.getRuntimePermissionState(permName, userId) != null
|| hadState) {
callback.onPermissionUpdatedNotifyListener(new int[] { userId }, false,
pkg.applicationInfo.uid);
}
}
}
/**
* Update the permission flags for all packages and runtime permissions of a user in order
* to allow device or profile owner to remove POLICY_FIXED.
*/
@Override
public void updatePermissionFlagsForAllApps(int flagMask, int flagValues,
final int userId) {
final int callingUid = getCallingUid();
if (!mUserManagerInt.exists(userId)) {
return;
}
enforceGrantRevokeRuntimePermissionPermissions(
"updatePermissionFlagsForAllApps");
enforceCrossUserPermission(callingUid, userId,
true, // requireFullPermission
true, // checkShell
false, // requirePermissionWhenSameUser
"updatePermissionFlagsForAllApps");
// Only the system can change system fixed flags.
final int effectiveFlagMask = (callingUid != Process.SYSTEM_UID)
? flagMask : flagMask & ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
final int effectiveFlagValues = (callingUid != Process.SYSTEM_UID)
? flagValues : flagValues & ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
final boolean[] changed = new boolean[1];
mPackageManagerInt.forEachPackage(new Consumer<PackageParser.Package>() {
@Override
public void accept(Package pkg) {
final PackageSetting ps = (PackageSetting) pkg.mExtras;
if (ps == null) {
return;
}
final PermissionsState permissionsState = ps.getPermissionsState();
changed[0] |= permissionsState.updatePermissionFlagsForAllPermissions(
userId, effectiveFlagMask, effectiveFlagValues);
mPackageManagerInt.onPermissionsChangedTEMP(pkg.applicationInfo.uid);
}
});
if (changed[0]) {
mPackageManagerInt.writePermissionSettings(new int[] { userId }, true);
}
}
private int checkPermission(String permName, String pkgName, int callingUid, int userId) {
if (!mUserManagerInt.exists(userId)) {
return PackageManager.PERMISSION_DENIED;
@@ -2102,7 +2356,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// In permission review mode we clear the review flag when we
// are asked to install the app with all permissions granted.
if ((flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
updatePermissionFlags(permission, pkg.packageName,
updatePermissionFlagsInternal(permission, pkg.packageName,
PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, 0, callingUid,
userId, false, callback);
}
@@ -2454,7 +2708,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
newFlags |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
}
updatePermissionFlags(permissionName, pkg.packageName, mask, newFlags,
updatePermissionFlagsInternal(permissionName, pkg.packageName, mask, newFlags,
callingUid, userId, false, null /*callback*/);
}
@@ -2541,37 +2795,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return runtimePermissionChangedUserIds;
}
private int getPermissionFlags(
String permName, String packageName, int callingUid, int userId) {
if (!mUserManagerInt.exists(userId)) {
return 0;
}
enforceGrantRevokeGetRuntimePermissionPermissions("getPermissionFlags");
enforceCrossUserPermission(callingUid, userId,
true, // requireFullPermission
false, // checkShell
false, // requirePermissionWhenSameUser
"getPermissionFlags");
final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
if (pkg == null || pkg.mExtras == null) {
return 0;
}
synchronized (mLock) {
if (mSettings.getPermissionLocked(permName) == null) {
return 0;
}
}
if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
return 0;
}
final PackageSetting ps = (PackageSetting) pkg.mExtras;
PermissionsState permissionsState = ps.getPermissionsState();
return permissionsState.getPermissionFlags(permName, userId);
}
/**
* Update permissions when a package changed.
*
@@ -2880,127 +3103,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return changed;
}
private void updatePermissionFlags(String permName, String packageName, int flagMask,
int flagValues, int callingUid, int userId, boolean overridePolicy,
PermissionCallback callback) {
if (ApplicationPackageManager.DEBUG_TRACE_GRANTS
&& ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
Log.i(TAG, "System is updating flags for "
+ permName + " for user " + userId + " "
+ DebugUtils.flagsToString(
PackageManager.class, "FLAG_PERMISSION_", flagMask)
+ " := "
+ DebugUtils.flagsToString(
PackageManager.class, "FLAG_PERMISSION_", flagValues)
+ " on behalf of uid " + callingUid
+ " " + mPackageManagerInt.getNameForUid(callingUid),
new RuntimeException());
}
if (!mUserManagerInt.exists(userId)) {
return;
}
enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
enforceCrossUserPermission(callingUid, userId,
true, // requireFullPermission
true, // checkShell
false, // requirePermissionWhenSameUser
"updatePermissionFlags");
if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0 && !overridePolicy) {
throw new SecurityException("updatePermissionFlags requires "
+ Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY);
}
// Only the system can change these flags and nothing else.
if (callingUid != Process.SYSTEM_UID) {
flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
flagMask &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
flagValues &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
flagValues &= ~PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
}
final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
if (pkg == null || pkg.mExtras == null) {
Log.e(TAG, "Unknown package: " + packageName);
return;
}
if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
final BasePermission bp;
synchronized (mLock) {
bp = mSettings.getPermissionLocked(permName);
}
if (bp == null) {
throw new IllegalArgumentException("Unknown permission: " + permName);
}
final PackageSetting ps = (PackageSetting) pkg.mExtras;
final PermissionsState permissionsState = ps.getPermissionsState();
final boolean hadState =
permissionsState.getRuntimePermissionState(permName, userId) != null;
final boolean permissionUpdated =
permissionsState.updatePermissionFlags(bp, userId, flagMask, flagValues);
if (permissionUpdated && bp.isRuntime()) {
notifyRuntimePermissionStateChanged(packageName, userId);
}
if (permissionUpdated && callback != null) {
// Install and runtime permissions are stored in different places,
// so figure out what permission changed and persist the change.
if (permissionsState.getInstallPermissionState(permName) != null) {
callback.onInstallPermissionUpdatedNotifyListener(pkg.applicationInfo.uid);
} else if (permissionsState.getRuntimePermissionState(permName, userId) != null
|| hadState) {
callback.onPermissionUpdatedNotifyListener(new int[] { userId }, false,
pkg.applicationInfo.uid);
}
}
}
private boolean updatePermissionFlagsForAllApps(int flagMask, int flagValues, int callingUid,
int userId, Collection<Package> packages, PermissionCallback callback) {
if (!mUserManagerInt.exists(userId)) {
return false;
}
enforceGrantRevokeRuntimePermissionPermissions(
"updatePermissionFlagsForAllApps");
enforceCrossUserPermission(callingUid, userId,
true, // requireFullPermission
true, // checkShell
false, // requirePermissionWhenSameUser
"updatePermissionFlagsForAllApps");
// Only the system can change system fixed flags.
if (callingUid != Process.SYSTEM_UID) {
flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
}
boolean changed = false;
for (PackageParser.Package pkg : packages) {
final PackageSetting ps = (PackageSetting) pkg.mExtras;
if (ps == null) {
continue;
}
PermissionsState permissionsState = ps.getPermissionsState();
changed |= permissionsState.updatePermissionFlagsForAllPermissions(
userId, flagMask, flagValues);
callback.onPermissionUpdatedNotifyListener(new int[] { userId }, false,
pkg.applicationInfo.uid);
}
return changed;
}
private void enforceGrantRevokeRuntimePermissionPermissions(String message) {
if (mContext.checkCallingOrSelfPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
!= PackageManager.PERMISSION_GRANTED
@@ -3231,24 +3333,18 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@Override
public int getPermissionFlags(String permName, String packageName, int callingUid,
int userId) {
return PermissionManagerService.this.getPermissionFlags(permName, packageName,
callingUid, userId);
return PermissionManagerService.this
.getPermissionFlagsInternal(permName, packageName, callingUid, userId);
}
@Override
public void updatePermissionFlags(String permName, String packageName, int flagMask,
int flagValues, int callingUid, int userId, boolean overridePolicy,
PermissionCallback callback) {
PermissionManagerService.this.updatePermissionFlags(
PermissionManagerService.this.updatePermissionFlagsInternal(
permName, packageName, flagMask, flagValues, callingUid, userId,
overridePolicy, callback);
}
@Override
public boolean updatePermissionFlagsForAllApps(int flagMask, int flagValues, int callingUid,
int userId, Collection<Package> packages, PermissionCallback callback) {
return PermissionManagerService.this.updatePermissionFlagsForAllApps(
flagMask, flagValues, callingUid, userId, packages, callback);
}
@Override
public void enforceCrossUserPermission(int callingUid, int userId,
boolean requireFullPermission, boolean checkShell, String message) {
PermissionManagerService.this.enforceCrossUserPermission(callingUid, userId,

View File

@@ -169,13 +169,6 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
public abstract void updatePermissionFlags(@NonNull String permName,
@NonNull String packageName, int flagMask, int flagValues, int callingUid, int userId,
boolean overridePolicy, @Nullable PermissionCallback callback);
/**
* Updates the flags for all applications by replacing the flags in the specified mask
* with the provided flag values.
*/
public abstract boolean updatePermissionFlagsForAllApps(int flagMask, int flagValues,
int callingUid, int userId, @NonNull Collection<PackageParser.Package> packages,
@Nullable PermissionCallback callback);
public abstract int checkPermission(@NonNull String permName, @NonNull String packageName,
int callingUid, int userId);

View File

@@ -196,6 +196,7 @@ import android.os.UserManager;
import android.os.UserManagerInternal;
import android.os.UserManagerInternal.UserRestrictionsListener;
import android.os.storage.StorageManager;
import android.permission.IPermissionManager;
import android.permission.PermissionControllerManager;
import android.provider.CalendarContract;
import android.provider.ContactsContract.QuickContact;
@@ -492,6 +493,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final Context mContext;
final Injector mInjector;
final IPackageManager mIPackageManager;
final IPermissionManager mIPermissionManager;
final UserManager mUserManager;
final UserManagerInternal mUserManagerInternal;
final UsageStatsManagerInternal mUsageStatsManagerInternal;
@@ -1974,6 +1976,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return AppGlobals.getPackageManager();
}
IPermissionManager getIPermissionManager() {
return AppGlobals.getPermissionManager();
}
IBackupManager getIBackupManager() {
return IBackupManager.Stub.asInterface(
ServiceManager.getService(Context.BACKUP_SERVICE));
@@ -2217,6 +2223,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
mUsageStatsManagerInternal = Preconditions.checkNotNull(
injector.getUsageStatsManagerInternal());
mIPackageManager = Preconditions.checkNotNull(injector.getIPackageManager());
mIPermissionManager = Preconditions.checkNotNull(injector.getIPermissionManager());
mTelephonyManager = Preconditions.checkNotNull(injector.getTelephonyManager());
mLocalService = new LocalService();
@@ -8217,7 +8224,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
saveSettingsLocked(userId);
try {
mIPackageManager.updatePermissionFlagsForAllApps(
mIPermissionManager.updatePermissionFlagsForAllApps(
PackageManager.FLAG_PERMISSION_POLICY_FIXED,
0 /* flagValues */, userId);
pushUserRestrictions(userId);

View File

@@ -37,6 +37,7 @@ import android.os.PowerManagerInternal;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.permission.IPermissionManager;
import android.security.KeyChain;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
@@ -198,6 +199,11 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi
return services.ipackageManager;
}
@Override
IPermissionManager getIPermissionManager() {
return services.ipermissionManager;
}
@Override
IBackupManager getIBackupManager() {
return services.ibackupManager;

View File

@@ -52,6 +52,7 @@ import android.os.PowerManagerInternal;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.permission.IPermissionManager;
import android.provider.Settings;
import android.security.KeyChain;
import android.telephony.TelephonyManager;
@@ -97,6 +98,7 @@ public class MockSystemServices {
public ActivityManagerInternal activityManagerInternal;
public ActivityTaskManagerInternal activityTaskManagerInternal;
public final IPackageManager ipackageManager;
public final IPermissionManager ipermissionManager;
public final IBackupManager ibackupManager;
public final IAudioService iaudioService;
public final LockPatternUtils lockPatternUtils;
@@ -137,6 +139,7 @@ public class MockSystemServices {
activityManagerInternal = mock(ActivityManagerInternal.class);
activityTaskManagerInternal = mock(ActivityTaskManagerInternal.class);
ipackageManager = mock(IPackageManager.class);
ipermissionManager = mock(IPermissionManager.class);
ibackupManager = mock(IBackupManager.class);
iaudioService = mock(IAudioService.class);
lockPatternUtils = mock(LockPatternUtils.class);