Loading packages/SystemUI/src/com/android/systemui/Dependency.java +4 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import com.android.systemui.plugins.PluginDependencyProvider; import com.android.systemui.plugins.VolumeDialogController; import com.android.systemui.power.EnhancedEstimates; import com.android.systemui.power.PowerUI; import com.android.systemui.privacy.PrivacyItemController; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.statusbar.AmbientPulseManager; Loading Loading @@ -278,6 +279,7 @@ public class Dependency extends SystemUI { @Inject Lazy<SensorPrivacyManager> mSensorPrivacyManager; @Inject Lazy<AutoHideController> mAutoHideController; @Inject Lazy<ForegroundServiceNotificationListener> mForegroundServiceNotificationListener; @Inject Lazy<PrivacyItemController> mPrivacyItemController; @Inject @Named(BG_LOOPER_NAME) Lazy<Looper> mBgLooper; @Inject @Named(BG_HANDLER_NAME) Lazy<Handler> mBgHandler; @Inject @Named(MAIN_HANDLER_NAME) Lazy<Handler> mMainHandler; Loading Loading @@ -452,6 +454,8 @@ public class Dependency extends SystemUI { mProviders.put(ForegroundServiceNotificationListener.class, mForegroundServiceNotificationListener::get); mProviders.put(ClockManager.class, mClockManager::get); mProviders.put(PrivacyItemController.class, mPrivacyItemController::get); // TODO(b/118592525): to support multi-display , we start to add something which is // per-display, while others may be global. I think it's time to add Loading packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt +43 −5 Original line number Diff line number Diff line Loading @@ -30,8 +30,12 @@ import com.android.systemui.Dependency import com.android.systemui.appops.AppOpItem import com.android.systemui.appops.AppOpsController import com.android.systemui.R import java.lang.ref.WeakReference import javax.inject.Inject import javax.inject.Singleton class PrivacyItemController(val context: Context, val callback: Callback) { @Singleton class PrivacyItemController @Inject constructor(val context: Context) { companion object { val OPS = intArrayOf(AppOpsManager.OP_CAMERA, Loading @@ -56,9 +60,10 @@ class PrivacyItemController(val context: Context, val callback: Callback) { private val uiHandler = Dependency.get(Dependency.MAIN_HANDLER) private var listening = false val systemApp = PrivacyApplication(context.getString(R.string.device_services), context) private val callbacks = mutableListOf<WeakReference<Callback>>() private val notifyChanges = Runnable { callback.privacyChanged(privacyList) callbacks.forEach { it.get()?.privacyChanged(privacyList) } } private val updateListAndNotifyChanges = Runnable { Loading Loading @@ -88,8 +93,8 @@ class PrivacyItemController(val context: Context, val callback: Callback) { registerReceiver() } init { registerReceiver() private fun unregisterReceiver() { context.unregisterReceiver(userSwitcherReceiver) } private fun registerReceiver() { Loading @@ -108,15 +113,39 @@ class PrivacyItemController(val context: Context, val callback: Callback) { bgHandler.post(updateListAndNotifyChanges) } fun setListening(listen: Boolean) { @VisibleForTesting internal fun setListening(listen: Boolean) { if (listening == listen) return listening = listen if (listening) { appOpsController.addCallback(OPS, cb) registerReceiver() update(true) } else { appOpsController.removeCallback(OPS, cb) unregisterReceiver() } } private fun addCallback(callback: WeakReference<Callback>) { callbacks.add(callback) if (callbacks.isNotEmpty() && !listening) setListening(true) // Notify this callback if we didn't set to listening else uiHandler.post(NotifyChangesToCallback(callback.get(), privacyList)) } private fun removeCallback(callback: WeakReference<Callback>) { // Removes also if the callback is null callbacks.removeIf { it.get()?.equals(callback.get()) ?: true } if (callbacks.isEmpty()) setListening(false) } fun addCallback(callback: Callback) { addCallback(WeakReference(callback)) } fun removeCallback(callback: Callback) { removeCallback(WeakReference(callback)) } private fun updatePrivacyList() { Loading Loading @@ -149,4 +178,13 @@ class PrivacyItemController(val context: Context, val callback: Callback) { } } } private class NotifyChangesToCallback( private val callback: Callback?, private val list: List<PrivacyItem> ) : Runnable { override fun run() { callback?.privacyChanged(list) } } } No newline at end of file packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +4 −3 Original line number Diff line number Diff line Loading @@ -180,14 +180,14 @@ public class QuickStatusBarHeader extends RelativeLayout implements public QuickStatusBarHeader(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs, NextAlarmController nextAlarmController, ZenModeController zenModeController, BatteryController batteryController, StatusBarIconController statusBarIconController, ActivityStarter activityStarter) { ActivityStarter activityStarter, PrivacyItemController privacyItemController) { super(context, attrs); mAlarmController = nextAlarmController; mZenController = zenModeController; mBatteryController = batteryController; mStatusBarIconController = statusBarIconController; mActivityStarter = activityStarter; mPrivacyItemController = new PrivacyItemController(context, mPICCallback); mPrivacyItemController = privacyItemController; mShownCount = getStoredShownCount(); } Loading Loading @@ -512,7 +512,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements return; } mHeaderQsPanel.setListening(listening); mPrivacyItemController.setListening(listening); mListening = listening; if (listening) { Loading @@ -520,9 +519,11 @@ public class QuickStatusBarHeader extends RelativeLayout implements mAlarmController.addCallback(this); mContext.registerReceiver(mRingerReceiver, new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION)); mPrivacyItemController.addCallback(mPICCallback); } else { mZenController.removeCallback(this); mAlarmController.removeCallback(this); mPrivacyItemController.removeCallback(mPICCallback); mContext.unregisterReceiver(mRingerReceiver); } } Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +3 −3 Original line number Diff line number Diff line Loading @@ -173,7 +173,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, mProvisionedController = Dependency.get(DeviceProvisionedController.class); mKeyguardMonitor = Dependency.get(KeyguardMonitor.class); mLocationController = Dependency.get(LocationController.class); mPrivacyItemController = new PrivacyItemController(mContext, this); mPrivacyItemController = Dependency.get(PrivacyItemController.class); mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast); mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot); Loading Loading @@ -266,7 +266,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, mNextAlarmController.addCallback(mNextAlarmCallback); mDataSaver.addCallback(this); mKeyguardMonitor.addCallback(this); mPrivacyItemController.setListening(true); mPrivacyItemController.addCallback(this); SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallback(this); ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskListener); Loading Loading @@ -294,7 +294,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, mNextAlarmController.removeCallback(mNextAlarmCallback); mDataSaver.removeCallback(this); mKeyguardMonitor.removeCallback(this); mPrivacyItemController.setListening(false); mPrivacyItemController.removeCallback(this); SysUiServiceProvider.getComponent(mContext, CommandQueue.class).removeCallback(this); mContext.unregisterReceiver(mIntentReceiver); Loading packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt +69 −7 Original line number Diff line number Diff line Loading @@ -45,9 +45,12 @@ import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.atLeastOnce import org.mockito.Mockito.doReturn import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.spy import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.MockitoAnnotations @RunWith(AndroidTestingRunner::class) Loading @@ -73,6 +76,8 @@ class PrivacyItemControllerTest : SysuiTestCase() { private lateinit var userManager: UserManager @Captor private lateinit var argCaptor: ArgumentCaptor<List<PrivacyItem>> @Captor private lateinit var argCaptorCallback: ArgumentCaptor<AppOpsController.Callback> private lateinit var testableLooper: TestableLooper private lateinit var privacyItemController: PrivacyItemController Loading @@ -95,18 +100,25 @@ class PrivacyItemControllerTest : SysuiTestCase() { } })).`when`(userManager).getProfiles(anyInt()) privacyItemController = PrivacyItemController(mContext, callback) privacyItemController = PrivacyItemController(mContext) } @Test fun testSetListeningTrue() { privacyItemController.setListening(true) fun testSetListeningTrueByAddingCallback() { privacyItemController.addCallback(callback) verify(appOpsController).addCallback(eq(PrivacyItemController.OPS), any(AppOpsController.Callback::class.java)) testableLooper.processAllMessages() verify(callback).privacyChanged(anyList()) } @Test fun testSetListeningTrue() { privacyItemController.setListening(true) verify(appOpsController).addCallback(eq(PrivacyItemController.OPS), any(AppOpsController.Callback::class.java)) } @Test fun testSetListeningFalse() { privacyItemController.setListening(true) Loading @@ -121,7 +133,7 @@ class PrivacyItemControllerTest : SysuiTestCase() { AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 1))) .`when`(appOpsController).getActiveAppOpsForUser(anyInt()) privacyItemController.setListening(true) privacyItemController.addCallback(callback) testableLooper.processAllMessages() verify(callback).privacyChanged(capture(argCaptor)) assertEquals(1, argCaptor.value.size) Loading @@ -131,7 +143,7 @@ class PrivacyItemControllerTest : SysuiTestCase() { fun testSystemApps() { doReturn(listOf(AppOpItem(AppOpsManager.OP_COARSE_LOCATION, SYSTEM_UID, TEST_PACKAGE_NAME, 0))).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) privacyItemController.setListening(true) privacyItemController.addCallback(callback) testableLooper.processAllMessages() verify(callback).privacyChanged(capture(argCaptor)) assertEquals(1, argCaptor.value.size) Loading @@ -142,8 +154,8 @@ class PrivacyItemControllerTest : SysuiTestCase() { @Test fun testRegisterReceiver_allUsers() { val spiedContext = spy(mContext) val itemController = PrivacyItemController(spiedContext, callback) val itemController = PrivacyItemController(spiedContext) itemController.setListening(true) verify(spiedContext, atLeastOnce()).registerReceiverAsUser( eq(itemController.userSwitcherReceiver), eq(UserHandle.ALL), any(), eq(null), eq(null)) Loading @@ -170,4 +182,54 @@ class PrivacyItemControllerTest : SysuiTestCase() { Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED)) verify(userManager).getProfiles(anyInt()) } @Test fun testAddMultipleCallbacks() { val otherCallback = mock(PrivacyItemController.Callback::class.java) privacyItemController.addCallback(callback) testableLooper.processAllMessages() verify(callback).privacyChanged(anyList()) privacyItemController.addCallback(otherCallback) testableLooper.processAllMessages() verify(otherCallback).privacyChanged(anyList()) // Adding a callback should not unnecessarily call previous ones verifyNoMoreInteractions(callback) } @Test fun testMultipleCallbacksAreUpdated() { doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) val otherCallback = mock(PrivacyItemController.Callback::class.java) privacyItemController.addCallback(callback) privacyItemController.addCallback(otherCallback) testableLooper.processAllMessages() reset(callback) reset(otherCallback) verify(appOpsController).addCallback(any<IntArray>(), capture(argCaptorCallback)) argCaptorCallback.value.onActiveStateChanged(0, TEST_UID, "", true) testableLooper.processAllMessages() verify(callback).privacyChanged(anyList()) verify(otherCallback).privacyChanged(anyList()) } @Test fun testRemoveCallback() { doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) val otherCallback = mock(PrivacyItemController.Callback::class.java) privacyItemController.addCallback(callback) privacyItemController.addCallback(otherCallback) testableLooper.processAllMessages() reset(callback) reset(otherCallback) verify(appOpsController).addCallback(any<IntArray>(), capture(argCaptorCallback)) privacyItemController.removeCallback(callback) argCaptorCallback.value.onActiveStateChanged(0, TEST_UID, "", true) testableLooper.processAllMessages() verify(callback, never()).privacyChanged(anyList()) verify(otherCallback).privacyChanged(anyList()) } } No newline at end of file Loading
packages/SystemUI/src/com/android/systemui/Dependency.java +4 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import com.android.systemui.plugins.PluginDependencyProvider; import com.android.systemui.plugins.VolumeDialogController; import com.android.systemui.power.EnhancedEstimates; import com.android.systemui.power.PowerUI; import com.android.systemui.privacy.PrivacyItemController; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.statusbar.AmbientPulseManager; Loading Loading @@ -278,6 +279,7 @@ public class Dependency extends SystemUI { @Inject Lazy<SensorPrivacyManager> mSensorPrivacyManager; @Inject Lazy<AutoHideController> mAutoHideController; @Inject Lazy<ForegroundServiceNotificationListener> mForegroundServiceNotificationListener; @Inject Lazy<PrivacyItemController> mPrivacyItemController; @Inject @Named(BG_LOOPER_NAME) Lazy<Looper> mBgLooper; @Inject @Named(BG_HANDLER_NAME) Lazy<Handler> mBgHandler; @Inject @Named(MAIN_HANDLER_NAME) Lazy<Handler> mMainHandler; Loading Loading @@ -452,6 +454,8 @@ public class Dependency extends SystemUI { mProviders.put(ForegroundServiceNotificationListener.class, mForegroundServiceNotificationListener::get); mProviders.put(ClockManager.class, mClockManager::get); mProviders.put(PrivacyItemController.class, mPrivacyItemController::get); // TODO(b/118592525): to support multi-display , we start to add something which is // per-display, while others may be global. I think it's time to add Loading
packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt +43 −5 Original line number Diff line number Diff line Loading @@ -30,8 +30,12 @@ import com.android.systemui.Dependency import com.android.systemui.appops.AppOpItem import com.android.systemui.appops.AppOpsController import com.android.systemui.R import java.lang.ref.WeakReference import javax.inject.Inject import javax.inject.Singleton class PrivacyItemController(val context: Context, val callback: Callback) { @Singleton class PrivacyItemController @Inject constructor(val context: Context) { companion object { val OPS = intArrayOf(AppOpsManager.OP_CAMERA, Loading @@ -56,9 +60,10 @@ class PrivacyItemController(val context: Context, val callback: Callback) { private val uiHandler = Dependency.get(Dependency.MAIN_HANDLER) private var listening = false val systemApp = PrivacyApplication(context.getString(R.string.device_services), context) private val callbacks = mutableListOf<WeakReference<Callback>>() private val notifyChanges = Runnable { callback.privacyChanged(privacyList) callbacks.forEach { it.get()?.privacyChanged(privacyList) } } private val updateListAndNotifyChanges = Runnable { Loading Loading @@ -88,8 +93,8 @@ class PrivacyItemController(val context: Context, val callback: Callback) { registerReceiver() } init { registerReceiver() private fun unregisterReceiver() { context.unregisterReceiver(userSwitcherReceiver) } private fun registerReceiver() { Loading @@ -108,15 +113,39 @@ class PrivacyItemController(val context: Context, val callback: Callback) { bgHandler.post(updateListAndNotifyChanges) } fun setListening(listen: Boolean) { @VisibleForTesting internal fun setListening(listen: Boolean) { if (listening == listen) return listening = listen if (listening) { appOpsController.addCallback(OPS, cb) registerReceiver() update(true) } else { appOpsController.removeCallback(OPS, cb) unregisterReceiver() } } private fun addCallback(callback: WeakReference<Callback>) { callbacks.add(callback) if (callbacks.isNotEmpty() && !listening) setListening(true) // Notify this callback if we didn't set to listening else uiHandler.post(NotifyChangesToCallback(callback.get(), privacyList)) } private fun removeCallback(callback: WeakReference<Callback>) { // Removes also if the callback is null callbacks.removeIf { it.get()?.equals(callback.get()) ?: true } if (callbacks.isEmpty()) setListening(false) } fun addCallback(callback: Callback) { addCallback(WeakReference(callback)) } fun removeCallback(callback: Callback) { removeCallback(WeakReference(callback)) } private fun updatePrivacyList() { Loading Loading @@ -149,4 +178,13 @@ class PrivacyItemController(val context: Context, val callback: Callback) { } } } private class NotifyChangesToCallback( private val callback: Callback?, private val list: List<PrivacyItem> ) : Runnable { override fun run() { callback?.privacyChanged(list) } } } No newline at end of file
packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +4 −3 Original line number Diff line number Diff line Loading @@ -180,14 +180,14 @@ public class QuickStatusBarHeader extends RelativeLayout implements public QuickStatusBarHeader(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs, NextAlarmController nextAlarmController, ZenModeController zenModeController, BatteryController batteryController, StatusBarIconController statusBarIconController, ActivityStarter activityStarter) { ActivityStarter activityStarter, PrivacyItemController privacyItemController) { super(context, attrs); mAlarmController = nextAlarmController; mZenController = zenModeController; mBatteryController = batteryController; mStatusBarIconController = statusBarIconController; mActivityStarter = activityStarter; mPrivacyItemController = new PrivacyItemController(context, mPICCallback); mPrivacyItemController = privacyItemController; mShownCount = getStoredShownCount(); } Loading Loading @@ -512,7 +512,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements return; } mHeaderQsPanel.setListening(listening); mPrivacyItemController.setListening(listening); mListening = listening; if (listening) { Loading @@ -520,9 +519,11 @@ public class QuickStatusBarHeader extends RelativeLayout implements mAlarmController.addCallback(this); mContext.registerReceiver(mRingerReceiver, new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION)); mPrivacyItemController.addCallback(mPICCallback); } else { mZenController.removeCallback(this); mAlarmController.removeCallback(this); mPrivacyItemController.removeCallback(mPICCallback); mContext.unregisterReceiver(mRingerReceiver); } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +3 −3 Original line number Diff line number Diff line Loading @@ -173,7 +173,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, mProvisionedController = Dependency.get(DeviceProvisionedController.class); mKeyguardMonitor = Dependency.get(KeyguardMonitor.class); mLocationController = Dependency.get(LocationController.class); mPrivacyItemController = new PrivacyItemController(mContext, this); mPrivacyItemController = Dependency.get(PrivacyItemController.class); mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast); mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot); Loading Loading @@ -266,7 +266,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, mNextAlarmController.addCallback(mNextAlarmCallback); mDataSaver.addCallback(this); mKeyguardMonitor.addCallback(this); mPrivacyItemController.setListening(true); mPrivacyItemController.addCallback(this); SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallback(this); ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskListener); Loading Loading @@ -294,7 +294,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, mNextAlarmController.removeCallback(mNextAlarmCallback); mDataSaver.removeCallback(this); mKeyguardMonitor.removeCallback(this); mPrivacyItemController.setListening(false); mPrivacyItemController.removeCallback(this); SysUiServiceProvider.getComponent(mContext, CommandQueue.class).removeCallback(this); mContext.unregisterReceiver(mIntentReceiver); Loading
packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt +69 −7 Original line number Diff line number Diff line Loading @@ -45,9 +45,12 @@ import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.atLeastOnce import org.mockito.Mockito.doReturn import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.spy import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.MockitoAnnotations @RunWith(AndroidTestingRunner::class) Loading @@ -73,6 +76,8 @@ class PrivacyItemControllerTest : SysuiTestCase() { private lateinit var userManager: UserManager @Captor private lateinit var argCaptor: ArgumentCaptor<List<PrivacyItem>> @Captor private lateinit var argCaptorCallback: ArgumentCaptor<AppOpsController.Callback> private lateinit var testableLooper: TestableLooper private lateinit var privacyItemController: PrivacyItemController Loading @@ -95,18 +100,25 @@ class PrivacyItemControllerTest : SysuiTestCase() { } })).`when`(userManager).getProfiles(anyInt()) privacyItemController = PrivacyItemController(mContext, callback) privacyItemController = PrivacyItemController(mContext) } @Test fun testSetListeningTrue() { privacyItemController.setListening(true) fun testSetListeningTrueByAddingCallback() { privacyItemController.addCallback(callback) verify(appOpsController).addCallback(eq(PrivacyItemController.OPS), any(AppOpsController.Callback::class.java)) testableLooper.processAllMessages() verify(callback).privacyChanged(anyList()) } @Test fun testSetListeningTrue() { privacyItemController.setListening(true) verify(appOpsController).addCallback(eq(PrivacyItemController.OPS), any(AppOpsController.Callback::class.java)) } @Test fun testSetListeningFalse() { privacyItemController.setListening(true) Loading @@ -121,7 +133,7 @@ class PrivacyItemControllerTest : SysuiTestCase() { AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 1))) .`when`(appOpsController).getActiveAppOpsForUser(anyInt()) privacyItemController.setListening(true) privacyItemController.addCallback(callback) testableLooper.processAllMessages() verify(callback).privacyChanged(capture(argCaptor)) assertEquals(1, argCaptor.value.size) Loading @@ -131,7 +143,7 @@ class PrivacyItemControllerTest : SysuiTestCase() { fun testSystemApps() { doReturn(listOf(AppOpItem(AppOpsManager.OP_COARSE_LOCATION, SYSTEM_UID, TEST_PACKAGE_NAME, 0))).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) privacyItemController.setListening(true) privacyItemController.addCallback(callback) testableLooper.processAllMessages() verify(callback).privacyChanged(capture(argCaptor)) assertEquals(1, argCaptor.value.size) Loading @@ -142,8 +154,8 @@ class PrivacyItemControllerTest : SysuiTestCase() { @Test fun testRegisterReceiver_allUsers() { val spiedContext = spy(mContext) val itemController = PrivacyItemController(spiedContext, callback) val itemController = PrivacyItemController(spiedContext) itemController.setListening(true) verify(spiedContext, atLeastOnce()).registerReceiverAsUser( eq(itemController.userSwitcherReceiver), eq(UserHandle.ALL), any(), eq(null), eq(null)) Loading @@ -170,4 +182,54 @@ class PrivacyItemControllerTest : SysuiTestCase() { Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED)) verify(userManager).getProfiles(anyInt()) } @Test fun testAddMultipleCallbacks() { val otherCallback = mock(PrivacyItemController.Callback::class.java) privacyItemController.addCallback(callback) testableLooper.processAllMessages() verify(callback).privacyChanged(anyList()) privacyItemController.addCallback(otherCallback) testableLooper.processAllMessages() verify(otherCallback).privacyChanged(anyList()) // Adding a callback should not unnecessarily call previous ones verifyNoMoreInteractions(callback) } @Test fun testMultipleCallbacksAreUpdated() { doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) val otherCallback = mock(PrivacyItemController.Callback::class.java) privacyItemController.addCallback(callback) privacyItemController.addCallback(otherCallback) testableLooper.processAllMessages() reset(callback) reset(otherCallback) verify(appOpsController).addCallback(any<IntArray>(), capture(argCaptorCallback)) argCaptorCallback.value.onActiveStateChanged(0, TEST_UID, "", true) testableLooper.processAllMessages() verify(callback).privacyChanged(anyList()) verify(otherCallback).privacyChanged(anyList()) } @Test fun testRemoveCallback() { doReturn(emptyList<AppOpItem>()).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) val otherCallback = mock(PrivacyItemController.Callback::class.java) privacyItemController.addCallback(callback) privacyItemController.addCallback(otherCallback) testableLooper.processAllMessages() reset(callback) reset(otherCallback) verify(appOpsController).addCallback(any<IntArray>(), capture(argCaptorCallback)) privacyItemController.removeCallback(callback) argCaptorCallback.value.onActiveStateChanged(0, TEST_UID, "", true) testableLooper.processAllMessages() verify(callback, never()).privacyChanged(anyList()) verify(otherCallback).privacyChanged(anyList()) } } No newline at end of file