Skip to content

Commit b711d57

Browse files
author
Victoria Lease
committed
Multiuser love for LocationManager
LocationManagerService now keeps track of the current user ID and denies location requests made by all but the foreground user. Additionally, location settings are now user-specific, rather than global to the device. Location provider services now run as specific users, and when the device's foreground user changes, we rebind to appropriately-owned providers. Bug: 6926385 Bug: 7247203 Change-Id: I346074959e96e52bcc77eeb188dffe322b690879
1 parent bb5f014 commit b711d57

File tree

9 files changed

+222
-118
lines changed

9 files changed

+222
-118
lines changed

core/java/android/provider/Settings.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4052,7 +4052,20 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val
40524052
* @return true if the provider is enabled
40534053
*/
40544054
public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) {
4055-
String allowedProviders = Settings.Secure.getString(cr, LOCATION_PROVIDERS_ALLOWED);
4055+
return isLocationProviderEnabledForUser(cr, provider, UserHandle.myUserId());
4056+
}
4057+
4058+
/**
4059+
* Helper method for determining if a location provider is enabled.
4060+
* @param cr the content resolver to use
4061+
* @param provider the location provider to query
4062+
* @param userId the userId to query
4063+
* @return true if the provider is enabled
4064+
* @hide
4065+
*/
4066+
public static final boolean isLocationProviderEnabledForUser(ContentResolver cr, String provider, int userId) {
4067+
String allowedProviders = Settings.Secure.getStringForUser(cr,
4068+
LOCATION_PROVIDERS_ALLOWED, userId);
40564069
return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
40574070
}
40584071

@@ -4064,6 +4077,19 @@ public static final boolean isLocationProviderEnabled(ContentResolver cr, String
40644077
*/
40654078
public static final void setLocationProviderEnabled(ContentResolver cr,
40664079
String provider, boolean enabled) {
4080+
setLocationProviderEnabledForUser(cr, provider, enabled, UserHandle.myUserId());
4081+
}
4082+
4083+
/**
4084+
* Thread-safe method for enabling or disabling a single location provider.
4085+
* @param cr the content resolver to use
4086+
* @param provider the location provider to enable or disable
4087+
* @param enabled true if the provider should be enabled
4088+
* @param userId the userId for which to enable/disable providers
4089+
* @hide
4090+
*/
4091+
public static final void setLocationProviderEnabledForUser(ContentResolver cr,
4092+
String provider, boolean enabled, int userId) {
40674093
// to ensure thread safety, we write the provider name with a '+' or '-'
40684094
// and let the SettingsProvider handle it rather than reading and modifying
40694095
// the list of enabled providers.
@@ -4072,7 +4098,8 @@ public static final void setLocationProviderEnabled(ContentResolver cr,
40724098
} else {
40734099
provider = "-" + provider;
40744100
}
4075-
putString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider);
4101+
putStringForUser(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider,
4102+
userId);
40764103
}
40774104
}
40784105

services/java/com/android/server/LocationManagerService.java

Lines changed: 111 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ public void onChange(boolean selfChange) {
226226
updateProvidersLocked();
227227
}
228228
}
229-
});
229+
}, UserHandle.USER_ALL);
230230
mPackageMonitor.register(mContext, Looper.myLooper(), true);
231231

232232
// listen for user change
@@ -289,7 +289,7 @@ Load package name(s) containing location provider support.
289289
mContext,
290290
LocationManager.NETWORK_PROVIDER,
291291
NETWORK_LOCATION_SERVICE_ACTION,
292-
providerPackageNames, mLocationHandler);
292+
providerPackageNames, mLocationHandler, mCurrentUserId);
293293
if (networkProvider != null) {
294294
mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
295295
mProxyProviders.add(networkProvider);
@@ -303,7 +303,7 @@ Load package name(s) containing location provider support.
303303
mContext,
304304
LocationManager.FUSED_PROVIDER,
305305
FUSED_LOCATION_SERVICE_ACTION,
306-
providerPackageNames, mLocationHandler);
306+
providerPackageNames, mLocationHandler, mCurrentUserId);
307307
if (fusedLocationProvider != null) {
308308
addProviderLocked(fusedLocationProvider);
309309
mProxyProviders.add(fusedLocationProvider);
@@ -314,7 +314,8 @@ Load package name(s) containing location provider support.
314314
}
315315

