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

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

Merge "SysUi: Display location icon on all deliveries."

parents ca834e02 9e52a92e
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -157,6 +157,12 @@ public final class SystemUiDeviceConfigFlags {
     */
    public static final String PROPERTY_LOCATION_INDICATORS_ENABLED = "location_indicators_enabled";

    /**
     * Whether to show old location indicator on all location accesses.
     */
    public static final String PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED =
            "location_indicators_small_enabled";

    // Flags related to Assistant

    /**
+57 −3
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.systemui.statusbar.policy;

import static android.app.AppOpsManager.OP_COARSE_LOCATION;
import static android.app.AppOpsManager.OP_FINE_LOCATION;
import static android.app.AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION;

import static com.android.settingslib.Utils.updateLocationEnabled;
@@ -30,11 +32,13 @@ import android.os.Looper;
import android.os.Message;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.DeviceConfig;
import android.provider.Settings;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.BootCompleteCache;
import com.android.systemui.appops.AppOpItem;
import com.android.systemui.appops.AppOpsController;
@@ -43,6 +47,7 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.Utils;

import java.util.ArrayList;
@@ -59,30 +64,47 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio

    private final Context mContext;
    private final AppOpsController mAppOpsController;
    private final DeviceConfigProxy mDeviceConfigProxy;
    private final BootCompleteCache mBootCompleteCache;
    private final UserTracker mUserTracker;
    private final H mHandler;


    private boolean mAreActiveLocationRequests;
    private boolean mShouldDisplayAllAccesses;

    @Inject
    public LocationControllerImpl(Context context, AppOpsController appOpsController,
            DeviceConfigProxy deviceConfigProxy,
            @Main Looper mainLooper, @Background Handler backgroundHandler,
            BroadcastDispatcher broadcastDispatcher, BootCompleteCache bootCompleteCache,
            UserTracker userTracker) {
        mContext = context;
        mAppOpsController = appOpsController;
        mDeviceConfigProxy = deviceConfigProxy;
        mBootCompleteCache = bootCompleteCache;
        mHandler = new H(mainLooper);
        mUserTracker = userTracker;
        mShouldDisplayAllAccesses = getDeviceConfigSetting();

        // Register to listen for changes in DeviceConfig settings.
        mDeviceConfigProxy.addOnPropertiesChangedListener(
                DeviceConfig.NAMESPACE_PRIVACY,
                backgroundHandler::post,
                properties -> {
                    mShouldDisplayAllAccesses = getDeviceConfigSetting();
                    updateActiveLocationRequests();
                });

        // Register to listen for changes in location settings.
        IntentFilter filter = new IntentFilter();
        filter.addAction(LocationManager.MODE_CHANGED_ACTION);
        broadcastDispatcher.registerReceiverWithHandler(this, filter, mHandler, UserHandle.ALL);

        mAppOpsController.addCallback(new int[]{OP_MONITOR_HIGH_POWER_LOCATION}, this);
        // Listen to all accesses and filter the ones interested in based on flags.
        mAppOpsController.addCallback(
                new int[]{OP_COARSE_LOCATION, OP_FINE_LOCATION, OP_MONITOR_HIGH_POWER_LOCATION},
                this);

        // Examine the current location state and initialize the status view.
        backgroundHandler.post(this::updateActiveLocationRequests);
@@ -154,6 +176,11 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
                UserHandle.of(userId));
    }

    private boolean getDeviceConfigSetting() {
        return mDeviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
                SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false);
    }

    /**
     * Returns true if there currently exist active high power location requests.
     */
@@ -171,10 +198,37 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
        return false;
    }

    // Reads the active location requests and updates the status view if necessary.
    /**
     * Returns true if there currently exist active location requests.
     */
    @VisibleForTesting
    protected boolean areActiveLocationRequests() {
        if (!mShouldDisplayAllAccesses) {
            return false;
        }
        List<AppOpItem> appOpsItems = mAppOpsController.getActiveAppOps();

        final int numItems = appOpsItems.size();
        for (int i = 0; i < numItems; i++) {
            if (appOpsItems.get(i).getCode() == OP_FINE_LOCATION
                    || appOpsItems.get(i).getCode() == OP_COARSE_LOCATION) {
                return true;
            }
        }

        return false;
    }

    // Reads the active location requests from either OP_MONITOR_HIGH_POWER_LOCATION,
    // OP_FINE_LOCATION, or OP_COARSE_LOCATION and updates the status view if necessary.
    private void updateActiveLocationRequests() {
        boolean hadActiveLocationRequests = mAreActiveLocationRequests;
        if (mShouldDisplayAllAccesses) {
            mAreActiveLocationRequests =
                    areActiveHighPowerLocationRequests() || areActiveLocationRequests();
        } else {
            mAreActiveLocationRequests = areActiveHighPowerLocationRequests();
        }
        if (mAreActiveLocationRequests != hadActiveLocationRequests) {
            mHandler.sendEmptyMessage(H.MSG_LOCATION_ACTIVE_CHANGED);
        }
+61 −7
Original line number Diff line number Diff line
@@ -15,9 +15,7 @@
package com.android.systemui.statusbar.policy;

import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -27,18 +25,25 @@ import android.content.Intent;
import android.location.LocationManager;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;

import androidx.test.filters.SmallTest;

import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.BootCompleteCache;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.appops.AppOpItem;
import com.android.systemui.appops.AppOpsController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.DeviceConfigProxyFake;

import com.google.common.collect.ImmutableList;

import org.junit.Before;
import org.junit.Test;
@@ -53,6 +58,7 @@ public class LocationControllerImplTest extends SysuiTestCase {

    private LocationControllerImpl mLocationController;
    private TestableLooper mTestableLooper;
    private DeviceConfigProxy mDeviceConfigProxy;

    @Mock private AppOpsController mAppOpsController;
    @Mock private UserTracker mUserTracker;
@@ -62,15 +68,17 @@ public class LocationControllerImplTest extends SysuiTestCase {
        MockitoAnnotations.initMocks(this);
        when(mUserTracker.getUserId()).thenReturn(UserHandle.USER_SYSTEM);
        when(mUserTracker.getUserHandle()).thenReturn(UserHandle.SYSTEM);
        mDeviceConfigProxy = new DeviceConfigProxyFake();

        mTestableLooper = TestableLooper.get(this);
        mLocationController = spy(new LocationControllerImpl(mContext,
        mLocationController = new LocationControllerImpl(mContext,
                mAppOpsController,
                mDeviceConfigProxy,
                mTestableLooper.getLooper(),
                new Handler(mTestableLooper.getLooper()),
                mock(BroadcastDispatcher.class),
                mock(BootCompleteCache.class),
                mUserTracker));
                mUserTracker);

        mTestableLooper.processAllMessages();
    }
@@ -86,10 +94,13 @@ public class LocationControllerImplTest extends SysuiTestCase {
        mLocationController.addCallback(callback);
        mLocationController.addCallback(mock(LocationChangeCallback.class));

        doReturn(false).when(mLocationController).areActiveHighPowerLocationRequests();
        when(mAppOpsController.getActiveAppOps()).thenReturn(ImmutableList.of());
        mLocationController.onActiveStateChanged(AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, 0,
                "", false);
        doReturn(true).when(mLocationController).areActiveHighPowerLocationRequests();
        when(mAppOpsController.getActiveAppOps())
                .thenReturn(ImmutableList.of(
                        new AppOpItem(AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, 0, "",
                                System.currentTimeMillis())));
        mLocationController.onActiveStateChanged(AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, 0,
                "", true);

@@ -135,7 +146,10 @@ public class LocationControllerImplTest extends SysuiTestCase {

        verify(callback, times(2)).onLocationSettingsChanged(anyBoolean());

        doReturn(true).when(mLocationController).areActiveHighPowerLocationRequests();
        when(mAppOpsController.getActiveAppOps())
                .thenReturn(ImmutableList.of(
                        new AppOpItem(AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, 0, "",
                                System.currentTimeMillis())));
        mLocationController.onActiveStateChanged(AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, 0,
                "", true);

@@ -144,6 +158,46 @@ public class LocationControllerImplTest extends SysuiTestCase {
        verify(callback, times(1)).onLocationActiveChanged(anyBoolean());
    }

    @Test
    public void testCallbackNotified_additionalOps() {
        LocationChangeCallback callback = mock(LocationChangeCallback.class);

        mLocationController.addCallback(callback);

        mTestableLooper.processAllMessages();

        mLocationController.onReceive(mContext, new Intent(LocationManager.MODE_CHANGED_ACTION));

        mTestableLooper.processAllMessages();

        verify(callback, times(2)).onLocationSettingsChanged(anyBoolean());

        mDeviceConfigProxy.setProperty(
                DeviceConfig.NAMESPACE_PRIVACY,
                SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED,
                "true",
                true);
        mTestableLooper.processAllMessages();

        when(mAppOpsController.getActiveAppOps())
                .thenReturn(ImmutableList.of(
                        new AppOpItem(AppOpsManager.OP_FINE_LOCATION, 0, "",
                                System.currentTimeMillis())));
        mLocationController.onActiveStateChanged(AppOpsManager.OP_FINE_LOCATION, 0,
                "", true);

        mTestableLooper.processAllMessages();

        verify(callback, times(1)).onLocationActiveChanged(true);

        when(mAppOpsController.getActiveAppOps()).thenReturn(ImmutableList.of());
        mLocationController.onActiveStateChanged(AppOpsManager.OP_FINE_LOCATION, 0,
                "", false);
        mTestableLooper.processAllMessages();

        verify(callback, times(1)).onLocationActiveChanged(false);
    }

    @Test
    public void testCallbackRemoved() {
        LocationChangeCallback callback = mock(LocationChangeCallback.class);