diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 9d6fc9ed85c26..6df6c7355e3b7 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -135,6 +135,7 @@ + diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java index c013df385987d..ace086f7af2c2 100644 --- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java @@ -20,6 +20,7 @@ import static com.android.systemui.Dependency.BG_LOOPER_NAME; import android.app.AppOpsManager; import android.content.Context; +import android.content.pm.PackageManager; import android.os.Handler; import android.os.Looper; import android.os.UserHandle; @@ -202,27 +203,38 @@ public class AppOpsControllerImpl implements AppOpsController, mBGHandler.scheduleRemoval(item, NOTED_OP_TIME_DELAY_MS); } + /** + * Does the app-op item refer to a user sensitive permission. Only user sensitive permission + * should be shown to the user by default. + * + * @param item The item + * + * @return {@code true} iff the app-op item is user sensitive + */ + private boolean isUserSensitive(AppOpItem item) { + String permission = AppOpsManager.opToPermission(item.getCode()); + if (permission == null) { + return false; + } + int permFlags = mContext.getPackageManager().getPermissionFlags(permission, + item.getPackageName(), UserHandle.getUserHandleForUid(item.getUid())); + return (permFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) != 0; + } + /** * Returns a copy of the list containing all the active AppOps that the controller tracks. * * @return List of active AppOps information */ public List getActiveAppOps() { - ArrayList active; - synchronized (mActiveItems) { - active = new ArrayList<>(mActiveItems); - } - synchronized (mNotedItems) { - active.addAll(mNotedItems); - } - return active; + return getActiveAppOpsForUser(UserHandle.USER_ALL); } /** * Returns a copy of the list containing all the active AppOps that the controller tracks, for * a given user id. * - * @param userId User id to track + * @param userId User id to track, can be {@link UserHandle#USER_ALL} * * @return List of active AppOps information for that user id */ @@ -232,7 +244,8 @@ public class AppOpsControllerImpl implements AppOpsController, final int numActiveItems = mActiveItems.size(); for (int i = 0; i < numActiveItems; i++) { AppOpItem item = mActiveItems.get(i); - if (UserHandle.getUserId(item.getUid()) == userId) { + if ((userId == UserHandle.USER_ALL || UserHandle.getUserId(item.getUid()) == userId) + && isUserSensitive(item)) { list.add(item); } } @@ -241,7 +254,8 @@ public class AppOpsControllerImpl implements AppOpsController, final int numNotedItems = mNotedItems.size(); for (int i = 0; i < numNotedItems; i++) { AppOpItem item = mNotedItems.get(i); - if (UserHandle.getUserId(item.getUid()) == userId) { + if ((userId == UserHandle.USER_ALL || UserHandle.getUserId(item.getUid()) == userId) + && isUserSensitive(item)) { list.add(item); } } 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 73ee0bdfc6194..b9afea155ccf9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java @@ -22,11 +22,14 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.app.AppOpsManager; +import android.content.pm.PackageManager; import android.os.UserHandle; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -47,12 +50,15 @@ import org.mockito.MockitoAnnotations; @TestableLooper.RunWithLooper public class AppOpsControllerTest extends SysuiTestCase { private static final String TEST_PACKAGE_NAME = "test"; - private static final int TEST_UID = 0; - private static final int TEST_UID_OTHER = 500000; + 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); @Mock private AppOpsManager mAppOpsManager; @Mock + private PackageManager mPackageManager; + @Mock private AppOpsController.Callback mCallback; @Mock private AppOpsControllerImpl.H mMockHandler; @@ -65,6 +71,18 @@ public class AppOpsControllerTest extends SysuiTestCase { 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(mPackageManager.getPermissionFlags(anyString(), anyString(), + eq(UserHandle.getUserHandleForUid(TEST_UID)))).thenReturn( + PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED); + when(mPackageManager.getPermissionFlags(anyString(), anyString(), + eq(UserHandle.getUserHandleForUid(TEST_UID_OTHER)))).thenReturn( + PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED); + when(mPackageManager.getPermissionFlags(anyString(), anyString(), + eq(UserHandle.getUserHandleForUid(TEST_UID_NON_USER_SENSITIVE)))).thenReturn(0); + mController = new AppOpsControllerImpl(mContext, Dependency.get(Dependency.BG_LOOPER)); } @@ -156,6 +174,14 @@ public class AppOpsControllerTest extends SysuiTestCase { mController.getActiveAppOpsForUser(UserHandle.getUserId(TEST_UID_OTHER)).size()); } + @Test + public void nonUserSensitiveOpsAreIgnored() { + mController.onOpActiveChanged(AppOpsManager.OP_RECORD_AUDIO, + TEST_UID_NON_USER_SENSITIVE, TEST_PACKAGE_NAME, true); + assertEquals(0, mController.getActiveAppOpsForUser( + UserHandle.getUserId(TEST_UID_NON_USER_SENSITIVE)).size()); + } + @Test public void opNotedScheduledForRemoval() { mController.setBGHandler(mMockHandler);