Merge changes from topic "AlwaysKeepAppOpsSynced" into qt-dev
* changes: Avoid overiding bg perm app-op for pre-M apps Also trigger PermPolicySvc on app-ops changes Combine successive PermPolicySvc syncs Always use PermMgrSrv APIs to change permission
This commit is contained in:
committed by
Android (Google) Code Review
commit
bf5506b240
@@ -111,9 +111,6 @@ import static com.android.server.pm.PackageManagerServiceUtils.getCompressedFile
|
||||
import static com.android.server.pm.PackageManagerServiceUtils.getLastModifiedTime;
|
||||
import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
|
||||
import static com.android.server.pm.PackageManagerServiceUtils.verifySignatures;
|
||||
import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_FAILURE;
|
||||
import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_SUCCESS;
|
||||
import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.IntDef;
|
||||
@@ -294,6 +291,7 @@ import com.android.internal.util.ConcurrentUtils;
|
||||
import com.android.internal.util.DumpUtils;
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.internal.util.IntPair;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.server.AttributeCache;
|
||||
import com.android.server.DeviceIdleController;
|
||||
@@ -19801,6 +19799,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
return;
|
||||
}
|
||||
|
||||
final String packageName = ps.pkg.packageName;
|
||||
|
||||
// These are flags that can change base on user actions.
|
||||
final int userSettableMask = FLAG_PERMISSION_USER_SET
|
||||
| FLAG_PERMISSION_USER_FIXED
|
||||
@@ -19810,8 +19810,59 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
final int policyOrSystemFlags = FLAG_PERMISSION_SYSTEM_FIXED
|
||||
| FLAG_PERMISSION_POLICY_FIXED;
|
||||
|
||||
boolean writeInstallPermissions = false;
|
||||
boolean writeRuntimePermissions = false;
|
||||
// Delay and combine non-async permission callbacks
|
||||
final boolean[] permissionRemoved = new boolean[1];
|
||||
final ArraySet<Long> revokedPermissions = new ArraySet<>();
|
||||
final SparseBooleanArray updatedUsers = new SparseBooleanArray();
|
||||
|
||||
PermissionCallback delayingPermCallback = new PermissionCallback() {
|
||||
public void onGidsChanged(int appId, int userId) {
|
||||
mPermissionCallback.onGidsChanged(appId, userId);
|
||||
}
|
||||
|
||||
public void onPermissionChanged() {
|
||||
mPermissionCallback.onPermissionChanged();
|
||||
}
|
||||
|
||||
public void onPermissionGranted(int uid, int userId) {
|
||||
mPermissionCallback.onPermissionGranted(uid, userId);
|
||||
}
|
||||
|
||||
public void onInstallPermissionGranted() {
|
||||
mPermissionCallback.onInstallPermissionGranted();
|
||||
}
|
||||
|
||||
public void onPermissionRevoked(int uid, int userId) {
|
||||
revokedPermissions.add(IntPair.of(uid, userId));
|
||||
|
||||
updatedUsers.put(userId, true);
|
||||
}
|
||||
|
||||
public void onInstallPermissionRevoked() {
|
||||
mPermissionCallback.onInstallPermissionRevoked();
|
||||
}
|
||||
|
||||
public void onPermissionUpdated(int[] updatedUserIds, boolean sync) {
|
||||
for (int userId : updatedUserIds) {
|
||||
if (sync) {
|
||||
updatedUsers.put(userId, true);
|
||||
} else {
|
||||
// Don't override sync=true by sync=false
|
||||
if (!updatedUsers.get(userId)) {
|
||||
updatedUsers.put(userId, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onPermissionRemoved() {
|
||||
permissionRemoved[0] = true;
|
||||
}
|
||||
|
||||
public void onInstallPermissionUpdated() {
|
||||
mPermissionCallback.onInstallPermissionUpdated();
|
||||
}
|
||||
};
|
||||
|
||||
final int permissionCount = ps.pkg.requestedPermissions.size();
|
||||
for (int i = 0; i < permissionCount; i++) {
|
||||
@@ -19843,26 +19894,20 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
final PermissionsState permissionsState = ps.getPermissionsState();
|
||||
|
||||
final int oldFlags = permissionsState.getPermissionFlags(permName, userId);
|
||||
final int oldFlags = mPermissionManager.getPermissionFlags(permName, packageName,
|
||||
Process.SYSTEM_UID, userId);
|
||||
|
||||
// Always clear the user settable flags.
|
||||
final boolean hasInstallState =
|
||||
permissionsState.getInstallPermissionState(permName) != null;
|
||||
// If permission review is enabled and this is a legacy app, mark the
|
||||
// permission as requiring a review as this is the initial state.
|
||||
int flags = 0;
|
||||
if (ps.pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M && bp.isRuntime()) {
|
||||
flags |= FLAG_PERMISSION_REVIEW_REQUIRED | FLAG_PERMISSION_REVOKE_ON_UPGRADE;
|
||||
}
|
||||
if (permissionsState.updatePermissionFlags(bp, userId, userSettableMask, flags)) {
|
||||
if (hasInstallState) {
|
||||
writeInstallPermissions = true;
|
||||
} else {
|
||||
writeRuntimePermissions = true;
|
||||
}
|
||||
}
|
||||
|
||||
mPermissionManager.updatePermissionFlags(permName, packageName,
|
||||
userSettableMask, flags, Process.SYSTEM_UID, userId, false,
|
||||
delayingPermCallback);
|
||||
|
||||
// Below is only runtime permission handling.
|
||||
if (!bp.isRuntime()) {
|
||||
@@ -19876,35 +19921,42 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
|
||||
// If this permission was granted by default, make sure it is.
|
||||
if ((oldFlags & FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0) {
|
||||
if (permissionsState.grantRuntimePermission(bp, userId)
|
||||
!= PERMISSION_OPERATION_FAILURE) {
|
||||
writeRuntimePermissions = true;
|
||||
}
|
||||
mPermissionManager.grantRuntimePermission(permName, packageName, false,
|
||||
Process.SYSTEM_UID, userId, delayingPermCallback);
|
||||
// If permission review is enabled the permissions for a legacy apps
|
||||
// are represented as constantly granted runtime ones, so don't revoke.
|
||||
} else if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
|
||||
// Otherwise, reset the permission.
|
||||
final int revokeResult = permissionsState.revokeRuntimePermission(bp, userId);
|
||||
switch (revokeResult) {
|
||||
case PERMISSION_OPERATION_SUCCESS:
|
||||
case PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
|
||||
writeRuntimePermissions = true;
|
||||
final int appId = ps.appId;
|
||||
mHandler.post(
|
||||
() -> killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED));
|
||||
} break;
|
||||
}
|
||||
mPermissionManager.revokeRuntimePermission(permName, packageName, false, userId,
|
||||
delayingPermCallback);
|
||||
}
|
||||
}
|
||||
|
||||
// Synchronously write as we are taking permissions away.
|
||||
if (writeRuntimePermissions) {
|
||||
mSettings.writeRuntimePermissionsForUserLPr(userId, true);
|
||||
// Execute delayed callbacks
|
||||
if (permissionRemoved[0]) {
|
||||
mPermissionCallback.onPermissionRemoved();
|
||||
}
|
||||
|
||||
// Synchronously write as we are taking permissions away.
|
||||
if (writeInstallPermissions) {
|
||||
mSettings.writeLPr();
|
||||
// Slight variation on the code in mPermissionCallback.onPermissionRevoked() as we cannot
|
||||
// kill uid while holding mPackages-lock
|
||||
if (!revokedPermissions.isEmpty()) {
|
||||
int numRevokedPermissions = revokedPermissions.size();
|
||||
for (int i = 0; i < numRevokedPermissions; i++) {
|
||||
int revocationUID = IntPair.first(revokedPermissions.valueAt(i));
|
||||
int revocationUserId = IntPair.second(revokedPermissions.valueAt(i));
|
||||
|
||||
mOnPermissionChangeListeners.onPermissionsChanged(revocationUID);
|
||||
|
||||
// Kill app later as we are holding mPackages
|
||||
mHandler.post(() -> killUid(UserHandle.getAppId(revocationUID), revocationUserId,
|
||||
KILL_APP_REASON_PERMISSIONS_REVOKED));
|
||||
}
|
||||
}
|
||||
|
||||
int numUpdatedUsers = updatedUsers.size();
|
||||
for (int i = 0; i < numUpdatedUsers; i++) {
|
||||
mSettings.writeRuntimePermissionsForUserLPr(updatedUsers.keyAt(i),
|
||||
updatedUsers.valueAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3126,6 +3126,27 @@ public class PermissionManagerService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ArrayList<PermissionInfo> getAllPermissionWithProtectionLevel(
|
||||
@PermissionInfo.Protection int protectionLevel) {
|
||||
ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
|
||||
|
||||
synchronized (PermissionManagerService.this.mLock) {
|
||||
int numTotalPermissions = mSettings.mPermissions.size();
|
||||
|
||||
for (int i = 0; i < numTotalPermissions; i++) {
|
||||
BasePermission bp = mSettings.mPermissions.valueAt(i);
|
||||
|
||||
if (bp.perm != null && bp.perm.info != null
|
||||
&& bp.protectionLevel == protectionLevel) {
|
||||
matchingPermissions.add(bp.perm.info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matchingPermissions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable byte[] backupRuntimePermissions(@NonNull UserHandle user) {
|
||||
return PermissionManagerService.this.backupRuntimePermissions(user);
|
||||
|
||||
@@ -195,4 +195,8 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
|
||||
|
||||
/** HACK HACK methods to allow for partial migration of data to the PermissionManager class */
|
||||
public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName);
|
||||
|
||||
/** Get all permission that have a certain protection level */
|
||||
public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionWithProtectionLevel(
|
||||
@PermissionInfo.Protection int protectionLevel);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import static android.app.AppOpsManager.MODE_FOREGROUND;
|
||||
import static android.app.AppOpsManager.MODE_IGNORED;
|
||||
import static android.app.AppOpsManager.OP_NONE;
|
||||
import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
|
||||
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
|
||||
import static android.content.pm.PackageManager.GET_PERMISSIONS;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
@@ -41,20 +42,27 @@ import android.content.pm.PackageParser;
|
||||
import android.content.pm.PermissionInfo;
|
||||
import android.os.Build;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManagerInternal;
|
||||
import android.permission.PermissionControllerManager;
|
||||
import android.permission.PermissionManagerInternal;
|
||||
import android.provider.Telephony;
|
||||
import android.telecom.TelecomManager;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.app.IAppOpsCallback;
|
||||
import com.android.internal.app.IAppOpsService;
|
||||
import com.android.internal.util.function.pooled.PooledLambda;
|
||||
import com.android.server.FgThread;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.pm.permission.PermissionManagerServiceInternal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@@ -76,6 +84,13 @@ public final class PermissionPolicyService extends SystemService {
|
||||
@GuardedBy("mLock")
|
||||
private final SparseBooleanArray mIsStarted = new SparseBooleanArray();
|
||||
|
||||
/**
|
||||
* Whether an async {@link #synchronizePackagePermissionsAndAppOpsForUser} is currently
|
||||
* scheduled for a package/user.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private final ArraySet<Pair<String, Integer>> mIsPackageSyncsScheduled = new ArraySet<>();
|
||||
|
||||
public PermissionPolicyService(@NonNull Context context) {
|
||||
super(context);
|
||||
|
||||
@@ -86,8 +101,10 @@ public final class PermissionPolicyService extends SystemService {
|
||||
public void onStart() {
|
||||
final PackageManagerInternal packageManagerInternal = LocalServices.getService(
|
||||
PackageManagerInternal.class);
|
||||
final PermissionManagerInternal permManagerInternal = LocalServices.getService(
|
||||
PermissionManagerInternal.class);
|
||||
final PermissionManagerServiceInternal permManagerInternal = LocalServices.getService(
|
||||
PermissionManagerServiceInternal.class);
|
||||
final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.APP_OPS_SERVICE));
|
||||
|
||||
packageManagerInternal.getPackageList(new PackageListObserver() {
|
||||
@Override
|
||||
@@ -111,11 +128,62 @@ public final class PermissionPolicyService extends SystemService {
|
||||
});
|
||||
|
||||
permManagerInternal.addOnRuntimePermissionStateChangedListener(
|
||||
(packageName, changedUserId) -> {
|
||||
if (isStarted(changedUserId)) {
|
||||
synchronizePackagePermissionsAndAppOpsForUser(packageName, changedUserId);
|
||||
this::synchronizePackagePermissionsAndAppOpsAsyncForUser);
|
||||
|
||||
IAppOpsCallback appOpsListener = new IAppOpsCallback.Stub() {
|
||||
public void opChanged(int op, int uid, String packageName) {
|
||||
synchronizePackagePermissionsAndAppOpsAsyncForUser(packageName,
|
||||
UserHandle.getUserId(uid));
|
||||
}
|
||||
};
|
||||
|
||||
final ArrayList<PermissionInfo> dangerousPerms =
|
||||
permManagerInternal.getAllPermissionWithProtectionLevel(
|
||||
PermissionInfo.PROTECTION_DANGEROUS);
|
||||
|
||||
try {
|
||||
int numDangerousPerms = dangerousPerms.size();
|
||||
for (int i = 0; i < numDangerousPerms; i++) {
|
||||
PermissionInfo perm = dangerousPerms.get(i);
|
||||
|
||||
if (perm.isHardRestricted() || perm.backgroundPermission != null) {
|
||||
appOpsService.startWatchingMode(AppOpsManager.permissionToOpCode(perm.name),
|
||||
null, appOpsListener);
|
||||
} else if (perm.isSoftRestricted()) {
|
||||
appOpsService.startWatchingMode(AppOpsManager.permissionToOpCode(perm.name),
|
||||
null, appOpsListener);
|
||||
|
||||
SoftRestrictedPermissionPolicy policy =
|
||||
SoftRestrictedPermissionPolicy.forPermission(null, null, null,
|
||||
perm.name);
|
||||
if (policy.resolveAppOp() != OP_NONE) {
|
||||
appOpsService.startWatchingMode(policy.resolveAppOp(), null,
|
||||
appOpsListener);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (RemoteException doesNotHappen) {
|
||||
Slog.wtf(LOG_TAG, "Cannot set up app-ops listener");
|
||||
}
|
||||
}
|
||||
|
||||
private void synchronizePackagePermissionsAndAppOpsAsyncForUser(@NonNull String packageName,
|
||||
@UserIdInt int changedUserId) {
|
||||
if (isStarted(changedUserId)) {
|
||||
synchronized (mLock) {
|
||||
if (mIsPackageSyncsScheduled.add(new Pair<>(packageName, changedUserId))) {
|
||||
FgThread.getHandler().sendMessage(PooledLambda.obtainMessage(
|
||||
PermissionPolicyService
|
||||
::synchronizePackagePermissionsAndAppOpsForUser,
|
||||
this, packageName, changedUserId));
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
Slog.v(LOG_TAG, "sync for " + packageName + "/" + changedUserId
|
||||
+ " already scheduled");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -230,10 +298,14 @@ public final class PermissionPolicyService extends SystemService {
|
||||
*/
|
||||
private void synchronizePackagePermissionsAndAppOpsForUser(@NonNull String packageName,
|
||||
@UserIdInt int userId) {
|
||||
synchronized (mLock) {
|
||||
mIsPackageSyncsScheduled.remove(new Pair<>(packageName, userId));
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.v(LOG_TAG,
|
||||
"synchronizePackagePermissionsAndAppOpsForUser(" + packageName + ", " + userId
|
||||
+ ")");
|
||||
"synchronizePackagePermissionsAndAppOpsForUser(" + packageName + ", "
|
||||
+ userId + ")");
|
||||
}
|
||||
|
||||
final PackageManagerInternal packageManagerInternal = LocalServices.getService(
|
||||
@@ -336,6 +408,16 @@ public final class PermissionPolicyService extends SystemService {
|
||||
*/
|
||||
private final @NonNull ArrayList<OpToUnrestrict> mOpsToForeground = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* All ops that need to be flipped to foreground if allow.
|
||||
*
|
||||
* Currently, only used by the foreground/background permissions logic.
|
||||
*
|
||||
* @see #syncPackages
|
||||
*/
|
||||
private final @NonNull ArrayList<OpToUnrestrict> mOpsToForegroundIfAllow =
|
||||
new ArrayList<>();
|
||||
|
||||
PermissionToOpSynchroniser(@NonNull Context context) {
|
||||
mContext = context;
|
||||
mPackageManager = context.getPackageManager();
|
||||
@@ -351,22 +433,27 @@ public final class PermissionPolicyService extends SystemService {
|
||||
final int allowCount = mOpsToAllow.size();
|
||||
for (int i = 0; i < allowCount; i++) {
|
||||
final OpToUnrestrict op = mOpsToAllow.get(i);
|
||||
setUidModeAllowed(op.code, op.uid);
|
||||
setUidModeAllowed(op.code, op.uid, op.packageName);
|
||||
}
|
||||
final int allowIfDefaultCount = mOpsToAllowIfDefault.size();
|
||||
for (int i = 0; i < allowIfDefaultCount; i++) {
|
||||
final OpToUnrestrict op = mOpsToAllowIfDefault.get(i);
|
||||
setUidModeAllowedIfDefault(op.code, op.uid, op.packageName);
|
||||
}
|
||||
final int foregroundCount = mOpsToForeground.size();
|
||||
final int foregroundCount = mOpsToForegroundIfAllow.size();
|
||||
for (int i = 0; i < foregroundCount; i++) {
|
||||
final OpToUnrestrict op = mOpsToForegroundIfAllow.get(i);
|
||||
setUidModeForegroundIfAllow(op.code, op.uid, op.packageName);
|
||||
}
|
||||
final int foregroundIfAllowCount = mOpsToForeground.size();
|
||||
for (int i = 0; i < foregroundIfAllowCount; i++) {
|
||||
final OpToUnrestrict op = mOpsToForeground.get(i);
|
||||
setUidModeForeground(op.code, op.uid);
|
||||
setUidModeForeground(op.code, op.uid, op.packageName);
|
||||
}
|
||||
final int ignoreCount = mOpsToIgnore.size();
|
||||
for (int i = 0; i < ignoreCount; i++) {
|
||||
final OpToUnrestrict op = mOpsToIgnore.get(i);
|
||||
setUidModeIgnored(op.code, op.uid);
|
||||
setUidModeIgnored(op.code, op.uid, op.packageName);
|
||||
}
|
||||
final int ignoreIfDefaultCount = mOpsToIgnoreIfDefault.size();
|
||||
for (int i = 0; i < ignoreIfDefaultCount; i++) {
|
||||
@@ -459,6 +546,24 @@ public final class PermissionPolicyService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBgPermRestricted(@NonNull String pkg, @NonNull String perm, int uid) {
|
||||
try {
|
||||
final PermissionInfo bgPermInfo = mPackageManager.getPermissionInfo(perm, 0);
|
||||
|
||||
if (bgPermInfo.isSoftRestricted()) {
|
||||
Slog.wtf(LOG_TAG, "Support for soft restricted background permissions not "
|
||||
+ "implemented");
|
||||
}
|
||||
|
||||
return bgPermInfo.isHardRestricted() && (mPackageManager.getPermissionFlags(
|
||||
perm, pkg, UserHandle.getUserHandleForUid(uid))
|
||||
& FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
|
||||
} catch (NameNotFoundException e) {
|
||||
Slog.w(LOG_TAG, "Cannot read permission state of " + perm, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add op that belong to a foreground permission for later processing in
|
||||
* {@link #syncPackages()}.
|
||||
@@ -481,26 +586,27 @@ public final class PermissionPolicyService extends SystemService {
|
||||
final String pkgName = pkg.packageName;
|
||||
final int uid = pkg.applicationInfo.uid;
|
||||
|
||||
if (mPackageManager.checkPermission(permission, pkgName)
|
||||
== PackageManager.PERMISSION_GRANTED) {
|
||||
boolean isBgHardRestricted = false;
|
||||
try {
|
||||
final PermissionInfo bgPermInfo = mPackageManager.getPermissionInfo(
|
||||
bgPermissionName, 0);
|
||||
// App does not support runtime permissions. Hence the state is encoded in the app-op.
|
||||
// To not override unrecoverable state don't change app-op unless bg perm is reviewed.
|
||||
if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
|
||||
// If the review is required for this permission, the grant state does not
|
||||
// really matter. To have a stable state, don't change the app-op if review is still
|
||||
// pending.
|
||||
int flags = mPackageManager.getPermissionFlags(bgPermissionName,
|
||||
pkg.packageName, UserHandle.getUserHandleForUid(uid));
|
||||
|
||||
if (bgPermInfo.isSoftRestricted()) {
|
||||
Slog.wtf(LOG_TAG, "Support for soft restricted background permissions not "
|
||||
+ "implemented");
|
||||
}
|
||||
|
||||
isBgHardRestricted =
|
||||
bgPermInfo.isHardRestricted() && (mPackageManager.getPermissionFlags(
|
||||
bgPermissionName, pkgName, UserHandle.getUserHandleForUid(uid))
|
||||
& FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
|
||||
} catch (NameNotFoundException e) {
|
||||
Slog.w(LOG_TAG, "Cannot read permission state of " + bgPermissionName, e);
|
||||
if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0
|
||||
&& isBgPermRestricted(pkgName, bgPermissionName, uid)) {
|
||||
mOpsToForegroundIfAllow.add(new OpToUnrestrict(uid, pkgName, opCode));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (mPackageManager.checkPermission(permission, pkgName)
|
||||
== PackageManager.PERMISSION_GRANTED) {
|
||||
final boolean isBgHardRestricted = isBgPermRestricted(pkgName, bgPermissionName,
|
||||
uid);
|
||||
final boolean isBgPermGranted = mPackageManager.checkPermission(bgPermissionName,
|
||||
pkgName) == PackageManager.PERMISSION_GRANTED;
|
||||
|
||||
@@ -554,45 +660,49 @@ public final class PermissionPolicyService extends SystemService {
|
||||
}
|
||||
|
||||
private void setUidModeAllowedIfDefault(int opCode, int uid, @NonNull String packageName) {
|
||||
setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_ALLOWED, packageName);
|
||||
setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_ALLOWED, packageName);
|
||||
}
|
||||
|
||||
private void setUidModeAllowed(int opCode, int uid) {
|
||||
mAppOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_ALLOWED);
|
||||
private void setUidModeAllowed(int opCode, int uid, @NonNull String packageName) {
|
||||
setUidMode(opCode, uid, MODE_ALLOWED, packageName);
|
||||
}
|
||||
|
||||
private void setUidModeForeground(int opCode, int uid) {
|
||||
mAppOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_FOREGROUND);
|
||||
private void setUidModeForegroundIfAllow(int opCode, int uid, @NonNull String packageName) {
|
||||
setUidModeIfMode(opCode, uid, MODE_ALLOWED, MODE_FOREGROUND, packageName);
|
||||
}
|
||||
|
||||
private void setUidModeForeground(int opCode, int uid, @NonNull String packageName) {
|
||||
setUidMode(opCode, uid, MODE_FOREGROUND, packageName);
|
||||
}
|
||||
|
||||
private void setUidModeIgnoredIfDefault(int opCode, int uid, @NonNull String packageName) {
|
||||
setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_IGNORED, packageName);
|
||||
setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_IGNORED, packageName);
|
||||
}
|
||||
|
||||
private void setUidModeIgnored(int opCode, int uid) {
|
||||
mAppOpsManager.setUidMode(opCode, uid, MODE_IGNORED);
|
||||
private void setUidModeIgnored(int opCode, int uid, @NonNull String packageName) {
|
||||
setUidMode(opCode, uid, MODE_IGNORED, packageName);
|
||||
}
|
||||
|
||||
private void setUidModeIfDefault(int opCode, int uid, int mode,
|
||||
private void setUidMode(int opCode, int uid, int mode,
|
||||
@NonNull String packageName) {
|
||||
final int currentMode;
|
||||
try {
|
||||
currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager
|
||||
.opToPublicName(opCode), uid, packageName);
|
||||
} catch (SecurityException e) {
|
||||
// This might happen if the app was uninstalled in between the add and sync step.
|
||||
// In this case the package name cannot be resolved inside appops service and hence
|
||||
// the uid does not match.
|
||||
Slog.w(LOG_TAG, "Cannot set mode of uid=" + uid + " op=" + opCode + " to " + mode,
|
||||
e);
|
||||
return;
|
||||
}
|
||||
final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager
|
||||
.opToPublicName(opCode), uid, packageName);
|
||||
|
||||
if (currentMode == MODE_DEFAULT) {
|
||||
if (currentMode != mode) {
|
||||
mAppOpsManager.setUidMode(opCode, uid, mode);
|
||||
}
|
||||
}
|
||||
|
||||
private void setUidModeIfMode(int opCode, int uid, int requiredModeBefore, int newMode,
|
||||
@NonNull String packageName) {
|
||||
final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager
|
||||
.opToPublicName(opCode), uid, packageName);
|
||||
|
||||
if (currentMode == requiredModeBefore) {
|
||||
mAppOpsManager.setUidMode(opCode, uid, newMode);
|
||||
}
|
||||
}
|
||||
|
||||
private void setUidModeDefault(int opCode, int uid) {
|
||||
mAppOpsManager.setUidMode(opCode, uid, MODE_DEFAULT);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYST
|
||||
import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
@@ -75,14 +76,16 @@ public abstract class SoftRestrictedPermissionPolicy {
|
||||
* Get the policy for a soft restricted permission.
|
||||
*
|
||||
* @param context A context to use
|
||||
* @param appInfo The application the permission belongs to
|
||||
* @param user The user the app belongs to
|
||||
* @param appInfo The application the permission belongs to. Can be {@code null}, but then
|
||||
* only {@link #resolveAppOp} will work.
|
||||
* @param user The user the app belongs to. Can be {@code null}, but then only
|
||||
* {@link #resolveAppOp} will work.
|
||||
* @param permission The name of the permission
|
||||
*
|
||||
* @return The policy for this permission
|
||||
*/
|
||||
public static @NonNull SoftRestrictedPermissionPolicy forPermission(@NonNull Context context,
|
||||
@NonNull ApplicationInfo appInfo, @NonNull UserHandle user,
|
||||
@Nullable ApplicationInfo appInfo, @Nullable UserHandle user,
|
||||
@NonNull String permission) {
|
||||
switch (permission) {
|
||||
// Storage uses a special app op to decide the mount state and supports soft restriction
|
||||
@@ -90,13 +93,26 @@ public abstract class SoftRestrictedPermissionPolicy {
|
||||
// collections.
|
||||
case READ_EXTERNAL_STORAGE:
|
||||
case WRITE_EXTERNAL_STORAGE: {
|
||||
int flags = context.getPackageManager().getPermissionFlags(
|
||||
permission, appInfo.packageName, user);
|
||||
boolean applyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
|
||||
boolean isWhiteListed = (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;
|
||||
boolean hasRequestedLegacyExternalStorage =
|
||||
appInfo.hasRequestedLegacyExternalStorage();
|
||||
int targetSDK = appInfo.targetSdkVersion;
|
||||
final int flags;
|
||||
final boolean applyRestriction;
|
||||
final boolean isWhiteListed;
|
||||
final boolean hasRequestedLegacyExternalStorage;
|
||||
final int targetSDK;
|
||||
|
||||
if (appInfo != null) {
|
||||
flags = context.getPackageManager().getPermissionFlags(permission,
|
||||
appInfo.packageName, user);
|
||||
applyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
|
||||
isWhiteListed = (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;
|
||||
hasRequestedLegacyExternalStorage = appInfo.hasRequestedLegacyExternalStorage();
|
||||
targetSDK = appInfo.targetSdkVersion;
|
||||
} else {
|
||||
flags = 0;
|
||||
applyRestriction = false;
|
||||
isWhiteListed = false;
|
||||
hasRequestedLegacyExternalStorage = false;
|
||||
targetSDK = 0;
|
||||
}
|
||||
|
||||
return new SoftRestrictedPermissionPolicy() {
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user