Merge "Reset mode for app op permission when app no longer requests it." into rvc-dev
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
Reference in New Issue
Block a user