Skip to content

Commit c0c0c0e

Browse files
Victoria LeaseAndroid (Google) Code Review
authored andcommitted
Merge "Multiuser love for LocationManager" into jb-mr1-dev
2 parents e45c4e4 + b711d57 commit c0c0c0e

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

@@ -1461,6 +1489,16 @@ private void handleLocationChangedLocked(Location location, boolean passive) {
14611489
Receiver receiver = r.mReceiver;
14621490
boolean receiverDead = false;
14631491

1492+
int receiverUserId = UserHandle.getUserId(receiver.mUid);
1493+
if (receiverUserId != mCurrentUserId) {
1494+
if (D) {
1495+
Log.d(TAG, "skipping loc update for background user " + receiverUserId +
1496+
" (current user: " + mCurrentUserId + ", app: " +
1497+
receiver.mPackageName + ")");
1498+
}
1499+
continue;
1500+
}
1501+
14641502
if (mBlacklist.isBlacklisted(receiver.mPackageName)) {
14651503
if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
14661504
receiver.mPackageName);
@@ -1551,7 +1589,7 @@ private void handleLocationChanged(Location location, boolean passive) {
15511589
}
15521590

15531591
synchronized (mLock) {
1554-
if (isAllowedBySettingsLocked(provider)) {
1592+
if (isAllowedBySettingsLocked(provider, mCurrentUserId)) {
15551593
handleLocationChangedLocked(location, passive);
15561594
}
15571595
}

0 commit comments

Comments
 (0)