Merge "Do not hold indicators for apps that become paused" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-04-15 21:35:10 +00:00
committed by Android (Google) Code Review
10 changed files with 252 additions and 61 deletions

View File

@@ -2010,6 +2010,7 @@ package android.permission {
public final class PermissionManager { public final class PermissionManager {
method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData(); method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData();
method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData(boolean);
method @NonNull public android.content.AttributionSource registerAttributionSource(@NonNull android.content.AttributionSource); method @NonNull public android.content.AttributionSource registerAttributionSource(@NonNull android.content.AttributionSource);
} }

View File

@@ -885,6 +885,24 @@ public final class PermissionManager {
return mUsageHelper.getOpUsageData(new AudioManager().isMicrophoneMute()); return mUsageHelper.getOpUsageData(new AudioManager().isMicrophoneMute());
} }
/**
* @param micMuted whether to consider the microphone muted when retrieving audio ops
* @return A list of permission groups currently or recently used by all apps by all users in
* the current profile group.
*
* @hide
*/
@TestApi
@NonNull
@RequiresPermission(Manifest.permission.GET_APP_OPS_STATS)
public List<PermGroupUsage> getIndicatorAppOpUsageData(boolean micMuted) {
// Lazily initialize the usage helper
if (mUsageHelper == null) {
mUsageHelper = new PermissionUsageHelper(mContext);
}
return mUsageHelper.getOpUsageData(micMuted);
}
/** /**
* Determine if a package should be shown in indicators. Only a select few roles, and the * 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. * system app itself, are hidden. These values are updated at most every 15 seconds.

View File

@@ -60,17 +60,31 @@ public interface AppOpsController {
/** /**
* Returns a copy of the list containing all the active AppOps that the controller tracks. * Returns a copy of the list containing all the active AppOps that the controller tracks.
* *
* @return List of active AppOps information * @return List of active AppOps information, without paused elements.
*/ */
List<AppOpItem> getActiveAppOps(); List<AppOpItem> getActiveAppOps();
/**
* Returns a copy of the list containing all the active AppOps that the controller tracks.
*
* @param showPaused {@code true} to also obtain paused items. {@code false} otherwise.
* @return List of active AppOps information
*/
List<AppOpItem> getActiveAppOps(boolean showPaused);
/** /**
* Returns a copy of the list containing all the active AppOps that the controller tracks, for * Returns a copy of the list containing all the active AppOps that the controller tracks, for
* a given user id. * a given user id.
* *
* @param userId User id to track * @param userId User id to track
* @param showPaused {@code true} to also obtain paused items. {@code false} otherwise.
* *
* @return List of active AppOps information for that user id * @return List of active AppOps information for that user id
*/ */
List<AppOpItem> getActiveAppOpsForUser(int userId); List<AppOpItem> getActiveAppOpsForUser(int userId, boolean showPaused);
/**
* @return whether this controller is considering the microphone as muted.
*/
boolean isMicMuted();
} }

View File

