SysUi: Distinguish between location indicator for system app ops vs others.
This change allows controlling via flag whether or not to show the location indicator for system app location accesses. Bug: 191503437 Test: atest SystemUITests Test: manual Change-Id: I1d3f29d07f340b1ef331c2eba8cedc0d66ba415e
This commit is contained in:
@@ -163,6 +163,12 @@ public final class SystemUiDeviceConfigFlags {
|
||||
public static final String PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED =
|
||||
"location_indicators_small_enabled";
|
||||
|
||||
/**
|
||||
* Whether to show the location indicator for system apps.
|
||||
*/
|
||||
public static final String PROPERTY_LOCATION_INDICATORS_SHOW_SYSTEM =
|
||||
"location_indicators_show_system";
|
||||
|
||||
// Flags related to Assistant
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,10 +22,14 @@ import static android.app.AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION;
|
||||
|
||||
import static com.android.settingslib.Utils.updateLocationEnabled;
|
||||
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.PermissionChecker;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
@@ -68,31 +72,37 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
|
||||
private final BootCompleteCache mBootCompleteCache;
|
||||
private final UserTracker mUserTracker;
|
||||
private final H mHandler;
|
||||
|
||||
private final Handler mBackgroundHandler;
|
||||
private final PackageManager mPackageManager;
|
||||
|
||||
private boolean mAreActiveLocationRequests;
|
||||
private boolean mShouldDisplayAllAccesses;
|
||||
private boolean mShowSystemAccesses;
|
||||
|
||||
@Inject
|
||||
public LocationControllerImpl(Context context, AppOpsController appOpsController,
|
||||
DeviceConfigProxy deviceConfigProxy,
|
||||
@Main Looper mainLooper, @Background Handler backgroundHandler,
|
||||
BroadcastDispatcher broadcastDispatcher, BootCompleteCache bootCompleteCache,
|
||||
UserTracker userTracker) {
|
||||
UserTracker userTracker, PackageManager packageManager) {
|
||||
mContext = context;
|
||||
mAppOpsController = appOpsController;
|
||||
mDeviceConfigProxy = deviceConfigProxy;
|
||||
mBootCompleteCache = bootCompleteCache;
|
||||
mHandler = new H(mainLooper);
|
||||
mUserTracker = userTracker;
|
||||
mShouldDisplayAllAccesses = getDeviceConfigSetting();
|
||||
mBackgroundHandler = backgroundHandler;
|
||||
mPackageManager = packageManager;
|
||||
mShouldDisplayAllAccesses = getAllAccessesSetting();
|
||||
mShowSystemAccesses = getShowSystemSetting();
|
||||
|
||||
// Register to listen for changes in DeviceConfig settings.
|
||||
mDeviceConfigProxy.addOnPropertiesChangedListener(
|
||||
DeviceConfig.NAMESPACE_PRIVACY,
|
||||
backgroundHandler::post,
|
||||
properties -> {
|
||||
mShouldDisplayAllAccesses = getDeviceConfigSetting();
|
||||
mShouldDisplayAllAccesses = getAllAccessesSetting();
|
||||
mShowSystemAccesses = getShowSystemSetting();
|
||||
updateActiveLocationRequests();
|
||||
});
|
||||
|
||||
@@ -176,11 +186,15 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
|
||||
UserHandle.of(userId));
|
||||
}
|
||||
|
||||
private boolean getDeviceConfigSetting() {
|
||||
private boolean getAllAccessesSetting() {
|
||||
return mDeviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
|
||||
SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false);
|
||||
}
|
||||
|
||||
private boolean getShowSystemSetting() {
|
||||
return mDeviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
|
||||
SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SHOW_SYSTEM, false);
|
||||
}
|
||||
/**
|
||||
* Returns true if there currently exist active high power location requests.
|
||||
*/
|
||||
@@ -202,35 +216,74 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
|
||||
* Returns true if there currently exist active location requests.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
protected boolean areActiveLocationRequests() {
|
||||
protected void areActiveLocationRequests() {
|
||||
if (!mShouldDisplayAllAccesses) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
List<AppOpItem> appOpsItems = mAppOpsController.getActiveAppOps();
|
||||
boolean hadActiveLocationRequests = mAreActiveLocationRequests;
|
||||
boolean shouldDisplay = false;
|
||||
|
||||
List<AppOpItem> appOpsItems = mAppOpsController.getActiveAppOps();
|
||||
final List<UserInfo> profiles = mUserTracker.getUserProfiles();
|
||||
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;
|
||||
if (mShowSystemAccesses) {
|
||||
shouldDisplay = true;
|
||||
} else {
|
||||
shouldDisplay |= !isSystemApp(profiles, appOpsItems.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
mAreActiveLocationRequests = areActiveHighPowerLocationRequests() || shouldDisplay;
|
||||
if (mAreActiveLocationRequests != hadActiveLocationRequests) {
|
||||
mHandler.sendEmptyMessage(H.MSG_LOCATION_ACTIVE_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSystemApp(List<UserInfo> profiles, AppOpItem item) {
|
||||
final String permission = AppOpsManager.opToPermission(item.getCode());
|
||||
UserHandle user = UserHandle.getUserHandleForUid(item.getUid());
|
||||
|
||||
// Don't show apps belonging to background users except managed users.
|
||||
boolean foundUser = false;
|
||||
final int numProfiles = profiles.size();
|
||||
for (int i = 0; i < numProfiles; i++) {
|
||||
if (profiles.get(i).getUserHandle().equals(user)) {
|
||||
foundUser = true;
|
||||
}
|
||||
}
|
||||
if (!foundUser) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final int permissionFlags = mPackageManager.getPermissionFlags(
|
||||
permission, item.getPackageName(), user);
|
||||
if (PermissionChecker.checkPermissionForPreflight(mContext, permission,
|
||||
PermissionChecker.PID_UNKNOWN, item.getUid(), item.getPackageName())
|
||||
== PermissionChecker.PERMISSION_GRANTED) {
|
||||
return (permissionFlags
|
||||
& PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED)
|
||||
== 0;
|
||||
} else {
|
||||
return (permissionFlags
|
||||
& PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
mBackgroundHandler.post(this::areActiveLocationRequests);
|
||||
} else {
|
||||
boolean hadActiveLocationRequests = mAreActiveLocationRequests;
|
||||
mAreActiveLocationRequests = areActiveHighPowerLocationRequests();
|
||||
}
|
||||
if (mAreActiveLocationRequests != hadActiveLocationRequests) {
|
||||
mHandler.sendEmptyMessage(H.MSG_LOCATION_ACTIVE_CHANGED);
|
||||
if (mAreActiveLocationRequests != hadActiveLocationRequests) {
|
||||
mHandler.sendEmptyMessage(H.MSG_LOCATION_ACTIVE_CHANGED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Handler;
|
||||
import android.os.UserHandle;
|
||||
@@ -68,6 +69,8 @@ public class LocationControllerImplTest extends SysuiTestCase {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
when(mUserTracker.getUserId()).thenReturn(UserHandle.USER_SYSTEM);
|
||||
when(mUserTracker.getUserHandle()).thenReturn(UserHandle.SYSTEM);
|
||||
when(mUserTracker.getUserProfiles())
|
||||
.thenReturn(ImmutableList.of(new UserInfo(0, "name", 0)));
|
||||
mDeviceConfigProxy = new DeviceConfigProxyFake();
|
||||
|
||||
mTestableLooper = TestableLooper.get(this);
|
||||
@@ -78,7 +81,8 @@ public class LocationControllerImplTest extends SysuiTestCase {
|
||||
new Handler(mTestableLooper.getLooper()),
|
||||
mock(BroadcastDispatcher.class),
|
||||
mock(BootCompleteCache.class),
|
||||
mUserTracker);
|
||||
mUserTracker,
|
||||
mContext.getPackageManager());
|
||||
|
||||
mTestableLooper.processAllMessages();
|
||||
}
|
||||
@@ -161,17 +165,7 @@ public class LocationControllerImplTest extends SysuiTestCase {
|
||||
@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,
|
||||
@@ -181,10 +175,11 @@ public class LocationControllerImplTest extends SysuiTestCase {
|
||||
|
||||
when(mAppOpsController.getActiveAppOps())
|
||||
.thenReturn(ImmutableList.of(
|
||||
new AppOpItem(AppOpsManager.OP_FINE_LOCATION, 0, "",
|
||||
new AppOpItem(AppOpsManager.OP_FINE_LOCATION, 0,
|
||||
"com.google.android.googlequicksearchbox",
|
||||
System.currentTimeMillis())));
|
||||
mLocationController.onActiveStateChanged(AppOpsManager.OP_FINE_LOCATION, 0,
|
||||
"", true);
|
||||
"com.google.android.googlequicksearchbox", true);
|
||||
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
@@ -192,7 +187,67 @@ public class LocationControllerImplTest extends SysuiTestCase {
|
||||
|
||||
when(mAppOpsController.getActiveAppOps()).thenReturn(ImmutableList.of());
|
||||
mLocationController.onActiveStateChanged(AppOpsManager.OP_FINE_LOCATION, 0,
|
||||
"", false);
|
||||
"com.google.android.googlequicksearchbox", false);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(callback, times(1)).onLocationActiveChanged(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCallbackNotified_additionalOps_shouldShowSystem() {
|
||||
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())));
|
||||
mLocationController.onActiveStateChanged(AppOpsManager.OP_FINE_LOCATION, 0,
|
||||
"com.google.android.gms", true);
|
||||
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(callback, times(0)).onLocationActiveChanged(true);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCallbackNotified_additionalOps_shouldNotShowSystem() {
|
||||
LocationChangeCallback callback = mock(LocationChangeCallback.class);
|
||||
mLocationController.addCallback(callback);
|
||||
mDeviceConfigProxy.setProperty(
|
||||
DeviceConfig.NAMESPACE_PRIVACY,
|
||||
SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED,
|
||||
"true",
|
||||
true);
|
||||
mDeviceConfigProxy.setProperty(
|
||||
DeviceConfig.NAMESPACE_PRIVACY,
|
||||
SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SHOW_SYSTEM,
|
||||
"true",
|
||||
true);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
when(mAppOpsController.getActiveAppOps())
|
||||
.thenReturn(ImmutableList.of(
|
||||
new AppOpItem(AppOpsManager.OP_FINE_LOCATION, 0, "com.google.android.gms",
|
||||
System.currentTimeMillis())));
|
||||
mLocationController.onActiveStateChanged(AppOpsManager.OP_FINE_LOCATION, 0,
|
||||
"com.google.android.gms", true);
|
||||
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(callback, times(1)).onLocationActiveChanged(true);
|
||||
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user