From 2d400b8737a020db94f43e90b20a2600fb2949d5 Mon Sep 17 00:00:00 2001 From: Nate Myren Date: Wed, 7 Apr 2021 08:32:39 -0700 Subject: [PATCH] Exclude only system and device intelligence roles from indicators Converts both the AppOpsControllerImpl and the PermissionUsageHelper to use the same static method when filtering which packages to show. The only packages which are filtered are 6 device intelligence roles, and the system package. These values are updated at most every 15 seconds Fixes: 184141707 Test: manual Change-Id: I9dc44197a2ff3df7783b37f450ada4ef2fb1ca6f --- .../android/permission/PermissionManager.java | 47 ++++-- .../permission/PermissionUsageHelper.java | 27 +--- .../systemui/appops/AppOpsControllerImpl.java | 120 +-------------- .../systemui/appops/PermissionFlagsCache.kt | 88 ----------- .../systemui/appops/AppOpsControllerTest.java | 31 ++-- .../appops/PermissionFlagsCacheTest.kt | 145 ------------------ 6 files changed, 64 insertions(+), 394 deletions(-) delete mode 100644 packages/SystemUI/src/com/android/systemui/appops/PermissionFlagsCache.kt delete mode 100644 packages/SystemUI/tests/src/com/android/systemui/appops/PermissionFlagsCacheTest.kt diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java index 751e9aafdf094..1a40f0640a8d7 100644 --- a/core/java/android/permission/PermissionManager.java +++ b/core/java/android/permission/PermissionManager.java @@ -35,6 +35,7 @@ import android.app.IActivityManager; import android.app.PropertyInvalidatedCache; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; +import android.content.AttributionSource; import android.content.Context; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; @@ -42,9 +43,7 @@ import android.content.pm.ParceledListSlice; import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; import android.content.pm.permission.SplitPermissionInfoParcelable; -import android.location.LocationManager; import android.media.AudioManager; -import android.content.AttributionSource; import android.os.Build; import android.os.Handler; import android.os.Looper; @@ -52,8 +51,8 @@ import android.os.Message; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.SystemClock; import android.os.UserHandle; -import android.provider.DeviceConfig; import android.util.ArrayMap; import android.util.ArraySet; import android.util.DebugUtils; @@ -103,6 +102,20 @@ public final class PermissionManager { @EnabledAfter(targetSdkVersion = S) public static final long CANNOT_INSTALL_WITH_BAD_PERMISSION_GROUPS = 146211400; + /** + * The time to wait in between refreshing the exempted indicator role packages + */ + private static final long EXEMPTED_INDICATOR_ROLE_UPDATE_FREQUENCY_MS = 15000; + + private static long sLastIndicatorUpdateTime = -1; + + private static final int[] EXEMPTED_ROLES = {R.string.config_systemAmbientAudioIntelligence, + R.string.config_systemUiIntelligence, R.string.config_systemAudioIntelligence, + R.string.config_systemNotificationIntelligence, R.string.config_systemTextIntelligence, + R.string.config_systemVisualIntelligence}; + + private static final String[] INDICATOR_EXEMPTED_PACKAGES = new String[EXEMPTED_ROLES.length]; + /** * Note: Changing this won't do anything on its own - you should also change the filtering in * {@link #shouldTraceGrant}. @@ -873,21 +886,31 @@ public final class PermissionManager { } /** - * Check if this package/op combination is exempted from indicators - * @return + * Determine if a package should be shown in indicators. Only a select few roles, and the + * system app itself, are hidden. These values are updated at most every 15 seconds. * @hide */ - public static boolean isSpecialCaseShownIndicator(@NonNull Context context, + public static boolean shouldShowPackageForIndicatorCached(@NonNull Context context, @NonNull String packageName) { - - if (packageName.equals(SYSTEM_PKG)) { + if (SYSTEM_PKG.equals(packageName)) { return false; } + long now = SystemClock.elapsedRealtime(); + if (sLastIndicatorUpdateTime == -1 + || (now - sLastIndicatorUpdateTime) > EXEMPTED_INDICATOR_ROLE_UPDATE_FREQUENCY_MS) { + sLastIndicatorUpdateTime = now; + for (int i = 0; i < EXEMPTED_ROLES.length; i++) { + INDICATOR_EXEMPTED_PACKAGES[i] = context.getString(EXEMPTED_ROLES[i]); + } + } + for (int i = 0; i < EXEMPTED_ROLES.length; i++) { + String exemptedPackage = INDICATOR_EXEMPTED_PACKAGES[i]; + if (exemptedPackage != null && exemptedPackage.equals(packageName)) { + return false; + } + } - return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, "permissions_hub_2_enabled", - false) - || packageName.equals(context.getString(R.string.config_systemSpeechRecognizer)) - || context.getSystemService(LocationManager.class).isProviderPackage(packageName); + return true; } /** * Gets the list of packages that have permissions that specified diff --git a/core/java/android/permission/PermissionUsageHelper.java b/core/java/android/permission/PermissionUsageHelper.java index b427df7256639..53ba25924d3d7 100644 --- a/core/java/android/permission/PermissionUsageHelper.java +++ b/core/java/android/permission/PermissionUsageHelper.java @@ -26,8 +26,6 @@ import static android.app.AppOpsManager.OPSTR_PHONE_CALL_CAMERA; import static android.app.AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE; import static android.app.AppOpsManager.OPSTR_RECORD_AUDIO; import static android.app.AppOpsManager.OP_FLAGS_ALL_TRUSTED; -import static android.app.AppOpsManager.opToPermission; -import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED; import static android.media.AudioSystem.MODE_IN_COMMUNICATION; import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; @@ -284,10 +282,6 @@ public class PermissionUsageHelper { continue; } - if (!shouldShowPermissionsHub() && !isUserSensitive(packageName, user, op)) { - continue; - } - boolean isRunning = attrOpEntry.isRunning() || lastAccessTime >= runningThreshold; @@ -375,7 +369,7 @@ public class PermissionUsageHelper { // for it's uid and package name, save it. int usageId = usage.getPackageIdHash(); OpUsage lastMostRecent = mostRecentUsages.get(usageId); - if (!usage.packageName.equals(SYSTEM_PKG) && (lastMostRecent == null + if (shouldShowPackage(usage.packageName) && (lastMostRecent == null || usage.lastAccessTime > lastMostRecent.lastAccessTime)) { mostRecentUsages.put(usageId, usage); } @@ -401,8 +395,7 @@ public class PermissionUsageHelper { // We are missing the proxy usage. This may be because it's a one-step trusted // proxy. Check if we should show the proxy label, and show it, if so. OpUsage proxy = currentUsage.proxy; - if (PermissionManager.isSpecialCaseShownIndicator(mContext, proxy.packageName) - || isUserSensitive(proxy.packageName, proxy.getUser(), proxy.op)) { + if (shouldShowPackage(proxy.packageName)) { currentUsage = proxy; // We've effectively added one usage, so increment the max number of usages maxUsages++; @@ -411,7 +404,6 @@ public class PermissionUsageHelper { } } - if (currentUsage == null || iterNum == maxUsages || currentUsage.getPackageIdHash() == start.getPackageIdHash()) { // We have an invalid state, or a cycle, so break @@ -421,7 +413,7 @@ public class PermissionUsageHelper { proxyPackages.add(currentUsage.getPackageIdHash()); // Don't add an app label for the main app, or the system app if (!currentUsage.packageName.equals(start.packageName) - && !currentUsage.packageName.equals(SYSTEM_PKG)) { + && shouldShowPackage(currentUsage.packageName)) { try { PackageManager userPkgManager = getUserContext(currentUsage.getUser()).getPackageManager(); @@ -451,17 +443,8 @@ public class PermissionUsageHelper { return usagesAndLabels; } - private boolean isUserSensitive(String packageName, UserHandle user, String op) { - if (op.equals(OPSTR_PHONE_CALL_CAMERA) || op.equals(OPSTR_PHONE_CALL_MICROPHONE)) { - return true; - } - - if (opToPermission(op) == null) { - return false; - } - - int permFlags = mPkgManager.getPermissionFlags(opToPermission(op), packageName, user); - return (permFlags & FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) != 0; + private boolean shouldShowPackage(String packageName) { + return PermissionManager.shouldShowPackageForIndicatorCached(mContext, packageName); } /** diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java index 74f855b02a43e..994401db43801 100644 --- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java @@ -25,24 +25,20 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.location.LocationManager; import android.media.AudioManager; import android.media.AudioRecordingConfiguration; import android.os.Handler; import android.os.Looper; import android.os.UserHandle; -import android.provider.DeviceConfig; +import android.permission.PermissionManager; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import androidx.annotation.WorkerThread; -import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.systemui.Dumpable; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; @@ -83,19 +79,12 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon private final Context mContext; private final AppOpsManager mAppOps; private final AudioManager mAudioManager; - private final LocationManager mLocationManager; private final IndividualSensorPrivacyController mSensorPrivacyController; private final SystemClock mClock; - // mLocationProviderPackages are cached and updated only occasionally - private static final long LOCATION_PROVIDER_UPDATE_FREQUENCY_MS = 30000; - private long mLastLocationProviderPackageUpdate; - private List mLocationProviderPackages; - private H mBGHandler; private final List mCallbacks = new ArrayList<>(); private final SparseArray> mCallbacksByCode = new SparseArray<>(); - private final PermissionFlagsCache mFlagsCache; private boolean mListening; private boolean mMicMuted; private boolean mCameraDisabled; @@ -124,7 +113,6 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon Context context, @Background Looper bgLooper, DumpManager dumpManager, - PermissionFlagsCache cache, AudioManager audioManager, IndividualSensorPrivacyController sensorPrivacyController, BroadcastDispatcher dispatcher, @@ -132,7 +120,6 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon ) { mDispatcher = dispatcher; mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); - mFlagsCache = cache; mBGHandler = new H(bgLooper); final int numOps = OPS.length; for (int i = 0; i < numOps; i++) { @@ -143,7 +130,6 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon mMicMuted = audioManager.isMicrophoneMute() || mSensorPrivacyController.isSensorBlocked(MICROPHONE); mCameraDisabled = mSensorPrivacyController.isSensorBlocked(CAMERA); - mLocationManager = context.getSystemService(LocationManager.class); mContext = context; mClock = clock; dumpManager.registerDumpable(TAG, this); @@ -308,102 +294,8 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon return createdNew; } - /** - * Does the app-op code refer to a user sensitive permission for the specified user id - * and package. Only user sensitive permission should be shown to the user by default. - * - * @param appOpCode The code of the app-op. - * @param uid The uid of the user. - * @param packageName The name of the package. - * - * @return {@code true} iff the app-op item is user sensitive - */ - private boolean isUserSensitive(int appOpCode, int uid, String packageName) { - String permission = AppOpsManager.opToPermission(appOpCode); - if (permission == null) { - return false; - } - int permFlags = mFlagsCache.getPermissionFlags(permission, - packageName, uid); - return (permFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) != 0; - } - - /** - * Does the app-op item refer to an operation that should be shown to the user. - * Only specficic ops (like SYSTEM_ALERT_WINDOW) or ops that refer to user sensitive - * permission should be shown to the user by default. - * - * @param item The item - * - * @return {@code true} iff the app-op item should be shown to the user - */ - private boolean isUserVisible(AppOpItem item) { - return isUserVisible(item.getCode(), item.getUid(), item.getPackageName()); - } - - /** - * Checks if a package is the current location provider. - * - *

Data is cached to avoid too many calls into system server - * - * @param packageName The package that might be the location provider - * - * @return {@code true} iff the package is the location provider. - */ - private boolean isLocationProvider(String packageName) { - long now = System.currentTimeMillis(); - - if (mLastLocationProviderPackageUpdate + LOCATION_PROVIDER_UPDATE_FREQUENCY_MS < now) { - mLastLocationProviderPackageUpdate = now; - mLocationProviderPackages = mLocationManager.getProviderPackages( - LocationManager.FUSED_PROVIDER); - } - - return mLocationProviderPackages.contains(packageName); - } - - private boolean isSpeechRecognizerUsage(int opCode, String packageName) { - if (AppOpsManager.OP_RECORD_AUDIO != opCode) { - return false; - } - - return packageName.equals( - mContext.getString(R.string.config_systemSpeechRecognizer)); - } - - // TODO ntmyren: remove after teamfood is finished - private boolean showSystemApps() { - return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, - SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED, false); - } - - /** - * Does the app-op, uid and package name, refer to an operation that should be shown to the - * user. Only specficic ops (like {@link AppOpsManager.OP_SYSTEM_ALERT_WINDOW}) or - * ops that refer to user sensitive permission should be shown to the user by default. - * - * @param item The item - * - * @return {@code true} iff the app-op for should be shown to the user - */ - private boolean isUserVisible(int appOpCode, int uid, String packageName) { - // currently OP_SYSTEM_ALERT_WINDOW and OP_MONITOR_HIGH_POWER_LOCATION - // does not correspond to a platform permission - // which may be user sensitive, so for now always show it to the user. - if (appOpCode == AppOpsManager.OP_SYSTEM_ALERT_WINDOW - || appOpCode == AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION - || appOpCode == AppOpsManager.OP_PHONE_CALL_CAMERA - || appOpCode == AppOpsManager.OP_PHONE_CALL_MICROPHONE) { - return true; - } - // TODO ntmyren: Replace this with more robust check if this moves beyond teamfood - if (((showSystemApps() && !packageName.equals("android")) - || appOpCode == AppOpsManager.OP_CAMERA && isLocationProvider(packageName)) - || isSpeechRecognizerUsage(appOpCode, packageName)) { - return true; - } - - return isUserSensitive(appOpCode, uid, packageName); + private boolean isUserVisible(String packageName) { + return PermissionManager.shouldShowPackageForIndicatorCached(mContext, packageName); } /** @@ -438,7 +330,7 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon AppOpItem item = mActiveItems.get(i); if ((userId == UserHandle.USER_ALL || UserHandle.getUserId(item.getUid()) == userId) - && isUserVisible(item) && !item.isDisabled()) { + && isUserVisible(item.getPackageName()) && !item.isDisabled()) { list.add(item); } } @@ -449,7 +341,7 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon AppOpItem item = mNotedItems.get(i); if ((userId == UserHandle.USER_ALL || UserHandle.getUserId(item.getUid()) == userId) - && isUserVisible(item)) { + && isUserVisible(item.getPackageName())) { list.add(item); } } @@ -503,7 +395,7 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon } private void notifySuscribersWorker(int code, int uid, String packageName, boolean active) { - if (mCallbacksByCode.contains(code) && isUserVisible(code, uid, packageName)) { + if (mCallbacksByCode.contains(code) && isUserVisible(packageName)) { if (DEBUG) Log.d(TAG, "Notifying of change in package " + packageName); for (Callback cb: mCallbacksByCode.get(code)) { cb.onActiveStateChanged(code, uid, packageName, active); diff --git a/packages/SystemUI/src/com/android/systemui/appops/PermissionFlagsCache.kt b/packages/SystemUI/src/com/android/systemui/appops/PermissionFlagsCache.kt deleted file mode 100644 index 3fd838be781de..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/appops/PermissionFlagsCache.kt +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.systemui.appops - -import android.content.pm.PackageManager -import android.os.UserHandle -import androidx.annotation.WorkerThread -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.Background -import com.android.systemui.util.Assert -import java.util.concurrent.Executor -import javax.inject.Inject - -private data class PermissionFlagKey( - val permission: String, - val packageName: String, - val uid: Int -) - -/** - * Cache for PackageManager's PermissionFlags. - * - * After a specific `{permission, package, uid}` has been requested, updates to it will be tracked, - * and changes to the uid will trigger new requests (in the background). - */ -@SysUISingleton -class PermissionFlagsCache @Inject constructor( - private val packageManager: PackageManager, - @Background private val executor: Executor -) : PackageManager.OnPermissionsChangedListener { - - private val permissionFlagsCache = - mutableMapOf>() - private var listening = false - - override fun onPermissionsChanged(uid: Int) { - executor.execute { - // Only track those that we've seen before - val keys = permissionFlagsCache.get(uid) - if (keys != null) { - keys.mapValuesTo(keys) { - getFlags(it.key) - } - } - } - } - - /** - * Retrieve permission flags from cache or PackageManager. There parameters will be passed - * directly to [PackageManager]. - * - * Calls to this method should be done from a background thread (though it will only be - * enforced if the cache is not hit). - */ - @WorkerThread - fun getPermissionFlags(permission: String, packageName: String, uid: Int): Int { - if (!listening) { - listening = true - packageManager.addOnPermissionsChangeListener(this) - } - val key = PermissionFlagKey(permission, packageName, uid) - return permissionFlagsCache.getOrPut(uid, { mutableMapOf() }).get(key) ?: run { - getFlags(key).also { - Assert.isNotMainThread() - permissionFlagsCache.get(uid)?.put(key, it) - } - } - } - - private fun getFlags(key: PermissionFlagKey): Int { - return packageManager.getPermissionFlags(key.permission, key.packageName, - UserHandle.getUserHandleForUid(key.uid)) - } -} \ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java index 8252ff48bd816..3f0831cadd1f0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java @@ -24,6 +24,7 @@ import static junit.framework.TestCase.assertFalse; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeFalse; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; @@ -49,6 +50,7 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; +import com.android.internal.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dump.DumpManager; @@ -71,6 +73,7 @@ import java.util.List; public class AppOpsControllerTest extends SysuiTestCase { private static final String TEST_PACKAGE_NAME = "test"; private static final String TEST_ATTRIBUTION_NAME = "attribution"; + private static final String SYSTEM_PKG = "android"; private static final int TEST_UID = UserHandle.getUid(0, 0); private static final int TEST_UID_OTHER = UserHandle.getUid(1, 0); private static final int TEST_UID_NON_USER_SENSITIVE = UserHandle.getUid(2, 0); @@ -84,8 +87,6 @@ public class AppOpsControllerTest extends SysuiTestCase { @Mock private DumpManager mDumpManager; @Mock - private PermissionFlagsCache mFlagsCache; - @Mock private PackageManager mPackageManager; @Mock private IndividualSensorPrivacyController mSensorPrivacyController; @@ -101,22 +102,19 @@ public class AppOpsControllerTest extends SysuiTestCase { private AppOpsControllerImpl mController; private TestableLooper mTestableLooper; + private String mExemptedRolePkgName; + @Before public void setUp() { MockitoAnnotations.initMocks(this); mTestableLooper = TestableLooper.get(this); + mExemptedRolePkgName = getContext().getString(R.string.config_systemUiIntelligence); getContext().addMockSystemService(AppOpsManager.class, mAppOpsManager); // All permissions of TEST_UID and TEST_UID_OTHER are user sensitive. None of // TEST_UID_NON_USER_SENSITIVE are user sensitive. getContext().setMockPackageManager(mPackageManager); - when(mFlagsCache.getPermissionFlags(anyString(), anyString(), eq(TEST_UID))).thenReturn( - PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED); - when(mFlagsCache.getPermissionFlags(anyString(), anyString(), eq(TEST_UID_OTHER))) - .thenReturn(PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED); - when(mFlagsCache.getPermissionFlags(anyString(), anyString(), - eq(TEST_UID_NON_USER_SENSITIVE))).thenReturn(0); doAnswer((invocation) -> mRecordingCallback = invocation.getArgument(0)) .when(mAudioManager).registerAudioRecordingCallback(any(), any()); @@ -135,7 +133,6 @@ public class AppOpsControllerTest extends SysuiTestCase { mContext, mTestableLooper.getLooper(), mDumpManager, - mFlagsCache, mAudioManager, mSensorPrivacyController, mDispatcher, @@ -242,18 +239,26 @@ public class AppOpsControllerTest extends SysuiTestCase { } @Test - public void nonUserSensitiveOpsAreIgnored() { + public void systemAndExemptedRolesAreIgnored() { + assumeFalse(mExemptedRolePkgName == null || mExemptedRolePkgName.equals("")); + mController.onOpActiveChanged(AppOpsManager.OP_RECORD_AUDIO, - TEST_UID_NON_USER_SENSITIVE, TEST_PACKAGE_NAME, true); + TEST_UID_NON_USER_SENSITIVE, mExemptedRolePkgName, true); + assertEquals(0, mController.getActiveAppOpsForUser( + UserHandle.getUserId(TEST_UID_NON_USER_SENSITIVE)).size()); + mController.onOpActiveChanged(AppOpsManager.OP_RECORD_AUDIO, + TEST_UID_NON_USER_SENSITIVE, SYSTEM_PKG, true); assertEquals(0, mController.getActiveAppOpsForUser( UserHandle.getUserId(TEST_UID_NON_USER_SENSITIVE)).size()); } @Test - public void nonUserSensitiveOpsNotNotified() { + public void exemptedRoleNotNotified() { + assumeFalse(mExemptedRolePkgName == null || mExemptedRolePkgName.equals("")); + mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback); mController.onOpActiveChanged(AppOpsManager.OP_RECORD_AUDIO, - TEST_UID_NON_USER_SENSITIVE, TEST_PACKAGE_NAME, true); + TEST_UID_NON_USER_SENSITIVE, mExemptedRolePkgName, true); mTestableLooper.processAllMessages(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/PermissionFlagsCacheTest.kt b/packages/SystemUI/tests/src/com/android/systemui/appops/PermissionFlagsCacheTest.kt deleted file mode 100644 index 0fb0ce087ee38..0000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/appops/PermissionFlagsCacheTest.kt +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.systemui.appops - -import android.content.pm.PackageManager -import android.os.UserHandle -import android.testing.AndroidTestingRunner -import androidx.test.filters.SmallTest -import com.android.systemui.SysuiTestCase -import com.android.systemui.util.concurrency.FakeExecutor -import com.android.systemui.util.time.FakeSystemClock -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotEquals -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.ArgumentMatchers.any -import org.mockito.ArgumentMatchers.anyString -import org.mockito.Mock -import org.mockito.Mockito.`when` -import org.mockito.Mockito.never -import org.mockito.Mockito.times -import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations - -@SmallTest -@RunWith(AndroidTestingRunner::class) -class PermissionFlagsCacheTest : SysuiTestCase() { - - companion object { - const val TEST_PERMISSION = "test_permission" - const val TEST_PACKAGE = "test_package" - const val TEST_UID1 = 1000 - const val TEST_UID2 = UserHandle.PER_USER_RANGE + 1000 - } - - @Mock - private lateinit var packageManager: PackageManager - - private lateinit var executor: FakeExecutor - private lateinit var flagsCache: PermissionFlagsCache - - @Before - fun setUp() { - MockitoAnnotations.initMocks(this) - - executor = FakeExecutor(FakeSystemClock()) - - flagsCache = PermissionFlagsCache(packageManager, executor) - executor.runAllReady() - } - - @Test - fun testNotListeningByDefault() { - verify(packageManager, never()).addOnPermissionsChangeListener(any()) - } - - @Test - fun testGetCorrectFlags() { - `when`(packageManager.getPermissionFlags(anyString(), anyString(), any())).thenReturn(0) - `when`(packageManager.getPermissionFlags( - TEST_PERMISSION, - TEST_PACKAGE, - UserHandle.getUserHandleForUid(TEST_UID1)) - ).thenReturn(1) - - assertEquals(1, flagsCache.getPermissionFlags(TEST_PERMISSION, TEST_PACKAGE, TEST_UID1)) - assertNotEquals(1, flagsCache.getPermissionFlags(TEST_PERMISSION, TEST_PACKAGE, TEST_UID2)) - } - - @Test - fun testFlagIsCached() { - flagsCache.getPermissionFlags(TEST_PERMISSION, TEST_PACKAGE, TEST_UID1) - - flagsCache.getPermissionFlags(TEST_PERMISSION, TEST_PACKAGE, TEST_UID1) - - verify(packageManager, times(1)).getPermissionFlags( - TEST_PERMISSION, - TEST_PACKAGE, - UserHandle.getUserHandleForUid(TEST_UID1) - ) - } - - @Test - fun testListeningAfterFirstRequest() { - flagsCache.getPermissionFlags(TEST_PERMISSION, TEST_PACKAGE, TEST_UID1) - - verify(packageManager).addOnPermissionsChangeListener(any()) - } - - @Test - fun testListeningOnlyOnce() { - flagsCache.getPermissionFlags(TEST_PERMISSION, TEST_PACKAGE, TEST_UID1) - - flagsCache.getPermissionFlags(TEST_PERMISSION, TEST_PACKAGE, TEST_UID2) - - verify(packageManager, times(1)).addOnPermissionsChangeListener(any()) - } - - @Test - fun testUpdateFlag() { - assertEquals(0, flagsCache.getPermissionFlags(TEST_PERMISSION, TEST_PACKAGE, TEST_UID1)) - - `when`(packageManager.getPermissionFlags( - TEST_PERMISSION, - TEST_PACKAGE, - UserHandle.getUserHandleForUid(TEST_UID1)) - ).thenReturn(1) - - flagsCache.onPermissionsChanged(TEST_UID1) - - executor.runAllReady() - - assertEquals(1, flagsCache.getPermissionFlags(TEST_PERMISSION, TEST_PACKAGE, TEST_UID1)) - } - - @Test - fun testUpdateFlag_notUpdatedIfUidHasNotBeenRequestedBefore() { - flagsCache.getPermissionFlags(TEST_PERMISSION, TEST_PACKAGE, TEST_UID1) - - flagsCache.onPermissionsChanged(TEST_UID2) - - executor.runAllReady() - - verify(packageManager, never()).getPermissionFlags( - TEST_PERMISSION, - TEST_PACKAGE, - UserHandle.getUserHandleForUid(TEST_UID2) - ) - } -} \ No newline at end of file