316316
// bind to geocoder provider
317-
mGeocodeProvider = GeocoderProxy.createAndBind(mContext, providerPackageNames);
317+
mGeocodeProvider = GeocoderProxy.createAndBind(mContext, providerPackageNames,
318+
mCurrentUserId);
318319
if (mGeocodeProvider == null) {
319320
Slog.e(TAG, "no geocoder provider found");
320321
}
@@ -326,11 +327,14 @@ Load package name(s) containing location provider support.
326327
*/
327328
private void switchUser(int userId) {
328329
mBlacklist.switchUser(userId);
329-
//Log.d("LocationManagerService", "switchUser(" + mCurrentUserId + " -> " + userId + ")"); // TODO: remove this
330330
synchronized (mLock) {
331-
// TODO: inform previous user's Receivers that they will no longer receive updates
331+
mLastLocation.clear();
332+
for (LocationProviderInterface p : mProviders) {
333+
updateProviderListenersLocked(p.getName(), false, mCurrentUserId);
334+
p.switchUser(userId);
335+
}
332336
mCurrentUserId = userId;
333-
// TODO: inform new user's Receivers that they are back on the update train
337+
updateProvidersLocked();
334338
}
335339
}
336340

@@ -587,7 +591,10 @@ private void removeProviderLocked(LocationProviderInterface provider) {
587591
}
588592

589593