@@ -241,9 +241,9 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
AppOpItem item = getAppOpItemLocked(mActiveItems, code, uid, packageName); AppOpItem item = getAppOpItemLocked(mActiveItems, code, uid, packageName);
if (item == null && active) { if (item == null && active) {
item = new AppOpItem(code, uid, packageName, mClock.elapsedRealtime()); item = new AppOpItem(code, uid, packageName, mClock.elapsedRealtime());
if (code == AppOpsManager.OP_RECORD_AUDIO) { if (isOpMicrophone(code)) {
item.setDisabled(isAnyRecordingPausedLocked(uid)); item.setDisabled(isAnyRecordingPausedLocked(uid));
} else if (code == AppOpsManager.OP_CAMERA) { } else if (isOpCamera(code)) {
item.setDisabled(mCameraDisabled); item.setDisabled(mCameraDisabled);
} }
mActiveItems.add(item); mActiveItems.add(item);
@@ -298,6 +298,11 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
return PermissionManager.shouldShowPackageForIndicatorCached(mContext, packageName); return PermissionManager.shouldShowPackageForIndicatorCached(mContext, packageName);
} }
@WorkerThread
public List<AppOpItem> getActiveAppOps() {
return getActiveAppOps(false);
}
/** /**
* Returns a copy of the list containing all the active AppOps that the controller tracks. * Returns a copy of the list containing all the active AppOps that the controller tracks.
* *
@@ -306,8 +311,8 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
* @return List of active AppOps information * @return List of active AppOps information
*/ */
@WorkerThread @WorkerThread
public List<AppOpItem> getActiveAppOps() { public List<AppOpItem> getActiveAppOps(boolean showPaused) {
return getActiveAppOpsForUser(UserHandle.USER_ALL); return getActiveAppOpsForUser(UserHandle.USER_ALL, showPaused);
} }
/** /**
@@ -321,7 +326,7 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
* @return List of active AppOps information for that user id * @return List of active AppOps information for that user id
*/ */
@WorkerThread @WorkerThread
public List<AppOpItem> getActiveAppOpsForUser(int userId) { public List<AppOpItem> getActiveAppOpsForUser(int userId, boolean showPaused) {
Assert.isNotMainThread(); Assert.isNotMainThread();
List<AppOpItem> list = new ArrayList<>(); List<AppOpItem> list = new ArrayList<>();
synchronized (mActiveItems) { synchronized (mActiveItems) {
@@ -330,7 +335,8 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
AppOpItem item = mActiveItems.get(i); AppOpItem item = mActiveItems.get(i);
if ((userId == UserHandle.USER_ALL if ((userId == UserHandle.USER_ALL
|| UserHandle.getUserId(item.getUid()) == userId) || UserHandle.getUserId(item.getUid()) == userId)
&& isUserVisible(item.getPackageName()) && !item.isDisabled()) { && isUserVisible(item.getPackageName())
&& (showPaused || !item.isDisabled())) {
list.add(item); list.add(item);
} }
} }
@@ -441,9 +447,9 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
AppOpItem item = mActiveItems.get(i); AppOpItem item = mActiveItems.get(i);
boolean paused = false; boolean paused = false;
if (item.getCode() == AppOpsManager.OP_RECORD_AUDIO) { if (isOpMicrophone(item.getCode())) {
paused = isAnyRecordingPausedLocked(item.getUid()); paused = isAnyRecordingPausedLocked(item.getUid());
} else if (item.getCode() == AppOpsManager.OP_CAMERA) { } else if (isOpCamera(item.getCode())) {
paused = mCameraDisabled; paused = mCameraDisabled;
} }
@@ -502,6 +508,19 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
}); });
} }
@Override
public boolean isMicMuted() {
return mMicMuted;
}
private boolean isOpCamera(int op) {
return op == AppOpsManager.OP_CAMERA || op == AppOpsManager.OP_PHONE_CALL_CAMERA;
}
private boolean isOpMicrophone(int op) {
return op == AppOpsManager.OP_RECORD_AUDIO || op == AppOpsManager.OP_PHONE_CALL_MICROPHONE;
}
protected class H extends Handler { protected class H extends Handler {
H(Looper looper) { H(Looper looper) {
super(looper); super(looper);

View File

@@ -29,6 +29,7 @@ import android.util.Log
import androidx.annotation.MainThread import androidx.annotation.MainThread
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread
import com.android.systemui.appops.AppOpsController
import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dagger.qualifiers.Main
@@ -48,7 +49,6 @@ private val defaultDialogProvider = object : PrivacyDialogController.DialogProvi
return PrivacyDialog(context, list, starter) return PrivacyDialog(context, list, starter)
} }
} }
/** /**
* Controller for [PrivacyDialog]. * Controller for [PrivacyDialog].
* *
@@ -66,6 +66,7 @@ class PrivacyDialogController(
private val uiExecutor: Executor, private val uiExecutor: Executor,
private val privacyLogger: PrivacyLogger, private val privacyLogger: PrivacyLogger,
private val keyguardStateController: KeyguardStateController, private val keyguardStateController: KeyguardStateController,
private val appOpsController: AppOpsController,
@VisibleForTesting private val dialogProvider: DialogProvider @VisibleForTesting private val dialogProvider: DialogProvider
) { ) {
@@ -79,7 +80,8 @@ class PrivacyDialogController(
@Background backgroundExecutor: Executor, @Background backgroundExecutor: Executor,
@Main uiExecutor: Executor, @Main uiExecutor: Executor,
privacyLogger: PrivacyLogger, privacyLogger: PrivacyLogger,
keyguardStateController: KeyguardStateController keyguardStateController: KeyguardStateController,
appOpsController: AppOpsController
) : this( ) : this(
permissionManager, permissionManager,
packageManager, packageManager,
@@ -90,6 +92,7 @@ class PrivacyDialogController(
uiExecutor, uiExecutor,
privacyLogger, privacyLogger,
keyguardStateController, keyguardStateController,
appOpsController,
defaultDialogProvider defaultDialogProvider
) )
@@ -127,7 +130,9 @@ class PrivacyDialogController(
} }
@WorkerThread @WorkerThread
private fun permGroupUsage(): List<PermGroupUsage> = permissionManager.indicatorAppOpUsageData private fun permGroupUsage(): List<PermGroupUsage> {
return permissionManager.getIndicatorAppOpUsageData(appOpsController.isMicMuted)
}
/** /**
* Show the [PrivacyDialog] * Show the [PrivacyDialog]
@@ -261,4 +266,4 @@ class PrivacyDialogController(
starter: (String, Int) -> Unit starter: (String, Int) -> Unit
): PrivacyDialog ): PrivacyDialog
} }
} }

View File

@@ -54,7 +54,8 @@ private const val UNKNOWN_TIMESTAMP = -1L
data class PrivacyItem( data class PrivacyItem(
val privacyType: PrivacyType, val privacyType: PrivacyType,
val application: PrivacyApplication, val application: PrivacyApplication,
val timeStampElapsed: Long = UNKNOWN_TIMESTAMP val timeStampElapsed: Long = UNKNOWN_TIMESTAMP,
val paused: Boolean = false
) { ) {
val log = "(${privacyType.logName}, ${application.packageName}(${application.uid}), " + val log = "(${privacyType.logName}, ${application.packageName}(${application.uid}), " +
"$timeStampElapsed)" "$timeStampElapsed)"

View File

@@ -257,7 +257,7 @@ class PrivacyItemController @Inject constructor(
privacyList = emptyList() privacyList = emptyList()
return return
} }
val list = appOpsController.getActiveAppOpsForUser(UserHandle.USER_ALL).filter { val list = appOpsController.getActiveAppOps(true).filter {
UserHandle.getUserId(it.uid) in currentUserIds || UserHandle.getUserId(it.uid) in currentUserIds ||
it.code == AppOpsManager.OP_PHONE_CALL_MICROPHONE || it.code == AppOpsManager.OP_PHONE_CALL_MICROPHONE ||
it.code == AppOpsManager.OP_PHONE_CALL_CAMERA it.code == AppOpsManager.OP_PHONE_CALL_CAMERA
@@ -279,7 +279,9 @@ class PrivacyItemController @Inject constructor(
// Anything earlier than this timestamp can be removed // Anything earlier than this timestamp can be removed
val removeBeforeTime = systemClock.elapsedRealtime() - TIME_TO_HOLD_INDICATORS val removeBeforeTime = systemClock.elapsedRealtime() - TIME_TO_HOLD_INDICATORS
val mustKeep = privacyList.filter { it.timeStampElapsed > removeBeforeTime && it !in list } val mustKeep = privacyList.filter {
it.timeStampElapsed > removeBeforeTime && !(it isIn list)
}
// There are items we must keep because they haven't been around for enough time. // There are items we must keep because they haven't been around for enough time.
if (mustKeep.isNotEmpty()) { if (mustKeep.isNotEmpty()) {
@@ -291,7 +293,18 @@ class PrivacyItemController @Inject constructor(
logger.logPrivacyItemsUpdateScheduled(delay) logger.logPrivacyItemsUpdateScheduled(delay)
holdingRunnableCanceler = bgExecutor.executeDelayed(updateListAndNotifyChanges, delay) holdingRunnableCanceler = bgExecutor.executeDelayed(updateListAndNotifyChanges, delay)
} }
return list + mustKeep return list.filter { !it.paused } + mustKeep
}
/**
* Ignores the paused status to determine if the element is in the list
*/
private infix fun PrivacyItem.isIn(list: List<PrivacyItem>): Boolean {
return list.any {
it.privacyType == privacyType &&
it.application == application &&
it.timeStampElapsed == timeStampElapsed
}
} }
private fun toPrivacyItem(appOpItem: AppOpItem): PrivacyItem? { private fun toPrivacyItem(appOpItem: AppOpItem): PrivacyItem? {
@@ -308,7 +321,7 @@ class PrivacyItemController @Inject constructor(
return null return null
} }
val app = PrivacyApplication(appOpItem.packageName, appOpItem.uid) val app = PrivacyApplication(appOpItem.packageName, appOpItem.uid)
return PrivacyItem(type, app, appOpItem.timeStartedElapsed) return PrivacyItem(type, app, appOpItem.timeStartedElapsed, appOpItem.isDisabled)
} }
interface Callback { interface Callback {

View File

@@ -233,9 +233,9 @@ public class AppOpsControllerTest extends SysuiTestCase {
TEST_UID, TEST_PACKAGE_NAME, TEST_ATTRIBUTION_NAME, TEST_UID, TEST_PACKAGE_NAME, TEST_ATTRIBUTION_NAME,
AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED); AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
assertEquals(2, assertEquals(2,
mController.getActiveAppOpsForUser(UserHandle.getUserId(TEST_UID)).size()); mController.getActiveAppOpsForUser(UserHandle.getUserId(TEST_UID), false).size());
assertEquals(1, assertEquals(1, mController.getActiveAppOpsForUser(UserHandle.getUserId(TEST_UID_OTHER),
mController.getActiveAppOpsForUser(UserHandle.getUserId(TEST_UID_OTHER)).size()); false).size());
} }
@Test @Test
@@ -245,11 +245,11 @@ public class AppOpsControllerTest extends SysuiTestCase {
mController.onOpActiveChanged(AppOpsManager.OP_RECORD_AUDIO, mController.onOpActiveChanged(AppOpsManager.OP_RECORD_AUDIO,
TEST_UID_NON_USER_SENSITIVE, mExemptedRolePkgName, true); TEST_UID_NON_USER_SENSITIVE, mExemptedRolePkgName, true);
assertEquals(0, mController.getActiveAppOpsForUser( assertEquals(0, mController.getActiveAppOpsForUser(
UserHandle.getUserId(TEST_UID_NON_USER_SENSITIVE)).size()); UserHandle.getUserId(TEST_UID_NON_USER_SENSITIVE), false).size());
mController.onOpActiveChanged(AppOpsManager.OP_RECORD_AUDIO, mController.onOpActiveChanged(AppOpsManager.OP_RECORD_AUDIO,
TEST_UID_NON_USER_SENSITIVE, SYSTEM_PKG, true); TEST_UID_NON_USER_SENSITIVE, SYSTEM_PKG, true);
assertEquals(0, mController.getActiveAppOpsForUser( assertEquals(0, mController.getActiveAppOpsForUser(
UserHandle.getUserId(TEST_UID_NON_USER_SENSITIVE)).size()); UserHandle.getUserId(TEST_UID_NON_USER_SENSITIVE), false).size());
} }
@Test @Test
@@ -441,7 +441,19 @@ public class AppOpsControllerTest extends SysuiTestCase {
} }
@Test @Test
public void testOnlyRecordAudioPaused() { public void testPausedPhoneCallMicrophoneFilteredOut() {
mController.addCallback(new int[]{AppOpsManager.OP_PHONE_CALL_MICROPHONE}, mCallback);
mTestableLooper.processAllMessages();
mController.onOpActiveChanged(
AppOpsManager.OP_PHONE_CALL_MICROPHONE, TEST_UID, TEST_PACKAGE_NAME, true);
mTestableLooper.processAllMessages();
assertTrue(mController.getActiveAppOps().isEmpty());
}
@Test
public void testOnlyRecordAudioPhoneCallMicrophonePaused() {
mController.addCallback(new int[]{ mController.addCallback(new int[]{
AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_RECORD_AUDIO,
AppOpsManager.OP_CAMERA AppOpsManager.OP_CAMERA
@@ -531,6 +543,40 @@ public class AppOpsControllerTest extends SysuiTestCase {
assertEquals(AppOpsManager.OP_RECORD_AUDIO, list.get(micIdx).getCode()); assertEquals(AppOpsManager.OP_RECORD_AUDIO, list.get(micIdx).getCode());
} }
@Test
public void testPhoneCallMicrophoneFilteredWhenMicDisabled() {
mController.addCallback(
new int[]{AppOpsManager.OP_PHONE_CALL_MICROPHONE, AppOpsManager.OP_CAMERA},
mCallback);
mTestableLooper.processAllMessages();
mController.onOpActiveChanged(
AppOpsManager.OP_PHONE_CALL_MICROPHONE, TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
mTestableLooper.processAllMessages();
List<AppOpItem> list = mController.getActiveAppOps();
assertEquals(1, list.size());
assertEquals(AppOpsManager.OP_PHONE_CALL_MICROPHONE, list.get(0).getCode());
assertFalse(list.get(0).isDisabled());
// Add a camera op, and disable the microphone. The camera op should be the only op returned
mController.onSensorBlockedChanged(MICROPHONE, true);
mController.onOpActiveChanged(
AppOpsManager.OP_CAMERA, TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
mTestableLooper.processAllMessages();
list = mController.getActiveAppOps();
assertEquals(1, list.size());
assertEquals(AppOpsManager.OP_CAMERA, list.get(0).getCode());
// Re enable the microphone, and verify the op returns
mController.onSensorBlockedChanged(MICROPHONE, false);
mTestableLooper.processAllMessages();
list = mController.getActiveAppOps();
assertEquals(2, list.size());
int micIdx = list.get(0).getCode() == AppOpsManager.OP_CAMERA ? 1 : 0;
assertEquals(AppOpsManager.OP_PHONE_CALL_MICROPHONE, list.get(micIdx).getCode());
}
@Test @Test
public void testCameraFilteredWhenCameraDisabled() { public void testCameraFilteredWhenCameraDisabled() {
mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_CAMERA}, mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_CAMERA},
@@ -563,6 +609,39 @@ public class AppOpsControllerTest extends SysuiTestCase {
assertEquals(AppOpsManager.OP_CAMERA, list.get(cameraIdx).getCode()); assertEquals(AppOpsManager.OP_CAMERA, list.get(cameraIdx).getCode());
} }
@Test
public void testPhoneCallCameraFilteredWhenCameraDisabled() {
mController.addCallback(
new int[]{AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_PHONE_CALL_CAMERA},
mCallback);
mTestableLooper.processAllMessages();
mController.onOpActiveChanged(
AppOpsManager.OP_PHONE_CALL_CAMERA, TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
mTestableLooper.processAllMessages();
List<AppOpItem> list = mController.getActiveAppOps();
assertEquals(1, list.size());
assertEquals(AppOpsManager.OP_PHONE_CALL_CAMERA, list.get(0).getCode());
assertFalse(list.get(0).isDisabled());
// Add an audio op, and disable the camera. The audio op should be the only op returned
mController.onSensorBlockedChanged(CAMERA, true);
mController.onOpActiveChanged(
AppOpsManager.OP_RECORD_AUDIO, TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
mTestableLooper.processAllMessages();
list = mController.getActiveAppOps();
assertEquals(1, list.size());
assertEquals(AppOpsManager.OP_RECORD_AUDIO, list.get(0).getCode());
// Re enable the camera, and verify the op returns
mController.onSensorBlockedChanged(CAMERA, false);
mTestableLooper.processAllMessages();
list = mController.getActiveAppOps();
assertEquals(2, list.size());
int cameraIdx = list.get(0).getCode() == AppOpsManager.OP_PHONE_CALL_CAMERA ? 0 : 1;
assertEquals(AppOpsManager.OP_PHONE_CALL_CAMERA, list.get(cameraIdx).getCode());
}
private class TestHandler extends AppOpsControllerImpl.H { private class TestHandler extends AppOpsControllerImpl.H {
TestHandler(Looper looper) { TestHandler(Looper looper) {
mController.super(looper); mController.super(looper);

View File

@@ -28,6 +28,7 @@ import android.permission.PermissionManager
import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.android.systemui.appops.AppOpsController
import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.privacy.logging.PrivacyLogger import com.android.systemui.privacy.logging.PrivacyLogger
import com.android.systemui.settings.UserTracker import com.android.systemui.settings.UserTracker
@@ -43,6 +44,7 @@ import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyString import org.mockito.ArgumentMatchers.anyString
import org.mockito.Captor import org.mockito.Captor
@@ -86,6 +88,8 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
private lateinit var privacyLogger: PrivacyLogger private lateinit var privacyLogger: PrivacyLogger
@Mock @Mock
private lateinit var keyguardStateController: KeyguardStateController private lateinit var keyguardStateController: KeyguardStateController
@Mock
private lateinit var appOpsController: AppOpsController
@Captor @Captor
private lateinit var dialogDismissedCaptor: ArgumentCaptor<PrivacyDialog.OnDialogDismissed> private lateinit var dialogDismissedCaptor: ArgumentCaptor<PrivacyDialog.OnDialogDismissed>
@Captor @Captor
@@ -131,6 +135,7 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
uiExecutor, uiExecutor,
privacyLogger, privacyLogger,
keyguardStateController, keyguardStateController,
appOpsController,
dialogProvider dialogProvider
) )
} }
@@ -142,19 +147,28 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
dialogProvider.starter = null dialogProvider.starter = null
} }
@Test
fun testMicMutedParameter() {
`when`(appOpsController.isMicMuted).thenReturn(true)
controller.showDialog(context)
backgroundExecutor.runAllReady()
verify(permissionManager).getIndicatorAppOpUsageData(true)
}
@Test @Test
fun testPermissionManagerOnlyCalledInBackgroundThread() { fun testPermissionManagerOnlyCalledInBackgroundThread() {
controller.showDialog(context) controller.showDialog(context)
verify(permissionManager, never()).indicatorAppOpUsageData verify(permissionManager, never()).getIndicatorAppOpUsageData(anyBoolean())
backgroundExecutor.runAllReady() backgroundExecutor.runAllReady()
verify(permissionManager).indicatorAppOpUsageData verify(permissionManager).getIndicatorAppOpUsageData(anyBoolean())
} }
@Test @Test
fun testPackageManagerOnlyCalledInBackgroundThread() { fun testPackageManagerOnlyCalledInBackgroundThread() {
val usage = createMockPermGroupUsage() val usage = createMockPermGroupUsage()
`when`(usage.isPhoneCall).thenReturn(false) `when`(usage.isPhoneCall).thenReturn(false)
`when`(permissionManager.indicatorAppOpUsageData).thenReturn(listOf(usage)) `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage))
controller.showDialog(context) controller.showDialog(context)
verify(packageManager, never()).getApplicationInfoAsUser(anyString(), anyInt(), anyInt()) verify(packageManager, never()).getApplicationInfoAsUser(anyString(), anyInt(), anyInt())
@@ -217,7 +231,7 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
isPhoneCall = false, isPhoneCall = false,
attribution = TEST_ATTRIBUTION attribution = TEST_ATTRIBUTION
) )
`when`(permissionManager.indicatorAppOpUsageData).thenReturn(listOf(usage)) `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(listOf(usage))
controller.showDialog(context) controller.showDialog(context)
exhaustExecutors() exhaustExecutors()
@@ -246,7 +260,7 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
packageName = "${TEST_PACKAGE_NAME}_microphone", packageName = "${TEST_PACKAGE_NAME}_microphone",
permGroupName = PERM_MICROPHONE permGroupName = PERM_MICROPHONE
) )
`when`(permissionManager.indicatorAppOpUsageData).thenReturn( `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(
listOf(usage_microphone, usage_camera) listOf(usage_microphone, usage_camera)
) )
@@ -269,7 +283,7 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
packageName = "${TEST_PACKAGE_NAME}_recent", packageName = "${TEST_PACKAGE_NAME}_recent",
isActive = false isActive = false
) )
`when`(permissionManager.indicatorAppOpUsageData).thenReturn( `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(
listOf(usage_recent, usage_active) listOf(usage_recent, usage_active)
) )
@@ -292,7 +306,7 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
isActive = true, isActive = true,
lastAccess = 1L lastAccess = 1L
) )
`when`(permissionManager.indicatorAppOpUsageData).thenReturn( `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(
listOf(usage_active, usage_active_moreRecent) listOf(usage_active, usage_active_moreRecent)
) )
controller.showDialog(context) controller.showDialog(context)
@@ -319,7 +333,7 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
isActive = false, isActive = false,
lastAccess = 2L lastAccess = 2L
) )
`when`(permissionManager.indicatorAppOpUsageData).thenReturn( `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(
listOf(usage_recent, usage_mostRecent, usage_moreRecent) listOf(usage_recent, usage_mostRecent, usage_moreRecent)
) )
@@ -342,7 +356,7 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
permGroupName = PERM_LOCATION permGroupName = PERM_LOCATION
) )
`when`(permissionManager.indicatorAppOpUsageData).thenReturn( `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(
listOf(usage_camera, usage_location, usage_microphone) listOf(usage_camera, usage_location, usage_microphone)
) )
`when`(privacyItemController.micCameraAvailable).thenReturn(false) `when`(privacyItemController.micCameraAvailable).thenReturn(false)
@@ -366,7 +380,7 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
permGroupName = PERM_LOCATION permGroupName = PERM_LOCATION
) )
`when`(permissionManager.indicatorAppOpUsageData).thenReturn( `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(
listOf(usage_camera, usage_location, usage_microphone) listOf(usage_camera, usage_location, usage_microphone)
) )
`when`(privacyItemController.locationAvailable).thenReturn(false) `when`(privacyItemController.locationAvailable).thenReturn(false)
@@ -392,7 +406,7 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
permGroupName = PERM_LOCATION permGroupName = PERM_LOCATION
) )
`when`(permissionManager.indicatorAppOpUsageData).thenReturn( `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(
listOf(usage_camera, usage_location, usage_microphone) listOf(usage_camera, usage_location, usage_microphone)
) )
`when`(privacyItemController.micCameraAvailable).thenReturn(true) `when`(privacyItemController.micCameraAvailable).thenReturn(true)
@@ -416,7 +430,7 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
permGroupName = PERM_LOCATION permGroupName = PERM_LOCATION
) )
`when`(permissionManager.indicatorAppOpUsageData).thenReturn( `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(
listOf(usage_camera, usage_location, usage_microphone) listOf(usage_camera, usage_location, usage_microphone)
) )
`when`(privacyItemController.micCameraAvailable).thenReturn(false) `when`(privacyItemController.micCameraAvailable).thenReturn(false)
@@ -433,7 +447,8 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
val usage_enterprise = createMockPermGroupUsage( val usage_enterprise = createMockPermGroupUsage(
uid = generateUidForUser(ENT_USER_ID) uid = generateUidForUser(ENT_USER_ID)
) )
`when`(permissionManager.indicatorAppOpUsageData).thenReturn(listOf(usage_enterprise)) `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean()))
.thenReturn(listOf(usage_enterprise))
controller.showDialog(context) controller.showDialog(context)
exhaustExecutors() exhaustExecutors()
@@ -446,7 +461,8 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
val usage_other = createMockPermGroupUsage( val usage_other = createMockPermGroupUsage(
uid = generateUidForUser(ENT_USER_ID + 1) uid = generateUidForUser(ENT_USER_ID + 1)
) )
`when`(permissionManager.indicatorAppOpUsageData).thenReturn(listOf(usage_other)) `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean()))
.thenReturn(listOf(usage_other))
controller.showDialog(context) controller.showDialog(context)
exhaustExecutors() exhaustExecutors()
@@ -514,7 +530,8 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
} }
private fun setUpDefaultMockResponses() { private fun setUpDefaultMockResponses() {
`when`(permissionManager.indicatorAppOpUsageData).thenReturn(emptyList()) `when`(permissionManager.getIndicatorAppOpUsageData(anyBoolean())).thenReturn(emptyList())
`when`(appOpsController.isMicMuted).thenReturn(false)
`when`(packageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) `when`(packageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
.thenAnswer { .thenAnswer {

View File

@@ -46,7 +46,7 @@ import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyList import org.mockito.ArgumentMatchers.anyList
import org.mockito.Captor import org.mockito.Captor
import org.mockito.Mock import org.mockito.Mock
@@ -156,7 +156,7 @@ class PrivacyItemControllerTest : SysuiTestCase() {
fun testDistinctItems() { fun testDistinctItems() {
doReturn(listOf(AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 0), doReturn(listOf(AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 0),
AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 0))) AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 0)))
.`when`(appOpsController).getActiveAppOpsForUser(anyInt()) .`when`(appOpsController).getActiveAppOps(anyBoolean())
privacyItemController.addCallback(callback) privacyItemController.addCallback(callback)
executor.runAllReady() executor.runAllReady()
@@ -168,7 +168,7 @@ class PrivacyItemControllerTest : SysuiTestCase() {
fun testSimilarItemsDifferentTimeStamp() { fun testSimilarItemsDifferentTimeStamp() {
doReturn(listOf(AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 0), doReturn(listOf(AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 0),
AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 1))) AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 1)))
.`when`(appOpsController).getActiveAppOpsForUser(anyInt()) .`when`(appOpsController).getActiveAppOps(anyBoolean())
privacyItemController.addCallback(callback) privacyItemController.addCallback(callback)
executor.runAllReady() executor.runAllReady()
@@ -215,7 +215,7 @@ class PrivacyItemControllerTest : SysuiTestCase() {
@Test @Test
fun testMultipleCallbacksAreUpdated() { fun testMultipleCallbacksAreUpdated() {
doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOps(anyBoolean())
val otherCallback = mock(PrivacyItemController.Callback::class.java) val otherCallback = mock(PrivacyItemController.Callback::class.java)
privacyItemController.addCallback(callback) privacyItemController.addCallback(callback)
@@ -233,7 +233,7 @@ class PrivacyItemControllerTest : SysuiTestCase() {
@Test @Test
fun testRemoveCallback() { fun testRemoveCallback() {
doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOps(anyBoolean())
val otherCallback = mock(PrivacyItemController.Callback::class.java) val otherCallback = mock(PrivacyItemController.Callback::class.java)
privacyItemController.addCallback(callback) privacyItemController.addCallback(callback)
privacyItemController.addCallback(otherCallback) privacyItemController.addCallback(otherCallback)
@@ -254,7 +254,7 @@ class PrivacyItemControllerTest : SysuiTestCase() {
fun testListShouldNotHaveNull() { fun testListShouldNotHaveNull() {
doReturn(listOf(AppOpItem(AppOpsManager.OP_ACTIVATE_VPN, TEST_UID, "", 0), doReturn(listOf(AppOpItem(AppOpsManager.OP_ACTIVATE_VPN, TEST_UID, "", 0),
AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, "", 0))) AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, "", 0)))
.`when`(appOpsController).getActiveAppOpsForUser(anyInt()) .`when`(appOpsController).getActiveAppOps(anyBoolean())
privacyItemController.addCallback(callback) privacyItemController.addCallback(callback)
executor.runAllReady() executor.runAllReady()
executor.runAllReady() executor.runAllReady()
@@ -292,7 +292,7 @@ class PrivacyItemControllerTest : SysuiTestCase() {
doReturn(listOf(AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 0), doReturn(listOf(AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 0),
AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, "", 0))) AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, "", 0)))
.`when`(appOpsController).getActiveAppOpsForUser(anyInt()) .`when`(appOpsController).getActiveAppOps(anyBoolean())
privacyItemController.addCallback(callback) privacyItemController.addCallback(callback)
executor.runAllReady() executor.runAllReady()
@@ -306,7 +306,7 @@ class PrivacyItemControllerTest : SysuiTestCase() {
@Test @Test
fun testNotUpdated_LocationChangeWhenOnlyMicCamera() { fun testNotUpdated_LocationChangeWhenOnlyMicCamera() {
doReturn(listOf(AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, "", 0))) doReturn(listOf(AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, "", 0)))
.`when`(appOpsController).getActiveAppOpsForUser(anyInt()) .`when`(appOpsController).getActiveAppOps(anyBoolean())
privacyItemController.addCallback(callback) privacyItemController.addCallback(callback)
changeLocation(false) changeLocation(false)
@@ -338,7 +338,7 @@ class PrivacyItemControllerTest : SysuiTestCase() {
fun testLogListUpdated() { fun testLogListUpdated() {
doReturn(listOf( doReturn(listOf(
AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, 0)) AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, 0))
).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) ).`when`(appOpsController).getActiveAppOps(anyBoolean())
privacyItemController.addCallback(callback) privacyItemController.addCallback(callback)
executor.runAllReady() executor.runAllReady()
@@ -362,10 +362,10 @@ class PrivacyItemControllerTest : SysuiTestCase() {
} }
@Test @Test
fun testListRequestedForAllUsers() { fun testListRequestedShowPaused() {
privacyItemController.addCallback(callback) privacyItemController.addCallback(callback)
executor.runAllReady() executor.runAllReady()
verify(appOpsController).getActiveAppOpsForUser(UserHandle.USER_ALL) verify(appOpsController).getActiveAppOps(true)
} }
@Test @Test
@@ -377,7 +377,7 @@ class PrivacyItemControllerTest : SysuiTestCase() {
doReturn(listOf( doReturn(listOf(
AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, 0), AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, 0),
AppOpItem(AppOpsManager.OP_CAMERA, otherUserUid, TEST_PACKAGE_NAME, 0)) AppOpItem(AppOpsManager.OP_CAMERA, otherUserUid, TEST_PACKAGE_NAME, 0))
).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) ).`when`(appOpsController).getActiveAppOps(anyBoolean())
privacyItemController.userTrackerCallback.onUserChanged(otherUser, mContext) privacyItemController.userTrackerCallback.onUserChanged(otherUser, mContext)
executor.runAllReady() executor.runAllReady()
@@ -401,7 +401,7 @@ class PrivacyItemControllerTest : SysuiTestCase() {
AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, 0), AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, 0),
AppOpItem(AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, 0), AppOpItem(AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, 0),
AppOpItem(AppOpsManager.OP_PHONE_CALL_CAMERA, TEST_UID, TEST_PACKAGE_NAME, 0)) AppOpItem(AppOpsManager.OP_PHONE_CALL_CAMERA, TEST_UID, TEST_PACKAGE_NAME, 0))
).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) ).`when`(appOpsController).getActiveAppOps(anyBoolean())
privacyItemController.userTrackerCallback.onUserChanged(otherUser, mContext) privacyItemController.userTrackerCallback.onUserChanged(otherUser, mContext)
executor.runAllReady() executor.runAllReady()
@@ -424,7 +424,7 @@ class PrivacyItemControllerTest : SysuiTestCase() {
AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, 0), AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, 0),
AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, 0), AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, 0),
AppOpItem(AppOpsManager.OP_PHONE_CALL_MICROPHONE, TEST_UID, TEST_PACKAGE_NAME, 0)) AppOpItem(AppOpsManager.OP_PHONE_CALL_MICROPHONE, TEST_UID, TEST_PACKAGE_NAME, 0))
).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) ).`when`(appOpsController).getActiveAppOps(anyBoolean())
privacyItemController.userTrackerCallback.onUserChanged(otherUser, mContext) privacyItemController.userTrackerCallback.onUserChanged(otherUser, mContext)
executor.runAllReady() executor.runAllReady()
@@ -442,7 +442,7 @@ class PrivacyItemControllerTest : SysuiTestCase() {
fun testPassageOfTimeDoesNotRemoveIndicators() { fun testPassageOfTimeDoesNotRemoveIndicators() {
doReturn(listOf( doReturn(listOf(
AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, elapsedTime) AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, elapsedTime)
)).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) )).`when`(appOpsController).getActiveAppOps(anyBoolean())
privacyItemController.addCallback(callback) privacyItemController.addCallback(callback)
@@ -458,12 +458,12 @@ class PrivacyItemControllerTest : SysuiTestCase() {
// Start with some element at time 0 // Start with some element at time 0
doReturn(listOf( doReturn(listOf(
AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, elapsedTime) AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, elapsedTime)
)).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) )).`when`(appOpsController).getActiveAppOps(anyBoolean())
privacyItemController.addCallback(callback) privacyItemController.addCallback(callback)
executor.runAllReady() executor.runAllReady()
// Then remove it at time HOLD + 1 // Then remove it at time HOLD + 1
doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOps(anyBoolean())
fakeClock.advanceTime(PrivacyItemController.TIME_TO_HOLD_INDICATORS + 1) fakeClock.advanceTime(PrivacyItemController.TIME_TO_HOLD_INDICATORS + 1)
verify(appOpsController).addCallback(any(), capture(argCaptorCallback)) verify(appOpsController).addCallback(any(), capture(argCaptorCallback))
@@ -481,12 +481,12 @@ class PrivacyItemControllerTest : SysuiTestCase() {
// Start with some element at time 0 // Start with some element at time 0
doReturn(listOf( doReturn(listOf(
AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, elapsedTime) AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, elapsedTime)
)).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) )).`when`(appOpsController).getActiveAppOps(anyBoolean())
privacyItemController.addCallback(callback) privacyItemController.addCallback(callback)
executor.runAllReady() executor.runAllReady()
// Then remove it at time HOLD - 1 // Then remove it at time HOLD - 1
doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOps(anyBoolean())
fakeClock.advanceTime(PrivacyItemController.TIME_TO_HOLD_INDICATORS - 1) fakeClock.advanceTime(PrivacyItemController.TIME_TO_HOLD_INDICATORS - 1)
verify(appOpsController).addCallback(any(), capture(argCaptorCallback)) verify(appOpsController).addCallback(any(), capture(argCaptorCallback))
@@ -504,12 +504,12 @@ class PrivacyItemControllerTest : SysuiTestCase() {
// Start with some element at time 0 // Start with some element at time 0
doReturn(listOf( doReturn(listOf(
AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, elapsedTime) AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, elapsedTime)
)).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) )).`when`(appOpsController).getActiveAppOps(anyBoolean())
privacyItemController.addCallback(callback) privacyItemController.addCallback(callback)
executor.runAllReady() executor.runAllReady()
// Then remove it at time HOLD - 1 // Then remove it at time HOLD - 1
doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOps(anyBoolean())
fakeClock.advanceTime(PrivacyItemController.TIME_TO_HOLD_INDICATORS - 1) fakeClock.advanceTime(PrivacyItemController.TIME_TO_HOLD_INDICATORS - 1)
verify(appOpsController).addCallback(any(), capture(argCaptorCallback)) verify(appOpsController).addCallback(any(), capture(argCaptorCallback))
@@ -525,6 +525,30 @@ class PrivacyItemControllerTest : SysuiTestCase() {
assertTrue(privacyItemController.privacyList.isEmpty()) assertTrue(privacyItemController.privacyList.isEmpty())
} }
@Test
fun testPausedElementsAreRemoved() {
val item = AppOpItem(
AppOpsManager.OP_RECORD_AUDIO,
TEST_UID,
TEST_PACKAGE_NAME,
elapsedTime
)
`when`(appOpsController.getActiveAppOps(anyBoolean())).thenReturn(listOf(item))
privacyItemController.addCallback(callback)
executor.runAllReady()
item.isDisabled = true
fakeClock.advanceTime(1)
verify(appOpsController).addCallback(any(), capture(argCaptorCallback))
argCaptorCallback.value.onActiveStateChanged(
AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, false)
executor.runAllReady()
verify(callback).onPrivacyItemsChanged(emptyList())
assertTrue(privacyItemController.privacyList.isEmpty())
}
private fun changeMicCamera(value: Boolean?) = changeProperty(MIC_CAMERA, value) private fun changeMicCamera(value: Boolean?) = changeProperty(MIC_CAMERA, value)
private fun changeLocation(value: Boolean?) = changeProperty(LOCATION_INDICATOR, value) private fun changeLocation(value: Boolean?) = changeProperty(LOCATION_INDICATOR, value)