Loading core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +5 −0 Original line number Diff line number Diff line Loading @@ -132,6 +132,11 @@ public final class SystemUiDeviceConfigFlags { */ public static final String PROPERTY_MIC_CAMERA_ENABLED = "camera_mic_icons_enabled"; /** * Whether to show app ops chip for location. */ public static final String PROPERTY_LOCATION_INDICATORS_ENABLED = "location_indicators_enabled"; // Flags related to Assistant /** Loading packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt +24 −4 Original line number Diff line number Diff line Loading @@ -69,8 +69,10 @@ class PrivacyItemController @Inject constructor( private const val ALL_INDICATORS = SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED private const val MIC_CAMERA = SystemUiDeviceConfigFlags.PROPERTY_MIC_CAMERA_ENABLED private const val LOCATION = SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_ENABLED private const val DEFAULT_ALL_INDICATORS = false private const val DEFAULT_MIC_CAMERA = true private const val DEFAULT_LOCATION = false } @VisibleForTesting Loading @@ -88,6 +90,11 @@ class PrivacyItemController @Inject constructor( return true } private fun isLocationEnabled(): Boolean { return deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, LOCATION, DEFAULT_LOCATION) } private var currentUserIds = emptyList<Int>() private var listening = false private val callbacks = mutableListOf<WeakReference<Callback>>() Loading @@ -107,13 +114,15 @@ class PrivacyItemController @Inject constructor( private set var micCameraAvailable = isMicCameraEnabled() private set var locationAvailable = isLocationEnabled() private val devicePropertiesChangedListener = object : DeviceConfig.OnPropertiesChangedListener { override fun onPropertiesChanged(properties: DeviceConfig.Properties) { if (DeviceConfig.NAMESPACE_PRIVACY.equals(properties.getNamespace()) && (properties.keyset.contains(ALL_INDICATORS) || properties.keyset.contains(MIC_CAMERA))) { properties.keyset.contains(MIC_CAMERA) || properties.keyset.contains(LOCATION))) { // Running on the ui executor so can iterate on callbacks if (properties.keyset.contains(ALL_INDICATORS)) { Loading @@ -126,6 +135,10 @@ class PrivacyItemController @Inject constructor( // micCameraAvailable = properties.getBoolean(MIC_CAMERA, DEFAULT_MIC_CAMERA) // callbacks.forEach { it.get()?.onFlagMicCameraChanged(micCameraAvailable) } // } if (properties.keyset.contains(LOCATION)) { locationAvailable = properties.getBoolean(LOCATION, DEFAULT_LOCATION) callbacks.forEach { it.get()?.onFlagLocationChanged(locationAvailable) } } internalUiExecutor.updateListeningState() } } Loading @@ -139,7 +152,8 @@ class PrivacyItemController @Inject constructor( active: Boolean ) { // Check if we care about this code right now if (!allIndicatorsAvailable && code in OPS_LOCATION) { if (!allIndicatorsAvailable && (code in OPS_LOCATION && !locationAvailable)) { return } val userId = UserHandle.getUserId(uid) Loading Loading @@ -195,7 +209,8 @@ class PrivacyItemController @Inject constructor( * main thread. */ private fun setListeningState() { val listen = !callbacks.isEmpty() and (allIndicatorsAvailable || micCameraAvailable) val listen = !callbacks.isEmpty() and (allIndicatorsAvailable || micCameraAvailable || locationAvailable) if (listening == listen) return listening = listen if (listening) { Loading Loading @@ -258,7 +273,9 @@ class PrivacyItemController @Inject constructor( AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE else -> return null } if (type == PrivacyType.TYPE_LOCATION && !allIndicatorsAvailable) return null if (type == PrivacyType.TYPE_LOCATION && (!allIndicatorsAvailable && !locationAvailable)) { return null } val app = PrivacyApplication(appOpItem.packageName, appOpItem.uid) return PrivacyItem(type, app) } Loading @@ -271,6 +288,9 @@ class PrivacyItemController @Inject constructor( @JvmDefault fun onFlagMicCameraChanged(flag: Boolean) {} @JvmDefault fun onFlagLocationChanged(flag: Boolean) {} } private class NotifyChangesToCallback( Loading packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java +13 −2 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader private AlarmClockInfo mNextAlarm; private boolean mAllIndicatorsEnabled; private boolean mMicCameraIndicatorsEnabled; private boolean mLocationIndicatorsEnabled; private boolean mPrivacyChipLogged; private int mRingerMode = AudioManager.RINGER_MODE_NORMAL; Loading Loading @@ -156,6 +157,14 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader } } @Override public void onFlagLocationChanged(boolean flag) { if (mLocationIndicatorsEnabled != flag) { mLocationIndicatorsEnabled = flag; update(); } } private void update() { StatusIconContainer iconContainer = mView.requireViewById(R.id.statusIcons); iconContainer.setIgnoredSlots(getIgnoredIconSlots()); Loading Loading @@ -252,6 +261,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable(); mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable(); mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable(); setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE); Loading Loading @@ -292,6 +302,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader // Get the most up to date info mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable(); mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable(); mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable(); mPrivacyItemController.addCallback(mPICCallback); } else { mZenModeController.removeCallback(mZenModeControllerCallback); Loading Loading @@ -323,7 +334,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader com.android.internal.R.string.status_bar_camera)); ignored.add(mView.getResources().getString( com.android.internal.R.string.status_bar_microphone)); if (mAllIndicatorsEnabled) { if (mAllIndicatorsEnabled || mLocationIndicatorsEnabled) { ignored.add(mView.getResources().getString( com.android.internal.R.string.status_bar_location)); } Loading @@ -333,7 +344,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader } private boolean getChipEnabled() { return mMicCameraIndicatorsEnabled || mAllIndicatorsEnabled; return mMicCameraIndicatorsEnabled || mLocationIndicatorsEnabled || mAllIndicatorsEnabled; } private boolean isZenOverridingRinger() { Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +6 −2 Original line number Diff line number Diff line Loading @@ -671,14 +671,18 @@ public class PhoneStatusBarPolicy mIconController.setIconVisibility(mSlotCamera, showCamera); mIconController.setIconVisibility(mSlotMicrophone, showMicrophone); if (mPrivacyItemController.getAllIndicatorsAvailable()) { if (mPrivacyItemController.getAllIndicatorsAvailable() || mPrivacyItemController.getLocationAvailable()) { mIconController.setIconVisibility(mSlotLocation, showLocation); } } @Override public void onLocationActiveChanged(boolean active) { if (!mPrivacyItemController.getAllIndicatorsAvailable()) updateLocationFromController(); if (!mPrivacyItemController.getAllIndicatorsAvailable() && !mPrivacyItemController.getLocationAvailable()) { updateLocationFromController(); } } // Updates the status view based on the current state of location requests. Loading packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt +19 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() { private const val ALL_INDICATORS = SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED private const val MIC_CAMERA = SystemUiDeviceConfigFlags.PROPERTY_MIC_CAMERA_ENABLED private const val LOCATION = SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_ENABLED } @Mock Loading Loading @@ -115,6 +116,15 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() { assertFalse(privacyItemController.allIndicatorsAvailable) } @Test fun testLocationChanged() { changeLocation(true) executor.runAllReady() verify(callback).onFlagLocationChanged(true) assertTrue(privacyItemController.locationAvailable) } @Test fun testAllChanged() { changeAll(true) Loading Loading @@ -157,6 +167,14 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() { verify(appOpsController).addCallback(eq(PrivacyItemController.OPS), any()) } @Test fun testLocation_listening() { changeLocation(true) executor.runAllReady() verify(appOpsController).addCallback(eq(PrivacyItemController.OPS), any()) } @Test @Ignore // TODO(b/168209929) fun testAllFalse_notListening() { Loading Loading @@ -205,6 +223,7 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() { } private fun changeMicCamera(value: Boolean?) = changeProperty(MIC_CAMERA, value) private fun changeLocation(value: Boolean?) = changeProperty(LOCATION, value) private fun changeAll(value: Boolean?) = changeProperty(ALL_INDICATORS, value) private fun changeProperty(name: String, value: Boolean?) { Loading Loading
core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +5 −0 Original line number Diff line number Diff line Loading @@ -132,6 +132,11 @@ public final class SystemUiDeviceConfigFlags { */ public static final String PROPERTY_MIC_CAMERA_ENABLED = "camera_mic_icons_enabled"; /** * Whether to show app ops chip for location. */ public static final String PROPERTY_LOCATION_INDICATORS_ENABLED = "location_indicators_enabled"; // Flags related to Assistant /** Loading
packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt +24 −4 Original line number Diff line number Diff line Loading @@ -69,8 +69,10 @@ class PrivacyItemController @Inject constructor( private const val ALL_INDICATORS = SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED private const val MIC_CAMERA = SystemUiDeviceConfigFlags.PROPERTY_MIC_CAMERA_ENABLED private const val LOCATION = SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_ENABLED private const val DEFAULT_ALL_INDICATORS = false private const val DEFAULT_MIC_CAMERA = true private const val DEFAULT_LOCATION = false } @VisibleForTesting Loading @@ -88,6 +90,11 @@ class PrivacyItemController @Inject constructor( return true } private fun isLocationEnabled(): Boolean { return deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, LOCATION, DEFAULT_LOCATION) } private var currentUserIds = emptyList<Int>() private var listening = false private val callbacks = mutableListOf<WeakReference<Callback>>() Loading @@ -107,13 +114,15 @@ class PrivacyItemController @Inject constructor( private set var micCameraAvailable = isMicCameraEnabled() private set var locationAvailable = isLocationEnabled() private val devicePropertiesChangedListener = object : DeviceConfig.OnPropertiesChangedListener { override fun onPropertiesChanged(properties: DeviceConfig.Properties) { if (DeviceConfig.NAMESPACE_PRIVACY.equals(properties.getNamespace()) && (properties.keyset.contains(ALL_INDICATORS) || properties.keyset.contains(MIC_CAMERA))) { properties.keyset.contains(MIC_CAMERA) || properties.keyset.contains(LOCATION))) { // Running on the ui executor so can iterate on callbacks if (properties.keyset.contains(ALL_INDICATORS)) { Loading @@ -126,6 +135,10 @@ class PrivacyItemController @Inject constructor( // micCameraAvailable = properties.getBoolean(MIC_CAMERA, DEFAULT_MIC_CAMERA) // callbacks.forEach { it.get()?.onFlagMicCameraChanged(micCameraAvailable) } // } if (properties.keyset.contains(LOCATION)) { locationAvailable = properties.getBoolean(LOCATION, DEFAULT_LOCATION) callbacks.forEach { it.get()?.onFlagLocationChanged(locationAvailable) } } internalUiExecutor.updateListeningState() } } Loading @@ -139,7 +152,8 @@ class PrivacyItemController @Inject constructor( active: Boolean ) { // Check if we care about this code right now if (!allIndicatorsAvailable && code in OPS_LOCATION) { if (!allIndicatorsAvailable && (code in OPS_LOCATION && !locationAvailable)) { return } val userId = UserHandle.getUserId(uid) Loading Loading @@ -195,7 +209,8 @@ class PrivacyItemController @Inject constructor( * main thread. */ private fun setListeningState() { val listen = !callbacks.isEmpty() and (allIndicatorsAvailable || micCameraAvailable) val listen = !callbacks.isEmpty() and (allIndicatorsAvailable || micCameraAvailable || locationAvailable) if (listening == listen) return listening = listen if (listening) { Loading Loading @@ -258,7 +273,9 @@ class PrivacyItemController @Inject constructor( AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE else -> return null } if (type == PrivacyType.TYPE_LOCATION && !allIndicatorsAvailable) return null if (type == PrivacyType.TYPE_LOCATION && (!allIndicatorsAvailable && !locationAvailable)) { return null } val app = PrivacyApplication(appOpItem.packageName, appOpItem.uid) return PrivacyItem(type, app) } Loading @@ -271,6 +288,9 @@ class PrivacyItemController @Inject constructor( @JvmDefault fun onFlagMicCameraChanged(flag: Boolean) {} @JvmDefault fun onFlagLocationChanged(flag: Boolean) {} } private class NotifyChangesToCallback( Loading
packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java +13 −2 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader private AlarmClockInfo mNextAlarm; private boolean mAllIndicatorsEnabled; private boolean mMicCameraIndicatorsEnabled; private boolean mLocationIndicatorsEnabled; private boolean mPrivacyChipLogged; private int mRingerMode = AudioManager.RINGER_MODE_NORMAL; Loading Loading @@ -156,6 +157,14 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader } } @Override public void onFlagLocationChanged(boolean flag) { if (mLocationIndicatorsEnabled != flag) { mLocationIndicatorsEnabled = flag; update(); } } private void update() { StatusIconContainer iconContainer = mView.requireViewById(R.id.statusIcons); iconContainer.setIgnoredSlots(getIgnoredIconSlots()); Loading Loading @@ -252,6 +261,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable(); mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable(); mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable(); setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE); Loading Loading @@ -292,6 +302,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader // Get the most up to date info mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable(); mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable(); mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable(); mPrivacyItemController.addCallback(mPICCallback); } else { mZenModeController.removeCallback(mZenModeControllerCallback); Loading Loading @@ -323,7 +334,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader com.android.internal.R.string.status_bar_camera)); ignored.add(mView.getResources().getString( com.android.internal.R.string.status_bar_microphone)); if (mAllIndicatorsEnabled) { if (mAllIndicatorsEnabled || mLocationIndicatorsEnabled) { ignored.add(mView.getResources().getString( com.android.internal.R.string.status_bar_location)); } Loading @@ -333,7 +344,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader } private boolean getChipEnabled() { return mMicCameraIndicatorsEnabled || mAllIndicatorsEnabled; return mMicCameraIndicatorsEnabled || mLocationIndicatorsEnabled || mAllIndicatorsEnabled; } private boolean isZenOverridingRinger() { Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +6 −2 Original line number Diff line number Diff line Loading @@ -671,14 +671,18 @@ public class PhoneStatusBarPolicy mIconController.setIconVisibility(mSlotCamera, showCamera); mIconController.setIconVisibility(mSlotMicrophone, showMicrophone); if (mPrivacyItemController.getAllIndicatorsAvailable()) { if (mPrivacyItemController.getAllIndicatorsAvailable() || mPrivacyItemController.getLocationAvailable()) { mIconController.setIconVisibility(mSlotLocation, showLocation); } } @Override public void onLocationActiveChanged(boolean active) { if (!mPrivacyItemController.getAllIndicatorsAvailable()) updateLocationFromController(); if (!mPrivacyItemController.getAllIndicatorsAvailable() && !mPrivacyItemController.getLocationAvailable()) { updateLocationFromController(); } } // Updates the status view based on the current state of location requests. Loading
packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt +19 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() { private const val ALL_INDICATORS = SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED private const val MIC_CAMERA = SystemUiDeviceConfigFlags.PROPERTY_MIC_CAMERA_ENABLED private const val LOCATION = SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_ENABLED } @Mock Loading Loading @@ -115,6 +116,15 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() { assertFalse(privacyItemController.allIndicatorsAvailable) } @Test fun testLocationChanged() { changeLocation(true) executor.runAllReady() verify(callback).onFlagLocationChanged(true) assertTrue(privacyItemController.locationAvailable) } @Test fun testAllChanged() { changeAll(true) Loading Loading @@ -157,6 +167,14 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() { verify(appOpsController).addCallback(eq(PrivacyItemController.OPS), any()) } @Test fun testLocation_listening() { changeLocation(true) executor.runAllReady() verify(appOpsController).addCallback(eq(PrivacyItemController.OPS), any()) } @Test @Ignore // TODO(b/168209929) fun testAllFalse_notListening() { Loading Loading @@ -205,6 +223,7 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() { } private fun changeMicCamera(value: Boolean?) = changeProperty(MIC_CAMERA, value) private fun changeLocation(value: Boolean?) = changeProperty(LOCATION, value) private fun changeAll(value: Boolean?) = changeProperty(ALL_INDICATORS, value) private fun changeProperty(name: String, value: Boolean?) { Loading