Loading data/etc/com.android.systemui.xml +1 −0 Original line number Diff line number Diff line Loading @@ -79,5 +79,6 @@ <permission name="android.permission.LOG_COMPAT_CHANGE" /> <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" /> <permission name="android.permission.READ_DEVICE_CONFIG" /> <permission name="android.permission.READ_SAFETY_CENTER_STATUS" /> </privapp-permissions> </permissions> packages/SystemUI/AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -319,6 +319,9 @@ <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" /> <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> <!-- To read safety center status --> <uses-permission android:name="android.permission.READ_SAFETY_CENTER_STATUS" /> <protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" /> <protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" /> <protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" /> Loading packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java +8 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ import android.os.ServiceManager; import android.os.UserManager; import android.os.Vibrator; import android.permission.PermissionManager; import android.safetycenter.SafetyCenterManager; import android.service.dreams.DreamService; import android.service.dreams.IDreamManager; import android.telecom.TelecomManager; Loading Loading @@ -476,4 +477,11 @@ public class FrameworkServicesModule { static SmartspaceManager provideSmartspaceManager(Context context) { return context.getSystemService(SmartspaceManager.class); } @Provides @Singleton static SafetyCenterManager provideSafetyCenterManager(Context context) { return context.getSystemService(SafetyCenterManager.class); } } packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt +38 −19 Original line number Diff line number Diff line package com.android.systemui.qs import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.permission.PermissionGroupUsage import android.permission.PermissionManager import android.provider.DeviceConfig import android.safetycenter.SafetyCenterManager import android.view.View import androidx.annotation.WorkerThread import com.android.internal.R import com.android.internal.logging.UiEventLogger import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.appops.AppOpsController import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.plugins.ActivityStarter import com.android.systemui.privacy.OngoingPrivacyChip import com.android.systemui.privacy.PrivacyChipEvent Loading @@ -18,7 +22,6 @@ import com.android.systemui.privacy.PrivacyItem import com.android.systemui.privacy.PrivacyItemController import com.android.systemui.privacy.logging.PrivacyLogger import com.android.systemui.statusbar.phone.StatusIconContainer import com.android.systemui.util.DeviceConfigProxy import java.util.concurrent.Executor import javax.inject.Inject import com.android.systemui.dagger.qualifiers.Background Loading Loading @@ -50,15 +53,11 @@ class HeaderPrivacyIconsController @Inject constructor( @Main private val uiExecutor: Executor, private val activityStarter: ActivityStarter, private val appOpsController: AppOpsController, private val deviceConfigProxy: DeviceConfigProxy private val broadcastDispatcher: BroadcastDispatcher, private val safetyCenterManager: SafetyCenterManager ) { companion object { const val SAFETY_CENTER_ENABLED = "safety_center_is_enabled" } var chipVisibilityListener: ChipVisibilityListener? = null private var listening = false private var micCameraIndicatorsEnabled = false private var locationIndicatorsEnabled = false Loading @@ -68,20 +67,40 @@ class HeaderPrivacyIconsController @Inject constructor( private val micSlot = privacyChip.resources.getString(R.string.status_bar_microphone) private val locationSlot = privacyChip.resources.getString(R.string.status_bar_location) private val devicePropertiesChangedListener = object : DeviceConfig.OnPropertiesChangedListener { override fun onPropertiesChanged(properties: DeviceConfig.Properties) { safetyCenterEnabled = properties.getBoolean(SAFETY_CENTER_ENABLED, false) private val safetyCenterReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { safetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabled() } } val attachStateChangeListener = object : View.OnAttachStateChangeListener { override fun onViewAttachedToWindow(v: View) { broadcastDispatcher.registerReceiver( safetyCenterReceiver, IntentFilter(SafetyCenterManager.ACTION_SAFETY_CENTER_ENABLED_CHANGED), executor = backgroundExecutor ) } override fun onViewDetachedFromWindow(v: View) { broadcastDispatcher.unregisterReceiver(safetyCenterReceiver) } } init { safetyCenterEnabled = deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, SAFETY_CENTER_ENABLED, false) deviceConfigProxy.addOnPropertiesChangedListener( DeviceConfig.NAMESPACE_PRIVACY, uiExecutor, devicePropertiesChangedListener) backgroundExecutor.execute { safetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabled() } if (privacyChip.isAttachedToWindow()) { broadcastDispatcher.registerReceiver( safetyCenterReceiver, IntentFilter(SafetyCenterManager.ACTION_SAFETY_CENTER_ENABLED_CHANGED), executor = backgroundExecutor ) } privacyChip.addOnAttachStateChangeListener(attachStateChangeListener) } private val picCallback: PrivacyItemController.Callback = Loading packages/SystemUI/tests/src/com/android/systemui/qs/HeaderPrivacyIconsControllerTest.kt +53 −27 Original line number Diff line number Diff line package com.android.systemui.qs import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.permission.PermissionManager import android.provider.DeviceConfig import android.safetycenter.SafetyCenterManager import android.testing.AndroidTestingRunner import android.view.View import androidx.test.filters.SmallTest import com.android.internal.logging.UiEventLogger import com.android.systemui.SysuiTestCase import com.android.systemui.appops.AppOpsController import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.plugins.ActivityStarter import com.android.systemui.privacy.OngoingPrivacyChip import com.android.systemui.privacy.PrivacyDialogController Loading @@ -16,30 +20,30 @@ import com.android.systemui.privacy.PrivacyItemController import com.android.systemui.privacy.logging.PrivacyLogger import com.android.systemui.statusbar.phone.StatusIconContainer import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.DeviceConfigProxy import com.android.systemui.util.DeviceConfigProxyFake import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.nullable import com.android.systemui.util.time.FakeSystemClock import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations import java.util.concurrent.Executor import org.mockito.Mockito.`when` as whenever private fun <T> eq(value: T): T = Mockito.eq(value) ?: value private fun <T> any(): T = Mockito.any<T>() @SmallTest @RunWith(AndroidTestingRunner::class) class HeaderPrivacyIconsControllerTest : SysuiTestCase() { companion object { const val SAFETY_CENTER_ENABLED = "safety_center_is_enabled" } @Mock private lateinit var privacyItemController: PrivacyItemController @Mock Loading @@ -55,14 +59,16 @@ class HeaderPrivacyIconsControllerTest : SysuiTestCase() { @Mock private lateinit var permissionManager: PermissionManager @Mock private lateinit var backgroundExecutor: Executor @Mock private lateinit var activityStarter: ActivityStarter @Mock private lateinit var appOpsController: AppOpsController @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher @Mock private lateinit var safetyCenterManager: SafetyCenterManager private val uiExecutor = FakeExecutor(FakeSystemClock()) private lateinit var deviceConfigProxy: DeviceConfigProxy private val backgroundExecutor = FakeExecutor(FakeSystemClock()) private lateinit var cameraSlotName: String private lateinit var microphoneSlotName: String private lateinit var locationSlotName: String Loading @@ -73,11 +79,11 @@ class HeaderPrivacyIconsControllerTest : SysuiTestCase() { MockitoAnnotations.initMocks(this) whenever(privacyChip.context).thenReturn(context) whenever(privacyChip.resources).thenReturn(context.resources) whenever(privacyChip.isAttachedToWindow).thenReturn(true) cameraSlotName = context.getString(com.android.internal.R.string.status_bar_camera) microphoneSlotName = context.getString(com.android.internal.R.string.status_bar_microphone) locationSlotName = context.getString(com.android.internal.R.string.status_bar_location) deviceConfigProxy = DeviceConfigProxyFake() controller = HeaderPrivacyIconsController( privacyItemController, Loading @@ -91,8 +97,11 @@ class HeaderPrivacyIconsControllerTest : SysuiTestCase() { uiExecutor, activityStarter, appOpsController, deviceConfigProxy broadcastDispatcher, safetyCenterManager ) backgroundExecutor.runAllReady() } @Test Loading Loading @@ -141,19 +150,25 @@ class HeaderPrivacyIconsControllerTest : SysuiTestCase() { @Test fun testPrivacyChipClicked() { changeProperty(SAFETY_CENTER_ENABLED, false) whenever(safetyCenterManager.isSafetyCenterEnabled).thenReturn(false) controller.onParentVisible() val captor = argumentCaptor<View.OnClickListener>() verify(privacyChip).setOnClickListener(capture(captor)) captor.value.onClick(privacyChip) verify(privacyDialogController).showDialog(any(Context::class.java)) } @Test fun testSafetyCenterFlag() { changeProperty(SAFETY_CENTER_ENABLED, true) val receiverCaptor = argumentCaptor<BroadcastReceiver>() whenever(safetyCenterManager.isSafetyCenterEnabled).thenReturn(true) verify(broadcastDispatcher).registerReceiver(capture(receiverCaptor), any(), any(), nullable(), anyInt()) receiverCaptor.value.onReceive( context, Intent(SafetyCenterManager.ACTION_SAFETY_CENTER_ENABLED_CHANGED) ) backgroundExecutor.runAllReady() controller.onParentVisible() val captor = argumentCaptor<View.OnClickListener>() verify(privacyChip).setOnClickListener(capture(captor)) Loading @@ -161,18 +176,29 @@ class HeaderPrivacyIconsControllerTest : SysuiTestCase() { verify(privacyDialogController, never()).showDialog(any(Context::class.java)) } @Test fun testBroadcastReceiverUnregisteredWhenChipDetached() { whenever(safetyCenterManager.isSafetyCenterEnabled).thenReturn(false) controller.attachStateChangeListener.onViewDetachedFromWindow(privacyChip) backgroundExecutor.runAllReady() val broadcastReceiverCaptor = argumentCaptor<BroadcastReceiver>() verify(broadcastDispatcher).unregisterReceiver(capture(broadcastReceiverCaptor)) } @Test fun testBroadcastReceiverRegisteredWhenChipAttached() { whenever(safetyCenterManager.isSafetyCenterEnabled).thenReturn(false) controller.attachStateChangeListener.onViewAttachedToWindow(privacyChip) backgroundExecutor.runAllReady() val broadcastReceiverCaptor = argumentCaptor<BroadcastReceiver>() val intentFilterCaptor = argumentCaptor<IntentFilter>() // Broadcast receiver is registered on init and when privacy chip is attached verify(broadcastDispatcher, times(2)).registerReceiver(capture(broadcastReceiverCaptor), capture(intentFilterCaptor), any(), nullable(), anyInt()) } private fun setPrivacyController(micCamera: Boolean, location: Boolean) { whenever(privacyItemController.micCameraAvailable).thenReturn(micCamera) whenever(privacyItemController.locationAvailable).thenReturn(location) } private fun changeProperty(name: String, value: Boolean?) { deviceConfigProxy.setProperty( DeviceConfig.NAMESPACE_PRIVACY, name, value?.toString(), false ) uiExecutor.runAllReady() } } No newline at end of file Loading
data/etc/com.android.systemui.xml +1 −0 Original line number Diff line number Diff line Loading @@ -79,5 +79,6 @@ <permission name="android.permission.LOG_COMPAT_CHANGE" /> <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" /> <permission name="android.permission.READ_DEVICE_CONFIG" /> <permission name="android.permission.READ_SAFETY_CENTER_STATUS" /> </privapp-permissions> </permissions>
packages/SystemUI/AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -319,6 +319,9 @@ <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" /> <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> <!-- To read safety center status --> <uses-permission android:name="android.permission.READ_SAFETY_CENTER_STATUS" /> <protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" /> <protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" /> <protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" /> Loading
packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java +8 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ import android.os.ServiceManager; import android.os.UserManager; import android.os.Vibrator; import android.permission.PermissionManager; import android.safetycenter.SafetyCenterManager; import android.service.dreams.DreamService; import android.service.dreams.IDreamManager; import android.telecom.TelecomManager; Loading Loading @@ -476,4 +477,11 @@ public class FrameworkServicesModule { static SmartspaceManager provideSmartspaceManager(Context context) { return context.getSystemService(SmartspaceManager.class); } @Provides @Singleton static SafetyCenterManager provideSafetyCenterManager(Context context) { return context.getSystemService(SafetyCenterManager.class); } }
packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt +38 −19 Original line number Diff line number Diff line package com.android.systemui.qs import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.permission.PermissionGroupUsage import android.permission.PermissionManager import android.provider.DeviceConfig import android.safetycenter.SafetyCenterManager import android.view.View import androidx.annotation.WorkerThread import com.android.internal.R import com.android.internal.logging.UiEventLogger import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.appops.AppOpsController import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.plugins.ActivityStarter import com.android.systemui.privacy.OngoingPrivacyChip import com.android.systemui.privacy.PrivacyChipEvent Loading @@ -18,7 +22,6 @@ import com.android.systemui.privacy.PrivacyItem import com.android.systemui.privacy.PrivacyItemController import com.android.systemui.privacy.logging.PrivacyLogger import com.android.systemui.statusbar.phone.StatusIconContainer import com.android.systemui.util.DeviceConfigProxy import java.util.concurrent.Executor import javax.inject.Inject import com.android.systemui.dagger.qualifiers.Background Loading Loading @@ -50,15 +53,11 @@ class HeaderPrivacyIconsController @Inject constructor( @Main private val uiExecutor: Executor, private val activityStarter: ActivityStarter, private val appOpsController: AppOpsController, private val deviceConfigProxy: DeviceConfigProxy private val broadcastDispatcher: BroadcastDispatcher, private val safetyCenterManager: SafetyCenterManager ) { companion object { const val SAFETY_CENTER_ENABLED = "safety_center_is_enabled" } var chipVisibilityListener: ChipVisibilityListener? = null private var listening = false private var micCameraIndicatorsEnabled = false private var locationIndicatorsEnabled = false Loading @@ -68,20 +67,40 @@ class HeaderPrivacyIconsController @Inject constructor( private val micSlot = privacyChip.resources.getString(R.string.status_bar_microphone) private val locationSlot = privacyChip.resources.getString(R.string.status_bar_location) private val devicePropertiesChangedListener = object : DeviceConfig.OnPropertiesChangedListener { override fun onPropertiesChanged(properties: DeviceConfig.Properties) { safetyCenterEnabled = properties.getBoolean(SAFETY_CENTER_ENABLED, false) private val safetyCenterReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { safetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabled() } } val attachStateChangeListener = object : View.OnAttachStateChangeListener { override fun onViewAttachedToWindow(v: View) { broadcastDispatcher.registerReceiver( safetyCenterReceiver, IntentFilter(SafetyCenterManager.ACTION_SAFETY_CENTER_ENABLED_CHANGED), executor = backgroundExecutor ) } override fun onViewDetachedFromWindow(v: View) { broadcastDispatcher.unregisterReceiver(safetyCenterReceiver) } } init { safetyCenterEnabled = deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, SAFETY_CENTER_ENABLED, false) deviceConfigProxy.addOnPropertiesChangedListener( DeviceConfig.NAMESPACE_PRIVACY, uiExecutor, devicePropertiesChangedListener) backgroundExecutor.execute { safetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabled() } if (privacyChip.isAttachedToWindow()) { broadcastDispatcher.registerReceiver( safetyCenterReceiver, IntentFilter(SafetyCenterManager.ACTION_SAFETY_CENTER_ENABLED_CHANGED), executor = backgroundExecutor ) } privacyChip.addOnAttachStateChangeListener(attachStateChangeListener) } private val picCallback: PrivacyItemController.Callback = Loading
packages/SystemUI/tests/src/com/android/systemui/qs/HeaderPrivacyIconsControllerTest.kt +53 −27 Original line number Diff line number Diff line package com.android.systemui.qs import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.permission.PermissionManager import android.provider.DeviceConfig import android.safetycenter.SafetyCenterManager import android.testing.AndroidTestingRunner import android.view.View import androidx.test.filters.SmallTest import com.android.internal.logging.UiEventLogger import com.android.systemui.SysuiTestCase import com.android.systemui.appops.AppOpsController import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.plugins.ActivityStarter import com.android.systemui.privacy.OngoingPrivacyChip import com.android.systemui.privacy.PrivacyDialogController Loading @@ -16,30 +20,30 @@ import com.android.systemui.privacy.PrivacyItemController import com.android.systemui.privacy.logging.PrivacyLogger import com.android.systemui.statusbar.phone.StatusIconContainer import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.DeviceConfigProxy import com.android.systemui.util.DeviceConfigProxyFake import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.nullable import com.android.systemui.util.time.FakeSystemClock import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations import java.util.concurrent.Executor import org.mockito.Mockito.`when` as whenever private fun <T> eq(value: T): T = Mockito.eq(value) ?: value private fun <T> any(): T = Mockito.any<T>() @SmallTest @RunWith(AndroidTestingRunner::class) class HeaderPrivacyIconsControllerTest : SysuiTestCase() { companion object { const val SAFETY_CENTER_ENABLED = "safety_center_is_enabled" } @Mock private lateinit var privacyItemController: PrivacyItemController @Mock Loading @@ -55,14 +59,16 @@ class HeaderPrivacyIconsControllerTest : SysuiTestCase() { @Mock private lateinit var permissionManager: PermissionManager @Mock private lateinit var backgroundExecutor: Executor @Mock private lateinit var activityStarter: ActivityStarter @Mock private lateinit var appOpsController: AppOpsController @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher @Mock private lateinit var safetyCenterManager: SafetyCenterManager private val uiExecutor = FakeExecutor(FakeSystemClock()) private lateinit var deviceConfigProxy: DeviceConfigProxy private val backgroundExecutor = FakeExecutor(FakeSystemClock()) private lateinit var cameraSlotName: String private lateinit var microphoneSlotName: String private lateinit var locationSlotName: String Loading @@ -73,11 +79,11 @@ class HeaderPrivacyIconsControllerTest : SysuiTestCase() { MockitoAnnotations.initMocks(this) whenever(privacyChip.context).thenReturn(context) whenever(privacyChip.resources).thenReturn(context.resources) whenever(privacyChip.isAttachedToWindow).thenReturn(true) cameraSlotName = context.getString(com.android.internal.R.string.status_bar_camera) microphoneSlotName = context.getString(com.android.internal.R.string.status_bar_microphone) locationSlotName = context.getString(com.android.internal.R.string.status_bar_location) deviceConfigProxy = DeviceConfigProxyFake() controller = HeaderPrivacyIconsController( privacyItemController, Loading @@ -91,8 +97,11 @@ class HeaderPrivacyIconsControllerTest : SysuiTestCase() { uiExecutor, activityStarter, appOpsController, deviceConfigProxy broadcastDispatcher, safetyCenterManager ) backgroundExecutor.runAllReady() } @Test Loading Loading @@ -141,19 +150,25 @@ class HeaderPrivacyIconsControllerTest : SysuiTestCase() { @Test fun testPrivacyChipClicked() { changeProperty(SAFETY_CENTER_ENABLED, false) whenever(safetyCenterManager.isSafetyCenterEnabled).thenReturn(false) controller.onParentVisible() val captor = argumentCaptor<View.OnClickListener>() verify(privacyChip).setOnClickListener(capture(captor)) captor.value.onClick(privacyChip) verify(privacyDialogController).showDialog(any(Context::class.java)) } @Test fun testSafetyCenterFlag() { changeProperty(SAFETY_CENTER_ENABLED, true) val receiverCaptor = argumentCaptor<BroadcastReceiver>() whenever(safetyCenterManager.isSafetyCenterEnabled).thenReturn(true) verify(broadcastDispatcher).registerReceiver(capture(receiverCaptor), any(), any(), nullable(), anyInt()) receiverCaptor.value.onReceive( context, Intent(SafetyCenterManager.ACTION_SAFETY_CENTER_ENABLED_CHANGED) ) backgroundExecutor.runAllReady() controller.onParentVisible() val captor = argumentCaptor<View.OnClickListener>() verify(privacyChip).setOnClickListener(capture(captor)) Loading @@ -161,18 +176,29 @@ class HeaderPrivacyIconsControllerTest : SysuiTestCase() { verify(privacyDialogController, never()).showDialog(any(Context::class.java)) } @Test fun testBroadcastReceiverUnregisteredWhenChipDetached() { whenever(safetyCenterManager.isSafetyCenterEnabled).thenReturn(false) controller.attachStateChangeListener.onViewDetachedFromWindow(privacyChip) backgroundExecutor.runAllReady() val broadcastReceiverCaptor = argumentCaptor<BroadcastReceiver>() verify(broadcastDispatcher).unregisterReceiver(capture(broadcastReceiverCaptor)) } @Test fun testBroadcastReceiverRegisteredWhenChipAttached() { whenever(safetyCenterManager.isSafetyCenterEnabled).thenReturn(false) controller.attachStateChangeListener.onViewAttachedToWindow(privacyChip) backgroundExecutor.runAllReady() val broadcastReceiverCaptor = argumentCaptor<BroadcastReceiver>() val intentFilterCaptor = argumentCaptor<IntentFilter>() // Broadcast receiver is registered on init and when privacy chip is attached verify(broadcastDispatcher, times(2)).registerReceiver(capture(broadcastReceiverCaptor), capture(intentFilterCaptor), any(), nullable(), anyInt()) } private fun setPrivacyController(micCamera: Boolean, location: Boolean) { whenever(privacyItemController.micCameraAvailable).thenReturn(micCamera) whenever(privacyItemController.locationAvailable).thenReturn(location) } private fun changeProperty(name: String, value: Boolean?) { deviceConfigProxy.setProperty( DeviceConfig.NAMESPACE_PRIVACY, name, value?.toString(), false ) uiExecutor.runAllReady() } } No newline at end of file