Also trigger PermPolicySvc on app-ops changes

PermissionPolicyService is supposed to keep permissions and app-ops in
sync. Hence listen for app-ops changes too.

Test: Reset app-ops and saw PermissionPolicyService triggered
Fixes: 132704705
Change-Id: Ic208d9aebaab52c84893716777964c5b5cb254d2
This commit is contained in:
Philip P. Moltmann
2019-06-14 09:02:24 -07:00
parent 78c155b8a4
commit fad1a8fb2f
4 changed files with 115 additions and 22 deletions

View File

@@ -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 @Override
public @Nullable byte[] backupRuntimePermissions(@NonNull UserHandle user) { public @Nullable byte[] backupRuntimePermissions(@NonNull UserHandle user) {
return PermissionManagerService.this.backupRuntimePermissions(user); return PermissionManagerService.this.backupRuntimePermissions(user);

View File

@@ -195,4 +195,8 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
/** HACK HACK methods to allow for partial migration of data to the PermissionManager class */ /** HACK HACK methods to allow for partial migration of data to the PermissionManager class */
public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName); 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);
} }

View File

@@ -41,10 +41,11 @@ import android.content.pm.PackageParser;
import android.content.pm.PermissionInfo; import android.content.pm.PermissionInfo;
import android.os.Build; import android.os.Build;
import android.os.Process; import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManagerInternal; import android.os.UserManagerInternal;
import android.permission.PermissionControllerManager; import android.permission.PermissionControllerManager;
import android.permission.PermissionManagerInternal;
import android.provider.Telephony; import android.provider.Telephony;
import android.telecom.TelecomManager; import android.telecom.TelecomManager;
import android.util.ArraySet; import android.util.ArraySet;
@@ -54,10 +55,13 @@ import android.util.SparseBooleanArray;
import android.util.SparseIntArray; import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy; 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.internal.util.function.pooled.PooledLambda;
import com.android.server.FgThread; import com.android.server.FgThread;
import com.android.server.LocalServices; import com.android.server.LocalServices;
import com.android.server.SystemService; import com.android.server.SystemService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
@@ -96,8 +100,10 @@ public final class PermissionPolicyService extends SystemService {
public void onStart() { public void onStart() {
final PackageManagerInternal packageManagerInternal = LocalServices.getService( final PackageManagerInternal packageManagerInternal = LocalServices.getService(
PackageManagerInternal.class); PackageManagerInternal.class);
final PermissionManagerInternal permManagerInternal = LocalServices.getService( final PermissionManagerServiceInternal permManagerInternal = LocalServices.getService(
PermissionManagerInternal.class); PermissionManagerServiceInternal.class);
final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
packageManagerInternal.getPackageList(new PackageListObserver() { packageManagerInternal.getPackageList(new PackageListObserver() {
@Override @Override
@@ -122,6 +128,42 @@ public final class PermissionPolicyService extends SystemService {
permManagerInternal.addOnRuntimePermissionStateChangedListener( permManagerInternal.addOnRuntimePermissionStateChangedListener(
this::synchronizePackagePermissionsAndAppOpsAsyncForUser); 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, private void synchronizePackagePermissionsAndAppOpsAsyncForUser(@NonNull String packageName,
@@ -380,7 +422,7 @@ public final class PermissionPolicyService extends SystemService {
final int allowCount = mOpsToAllow.size(); final int allowCount = mOpsToAllow.size();
for (int i = 0; i < allowCount; i++) { for (int i = 0; i < allowCount; i++) {
final OpToUnrestrict op = mOpsToAllow.get(i); final OpToUnrestrict op = mOpsToAllow.get(i);
setUidModeAllowed(op.code, op.uid); setUidModeAllowed(op.code, op.uid, op.packageName);
} }
final int allowIfDefaultCount = mOpsToAllowIfDefault.size(); final int allowIfDefaultCount = mOpsToAllowIfDefault.size();
for (int i = 0; i < allowIfDefaultCount; i++) { for (int i = 0; i < allowIfDefaultCount; i++) {
@@ -390,12 +432,12 @@ public final class PermissionPolicyService extends SystemService {
final int foregroundCount = mOpsToForeground.size(); final int foregroundCount = mOpsToForeground.size();
for (int i = 0; i < foregroundCount; i++) { for (int i = 0; i < foregroundCount; i++) {
final OpToUnrestrict op = mOpsToForeground.get(i); final OpToUnrestrict op = mOpsToForeground.get(i);
setUidModeForeground(op.code, op.uid); setUidModeForeground(op.code, op.uid, op.packageName);
} }
final int ignoreCount = mOpsToIgnore.size(); final int ignoreCount = mOpsToIgnore.size();
for (int i = 0; i < ignoreCount; i++) { for (int i = 0; i < ignoreCount; i++) {
final OpToUnrestrict op = mOpsToIgnore.get(i); final OpToUnrestrict op = mOpsToIgnore.get(i);
setUidModeIgnored(op.code, op.uid); setUidModeIgnored(op.code, op.uid, op.packageName);
} }
final int ignoreIfDefaultCount = mOpsToIgnoreIfDefault.size(); final int ignoreIfDefaultCount = mOpsToIgnoreIfDefault.size();
for (int i = 0; i < ignoreIfDefaultCount; i++) { for (int i = 0; i < ignoreIfDefaultCount; i++) {
@@ -586,20 +628,30 @@ public final class PermissionPolicyService extends SystemService {
setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_ALLOWED, packageName); setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_ALLOWED, packageName);
} }
private void setUidModeAllowed(int opCode, int uid) { private void setUidModeAllowed(int opCode, int uid, @NonNull String packageName) {
mAppOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_ALLOWED); setUidMode(opCode, uid, MODE_ALLOWED, packageName);
} }
private void setUidModeForeground(int opCode, int uid) { private void setUidModeForeground(int opCode, int uid, @NonNull String packageName) {
mAppOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_FOREGROUND); setUidMode(opCode, uid, MODE_FOREGROUND, packageName);
} }
private void setUidModeIgnoredIfDefault(int opCode, int uid, @NonNull String packageName) { private void setUidModeIgnoredIfDefault(int opCode, int uid, @NonNull String packageName) {
setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_IGNORED, packageName); setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_IGNORED, packageName);
} }
private void setUidModeIgnored(int opCode, int uid) { private void setUidModeIgnored(int opCode, int uid, @NonNull String packageName) {
mAppOpsManager.setUidMode(opCode, uid, MODE_IGNORED); setUidMode(opCode, uid, MODE_IGNORED, packageName);
}
private void setUidMode(int opCode, int uid, int mode,
@NonNull String packageName) {
final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager
.opToPublicName(opCode), uid, packageName);
if (currentMode != mode) {
mAppOpsManager.setUidMode(opCode, uid, mode);
}
} }
private void setUidModeIfDefault(int opCode, int uid, int mode, private void setUidModeIfDefault(int opCode, int uid, int mode,

View File

@@ -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 static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager; import android.app.AppOpsManager;
import android.content.Context; import android.content.Context;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
@@ -75,14 +76,16 @@ public abstract class SoftRestrictedPermissionPolicy {
* Get the policy for a soft restricted permission. * Get the policy for a soft restricted permission.
* *
* @param context A context to use * @param context A context to use
* @param appInfo The application the permission belongs to * @param appInfo The application the permission belongs to. Can be {@code null}, but then
* @param user The user the app belongs to * 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 * @param permission The name of the permission
* *
* @return The policy for this permission * @return The policy for this permission
*/ */
public static @NonNull SoftRestrictedPermissionPolicy forPermission(@NonNull Context context, public static @NonNull SoftRestrictedPermissionPolicy forPermission(@NonNull Context context,
@NonNull ApplicationInfo appInfo, @NonNull UserHandle user, @Nullable ApplicationInfo appInfo, @Nullable UserHandle user,
@NonNull String permission) { @NonNull String permission) {
switch (permission) { switch (permission) {
// Storage uses a special app op to decide the mount state and supports soft restriction // Storage uses a special app op to decide the mount state and supports soft restriction
@@ -90,13 +93,26 @@ public abstract class SoftRestrictedPermissionPolicy {
// collections. // collections.
case READ_EXTERNAL_STORAGE: case READ_EXTERNAL_STORAGE:
case WRITE_EXTERNAL_STORAGE: { case WRITE_EXTERNAL_STORAGE: {
int flags = context.getPackageManager().getPermissionFlags( final int flags;
permission, appInfo.packageName, user); final boolean applyRestriction;
boolean applyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0; final boolean isWhiteListed;
boolean isWhiteListed = (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0; final boolean hasRequestedLegacyExternalStorage;
boolean hasRequestedLegacyExternalStorage = final int targetSDK;
appInfo.hasRequestedLegacyExternalStorage();
int targetSDK = appInfo.targetSdkVersion; 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() { return new SoftRestrictedPermissionPolicy() {
@Override @Override