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

Commit 1757b7fc authored by Kate Montgomery's avatar Kate Montgomery Committed by Android (Google) Code Review
Browse files

Merge "Switch flag controller location indicator behavior from Device Config to aconfig." into main

parents ec3bba16 275480f4
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()