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

Commit 26fbbf3c authored by Kate Montgomery's avatar Kate Montgomery
Browse files

Log when the location indicator is displayed as well as the type of

location access which prompted the display.

Bug: 191503437
Test: atest LocationControllerImplTest
Test: manual
Change-Id: Ib83562b4037d21d958a2b4109cfe5020747fd916
parent 0925cfe5
Loading
Loading
Loading
Loading
+58 −6
Original line number Original line Diff line number Diff line
@@ -43,6 +43,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.annotation.VisibleForTesting;


import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.BootCompleteCache;
import com.android.systemui.BootCompleteCache;
import com.android.systemui.appops.AppOpItem;
import com.android.systemui.appops.AppOpItem;
import com.android.systemui.appops.AppOpsController;
import com.android.systemui.appops.AppOpsController;
@@ -71,6 +73,7 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
    private final DeviceConfigProxy mDeviceConfigProxy;
    private final DeviceConfigProxy mDeviceConfigProxy;
    private final BootCompleteCache mBootCompleteCache;
    private final BootCompleteCache mBootCompleteCache;
    private final UserTracker mUserTracker;
    private final UserTracker mUserTracker;
    private final UiEventLogger mUiEventLogger;
    private final H mHandler;
    private final H mHandler;
    private final Handler mBackgroundHandler;
    private final Handler mBackgroundHandler;
    private final PackageManager mPackageManager;
    private final PackageManager mPackageManager;
@@ -84,13 +87,14 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
            DeviceConfigProxy deviceConfigProxy,
            DeviceConfigProxy deviceConfigProxy,
            @Main Looper mainLooper, @Background Handler backgroundHandler,
            @Main Looper mainLooper, @Background Handler backgroundHandler,
            BroadcastDispatcher broadcastDispatcher, BootCompleteCache bootCompleteCache,
            BroadcastDispatcher broadcastDispatcher, BootCompleteCache bootCompleteCache,
            UserTracker userTracker, PackageManager packageManager) {
            UserTracker userTracker, PackageManager packageManager, UiEventLogger uiEventLogger) {
        mContext = context;
        mContext = context;
        mAppOpsController = appOpsController;
        mAppOpsController = appOpsController;
        mDeviceConfigProxy = deviceConfigProxy;
        mDeviceConfigProxy = deviceConfigProxy;
        mBootCompleteCache = bootCompleteCache;
        mBootCompleteCache = bootCompleteCache;
        mHandler = new H(mainLooper);
        mHandler = new H(mainLooper);
        mUserTracker = userTracker;
        mUserTracker = userTracker;
        mUiEventLogger = uiEventLogger;
        mBackgroundHandler = backgroundHandler;
        mBackgroundHandler = backgroundHandler;
        mPackageManager = packageManager;
        mPackageManager = packageManager;
        mShouldDisplayAllAccesses = getAllAccessesSetting();
        mShouldDisplayAllAccesses = getAllAccessesSetting();
@@ -222,6 +226,9 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
        }
        }
        boolean hadActiveLocationRequests = mAreActiveLocationRequests;
        boolean hadActiveLocationRequests = mAreActiveLocationRequests;
        boolean shouldDisplay = false;
        boolean shouldDisplay = false;
        boolean systemAppOp = false;
        boolean nonSystemAppOp = false;
        boolean isSystemApp;


        List<AppOpItem> appOpsItems = mAppOpsController.getActiveAppOps();
        List<AppOpItem> appOpsItems = mAppOpsController.getActiveAppOps();
        final List<UserInfo> profiles = mUserTracker.getUserProfiles();
        final List<UserInfo> profiles = mUserTracker.getUserProfiles();
