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

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

Merge "Log when the location indicator is displayed as well as the type of...

Merge "Log when the location indicator is displayed as well as the type of location access which prompted the display."
parents 2a1891a7 26fbbf3c
Loading
Loading
Loading
Loading
+58 −6
Original line number Diff line number Diff line
@@ -43,6 +43,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

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

        List<AppOpItem> appOpsItems = mAppOpsController.getActiveAppOps();
        final List<UserInfo> profiles = mUserTracker.getUserProfiles();
@@ -229,18 +236,38 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
        for (int i = 0; i < numItems; i++) {
            if (appOpsItems.get(i).getCode() == OP_FINE_LOCATION
                    || appOpsItems.get(i).getCode() == OP_COARSE_LOCATION) {
                if (mShowSystemAccesses) {
                    shouldDisplay = true;
                isSystemApp = isSystemApp(profiles, appOpsItems.get(i));
                if (isSystemApp) {
                    systemAppOp = true;
                } 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) {
            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) {
@@ -283,6 +310,11 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
            mAreActiveLocationRequests = areActiveHighPowerLocationRequests();
            if (mAreActiveLocationRequests != hadActiveLocationRequests) {
                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));
        }
    }

    /**
     * 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 Diff line number Diff line
@@ -14,6 +14,8 @@

package com.android.systemui.statusbar.policy;

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

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

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

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

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

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

        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
@@ -253,6 +263,56 @@ public class LocationControllerImplTest extends SysuiTestCase {
        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
    public void testCallbackRemoved() {
        LocationChangeCallback callback = mock(LocationChangeCallback.class);