590-
private boolean isAllowedBySettingsLocked(String provider) {
594+
private boolean isAllowedBySettingsLocked(String provider, int userId) {
595+
if (userId != mCurrentUserId) {
596+
return false;
597+
}
591598
if (mEnabledProviders.contains(provider)) {
592599
return true;
593600
}
@@ -597,7 +604,7 @@ private boolean isAllowedBySettingsLocked(String provider) {
597604
// Use system settings
598605
ContentResolver resolver = mContext.getContentResolver();
599606

600-
return Settings.Secure.isLocationProviderEnabled(resolver, provider);
607+
return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId);
601608
}
602609

603610
/**
@@ -695,24 +702,30 @@ public List<String> getAllProviders() {
695702
@Override
696703
public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
697704
ArrayList<String> out;
698-
synchronized (mLock) {
699-
out = new ArrayList<String>(mProviders.size());
700-
for (LocationProviderInterface provider : mProviders) {
701-
String name = provider.getName();
702-
if (LocationManager.FUSED_PROVIDER.equals(name)) {
703-
continue;
704-
}
705-
if (isAllowedProviderSafe(name)) {
706-
if (enabledOnly && !isAllowedBySettingsLocked(name)) {
705+
int callingUserId = UserHandle.getCallingUserId();
706+
long identity = Binder.clearCallingIdentity();
707+
try {
708+
synchronized (mLock) {
709+
out = new ArrayList<String>(mProviders.size());
710+
for (LocationProviderInterface provider : mProviders) {
711+
String name = provider.getName();
712+
if (LocationManager.FUSED_PROVIDER.equals(name)) {
707713
continue;
708714
}
709-
if (criteria != null && !LocationProvider.propertiesMeetCriteria(
710-
name, provider.getProperties(), criteria)) {
711-
continue;
715+
if (isAllowedProviderSafe(name)) {
716+
if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) {
717+
continue;
718+
}
719+
if (criteria != null && !LocationProvider.propertiesMeetCriteria(
720+
name, provider.getProperties(), criteria)) {
721+
continue;
722+
}
723+
out.add(name);
712724
}
713-
out.add(name);
714725
}
715726
}
727+
} finally {
728+
Binder.restoreCallingIdentity(identity);
716729
}
717730

718731
if (D) Log.d(TAG, "getProviders()=" + out);
@@ -778,12 +791,12 @@ private void updateProvidersLocked() {
778791
LocationProviderInterface p = mProviders.get(i);
779792
boolean isEnabled = p.isEnabled();
780793
String name = p.getName();
781-
boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
794+
boolean shouldBeEnabled = isAllowedBySettingsLocked(name, mCurrentUserId);
782795
if (isEnabled && !shouldBeEnabled) {
783-
updateProviderListenersLocked(name, false);
796+
updateProviderListenersLocked(name, false, mCurrentUserId);
784797
changesMade = true;
785798
} else if (!isEnabled && shouldBeEnabled) {
786-
updateProviderListenersLocked(name, true);
799+
updateProviderListenersLocked(name, true, mCurrentUserId);
787800
changesMade = true;
788801
}
789802
}
@@ -793,7 +806,7 @@ private void updateProvidersLocked() {
793806
}
794807
}
795808

796-
private void updateProviderListenersLocked(String provider, boolean enabled) {
809+
private void updateProviderListenersLocked(String provider, boolean enabled, int userId) {
797810
int listeners = 0;
798811

799812
LocationProviderInterface p = mProvidersByName.get(provider);
@@ -806,14 +819,16 @@ private void updateProviderListenersLocked(String provider, boolean enabled) {
806819
final int N = records.size();
807820
for (int i = 0; i < N; i++) {
808821
UpdateRecord record = records.get(i);
809-
// Sends a notification message to the receiver
810-
if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
811-
if (deadReceivers == null) {
812-
deadReceivers = new ArrayList<Receiver>();
822+
if (UserHandle.getUserId(record.mReceiver.mUid) == userId) {
823+
// Sends a notification message to the receiver
824+
if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
825+
if (deadReceivers == null) {
826+
deadReceivers = new ArrayList<Receiver>();
827+
}
828+
deadReceivers.add(record.mReceiver);
813829
}
814-
deadReceivers.add(record.mReceiver);
830+
listeners++;
815831
}
816-
listeners++;
817832
}
818833
}
819834

@@ -843,12 +858,13 @@ private void applyRequirementsLocked(String provider) {
843858

844859
if (records != null) {
845860
for (UpdateRecord record : records) {
846-
LocationRequest locationRequest = record.mRequest;
847-
848-
providerRequest.locationRequests.add(locationRequest);
849-
if (locationRequest.getInterval() < providerRequest.interval) {
850-
providerRequest.reportLocation = true;
851-
providerRequest.interval = locationRequest.getInterval();
861+
if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
862+
LocationRequest locationRequest = record.mRequest;
863+
providerRequest.locationRequests.add(locationRequest);
864+
if (locationRequest.getInterval() < providerRequest.interval) {
865+
providerRequest.reportLocation = true;
866+
providerRequest.interval = locationRequest.getInterval();
867+
}
852868
}
853869
}
854870

@@ -860,9 +876,11 @@ private void applyRequirementsLocked(String provider) {
860876
// under that threshold.
861877
long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
862878
for (UpdateRecord record : records) {
863-
LocationRequest locationRequest = record.mRequest;
864-
if (locationRequest.getInterval() <= thresholdInterval) {
865-
worksource.add(record.mReceiver.mUid);
879+
if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
880+
LocationRequest locationRequest = record.mRequest;
881+
if (locationRequest.getInterval() <= thresholdInterval) {
882+
worksource.add(record.mReceiver.mUid);
883+
}
866884
}
867885
}
868886
}
@@ -1084,7 +1102,7 @@ private void requestLocationUpdatesLocked(LocationRequest request, Receiver rece
10841102
oldRecord.disposeLocked(false);
10851103
}
10861104

1087-
boolean isProviderEnabled = isAllowedBySettingsLocked(name);
1105+
boolean isProviderEnabled = isAllowedBySettingsLocked(name, UserHandle.getUserId(uid));
10881106
if (isProviderEnabled) {
10891107
applyRequirementsLocked(name);
10901108
} else {
@@ -1141,7 +1159,7 @@ private void removeUpdatesLocked(Receiver receiver) {
11411159
// update provider
11421160
for (String provider : providers) {
11431161
// If provider is already disabled, don't need to do anything
1144-
if (!isAllowedBySettingsLocked(provider)) {
1162+
if (!isAllowedBySettingsLocked(provider, mCurrentUserId)) {
11451163
continue;
11461164
}
11471165

@@ -1156,36 +1174,41 @@ public Location getLastLocation(LocationRequest request, String packageName) {
11561174
String perm = checkPermissionAndRequest(request);
11571175
checkPackageName(packageName);
11581176

1159-
if (mBlacklist.isBlacklisted(packageName)) {
1160-
if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
1161-
packageName);
1162-
return null;
1163-
}
1164-
1165-
synchronized (mLock) {
1166-
// Figure out the provider. Either its explicitly request (deprecated API's),
1167-
// or use the fused provider
1168-
String name = request.getProvider();
1169-
if (name == null) name = LocationManager.FUSED_PROVIDER;
1170-
LocationProviderInterface provider = mProvidersByName.get(name);
1171-
if (provider == null) return null;
1172-
1173-
if (!isAllowedBySettingsLocked(name)) return null;
1174-
1175-
Location location = mLastLocation.get(name);
1176-
if (location == null) {
1177+
long identity = Binder.clearCallingIdentity();
1178+
try {
1179+
if (mBlacklist.isBlacklisted(packageName)) {
1180+
if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
1181+
packageName);
11771182
return null;
11781183
}
1179-
if (ACCESS_FINE_LOCATION.equals(perm)) {
1180-
return location;
1181-
} else {
1182-
Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
1183-
if (noGPSLocation != null) {
1184-
return mLocationFudger.getOrCreate(noGPSLocation);
1184+
1185+
synchronized (mLock) {
1186+
// Figure out the provider. Either its explicitly request (deprecated API's),
1187+
// or use the fused provider
1188+
String name = request.getProvider();
1189+
if (name == null) name = LocationManager.FUSED_PROVIDER;
1190+
LocationProviderInterface provider = mProvidersByName.get(name);
1191+
if (provider == null) return null;
1192+
1193+
if (!isAllowedBySettingsLocked(name, mCurrentUserId)) return null;
1194+
1195+
Location location = mLastLocation.get(name);
1196+
if (location == null) {
1197+
return null;
1198+
}
1199+
if (ACCESS_FINE_LOCATION.equals(perm)) {
1200+
return location;
1201+
} else {
1202+
Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
1203+
if (noGPSLocation != null) {
1204+
return mLocationFudger.getOrCreate(noGPSLocation);
1205+
}
11851206
}
11861207
}
1208+
return null;
1209+
} finally {
1210+
Binder.restoreCallingIdentity(identity);
11871211
}
1188-
return null;
11891212
}
11901213

11911214
@Override
@@ -1321,11 +1344,16 @@ public boolean isProviderEnabled(String provider) {
13211344
"\" provider requires ACCESS_FINE_LOCATION permission");
13221345
}
13231346

1324-
synchronized (mLock) {
1325-
LocationProviderInterface p = mProvidersByName.get(provider);
1326-
if (p == null) return false;
1347+
long identity = Binder.clearCallingIdentity();
1348+
try {
1349+
synchronized (mLock) {
1350+
LocationProviderInterface p = mProvidersByName.get(provider);
1351+
if (p == null) return false;
13271352

1328-
return isAllowedBySettingsLocked(provider);
1353+
return isAllowedBySettingsLocked(provider, mCurrentUserId);
1354+
}
1355+
} finally {
1356+
Binder.restoreCallingIdentity(identity);
13291357
}
13301358
}
13311359

@@ -1458,6 +1486,16 @@ private void handleLocationChangedLocked(Location location, boolean passive) {
14581486
Receiver receiver = r.mReceiver;
14591487
boolean receiverDead = false;
14601488

1489+
int receiverUserId = UserHandle.getUserId(receiver.mUid);
1490+
if (receiverUserId != mCurrentUserId) {
1491+
if (D) {
1492+
Log.d(TAG, "skipping loc update for background user " + receiverUserId +
1493+
" (current user: " + mCurrentUserId + ", app: " +
1494+
receiver.mPackageName + ")");
1495+
}
1496+
continue;
1497+
}
1498+
14611499
if (mBlacklist.isBlacklisted(receiver.mPackageName)) {
14621500
if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
14631501
receiver.mPackageName);
@@ -1548,7 +1586,7 @@ private void handleLocationChanged(Location location, boolean passive) {
15481586
}
15491587

15501588
synchronized (mLock) {
1551-
if (isAllowedBySettingsLocked(provider)) {
1589+
if (isAllowedBySettingsLocked(provider, mCurrentUserId)) {
15521590
handleLocationChangedLocked(location, passive);
15531591
}
15541592
}

0 commit comments

Comments
 (0)