Loading core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +6 −1 Original line number Diff line number Diff line Loading @@ -123,10 +123,15 @@ public final class SystemUiDeviceConfigFlags { // Flag related to Privacy Indicators /** * Whether the Permissions Hub is showing. * Whether to show the complete ongoing app ops chip. */ public static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_2_enabled"; /** * Whether to show app ops chip for just microphone + camera. */ public static final String PROPERTY_MIC_CAMERA_ENABLED = "camera_mic_icons_enabled"; // Flags related to Assistant /** Loading packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java +5 −3 Original line number Diff line number Diff line Loading @@ -279,9 +279,11 @@ public class AppOpsControllerImpl implements AppOpsController, * @return {@code true} iff the app-op for should be shown to the user */ private boolean isUserVisible(int appOpCode, int uid, String packageName) { // currently OP_SYSTEM_ALERT_WINDOW does not correspond to a platform permission // which may be user senstive, so for now always show it to the user. if (appOpCode == AppOpsManager.OP_SYSTEM_ALERT_WINDOW) { // currently OP_SYSTEM_ALERT_WINDOW and OP_MONITOR_HIGH_POWER_LOCATION // does not correspond to a platform permission // which may be user sensitive, so for now always show it to the user. if (appOpCode == AppOpsManager.OP_SYSTEM_ALERT_WINDOW || appOpCode == AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION) { return true; } Loading packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt +56 −21 Original line number Diff line number Diff line Loading @@ -45,27 +45,32 @@ import javax.inject.Singleton @Singleton class PrivacyItemController @Inject constructor( context: Context, private val appOpsController: AppOpsController, @Main uiExecutor: DelayableExecutor, @Background private val bgExecutor: Executor, private val broadcastDispatcher: BroadcastDispatcher, private val deviceConfigProxy: DeviceConfigProxy, private val userManager: UserManager, dumpManager: DumpManager ) : Dumpable { @VisibleForTesting internal companion object { val OPS = intArrayOf(AppOpsManager.OP_CAMERA, AppOpsManager.OP_RECORD_AUDIO, val OPS_MIC_CAMERA = intArrayOf(AppOpsManager.OP_CAMERA, AppOpsManager.OP_RECORD_AUDIO) val OPS_LOCATION = intArrayOf( AppOpsManager.OP_COARSE_LOCATION, AppOpsManager.OP_FINE_LOCATION) val OPS = OPS_MIC_CAMERA + OPS_LOCATION val intentFilter = IntentFilter().apply { addAction(Intent.ACTION_USER_SWITCHED) addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE) addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE) } const val TAG = "PrivacyItemController" private const val ALL_INDICATORS = SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED private const val MIC_CAMERA = SystemUiDeviceConfigFlags.PROPERTY_MIC_CAMERA_ENABLED } @VisibleForTesting Loading @@ -73,12 +78,16 @@ class PrivacyItemController @Inject constructor( @Synchronized get() = field.toList() // Returns a shallow copy of the list @Synchronized set fun isPermissionsHubEnabled(): Boolean { fun isAllIndicatorsEnabled(): Boolean { return deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED, false) ALL_INDICATORS, false) } private fun isMicCameraEnabled(): Boolean { return deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, MIC_CAMERA, false) } private val userManager = context.getSystemService(UserManager::class.java) private var currentUserIds = emptyList<Int>() private var listening = false private val callbacks = mutableListOf<WeakReference<Callback>>() Loading @@ -86,7 +95,7 @@ class PrivacyItemController @Inject constructor( private val notifyChanges = Runnable { val list = privacyList callbacks.forEach { it.get()?.privacyChanged(list) } callbacks.forEach { it.get()?.onPrivacyItemsChanged(list) } } private val updateListAndNotifyChanges = Runnable { Loading @@ -94,16 +103,28 @@ class PrivacyItemController @Inject constructor( uiExecutor.execute(notifyChanges) } private var indicatorsAvailable = isPermissionsHubEnabled() @VisibleForTesting internal val devicePropertiesChangedListener = var allIndicatorsAvailable = isAllIndicatorsEnabled() private set var micCameraAvailable = isMicCameraEnabled() private set private val devicePropertiesChangedListener = object : DeviceConfig.OnPropertiesChangedListener { override fun onPropertiesChanged(properties: DeviceConfig.Properties) { if (DeviceConfig.NAMESPACE_PRIVACY.equals(properties.getNamespace()) && properties.getKeyset().contains( SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED)) { indicatorsAvailable = properties.getBoolean( SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED, false) (properties.keyset.contains(ALL_INDICATORS) || properties.keyset.contains(MIC_CAMERA))) { // Running on the ui executor so can iterate on callbacks if (properties.keyset.contains(ALL_INDICATORS)) { allIndicatorsAvailable = properties.getBoolean(ALL_INDICATORS, false) callbacks.forEach { it.get()?.onFlagAllChanged(allIndicatorsAvailable) } } if (properties.keyset.contains(MIC_CAMERA)) { micCameraAvailable = properties.getBoolean(MIC_CAMERA, false) callbacks.forEach { it.get()?.onFlagMicCameraChanged(micCameraAvailable) } } internalUiExecutor.updateListeningState() } } Loading @@ -116,6 +137,10 @@ class PrivacyItemController @Inject constructor( packageName: String, active: Boolean ) { // Check if we care about this code right now if (!allIndicatorsAvailable && code in OPS_LOCATION) { return } val userId = UserHandle.getUserId(uid) if (userId in currentUserIds) { update(false) Loading Loading @@ -159,13 +184,16 @@ class PrivacyItemController @Inject constructor( } /** * Updates listening status based on whether there are callbacks and the indicators are enabled * Updates listening status based on whether there are callbacks and the indicators are enabled. * * Always listen to all OPS so we don't have to figure out what we should be listening to. We * still have to filter anyway. Updates are filtered in the callback. * * This is only called from private (add/remove)Callback and from the config listener, all in * main thread. */ private fun setListeningState() { val listen = !callbacks.isEmpty() and indicatorsAvailable val listen = !callbacks.isEmpty() and (allIndicatorsAvailable || micCameraAvailable) if (listening == listen) return listening = listen if (listening) { Loading Loading @@ -226,13 +254,20 @@ class PrivacyItemController @Inject constructor( AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE else -> return null } if (type == PrivacyType.TYPE_LOCATION && !allIndicatorsAvailable) return null val app = PrivacyApplication(appOpItem.packageName, appOpItem.uid) return PrivacyItem(type, app) } // Used by containing class to get notified of changes interface Callback { fun privacyChanged(privacyItems: List<PrivacyItem>) fun onPrivacyItemsChanged(privacyItems: List<PrivacyItem>) @JvmDefault fun onFlagAllChanged(flag: Boolean) {} @JvmDefault fun onFlagMicCameraChanged(flag: Boolean) {} } internal inner class Receiver : BroadcastReceiver() { Loading @@ -248,7 +283,7 @@ class PrivacyItemController @Inject constructor( private val list: List<PrivacyItem> ) : Runnable { override fun run() { callback?.privacyChanged(list) callback?.onPrivacyItemsChanged(list) } } Loading packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +43 −31 Original line number Diff line number Diff line Loading @@ -33,7 +33,6 @@ import android.media.AudioManager; import android.os.Handler; import android.os.Looper; import android.provider.AlarmClock; import android.provider.DeviceConfig; import android.provider.Settings; import android.service.notification.ZenModeConfig; import android.text.format.DateUtils; Loading @@ -59,7 +58,6 @@ import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleRegistry; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.logging.UiEventLogger; import com.android.settingslib.Utils; import com.android.systemui.BatteryMeterView; Loading Loading @@ -154,7 +152,8 @@ public class QuickStatusBarHeader extends RelativeLayout implements private Space mSpace; private BatteryMeterView mBatteryRemainingIcon; private RingerModeTracker mRingerModeTracker; private boolean mPermissionsHubEnabled; private boolean mAllIndicatorsEnabled; private boolean mMicCameraIndicatorsEnabled; private PrivacyItemController mPrivacyItemController; private final UiEventLogger mUiEventLogger; Loading @@ -173,26 +172,33 @@ public class QuickStatusBarHeader extends RelativeLayout implements private float mKeyguardExpansionFraction; private boolean mPrivacyChipLogged = false; private final DeviceConfig.OnPropertiesChangedListener mPropertiesListener = new DeviceConfig.OnPropertiesChangedListener() { private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() { @Override public void onPropertiesChanged(DeviceConfig.Properties properties) { if (DeviceConfig.NAMESPACE_PRIVACY.equals(properties.getNamespace()) && properties.getKeyset() .contains(SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED)) { mPermissionsHubEnabled = properties.getBoolean( SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED, false); StatusIconContainer iconContainer = findViewById(R.id.statusIcons); iconContainer.setIgnoredSlots(getIgnoredIconSlots()); public void onPrivacyItemsChanged(List<PrivacyItem> privacyItems) { mPrivacyChip.setPrivacyList(privacyItems); setChipVisibility(!privacyItems.isEmpty()); } @Override public void onFlagAllChanged(boolean flag) { if (mAllIndicatorsEnabled != flag) { mAllIndicatorsEnabled = flag; update(); } } }; private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() { @Override public void privacyChanged(List<PrivacyItem> privacyItems) { mPrivacyChip.setPrivacyList(privacyItems); setChipVisibility(!privacyItems.isEmpty()); public void onFlagMicCameraChanged(boolean flag) { if (mMicCameraIndicatorsEnabled != flag) { mMicCameraIndicatorsEnabled = flag; update(); } } private void update() { StatusIconContainer iconContainer = requireViewById(R.id.statusIcons); iconContainer.setIgnoredSlots(getIgnoredIconSlots()); setChipVisibility(!mPrivacyChip.getPrivacyList().isEmpty()); } }; Loading Loading @@ -276,7 +282,8 @@ public class QuickStatusBarHeader extends RelativeLayout implements mRingerModeTextView.setSelected(true); mNextAlarmTextView.setSelected(true); mPermissionsHubEnabled = mPrivacyItemController.isPermissionsHubEnabled(); mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable(); mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable(); } public QuickQSPanel getHeaderQsPanel() { Loading @@ -285,14 +292,16 @@ public class QuickStatusBarHeader extends RelativeLayout implements private List<String> getIgnoredIconSlots() { ArrayList<String> ignored = new ArrayList<>(); if (getChipEnabled()) { ignored.add(mContext.getResources().getString( com.android.internal.R.string.status_bar_camera)); ignored.add(mContext.getResources().getString( com.android.internal.R.string.status_bar_microphone)); if (mPermissionsHubEnabled) { if (mAllIndicatorsEnabled) { ignored.add(mContext.getResources().getString( com.android.internal.R.string.status_bar_location)); } } return ignored; } Loading @@ -309,7 +318,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements } private void setChipVisibility(boolean chipVisible) { if (chipVisible && mPermissionsHubEnabled) { if (chipVisible && getChipEnabled()) { mPrivacyChip.setVisibility(View.VISIBLE); // Makes sure that the chip is logged as viewed at most once each time QS is opened // mListening makes sure that the callback didn't return after the user closed QS Loading Loading @@ -519,9 +528,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements }); mStatusBarIconController.addIconGroup(mIconManager); requestApplyInsets(); // Change the ignored slots when DeviceConfig flag changes DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_PRIVACY, mContext.getMainExecutor(), mPropertiesListener); } @Override Loading Loading @@ -601,7 +607,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements setListening(false); mRingerModeTracker.getRingerModeInternal().removeObservers(this); mStatusBarIconController.removeIconGroup(mIconManager); DeviceConfig.removeOnPropertiesChangedListener(mPropertiesListener); super.onDetachedFromWindow(); } Loading @@ -619,6 +624,9 @@ public class QuickStatusBarHeader extends RelativeLayout implements mZenController.addCallback(this); mAlarmController.addCallback(this); mLifecycle.setCurrentState(Lifecycle.State.RESUMED); // Get the most up to date info mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable(); mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable(); mPrivacyItemController.addCallback(mPICCallback); } else { mZenController.removeCallback(this); Loading Loading @@ -760,4 +768,8 @@ public class QuickStatusBarHeader extends RelativeLayout implements updateHeaderTextContainerAlphaAnimator(); } } private boolean getChipEnabled() { return mMicCameraIndicatorsEnabled || mAllIndicatorsEnabled; } } packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +6 −4 Original line number Diff line number Diff line Loading @@ -631,7 +631,7 @@ public class PhoneStatusBarPolicy } @Override // PrivacyItemController.Callback public void privacyChanged(List<PrivacyItem> privacyItems) { public void onPrivacyItemsChanged(List<PrivacyItem> privacyItems) { updatePrivacyItems(privacyItems); } Loading Loading @@ -664,16 +664,18 @@ public class PhoneStatusBarPolicy mIconController.setIconVisibility(mSlotCamera, showCamera); mIconController.setIconVisibility(mSlotMicrophone, showMicrophone); if (mPrivacyItemController.getAllIndicatorsAvailable()) { mIconController.setIconVisibility(mSlotLocation, showLocation); } } @Override public void onLocationActiveChanged(boolean active) { if (!mPrivacyItemController.isPermissionsHubEnabled()) updateLocation(); if (!mPrivacyItemController.getAllIndicatorsAvailable()) updateLocationFromController(); } // Updates the status view based on the current state of location requests. private void updateLocation() { private void updateLocationFromController() { if (mLocationController.isLocationActive()) { mIconController.setIconVisibility(mSlotLocation, true); } else { Loading Loading
core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +6 −1 Original line number Diff line number Diff line Loading @@ -123,10 +123,15 @@ public final class SystemUiDeviceConfigFlags { // Flag related to Privacy Indicators /** * Whether the Permissions Hub is showing. * Whether to show the complete ongoing app ops chip. */ public static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_2_enabled"; /** * Whether to show app ops chip for just microphone + camera. */ public static final String PROPERTY_MIC_CAMERA_ENABLED = "camera_mic_icons_enabled"; // Flags related to Assistant /** Loading
packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java +5 −3 Original line number Diff line number Diff line Loading @@ -279,9 +279,11 @@ public class AppOpsControllerImpl implements AppOpsController, * @return {@code true} iff the app-op for should be shown to the user */ private boolean isUserVisible(int appOpCode, int uid, String packageName) { // currently OP_SYSTEM_ALERT_WINDOW does not correspond to a platform permission // which may be user senstive, so for now always show it to the user. if (appOpCode == AppOpsManager.OP_SYSTEM_ALERT_WINDOW) { // currently OP_SYSTEM_ALERT_WINDOW and OP_MONITOR_HIGH_POWER_LOCATION // does not correspond to a platform permission // which may be user sensitive, so for now always show it to the user. if (appOpCode == AppOpsManager.OP_SYSTEM_ALERT_WINDOW || appOpCode == AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION) { return true; } Loading
packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt +56 −21 Original line number Diff line number Diff line Loading @@ -45,27 +45,32 @@ import javax.inject.Singleton @Singleton class PrivacyItemController @Inject constructor( context: Context, private val appOpsController: AppOpsController, @Main uiExecutor: DelayableExecutor, @Background private val bgExecutor: Executor, private val broadcastDispatcher: BroadcastDispatcher, private val deviceConfigProxy: DeviceConfigProxy, private val userManager: UserManager, dumpManager: DumpManager ) : Dumpable { @VisibleForTesting internal companion object { val OPS = intArrayOf(AppOpsManager.OP_CAMERA, AppOpsManager.OP_RECORD_AUDIO, val OPS_MIC_CAMERA = intArrayOf(AppOpsManager.OP_CAMERA, AppOpsManager.OP_RECORD_AUDIO) val OPS_LOCATION = intArrayOf( AppOpsManager.OP_COARSE_LOCATION, AppOpsManager.OP_FINE_LOCATION) val OPS = OPS_MIC_CAMERA + OPS_LOCATION val intentFilter = IntentFilter().apply { addAction(Intent.ACTION_USER_SWITCHED) addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE) addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE) } const val TAG = "PrivacyItemController" private const val ALL_INDICATORS = SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED private const val MIC_CAMERA = SystemUiDeviceConfigFlags.PROPERTY_MIC_CAMERA_ENABLED } @VisibleForTesting Loading @@ -73,12 +78,16 @@ class PrivacyItemController @Inject constructor( @Synchronized get() = field.toList() // Returns a shallow copy of the list @Synchronized set fun isPermissionsHubEnabled(): Boolean { fun isAllIndicatorsEnabled(): Boolean { return deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED, false) ALL_INDICATORS, false) } private fun isMicCameraEnabled(): Boolean { return deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, MIC_CAMERA, false) } private val userManager = context.getSystemService(UserManager::class.java) private var currentUserIds = emptyList<Int>() private var listening = false private val callbacks = mutableListOf<WeakReference<Callback>>() Loading @@ -86,7 +95,7 @@ class PrivacyItemController @Inject constructor( private val notifyChanges = Runnable { val list = privacyList callbacks.forEach { it.get()?.privacyChanged(list) } callbacks.forEach { it.get()?.onPrivacyItemsChanged(list) } } private val updateListAndNotifyChanges = Runnable { Loading @@ -94,16 +103,28 @@ class PrivacyItemController @Inject constructor( uiExecutor.execute(notifyChanges) } private var indicatorsAvailable = isPermissionsHubEnabled() @VisibleForTesting internal val devicePropertiesChangedListener = var allIndicatorsAvailable = isAllIndicatorsEnabled() private set var micCameraAvailable = isMicCameraEnabled() private set private val devicePropertiesChangedListener = object : DeviceConfig.OnPropertiesChangedListener { override fun onPropertiesChanged(properties: DeviceConfig.Properties) { if (DeviceConfig.NAMESPACE_PRIVACY.equals(properties.getNamespace()) && properties.getKeyset().contains( SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED)) { indicatorsAvailable = properties.getBoolean( SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED, false) (properties.keyset.contains(ALL_INDICATORS) || properties.keyset.contains(MIC_CAMERA))) { // Running on the ui executor so can iterate on callbacks if (properties.keyset.contains(ALL_INDICATORS)) { allIndicatorsAvailable = properties.getBoolean(ALL_INDICATORS, false) callbacks.forEach { it.get()?.onFlagAllChanged(allIndicatorsAvailable) } } if (properties.keyset.contains(MIC_CAMERA)) { micCameraAvailable = properties.getBoolean(MIC_CAMERA, false) callbacks.forEach { it.get()?.onFlagMicCameraChanged(micCameraAvailable) } } internalUiExecutor.updateListeningState() } } Loading @@ -116,6 +137,10 @@ class PrivacyItemController @Inject constructor( packageName: String, active: Boolean ) { // Check if we care about this code right now if (!allIndicatorsAvailable && code in OPS_LOCATION) { return } val userId = UserHandle.getUserId(uid) if (userId in currentUserIds) { update(false) Loading Loading @@ -159,13 +184,16 @@ class PrivacyItemController @Inject constructor( } /** * Updates listening status based on whether there are callbacks and the indicators are enabled * Updates listening status based on whether there are callbacks and the indicators are enabled. * * Always listen to all OPS so we don't have to figure out what we should be listening to. We * still have to filter anyway. Updates are filtered in the callback. * * This is only called from private (add/remove)Callback and from the config listener, all in * main thread. */ private fun setListeningState() { val listen = !callbacks.isEmpty() and indicatorsAvailable val listen = !callbacks.isEmpty() and (allIndicatorsAvailable || micCameraAvailable) if (listening == listen) return listening = listen if (listening) { Loading Loading @@ -226,13 +254,20 @@ class PrivacyItemController @Inject constructor( AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE else -> return null } if (type == PrivacyType.TYPE_LOCATION && !allIndicatorsAvailable) return null val app = PrivacyApplication(appOpItem.packageName, appOpItem.uid) return PrivacyItem(type, app) } // Used by containing class to get notified of changes interface Callback { fun privacyChanged(privacyItems: List<PrivacyItem>) fun onPrivacyItemsChanged(privacyItems: List<PrivacyItem>) @JvmDefault fun onFlagAllChanged(flag: Boolean) {} @JvmDefault fun onFlagMicCameraChanged(flag: Boolean) {} } internal inner class Receiver : BroadcastReceiver() { Loading @@ -248,7 +283,7 @@ class PrivacyItemController @Inject constructor( private val list: List<PrivacyItem> ) : Runnable { override fun run() { callback?.privacyChanged(list) callback?.onPrivacyItemsChanged(list) } } Loading
packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +43 −31 Original line number Diff line number Diff line Loading @@ -33,7 +33,6 @@ import android.media.AudioManager; import android.os.Handler; import android.os.Looper; import android.provider.AlarmClock; import android.provider.DeviceConfig; import android.provider.Settings; import android.service.notification.ZenModeConfig; import android.text.format.DateUtils; Loading @@ -59,7 +58,6 @@ import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleRegistry; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.logging.UiEventLogger; import com.android.settingslib.Utils; import com.android.systemui.BatteryMeterView; Loading Loading @@ -154,7 +152,8 @@ public class QuickStatusBarHeader extends RelativeLayout implements private Space mSpace; private BatteryMeterView mBatteryRemainingIcon; private RingerModeTracker mRingerModeTracker; private boolean mPermissionsHubEnabled; private boolean mAllIndicatorsEnabled; private boolean mMicCameraIndicatorsEnabled; private PrivacyItemController mPrivacyItemController; private final UiEventLogger mUiEventLogger; Loading @@ -173,26 +172,33 @@ public class QuickStatusBarHeader extends RelativeLayout implements private float mKeyguardExpansionFraction; private boolean mPrivacyChipLogged = false; private final DeviceConfig.OnPropertiesChangedListener mPropertiesListener = new DeviceConfig.OnPropertiesChangedListener() { private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() { @Override public void onPropertiesChanged(DeviceConfig.Properties properties) { if (DeviceConfig.NAMESPACE_PRIVACY.equals(properties.getNamespace()) && properties.getKeyset() .contains(SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED)) { mPermissionsHubEnabled = properties.getBoolean( SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED, false); StatusIconContainer iconContainer = findViewById(R.id.statusIcons); iconContainer.setIgnoredSlots(getIgnoredIconSlots()); public void onPrivacyItemsChanged(List<PrivacyItem> privacyItems) { mPrivacyChip.setPrivacyList(privacyItems); setChipVisibility(!privacyItems.isEmpty()); } @Override public void onFlagAllChanged(boolean flag) { if (mAllIndicatorsEnabled != flag) { mAllIndicatorsEnabled = flag; update(); } } }; private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() { @Override public void privacyChanged(List<PrivacyItem> privacyItems) { mPrivacyChip.setPrivacyList(privacyItems); setChipVisibility(!privacyItems.isEmpty()); public void onFlagMicCameraChanged(boolean flag) { if (mMicCameraIndicatorsEnabled != flag) { mMicCameraIndicatorsEnabled = flag; update(); } } private void update() { StatusIconContainer iconContainer = requireViewById(R.id.statusIcons); iconContainer.setIgnoredSlots(getIgnoredIconSlots()); setChipVisibility(!mPrivacyChip.getPrivacyList().isEmpty()); } }; Loading Loading @@ -276,7 +282,8 @@ public class QuickStatusBarHeader extends RelativeLayout implements mRingerModeTextView.setSelected(true); mNextAlarmTextView.setSelected(true); mPermissionsHubEnabled = mPrivacyItemController.isPermissionsHubEnabled(); mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable(); mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable(); } public QuickQSPanel getHeaderQsPanel() { Loading @@ -285,14 +292,16 @@ public class QuickStatusBarHeader extends RelativeLayout implements private List<String> getIgnoredIconSlots() { ArrayList<String> ignored = new ArrayList<>(); if (getChipEnabled()) { ignored.add(mContext.getResources().getString( com.android.internal.R.string.status_bar_camera)); ignored.add(mContext.getResources().getString( com.android.internal.R.string.status_bar_microphone)); if (mPermissionsHubEnabled) { if (mAllIndicatorsEnabled) { ignored.add(mContext.getResources().getString( com.android.internal.R.string.status_bar_location)); } } return ignored; } Loading @@ -309,7 +318,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements } private void setChipVisibility(boolean chipVisible) { if (chipVisible && mPermissionsHubEnabled) { if (chipVisible && getChipEnabled()) { mPrivacyChip.setVisibility(View.VISIBLE); // Makes sure that the chip is logged as viewed at most once each time QS is opened // mListening makes sure that the callback didn't return after the user closed QS Loading Loading @@ -519,9 +528,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements }); mStatusBarIconController.addIconGroup(mIconManager); requestApplyInsets(); // Change the ignored slots when DeviceConfig flag changes DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_PRIVACY, mContext.getMainExecutor(), mPropertiesListener); } @Override Loading Loading @@ -601,7 +607,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements setListening(false); mRingerModeTracker.getRingerModeInternal().removeObservers(this); mStatusBarIconController.removeIconGroup(mIconManager); DeviceConfig.removeOnPropertiesChangedListener(mPropertiesListener); super.onDetachedFromWindow(); } Loading @@ -619,6 +624,9 @@ public class QuickStatusBarHeader extends RelativeLayout implements mZenController.addCallback(this); mAlarmController.addCallback(this); mLifecycle.setCurrentState(Lifecycle.State.RESUMED); // Get the most up to date info mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable(); mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable(); mPrivacyItemController.addCallback(mPICCallback); } else { mZenController.removeCallback(this); Loading Loading @@ -760,4 +768,8 @@ public class QuickStatusBarHeader extends RelativeLayout implements updateHeaderTextContainerAlphaAnimator(); } } private boolean getChipEnabled() { return mMicCameraIndicatorsEnabled || mAllIndicatorsEnabled; } }
packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +6 −4 Original line number Diff line number Diff line Loading @@ -631,7 +631,7 @@ public class PhoneStatusBarPolicy } @Override // PrivacyItemController.Callback public void privacyChanged(List<PrivacyItem> privacyItems) { public void onPrivacyItemsChanged(List<PrivacyItem> privacyItems) { updatePrivacyItems(privacyItems); } Loading Loading @@ -664,16 +664,18 @@ public class PhoneStatusBarPolicy mIconController.setIconVisibility(mSlotCamera, showCamera); mIconController.setIconVisibility(mSlotMicrophone, showMicrophone); if (mPrivacyItemController.getAllIndicatorsAvailable()) { mIconController.setIconVisibility(mSlotLocation, showLocation); } } @Override public void onLocationActiveChanged(boolean active) { if (!mPrivacyItemController.isPermissionsHubEnabled()) updateLocation(); if (!mPrivacyItemController.getAllIndicatorsAvailable()) updateLocationFromController(); } // Updates the status view based on the current state of location requests. private void updateLocation() { private void updateLocationFromController() { if (mLocationController.isLocationActive()) { mIconController.setIconVisibility(mSlotLocation, true); } else { Loading