Loading core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +6 −0 Original line number Diff line number Diff line Loading @@ -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 /** Loading packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java +57 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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); Loading Loading @@ -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. */ Loading @@ -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); } Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java +61 −7 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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(); } Loading @@ -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); Loading Loading @@ -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); Loading @@ -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); Loading Loading
core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +6 −0 Original line number Diff line number Diff line Loading @@ -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 /** Loading
packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java +57 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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); Loading Loading @@ -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. */ Loading @@ -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); } Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java +61 −7 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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(); } Loading @@ -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); Loading Loading @@ -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); Loading @@ -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); Loading