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

Commit 275480f4 authored by Kate Montgomery's avatar Kate Montgomery
Browse files

Switch flag controller location indicator behavior from Device Config to

aconfig.

Bug: 419834493
Flag: android.location.flags.location_indicators_enabled
Test: atest SystemUITests
Change-Id: I68ae7e7b49eb6d0bb6829a18c338696b926ae982
parent a5947d60
Loading
Loading
Loading
Loading
+0 −19
Original line number Diff line number Diff line
@@ -86,12 +86,6 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
     */
    private static final String PROPERTY_CAMERA_MIC_ICONS_ENABLED = "camera_mic_icons_enabled";

    /**
     * Whether to show the location indicators.
     */
    private static final String PROPERTY_LOCATION_INDICATORS_ENABLED =
            "location_indicators_enabled";

    /**
     * How long after an access to show it as "recent"
     */
@@ -112,11 +106,6 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
                PROPERTY_CAMERA_MIC_ICONS_ENABLED, true);
    }

    private static boolean shouldShowLocationIndicator() {
        return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
                PROPERTY_LOCATION_INDICATORS_ENABLED, false);
    }

    private static long getRecentThreshold(Long now) {
        return now - DeviceConfig.getLong(DeviceConfig.NAMESPACE_PRIVACY,
                RECENT_ACCESS_TIME_MS, DEFAULT_RECENT_TIME_MS);
@@ -127,11 +116,6 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
                RUNNING_ACCESS_TIME_MS, DEFAULT_RUNNING_TIME_MS);
    }

    private static final List<String> LOCATION_OPS = List.of(
            OPSTR_COARSE_LOCATION,
            OPSTR_FINE_LOCATION
    );

    private static final List<String> MIC_OPS = List.of(
            OPSTR_PHONE_CALL_MICROPHONE,
            OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO,
@@ -300,9 +284,6 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
        }

        List<String> ops = new ArrayList<>(CAMERA_OPS);
        if (shouldShowLocationIndicator()) {
            ops.addAll(LOCATION_OPS);
        }
        if (includeMicrophoneUsage) {
            ops.addAll(MIC_OPS);
        }
+0 −5
Original line number Diff line number Diff line
@@ -132,11 +132,6 @@ 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";

    /**
     * Whether to show privacy chip for media projection.
     */
+8 −0
Original line number Diff line number Diff line
@@ -187,3 +187,11 @@ flag {
    description: "Adds missing attribution tags in the Fused and Gnss overlay"
    bug: "403337028"
}


flag {
    name: "location_indicators_enabled"
    namespace: "location"
    description: "Enables modified location privacy item behavior"
    bug: "419834493"
}
 No newline at end of file
+34 −20
Original line number Diff line number Diff line
@@ -16,8 +16,11 @@

package com.android.systemui.privacy

import android.location.flags.Flags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import android.platform.test.flag.junit.FlagsParameterization.allCombinationsOf
import android.provider.DeviceConfig
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
import com.android.systemui.SysuiTestCase
@@ -36,33 +39,39 @@ import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import platform.test.runner.parameterized.ParameterizedAndroidJunit4
import platform.test.runner.parameterized.Parameters

@RunWith(AndroidJUnit4::class)
@RunWith(ParameterizedAndroidJunit4::class)
@SmallTest
@android.platform.test.annotations.EnabledOnRavenwood
class PrivacyConfigFlagsTest : SysuiTestCase() {
class PrivacyConfigFlagsTest(flags: FlagsParameterization) : SysuiTestCase() {
    companion object {
        private const val MIC_CAMERA = SystemUiDeviceConfigFlags.PROPERTY_MIC_CAMERA_ENABLED
        private const val LOCATION = SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_ENABLED
        private const val MEDIA_PROJECTION =
            SystemUiDeviceConfigFlags.PROPERTY_MEDIA_PROJECTION_INDICATORS_ENABLED

        @JvmStatic
        @Parameters(name = "{0}")
        fun getParams(): List<FlagsParameterization> {
            return allCombinationsOf(Flags.FLAG_LOCATION_INDICATORS_ENABLED)
        }
    }

