Notify all packages is uid-mode is changed

Multiple packages might share a UID, but appOpsService might not have
cached the uid->package mapping for those yet. Hence the only way to
list all packages for a uid is to ask package manager.

setUidMode already handled this correctly, hence factor out the code
into notifyOpChangedForAllPkgsInUid and reuse it from
commitUidStatePendingLocked.

Bug: 148180766
Test: atest CtsAppOpsTestCases:android.app.appops.cts.ForegroundModeTest
Change-Id: I2d5d6c7aa38d201707349a137c9c29b7987775be
This commit is contained in:
Philip P. Moltmann
2020-01-24 14:21:12 -08:00
parent 04c84989d3
commit 584c23a1d0

View File

@@ -41,6 +41,7 @@ import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE;
import static android.app.AppOpsManager.UID_STATE_MAX_LAST_NON_RESTRICTED;
import static android.app.AppOpsManager.UID_STATE_PERSISTENT;
import static android.app.AppOpsManager.UID_STATE_TOP;
import static android.app.AppOpsManager.WATCH_FOREGROUND_CHANGES;
import static android.app.AppOpsManager._NUM_OP;
import static android.app.AppOpsManager.extractFlagsFromKey;
import static android.app.AppOpsManager.extractUidStateFromKey;
@@ -2014,6 +2015,19 @@ public class AppOpsService extends IAppOpsService.Stub {
uidState.evalForegroundOps(mOpModeWatchers);
}
notifyOpChangedForAllPkgsInUid(code, uid, false, callbackToIgnore);
notifyOpChangedSync(code, uid, null, mode);
}
/**
* Notify that an op changed for all packages in an uid.
*
* @param code The op that changed
* @param uid The uid the op was changed for
* @param onlyForeground Only notify watchers that watch for foreground changes
*/
private void notifyOpChangedForAllPkgsInUid(int code, int uid, boolean onlyForeground,
@Nullable IAppOpsCallback callbackToIgnore) {
String[] uidPackageNames = getPackagesForUid(uid);
ArrayMap<ModeCallback, ArraySet<String>> callbackSpecs = null;
@@ -2023,6 +2037,10 @@ public class AppOpsService extends IAppOpsService.Stub {
final int callbackCount = callbacks.size();
for (int i = 0; i < callbackCount; i++) {
ModeCallback callback = callbacks.valueAt(i);
if (onlyForeground && (callback.mFlags & WATCH_FOREGROUND_CHANGES) == 0) {
continue;
}
ArraySet<String> changedPackages = new ArraySet<>();
Collections.addAll(changedPackages, uidPackageNames);
if (callbackSpecs == null) {
@@ -2041,6 +2059,10 @@ public class AppOpsService extends IAppOpsService.Stub {
final int callbackCount = callbacks.size();
for (int i = 0; i < callbackCount; i++) {
ModeCallback callback = callbacks.valueAt(i);
if (onlyForeground && (callback.mFlags & WATCH_FOREGROUND_CHANGES) == 0) {
continue;
}
ArraySet<String> changedPackages = callbackSpecs.get(callback);
if (changedPackages == null) {
changedPackages = new ArraySet<>();
@@ -2057,7 +2079,6 @@ public class AppOpsService extends IAppOpsService.Stub {
}
if (callbackSpecs == null) {
notifyOpChangedSync(code, uid, null, mode);
return;
}
@@ -2079,8 +2100,6 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
}
notifyOpChangedSync(code, uid, null, mode);
}
private void updatePermissionRevokedCompat(int uid, int switchCode, int mode) {
@@ -3356,24 +3375,28 @@ public class AppOpsService extends IAppOpsService.Stub {
&& uidState.appWidgetVisible == uidState.pendingAppWidgetVisible) {
continue;
}
final ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code);
if (callbacks != null) {
for (int cbi = callbacks.size() - 1; cbi >= 0; cbi--) {
final ModeCallback callback = callbacks.valueAt(cbi);
if ((callback.mFlags & AppOpsManager.WATCH_FOREGROUND_CHANGES) == 0
|| !callback.isWatchingUid(uidState.uid)) {
continue;
}
boolean doAllPackages = uidState.opModes != null
&& uidState.opModes.indexOfKey(code) >= 0
&& uidState.opModes.get(code) == AppOpsManager.MODE_FOREGROUND;
if (uidState.pkgOps != null) {
if (uidState.opModes != null
&& uidState.opModes.indexOfKey(code) >= 0
&& uidState.opModes.get(code) == AppOpsManager.MODE_FOREGROUND) {
mHandler.sendMessage(PooledLambda.obtainMessage(
AppOpsService::notifyOpChangedForAllPkgsInUid,
this, code, uidState.uid, true, null));
} else {
final ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code);
if (callbacks != null) {
for (int cbi = callbacks.size() - 1; cbi >= 0; cbi--) {
final ModeCallback callback = callbacks.valueAt(cbi);
if ((callback.mFlags & AppOpsManager.WATCH_FOREGROUND_CHANGES) == 0
|| !callback.isWatchingUid(uidState.uid)) {
continue;
}
for (int pkgi = uidState.pkgOps.size() - 1; pkgi >= 0; pkgi--) {
final Op op = uidState.pkgOps.valueAt(pkgi).get(code);
if (op == null) {
continue;
}
if (doAllPackages || op.mode == AppOpsManager.MODE_FOREGROUND) {
if (op.mode == AppOpsManager.MODE_FOREGROUND) {
mHandler.sendMessage(PooledLambda.obtainMessage(
AppOpsService::notifyOpChanged,
this, callback, code, uidState.uid,