@@ -229,18 +236,38 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
        for (int i = 0; i < numItems; i++) {
        for (int i = 0; i < numItems; i++) {
            if (appOpsItems.get(i).getCode() == OP_FINE_LOCATION
            if (appOpsItems.get(i).getCode() == OP_FINE_LOCATION
                    || appOpsItems.get(i).getCode() == OP_COARSE_LOCATION) {
                    || appOpsItems.get(i).getCode() == OP_COARSE_LOCATION) {
                if (mShowSystemAccesses) {
                isSystemApp = isSystemApp(profiles, appOpsItems.get(i));
                    shouldDisplay = true;
                if (isSystemApp) {
                    systemAppOp = true;
                } else {
                } else {
                    shouldDisplay |= !isSystemApp(profiles, appOpsItems.get(i));
                    nonSystemAppOp = true;
                }
                }

                shouldDisplay = mShowSystemAccesses || shouldDisplay || !isSystemApp;
            }
            }
        }
        }


        mAreActiveLocationRequests = areActiveHighPowerLocationRequests() || shouldDisplay;
        boolean highPowerOp = areActiveHighPowerLocationRequests();
        mAreActiveLocationRequests = highPowerOp || shouldDisplay;
        if (mAreActiveLocationRequests != hadActiveLocationRequests) {
        if (mAreActiveLocationRequests != hadActiveLocationRequests) {
            mHandler.sendEmptyMessage(H.MSG_LOCATION_ACTIVE_CHANGED);
            mHandler.sendEmptyMessage(H.MSG_LOCATION_ACTIVE_CHANGED);
        }
        }

        // Log each of the types of location access that would cause the location indicator to be
        // shown, regardless of device's setting state. This is used to understand how often a
        // user would see the location indicator based on any settings state the device could be in.
        if (!hadActiveLocationRequests && (highPowerOp || systemAppOp || nonSystemAppOp)) {
            if (highPowerOp) {
                mUiEventLogger.log(
                        LocationIndicatorEvent.LOCATION_INDICATOR_MONITOR_HIGH_POWER);
            }
            if (systemAppOp) {
                mUiEventLogger.log(LocationIndicatorEvent.LOCATION_INDICATOR_SYSTEM_APP);
            }
            if (nonSystemAppOp) {
                mUiEventLogger.log(LocationIndicatorEvent.LOCATION_INDICATOR_NON_SYSTEM_APP);
            }
        }
    }
    }


    private boolean isSystemApp(List<UserInfo> profiles, AppOpItem item) {
    private boolean isSystemApp(List<UserInfo> profiles, AppOpItem item) {
@@ -283,6 +310,11 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
            mAreActiveLocationRequests = areActiveHighPowerLocationRequests();
            mAreActiveLocationRequests = areActiveHighPowerLocationRequests();
            if (mAreActiveLocationRequests != hadActiveLocationRequests) {
            if (mAreActiveLocationRequests != hadActiveLocationRequests) {
                mHandler.sendEmptyMessage(H.MSG_LOCATION_ACTIVE_CHANGED);
                mHandler.sendEmptyMessage(H.MSG_LOCATION_ACTIVE_CHANGED);
                if (mAreActiveLocationRequests) {
                    // Log that the indicator was shown for a high power op.
                    mUiEventLogger.log(
                            LocationIndicatorEvent.LOCATION_INDICATOR_MONITOR_HIGH_POWER);
                }
            }
            }
        }
        }
    }
    }
@@ -341,4 +373,24 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
                    cb -> cb.onLocationSettingsChanged(isEnabled));
                    cb -> cb.onLocationSettingsChanged(isEnabled));
        }
        }
    }
    }

    /**
     * Enum for events which prompt the location indicator to appear.
     */
    enum LocationIndicatorEvent implements UiEventLogger.UiEventEnum {
        @UiEvent(doc = "Location indicator shown for high power access")
        LOCATION_INDICATOR_MONITOR_HIGH_POWER(935),
        @UiEvent(doc = "Location indicator shown for system app access")
        LOCATION_INDICATOR_SYSTEM_APP(936),
        @UiEvent(doc = "Location indicator shown for non system app access")
        LOCATION_INDICATOR_NON_SYSTEM_APP(937);

        private final int mId;
        LocationIndicatorEvent(int id) {
            mId = id;
        }
        @Override public int getId() {
            return mId;
        }
    }
}
}
 No newline at end of file
+61 −1
Original line number Original line Diff line number Diff line
@@ -14,6 +14,8 @@


package com.android.systemui.statusbar.policy;
package com.android.systemui.statusbar.policy;


import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.times;
@@ -34,6 +36,7 @@ import android.testing.TestableLooper.RunWithLooper;
import androidx.test.filters.SmallTest;
import androidx.test.filters.SmallTest;