    init {
        mSetFlagsRule.setFlagsParameterization(flags)
    }

    private lateinit var privacyConfig: PrivacyConfig

    @Mock
    private lateinit var callback: PrivacyConfig.Callback
    @Mock
    private lateinit var dumpManager: DumpManager
    @Mock private lateinit var callback: PrivacyConfig.Callback
    @Mock private lateinit var dumpManager: DumpManager

    private lateinit var executor: FakeExecutor
    private lateinit var deviceConfigProxy: DeviceConfigProxy

    fun createPrivacyConfig(): PrivacyConfig {
        return PrivacyConfig(
                executor,
                deviceConfigProxy,
                dumpManager)
        return PrivacyConfig(executor, deviceConfigProxy, dumpManager)
    }

    @Before
@@ -78,11 +87,13 @@ class PrivacyConfigFlagsTest : SysuiTestCase() {
    }

    @Test
    @EnableFlags(Flags.FLAG_LOCATION_INDICATORS_ENABLED)
    fun testMicCameraListeningByDefault() {
        assertTrue(privacyConfig.micCameraAvailable)
    }

    @Test
    @EnableFlags(Flags.FLAG_LOCATION_INDICATORS_ENABLED)
    fun testMicCameraChanged() {
        changeMicCamera(false) // default is true
        executor.runAllReady()
@@ -93,6 +104,7 @@ class PrivacyConfigFlagsTest : SysuiTestCase() {
    }

    @Test
    @EnableFlags(Flags.FLAG_LOCATION_INDICATORS_ENABLED)
    fun testMediaProjectionChanged() {
        changeMediaProjection(false) // default is true
        executor.runAllReady()
@@ -103,8 +115,9 @@ class PrivacyConfigFlagsTest : SysuiTestCase() {
    }

    @Test
    @EnableFlags(Flags.FLAG_LOCATION_INDICATORS_ENABLED)
    fun testLocationChanged() {
        changeLocation(true)
        changeMicCamera(true)
        executor.runAllReady()

        verify(callback).onFlagLocationChanged(true)
@@ -112,8 +125,8 @@ class PrivacyConfigFlagsTest : SysuiTestCase() {
    }

    @Test
    @EnableFlags(Flags.FLAG_LOCATION_INDICATORS_ENABLED)
    fun testMicCamAndLocationChanged() {
        changeLocation(true)
        changeMicCamera(false)
        executor.runAllReady()

@@ -125,6 +138,7 @@ class PrivacyConfigFlagsTest : SysuiTestCase() {
    }

    @Test
    @EnableFlags(Flags.FLAG_LOCATION_INDICATORS_ENABLED)
    fun testMicDeleted_stillAvailable() {
        changeMicCamera(true)
        executor.runAllReady()
@@ -136,7 +150,7 @@ class PrivacyConfigFlagsTest : SysuiTestCase() {
    }

    private fun changeMicCamera(value: Boolean?) = changeProperty(MIC_CAMERA, value)
    private fun changeLocation(value: Boolean?) = changeProperty(LOCATION, value)

    private fun changeMediaProjection(value: Boolean?) = changeProperty(MEDIA_PROJECTION, value)

    private fun changeProperty(name: String, value: Boolean?) {
@@ -144,7 +158,7 @@ class PrivacyConfigFlagsTest : SysuiTestCase() {
            DeviceConfig.NAMESPACE_PRIVACY,
            name,
            value?.toString(),
                false
            false,
        )
    }
}
+42 −42
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.privacy

import android.location.flags.Flags.locationIndicatorsEnabled
import android.provider.DeviceConfig
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.annotations.WeaklyReferencedCallback
@@ -33,21 +34,21 @@ import java.lang.ref.WeakReference
import javax.inject.Inject

@SysUISingleton
class PrivacyConfig @Inject constructor(
class PrivacyConfig
@Inject
constructor(
    @Main private val uiExecutor: DelayableExecutor,
    private val deviceConfigProxy: DeviceConfigProxy,
    dumpManager: DumpManager
    dumpManager: DumpManager,
) : Dumpable {

    @VisibleForTesting
    internal companion object {
        const val TAG = "PrivacyConfig"
        private const val MIC_CAMERA = SystemUiDeviceConfigFlags.PROPERTY_MIC_CAMERA_ENABLED
        private const val LOCATION = SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_ENABLED
        private const val MEDIA_PROJECTION =
            SystemUiDeviceConfigFlags.PROPERTY_MEDIA_PROJECTION_INDICATORS_ENABLED
        private const val DEFAULT_MIC_CAMERA = true
        private const val DEFAULT_LOCATION = false
        private const val DEFAULT_MEDIA_PROJECTION = true
    }

@@ -55,8 +56,10 @@ class PrivacyConfig @Inject constructor(

    var micCameraAvailable = isMicCameraEnabled()
        private set
    var locationAvailable = isLocationEnabled()

    var locationAvailable = locationIndicatorsEnabled()
        private set

    var mediaProjectionAvailable = isMediaProjectionEnabled()
        private set

@@ -69,8 +72,7 @@ class PrivacyConfig @Inject constructor(
                    callbacks.forEach { it.get()?.onFlagMicCameraChanged(micCameraAvailable) }
                }

                    if (properties.keyset.contains(LOCATION)) {
                        locationAvailable = properties.getBoolean(LOCATION, DEFAULT_LOCATION)
                if (locationAvailable) {
                    callbacks.forEach { it.get()?.onFlagLocationChanged(locationAvailable) }
                }

@@ -89,22 +91,24 @@ class PrivacyConfig @Inject constructor(
        deviceConfigProxy.addOnPropertiesChangedListener(
            DeviceConfig.NAMESPACE_PRIVACY,
            uiExecutor,
                devicePropertiesChangedListener)
            devicePropertiesChangedListener,
        )
    }

    private fun isMicCameraEnabled(): Boolean {
        return deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
                MIC_CAMERA, DEFAULT_MIC_CAMERA)
    }

    private fun isLocationEnabled(): Boolean {
        return deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
                LOCATION, DEFAULT_LOCATION)
        return deviceConfigProxy.getBoolean(
            DeviceConfig.NAMESPACE_PRIVACY,
            MIC_CAMERA,
            DEFAULT_MIC_CAMERA,
        )
    }

    private fun isMediaProjectionEnabled(): Boolean {
        return deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
                MEDIA_PROJECTION, DEFAULT_MEDIA_PROJECTION)
        return deviceConfigProxy.getBoolean(
            DeviceConfig.NAMESPACE_PRIVACY,
            MEDIA_PROJECTION,
            DEFAULT_MEDIA_PROJECTION,
        )
    }

    fun addCallback(callback: Callback) {
@@ -116,9 +120,7 @@ class PrivacyConfig @Inject constructor(
    }

    private fun addCallback(callback: WeakReference<Callback>) {
        uiExecutor.execute {
            callbacks.add(callback)
        }
        uiExecutor.execute { callbacks.add(callback) }
    }

    private fun removeCallback(callback: WeakReference<Callback>) {
@@ -137,9 +139,7 @@ class PrivacyConfig @Inject constructor(
            ipw.println("mediaProjectionAvailable: $mediaProjectionAvailable")
            ipw.println("Callbacks:")
            ipw.withIncreasedIndent {
                callbacks.forEach { callback ->
                    callback.get()?.let { ipw.println(it) }
                }
                callbacks.forEach { callback -> callback.get()?.let { ipw.println(it) } }
            }
        }
        ipw.flush()