Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 220f0234 authored by Wei Wang's avatar Wei Wang
Browse files

SysUI: add a flag to control location indicators behavior.

Under the new flag, the location indicators will display when either
location indicators flag is enabled, or when permission hub feature is
enabled.

Bug: 171057373
Test: atest PrivacyItemControllerFlagsTest
Test: Manual
Change-Id: I628ced3108f4844444915e10a7e0bfbb0a9b8309
parent 6f883edd
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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

    /**
+24 −4
Original line number Diff line number Diff line
@@ -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
@@ -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>>()
@@ -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)) {
@@ -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()
            }
        }
@@ -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)
@@ -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) {
@@ -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)
    }
@@ -271,6 +288,9 @@ class PrivacyItemController @Inject constructor(

        @JvmDefault
        fun onFlagMicCameraChanged(flag: Boolean) {}

        @JvmDefault
        fun onFlagLocationChanged(flag: Boolean) {}
    }

    private class NotifyChangesToCallback(
+13 −2
Original line number Diff line number Diff line
@@ -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;

@@ -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());
@@ -252,6 +261,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader

        mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable();
        mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
        mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable();

        setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);

@@ -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);
@@ -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));
            }
@@ -333,7 +344,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
    }

    private boolean getChipEnabled() {
        return mMicCameraIndicatorsEnabled || mAllIndicatorsEnabled;
        return mMicCameraIndicatorsEnabled || mLocationIndicatorsEnabled || mAllIndicatorsEnabled;
    }

    private boolean isZenOverridingRinger() {
+6 −2
Original line number Diff line number Diff line
@@ -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.
+19 −0
Original line number Diff line number Diff line
@@ -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
@@ -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)
@@ -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() {
@@ -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?) {