import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.systemui.BootCompleteCache;
import com.android.systemui.BootCompleteCache;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.appops.AppOpItem;
import com.android.systemui.appops.AppOpItem;
@@ -60,6 +63,7 @@ public class LocationControllerImplTest extends SysuiTestCase {
    private LocationControllerImpl mLocationController;
    private LocationControllerImpl mLocationController;
    private TestableLooper mTestableLooper;
    private TestableLooper mTestableLooper;
    private DeviceConfigProxy mDeviceConfigProxy;
    private DeviceConfigProxy mDeviceConfigProxy;
    private UiEventLoggerFake mUiEventLogger;


    @Mock private AppOpsController mAppOpsController;
    @Mock private AppOpsController mAppOpsController;
    @Mock private UserTracker mUserTracker;
    @Mock private UserTracker mUserTracker;
@@ -72,6 +76,7 @@ public class LocationControllerImplTest extends SysuiTestCase {
        when(mUserTracker.getUserProfiles())
        when(mUserTracker.getUserProfiles())
                .thenReturn(ImmutableList.of(new UserInfo(0, "name", 0)));
                .thenReturn(ImmutableList.of(new UserInfo(0, "name", 0)));
        mDeviceConfigProxy = new DeviceConfigProxyFake();
        mDeviceConfigProxy = new DeviceConfigProxyFake();
        mUiEventLogger = new UiEventLoggerFake();


        mTestableLooper = TestableLooper.get(this);
        mTestableLooper = TestableLooper.get(this);
        mLocationController = new LocationControllerImpl(mContext,
        mLocationController = new LocationControllerImpl(mContext,
@@ -82,7 +87,8 @@ public class LocationControllerImplTest extends SysuiTestCase {
                mock(BroadcastDispatcher.class),
                mock(BroadcastDispatcher.class),
                mock(BootCompleteCache.class),
                mock(BootCompleteCache.class),
                mUserTracker,
                mUserTracker,
                mContext.getPackageManager());
                mContext.getPackageManager(),
                mUiEventLogger);


        mTestableLooper.processAllMessages();
        mTestableLooper.processAllMessages();
    }
    }
@@ -160,6 +166,10 @@ public class LocationControllerImplTest extends SysuiTestCase {
        mTestableLooper.processAllMessages();
        mTestableLooper.processAllMessages();


        verify(callback, times(1)).onLocationActiveChanged(anyBoolean());
        verify(callback, times(1)).onLocationActiveChanged(anyBoolean());
        assertThat(mUiEventLogger.numLogs()).isEqualTo(1);
        assertThat(mUiEventLogger.eventId(0)).isEqualTo(
                LocationControllerImpl.LocationIndicatorEvent.LOCATION_INDICATOR_MONITOR_HIGH_POWER
                        .getId());
    }
    }


    @Test
    @Test
@@ -253,6 +263,56 @@ public class LocationControllerImplTest extends SysuiTestCase {
        verify(callback, times(1)).onLocationActiveChanged(false);
        verify(callback, times(1)).onLocationActiveChanged(false);
    }
    }


    @Test
    public void testCallbackNotified_verifyMetrics() {
        LocationChangeCallback callback = mock(LocationChangeCallback.class);
        mLocationController.addCallback(callback);
        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, "com.google.android.gms",
                                System.currentTimeMillis()),
                        new AppOpItem(AppOpsManager.OP_COARSE_LOCATION, 0,
                                "com.google.android.googlequicksearchbox",
                                System.currentTimeMillis()),
                        new AppOpItem(AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, 0,
                                "com.google.android.apps.maps",
                                System.currentTimeMillis())));
        mLocationController.onActiveStateChanged(AppOpsManager.OP_FINE_LOCATION, 0,
                "com.google.android.gms", true);

        mTestableLooper.processAllMessages();

        verify(callback, times(1)).onLocationActiveChanged(true);
        assertThat(mUiEventLogger.numLogs()).isEqualTo(3);
        assertThat(mUiEventLogger.eventId(0)).isEqualTo(
                LocationControllerImpl.LocationIndicatorEvent.LOCATION_INDICATOR_MONITOR_HIGH_POWER
                        .getId());
        // Even though the system access wasn't shown due to the device settings, ensure it was
        // still logged.
        assertThat(mUiEventLogger.eventId(1)).isEqualTo(
                LocationControllerImpl.LocationIndicatorEvent.LOCATION_INDICATOR_SYSTEM_APP
                        .getId());
        assertThat(mUiEventLogger.eventId(2)).isEqualTo(
                LocationControllerImpl.LocationIndicatorEvent.LOCATION_INDICATOR_NON_SYSTEM_APP
                        .getId());
        mUiEventLogger.getLogs().clear();

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

        verify(callback, times(1)).onLocationActiveChanged(false);
        assertThat(mUiEventLogger.numLogs()).isEqualTo(0);
    }

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