Merge "Reset mode for app op permission when app no longer requests it." into rvc-dev

This commit is contained in:
Hai Zhang
2020-05-04 23:33:48 +00:00
committed by Android (Google) Code Review
3 changed files with 142 additions and 16 deletions

View File

@@ -4639,11 +4639,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
public @NonNull ArrayList<PermissionInfo> getAllPermissionWithProtection(
public @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtection(
@PermissionInfo.Protection int protection) {
ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
synchronized (PermissionManagerService.this.mLock) {
synchronized (mLock) {
int numTotalPermissions = mSettings.mPermissions.size();
for (int i = 0; i < numTotalPermissions; i++) {
@@ -4659,6 +4659,28 @@ public class PermissionManagerService extends IPermissionManager.Stub {
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
public @Nullable byte[] backupRuntimePermissions(@NonNull UserHandle 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 */
public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName);
/** Get all permission that have a certain protection level */
public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionWithProtection(
/** Get all permissions that have a certain protection */
public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtection(
@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.
*

View File

@@ -77,6 +77,7 @@ import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -112,6 +113,15 @@ public final class PermissionPolicyService extends SystemService {
@GuardedBy("mLock")
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) {
super(context);
@@ -122,7 +132,7 @@ public final class PermissionPolicyService extends SystemService {
public void onStart() {
final PackageManagerInternal packageManagerInternal = LocalServices.getService(
PackageManagerInternal.class);
final PermissionManagerServiceInternal permManagerInternal = LocalServices.getService(
final PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
PermissionManagerServiceInternal.class);
final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
@@ -130,38 +140,44 @@ public final class PermissionPolicyService extends SystemService {
packageManagerInternal.getPackageList(new PackageListObserver() {
@Override
public void onPackageAdded(String packageName, int uid) {
onPackageChanged(packageName, uid);
}
@Override
public void onPackageChanged(String packageName, int uid) {
final int userId = UserHandle.getUserId(uid);
if (isStarted(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
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);
mAppOpsCallback = new IAppOpsCallback.Stub() {
public void opChanged(int op, int uid, String packageName) {
synchronizePackagePermissionsAndAppOpsAsyncForUser(packageName,
UserHandle.getUserId(uid));
resetAppOpPermissionsIfNotRequestedForUidAsync(uid);
}
};
final ArrayList<PermissionInfo> dangerousPerms =
permManagerInternal.getAllPermissionWithProtection(
permissionManagerInternal.getAllPermissionsWithProtection(
PermissionInfo.PROTECTION_DANGEROUS);
try {
int numDangerousPerms = dangerousPerms.size();
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");
}
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.addAction(Intent.ACTION_PACKAGE_ADDED);
intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
@@ -491,6 +527,70 @@ public final class PermissionPolicyService extends SystemService {
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
* 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.class);
List<PermissionInfo> permissionInfos =
permissionManagerInternal.getAllPermissionWithProtection(
permissionManagerInternal.getAllPermissionsWithProtection(
PermissionInfo.PROTECTION_DANGEROUS);
int permissionInfosSize = permissionInfos.size();
for (int i = 0; i < permissionInfosSize; i++) {