Merge "Reset mode for app op permission when app no longer requests it." into rvc-dev am: 9ddbdbf2b5 am: 3915f82117

Change-Id: Ia0a5e7cb54221f1242b990dcfc06a13c9dd8896f
This commit is contained in:
Hai Zhang
2020-05-04 23:44:33 +00:00
committed by Automerger Merge Worker
3 changed files with 142 additions and 16 deletions

View File

@@ -4639,11 +4639,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
} }
@Override @Override
public @NonNull ArrayList<PermissionInfo> getAllPermissionWithProtection( public @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtection(
@PermissionInfo.Protection int protection) { @PermissionInfo.Protection int protection) {
ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>(); ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
synchronized (PermissionManagerService.this.mLock) { synchronized (mLock) {
int numTotalPermissions = mSettings.mPermissions.size(); int numTotalPermissions = mSettings.mPermissions.size();
for (int i = 0; i < numTotalPermissions; i++) { for (int i = 0; i < numTotalPermissions; i++) {
@@ -4659,6 +4659,28 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return matchingPermissions; return matchingPermissions;
} }
@Override
public @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtectionFlags(
@PermissionInfo.ProtectionFlags int protectionFlags) {
ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
synchronized (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.getProtectionFlags() & protectionFlags)
== protectionFlags) {
matchingPermissions.add(
PackageInfoUtils.generatePermissionInfo(bp.perm, 0));
}
}
}
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

@@ -302,10 +302,14 @@ 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 */ /** Get all permissions that have a certain protection */
public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionWithProtection( public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtection(
@PermissionInfo.Protection int protection); @PermissionInfo.Protection int protection);
/** Get all permissions that have certain protection flags */
public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtectionFlags(
@PermissionInfo.ProtectionFlags int protectionFlags);
/** /**
* Returns the delegate used to influence permission checking. * Returns the delegate used to influence permission checking.
* *

View File

@@ -77,6 +77,7 @@ import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback; import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -112,6 +113,15 @@ public final class PermissionPolicyService extends SystemService {
@GuardedBy("mLock") @GuardedBy("mLock")
private final ArraySet<Pair<String, Integer>> mIsPackageSyncsScheduled = new ArraySet<>(); private final ArraySet<Pair<String, Integer>> mIsPackageSyncsScheduled = new ArraySet<>();
/**
* Whether an async {@link #resetAppOpPermissionsIfNotRequestedForUid} is currently
* scheduled for a uid.
*/
@GuardedBy("mLock")
private final SparseBooleanArray mIsUidSyncScheduled = new SparseBooleanArray();
private List<String> mAppOpPermissions;
public PermissionPolicyService(@NonNull Context context) { public PermissionPolicyService(@NonNull Context context) {
super(context); super(context);
@@ -122,7 +132,7 @@ 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 PermissionManagerServiceInternal permManagerInternal = LocalServices.getService( final PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
PermissionManagerServiceInternal.class); PermissionManagerServiceInternal.class);
final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface( final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE)); ServiceManager.getService(Context.APP_OPS_SERVICE));
@@ -130,38 +140,44 @@ public final class PermissionPolicyService extends SystemService {
packageManagerInternal.getPackageList(new PackageListObserver() { packageManagerInternal.getPackageList(new PackageListObserver() {
@Override @Override
public void onPackageAdded(String packageName, int uid) { public void onPackageAdded(String packageName, int uid) {
onPackageChanged(packageName, uid);
}
@Override
public void onPackageChanged(String packageName, int uid) {
final int userId = UserHandle.getUserId(uid); final int userId = UserHandle.getUserId(uid);
if (isStarted(userId)) { if (isStarted(userId)) {
synchronizePackagePermissionsAndAppOpsForUser(packageName, userId); synchronizePackagePermissionsAndAppOpsForUser(packageName, userId);
} }
} }
@Override
public void onPackageChanged(String packageName, int uid) {
final int userId = UserHandle.getUserId(uid);
if (isStarted(userId)) {
synchronizePackagePermissionsAndAppOpsForUser(packageName, userId);
resetAppOpPermissionsIfNotRequestedForUid(uid);
}
}
@Override @Override
public void onPackageRemoved(String packageName, int uid) { public void onPackageRemoved(String packageName, int uid) {
/* do nothing */ final int userId = UserHandle.getUserId(uid);
if (isStarted(userId)) {
resetAppOpPermissionsIfNotRequestedForUid(uid);
}
} }
}); });
permManagerInternal.addOnRuntimePermissionStateChangedListener( permissionManagerInternal.addOnRuntimePermissionStateChangedListener(
this::synchronizePackagePermissionsAndAppOpsAsyncForUser); this::synchronizePackagePermissionsAndAppOpsAsyncForUser);
mAppOpsCallback = new IAppOpsCallback.Stub() { mAppOpsCallback = new IAppOpsCallback.Stub() {
public void opChanged(int op, int uid, String packageName) { public void opChanged(int op, int uid, String packageName) {
synchronizePackagePermissionsAndAppOpsAsyncForUser(packageName, synchronizePackagePermissionsAndAppOpsAsyncForUser(packageName,
UserHandle.getUserId(uid)); UserHandle.getUserId(uid));
resetAppOpPermissionsIfNotRequestedForUidAsync(uid);
} }
}; };
final ArrayList<PermissionInfo> dangerousPerms = final ArrayList<PermissionInfo> dangerousPerms =
permManagerInternal.getAllPermissionWithProtection( permissionManagerInternal.getAllPermissionsWithProtection(
PermissionInfo.PROTECTION_DANGEROUS); PermissionInfo.PROTECTION_DANGEROUS);
try { try {
int numDangerousPerms = dangerousPerms.size(); int numDangerousPerms = dangerousPerms.size();
for (int i = 0; i < numDangerousPerms; i++) { for (int i = 0; i < numDangerousPerms; i++) {
@@ -184,6 +200,26 @@ public final class PermissionPolicyService extends SystemService {
Slog.wtf(LOG_TAG, "Cannot set up app-ops listener"); Slog.wtf(LOG_TAG, "Cannot set up app-ops listener");
} }
final List<PermissionInfo> appOpPermissionInfos =
permissionManagerInternal.getAllPermissionsWithProtectionFlags(
PermissionInfo.PROTECTION_FLAG_APPOP);
mAppOpPermissions = new ArrayList<>();
final int appOpPermissionInfosSize = appOpPermissionInfos.size();
for (int i = 0; i < appOpPermissionInfosSize; i++) {
final PermissionInfo appOpPermissionInfo = appOpPermissionInfos.get(i);
final int appOpCode = AppOpsManager.permissionToOpCode(appOpPermissionInfo.name);
if (appOpCode != OP_NONE) {
mAppOpPermissions.add(appOpPermissionInfo.name);
try {
appOpsService.startWatchingMode(appOpCode, null, mAppOpsCallback);
} catch (RemoteException e) {
Slog.wtf(LOG_TAG, "Cannot set up app-ops listener", e);
}
}
}
IntentFilter intentFilter = new IntentFilter(); IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
@@ -491,6 +527,70 @@ public final class PermissionPolicyService extends SystemService {
synchronizer.syncPackages(); synchronizer.syncPackages();
} }
private void resetAppOpPermissionsIfNotRequestedForUidAsync(int uid) {
if (isStarted(UserHandle.getUserId(uid))) {
synchronized (mLock) {
if (!mIsUidSyncScheduled.get(uid)) {
mIsUidSyncScheduled.put(uid, true);
FgThread.getHandler().sendMessage(PooledLambda.obtainMessage(
PermissionPolicyService::resetAppOpPermissionsIfNotRequestedForUid,
this, uid));
}
}
}
}
private void resetAppOpPermissionsIfNotRequestedForUid(int uid) {
synchronized (mLock) {
mIsUidSyncScheduled.delete(uid);
}
final Context context = getContext();
final PackageManager userPackageManager = getUserContext(context,
UserHandle.getUserHandleForUid(uid)).getPackageManager();
final String[] packageNames = userPackageManager.getPackagesForUid(uid);
if (packageNames == null || packageNames.length == 0) {
return;
}
final ArraySet<String> requestedPermissions = new ArraySet<>();
for (String packageName : packageNames) {
final PackageInfo packageInfo;
try {
packageInfo = userPackageManager.getPackageInfo(packageName, GET_PERMISSIONS);
} catch (NameNotFoundException e) {
continue;
}
if (packageInfo == null || packageInfo.requestedPermissions == null) {
continue;
}
Collections.addAll(requestedPermissions, packageInfo.requestedPermissions);
}
final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
final AppOpsManagerInternal appOpsManagerInternal = LocalServices.getService(
AppOpsManagerInternal.class);
final int appOpPermissionsSize = mAppOpPermissions.size();
for (int i = 0; i < appOpPermissionsSize; i++) {
final String appOpPermission = mAppOpPermissions.get(i);
if (!requestedPermissions.contains(appOpPermission)) {
final int appOpCode = AppOpsManager.permissionToOpCode(appOpPermission);
final int defaultAppOpMode = AppOpsManager.opToDefaultMode(appOpCode);
for (String packageName : packageNames) {
final int appOpMode = appOpsManager.unsafeCheckOpRawNoThrow(appOpCode, uid,
packageName);
if (appOpMode != defaultAppOpMode) {
appOpsManagerInternal.setUidModeFromPermissionPolicy(appOpCode, uid,
defaultAppOpMode, mAppOpsCallback);
appOpsManagerInternal.setModeFromPermissionPolicy(appOpCode, uid,
packageName, defaultAppOpMode, mAppOpsCallback);
}
}
}
}
}
/** /**
* Synchronizes permission to app ops. You *must* always sync all packages * Synchronizes permission to app ops. You *must* always sync all packages
* in a shared UID at the same time to ensure proper synchronization. * in a shared UID at the same time to ensure proper synchronization.
@@ -545,7 +645,7 @@ public final class PermissionPolicyService extends SystemService {
PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService( PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
PermissionManagerServiceInternal.class); PermissionManagerServiceInternal.class);
List<PermissionInfo> permissionInfos = List<PermissionInfo> permissionInfos =
permissionManagerInternal.getAllPermissionWithProtection( permissionManagerInternal.getAllPermissionsWithProtection(
PermissionInfo.PROTECTION_DANGEROUS); PermissionInfo.PROTECTION_DANGEROUS);
int permissionInfosSize = permissionInfos.size(); int permissionInfosSize = permissionInfos.size();
for (int i = 0; i < permissionInfosSize; i++) { for (int i = 0; i < permissionInfosSize; i++) {