Merge "Multiuser love for LocationManager" into jb-mr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c0c0c0e612
@ -4052,7 +4052,20 @@ public final class Settings {
|
|||||||
* @return true if the provider is enabled
|
* @return true if the provider is enabled
|
||||||
*/
|
*/
|
||||||
public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) {
|
public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) {
|
||||||
String allowedProviders = Settings.Secure.getString(cr, LOCATION_PROVIDERS_ALLOWED);
|
return isLocationProviderEnabledForUser(cr, provider, UserHandle.myUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for determining if a location provider is enabled.
|
||||||
|
* @param cr the content resolver to use
|
||||||
|
* @param provider the location provider to query
|
||||||
|
* @param userId the userId to query
|
||||||
|
* @return true if the provider is enabled
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final boolean isLocationProviderEnabledForUser(ContentResolver cr, String provider, int userId) {
|
||||||
|
String allowedProviders = Settings.Secure.getStringForUser(cr,
|
||||||
|
LOCATION_PROVIDERS_ALLOWED, userId);
|
||||||
return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
|
return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4064,6 +4077,19 @@ public final class Settings {
|
|||||||
*/
|
*/
|
||||||
public static final void setLocationProviderEnabled(ContentResolver cr,
|
public static final void setLocationProviderEnabled(ContentResolver cr,
|
||||||
String provider, boolean enabled) {
|
String provider, boolean enabled) {
|
||||||
|
setLocationProviderEnabledForUser(cr, provider, enabled, UserHandle.myUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread-safe method for enabling or disabling a single location provider.
|
||||||
|
* @param cr the content resolver to use
|
||||||
|
* @param provider the location provider to enable or disable
|
||||||
|
* @param enabled true if the provider should be enabled
|
||||||
|
* @param userId the userId for which to enable/disable providers
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final void setLocationProviderEnabledForUser(ContentResolver cr,
|
||||||
|
String provider, boolean enabled, int userId) {
|
||||||
// to ensure thread safety, we write the provider name with a '+' or '-'
|
// to ensure thread safety, we write the provider name with a '+' or '-'
|
||||||
// and let the SettingsProvider handle it rather than reading and modifying
|
// and let the SettingsProvider handle it rather than reading and modifying
|
||||||
// the list of enabled providers.
|
// the list of enabled providers.
|
||||||
@ -4072,7 +4098,8 @@ public final class Settings {
|
|||||||
} else {
|
} else {
|
||||||
provider = "-" + provider;
|
provider = "-" + provider;
|
||||||
}
|
}
|
||||||
putString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider);
|
putStringForUser(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider,
|
||||||
|
userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,7 +226,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
updateProvidersLocked();
|
updateProvidersLocked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}, UserHandle.USER_ALL);
|
||||||
mPackageMonitor.register(mContext, Looper.myLooper(), true);
|
mPackageMonitor.register(mContext, Looper.myLooper(), true);
|
||||||
|
|
||||||
// listen for user change
|
// listen for user change
|
||||||
@ -289,7 +289,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
mContext,
|
mContext,
|
||||||
LocationManager.NETWORK_PROVIDER,
|
LocationManager.NETWORK_PROVIDER,
|
||||||
NETWORK_LOCATION_SERVICE_ACTION,
|
NETWORK_LOCATION_SERVICE_ACTION,
|
||||||
providerPackageNames, mLocationHandler);
|
providerPackageNames, mLocationHandler, mCurrentUserId);
|
||||||
if (networkProvider != null) {
|
if (networkProvider != null) {
|
||||||
mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
|
mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
|
||||||
mProxyProviders.add(networkProvider);
|
mProxyProviders.add(networkProvider);
|
||||||
@ -303,7 +303,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
mContext,
|
mContext,
|
||||||
LocationManager.FUSED_PROVIDER,
|
LocationManager.FUSED_PROVIDER,
|
||||||
FUSED_LOCATION_SERVICE_ACTION,
|
FUSED_LOCATION_SERVICE_ACTION,
|
||||||
providerPackageNames, mLocationHandler);
|
providerPackageNames, mLocationHandler, mCurrentUserId);
|
||||||
if (fusedLocationProvider != null) {
|
if (fusedLocationProvider != null) {
|
||||||
addProviderLocked(fusedLocationProvider);
|
addProviderLocked(fusedLocationProvider);
|
||||||
mProxyProviders.add(fusedLocationProvider);
|
mProxyProviders.add(fusedLocationProvider);
|
||||||
@ -314,7 +314,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
}
|
}
|
||||||
|
|
||||||
// bind to geocoder provider
|
// bind to geocoder provider
|
||||||
mGeocodeProvider = GeocoderProxy.createAndBind(mContext, providerPackageNames);
|
mGeocodeProvider = GeocoderProxy.createAndBind(mContext, providerPackageNames,
|
||||||
|
mCurrentUserId);
|
||||||
if (mGeocodeProvider == null) {
|
if (mGeocodeProvider == null) {
|
||||||
Slog.e(TAG, "no geocoder provider found");
|
Slog.e(TAG, "no geocoder provider found");
|
||||||
}
|
}
|
||||||
@ -326,11 +327,14 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
*/
|
*/
|
||||||
private void switchUser(int userId) {
|
private void switchUser(int userId) {
|
||||||
mBlacklist.switchUser(userId);
|
mBlacklist.switchUser(userId);
|
||||||
//Log.d("LocationManagerService", "switchUser(" + mCurrentUserId + " -> " + userId + ")"); // TODO: remove this
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
// TODO: inform previous user's Receivers that they will no longer receive updates
|
mLastLocation.clear();
|
||||||
|
for (LocationProviderInterface p : mProviders) {
|
||||||
|
updateProviderListenersLocked(p.getName(), false, mCurrentUserId);
|
||||||
|
p.switchUser(userId);
|
||||||
|
}
|
||||||
mCurrentUserId = userId;
|
mCurrentUserId = userId;
|
||||||
// TODO: inform new user's Receivers that they are back on the update train
|
updateProvidersLocked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,7 +591,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean isAllowedBySettingsLocked(String provider) {
|
private boolean isAllowedBySettingsLocked(String provider, int userId) {
|
||||||
|
if (userId != mCurrentUserId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (mEnabledProviders.contains(provider)) {
|
if (mEnabledProviders.contains(provider)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -597,7 +604,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
// Use system settings
|
// Use system settings
|
||||||
ContentResolver resolver = mContext.getContentResolver();
|
ContentResolver resolver = mContext.getContentResolver();
|
||||||
|
|
||||||
return Settings.Secure.isLocationProviderEnabled(resolver, provider);
|
return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -695,24 +702,30 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
@Override
|
@Override
|
||||||
public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
|
public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
|
||||||
ArrayList<String> out;
|
ArrayList<String> out;
|
||||||
synchronized (mLock) {
|
int callingUserId = UserHandle.getCallingUserId();
|
||||||
out = new ArrayList<String>(mProviders.size());
|
long identity = Binder.clearCallingIdentity();
|
||||||
for (LocationProviderInterface provider : mProviders) {
|
try {
|
||||||
String name = provider.getName();
|
synchronized (mLock) {
|
||||||
if (LocationManager.FUSED_PROVIDER.equals(name)) {
|
out = new ArrayList<String>(mProviders.size());
|
||||||
continue;
|
for (LocationProviderInterface provider : mProviders) {
|
||||||
}
|
String name = provider.getName();
|
||||||
if (isAllowedProviderSafe(name)) {
|
if (LocationManager.FUSED_PROVIDER.equals(name)) {
|
||||||
if (enabledOnly && !isAllowedBySettingsLocked(name)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (criteria != null && !LocationProvider.propertiesMeetCriteria(
|
if (isAllowedProviderSafe(name)) {
|
||||||
name, provider.getProperties(), criteria)) {
|
if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
if (criteria != null && !LocationProvider.propertiesMeetCriteria(
|
||||||
|
name, provider.getProperties(), criteria)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
out.add(name);
|
||||||
}
|
}
|
||||||
out.add(name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (D) Log.d(TAG, "getProviders()=" + out);
|
if (D) Log.d(TAG, "getProviders()=" + out);
|
||||||
@ -778,12 +791,12 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
LocationProviderInterface p = mProviders.get(i);
|
LocationProviderInterface p = mProviders.get(i);
|
||||||
boolean isEnabled = p.isEnabled();
|
boolean isEnabled = p.isEnabled();
|
||||||
String name = p.getName();
|
String name = p.getName();
|
||||||
boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
|
boolean shouldBeEnabled = isAllowedBySettingsLocked(name, mCurrentUserId);
|
||||||
if (isEnabled && !shouldBeEnabled) {
|
if (isEnabled && !shouldBeEnabled) {
|
||||||
updateProviderListenersLocked(name, false);
|
updateProviderListenersLocked(name, false, mCurrentUserId);
|
||||||
changesMade = true;
|
changesMade = true;
|
||||||
} else if (!isEnabled && shouldBeEnabled) {
|
} else if (!isEnabled && shouldBeEnabled) {
|
||||||
updateProviderListenersLocked(name, true);
|
updateProviderListenersLocked(name, true, mCurrentUserId);
|
||||||
changesMade = true;
|
changesMade = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -793,7 +806,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateProviderListenersLocked(String provider, boolean enabled) {
|
private void updateProviderListenersLocked(String provider, boolean enabled, int userId) {
|
||||||
int listeners = 0;
|
int listeners = 0;
|
||||||
|
|
||||||
LocationProviderInterface p = mProvidersByName.get(provider);
|
LocationProviderInterface p = mProvidersByName.get(provider);
|
||||||
@ -806,14 +819,16 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
final int N = records.size();
|
final int N = records.size();
|
||||||
for (int i = 0; i < N; i++) {
|
for (int i = 0; i < N; i++) {
|
||||||
UpdateRecord record = records.get(i);
|
UpdateRecord record = records.get(i);
|
||||||
// Sends a notification message to the receiver
|
if (UserHandle.getUserId(record.mReceiver.mUid) == userId) {
|
||||||
if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
|
// Sends a notification message to the receiver
|
||||||
if (deadReceivers == null) {
|
if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
|
||||||
deadReceivers = new ArrayList<Receiver>();
|
if (deadReceivers == null) {
|
||||||
|
deadReceivers = new ArrayList<Receiver>();
|
||||||
|
}
|
||||||
|
deadReceivers.add(record.mReceiver);
|
||||||
}
|
}
|
||||||
deadReceivers.add(record.mReceiver);
|
listeners++;
|
||||||
}
|
}
|
||||||
listeners++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -843,12 +858,13 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
|
|
||||||
if (records != null) {
|
if (records != null) {
|
||||||
for (UpdateRecord record : records) {
|
for (UpdateRecord record : records) {
|
||||||
LocationRequest locationRequest = record.mRequest;
|
if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
|
||||||
|
LocationRequest locationRequest = record.mRequest;
|
||||||
providerRequest.locationRequests.add(locationRequest);
|
providerRequest.locationRequests.add(locationRequest);
|
||||||
if (locationRequest.getInterval() < providerRequest.interval) {
|
if (locationRequest.getInterval() < providerRequest.interval) {
|
||||||
providerRequest.reportLocation = true;
|
providerRequest.reportLocation = true;
|
||||||
providerRequest.interval = locationRequest.getInterval();
|
providerRequest.interval = locationRequest.getInterval();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -860,9 +876,11 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
// under that threshold.
|
// under that threshold.
|
||||||
long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
|
long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
|
||||||
for (UpdateRecord record : records) {
|
for (UpdateRecord record : records) {
|
||||||
LocationRequest locationRequest = record.mRequest;
|
if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
|
||||||
if (locationRequest.getInterval() <= thresholdInterval) {
|
LocationRequest locationRequest = record.mRequest;
|
||||||
worksource.add(record.mReceiver.mUid);
|
if (locationRequest.getInterval() <= thresholdInterval) {
|
||||||
|
worksource.add(record.mReceiver.mUid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1084,7 +1102,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
oldRecord.disposeLocked(false);
|
oldRecord.disposeLocked(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isProviderEnabled = isAllowedBySettingsLocked(name);
|
boolean isProviderEnabled = isAllowedBySettingsLocked(name, UserHandle.getUserId(uid));
|
||||||
if (isProviderEnabled) {
|
if (isProviderEnabled) {
|
||||||
applyRequirementsLocked(name);
|
applyRequirementsLocked(name);
|
||||||
} else {
|
} else {
|
||||||
@ -1141,7 +1159,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
// update provider
|
// update provider
|
||||||
for (String provider : providers) {
|
for (String provider : providers) {
|
||||||
// If provider is already disabled, don't need to do anything
|
// If provider is already disabled, don't need to do anything
|
||||||
if (!isAllowedBySettingsLocked(provider)) {
|
if (!isAllowedBySettingsLocked(provider, mCurrentUserId)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1156,36 +1174,41 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
String perm = checkPermissionAndRequest(request);
|
String perm = checkPermissionAndRequest(request);
|
||||||
checkPackageName(packageName);
|
checkPackageName(packageName);
|
||||||
|
|
||||||
if (mBlacklist.isBlacklisted(packageName)) {
|
long identity = Binder.clearCallingIdentity();
|
||||||
if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
|
try {
|
||||||
packageName);
|
if (mBlacklist.isBlacklisted(packageName)) {
|
||||||
return null;
|
if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
|
||||||
}
|
packageName);
|
||||||
|
|
||||||
synchronized (mLock) {
|
|
||||||
// Figure out the provider. Either its explicitly request (deprecated API's),
|
|
||||||
// or use the fused provider
|
|
||||||
String name = request.getProvider();
|
|
||||||
if (name == null) name = LocationManager.FUSED_PROVIDER;
|
|
||||||
LocationProviderInterface provider = mProvidersByName.get(name);
|
|
||||||
if (provider == null) return null;
|
|
||||||
|
|
||||||
if (!isAllowedBySettingsLocked(name)) return null;
|
|
||||||
|
|
||||||
Location location = mLastLocation.get(name);
|
|
||||||
if (location == null) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (ACCESS_FINE_LOCATION.equals(perm)) {
|
|
||||||
return location;
|
synchronized (mLock) {
|
||||||
} else {
|
// Figure out the provider. Either its explicitly request (deprecated API's),
|
||||||
Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
|
// or use the fused provider
|
||||||
if (noGPSLocation != null) {
|
String name = request.getProvider();
|
||||||
return mLocationFudger.getOrCreate(noGPSLocation);
|
if (name == null) name = LocationManager.FUSED_PROVIDER;
|
||||||
|
LocationProviderInterface provider = mProvidersByName.get(name);
|
||||||
|
if (provider == null) return null;
|
||||||
|
|
||||||
|
if (!isAllowedBySettingsLocked(name, mCurrentUserId)) return null;
|
||||||
|
|
||||||
|
Location location = mLastLocation.get(name);
|
||||||
|
if (location == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (ACCESS_FINE_LOCATION.equals(perm)) {
|
||||||
|
return location;
|
||||||
|
} else {
|
||||||
|
Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
|
||||||
|
if (noGPSLocation != null) {
|
||||||
|
return mLocationFudger.getOrCreate(noGPSLocation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(identity);
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1321,11 +1344,16 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
"\" provider requires ACCESS_FINE_LOCATION permission");
|
"\" provider requires ACCESS_FINE_LOCATION permission");
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (mLock) {
|
long identity = Binder.clearCallingIdentity();
|
||||||
LocationProviderInterface p = mProvidersByName.get(provider);
|
try {
|
||||||
if (p == null) return false;
|
synchronized (mLock) {
|
||||||
|
LocationProviderInterface p = mProvidersByName.get(provider);
|
||||||
|
if (p == null) return false;
|
||||||
|
|
||||||
return isAllowedBySettingsLocked(provider);
|
return isAllowedBySettingsLocked(provider, mCurrentUserId);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(identity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1461,6 +1489,16 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
Receiver receiver = r.mReceiver;
|
Receiver receiver = r.mReceiver;
|
||||||
boolean receiverDead = false;
|
boolean receiverDead = false;
|
||||||
|
|
||||||
|
int receiverUserId = UserHandle.getUserId(receiver.mUid);
|
||||||
|
if (receiverUserId != mCurrentUserId) {
|
||||||
|
if (D) {
|
||||||
|
Log.d(TAG, "skipping loc update for background user " + receiverUserId +
|
||||||
|
" (current user: " + mCurrentUserId + ", app: " +
|
||||||
|
receiver.mPackageName + ")");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (mBlacklist.isBlacklisted(receiver.mPackageName)) {
|
if (mBlacklist.isBlacklisted(receiver.mPackageName)) {
|
||||||
if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
|
if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
|
||||||
receiver.mPackageName);
|
receiver.mPackageName);
|
||||||
@ -1551,7 +1589,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
}
|
}
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (isAllowedBySettingsLocked(provider)) {
|
if (isAllowedBySettingsLocked(provider, mCurrentUserId)) {
|
||||||
handleLocationChangedLocked(location, passive);
|
handleLocationChangedLocked(location, passive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import android.content.pm.ResolveInfo;
|
|||||||
import android.content.pm.Signature;
|
import android.content.pm.Signature;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.UserHandle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.internal.content.PackageMonitor;
|
import com.android.internal.content.PackageMonitor;
|
||||||
@ -58,15 +59,17 @@ public class ServiceWatcher implements ServiceConnection {
|
|||||||
private IBinder mBinder; // connected service
|
private IBinder mBinder; // connected service
|
||||||
private String mPackageName; // current best package
|
private String mPackageName; // current best package
|
||||||
private int mVersion; // current best version
|
private int mVersion; // current best version
|
||||||
|
private int mCurrentUserId;
|
||||||
|
|
||||||
public ServiceWatcher(Context context, String logTag, String action,
|
public ServiceWatcher(Context context, String logTag, String action,
|
||||||
List<String> initialPackageNames, Runnable newServiceWork, Handler handler) {
|
List<String> initialPackageNames, Runnable newServiceWork, Handler handler, int userId) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mTag = logTag;
|
mTag = logTag;
|
||||||
mAction = action;
|
mAction = action;
|
||||||
mPm = mContext.getPackageManager();
|
mPm = mContext.getPackageManager();
|
||||||
mNewServiceWork = newServiceWork;
|
mNewServiceWork = newServiceWork;
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
|
mCurrentUserId = userId;
|
||||||
|
|
||||||
mSignatureSets = new ArrayList<HashSet<Signature>>();
|
mSignatureSets = new ArrayList<HashSet<Signature>>();
|
||||||
for (int i=0; i < initialPackageNames.size(); i++) {
|
for (int i=0; i < initialPackageNames.size(); i++) {
|
||||||
@ -85,9 +88,11 @@ public class ServiceWatcher implements ServiceConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean start() {
|
public boolean start() {
|
||||||
if (!bindBestPackage(null)) return false;
|
synchronized (mLock) {
|
||||||
|
if (!bindBestPackageLocked(null)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
mPackageMonitor.register(mContext, null, true);
|
mPackageMonitor.register(mContext, null, UserHandle.ALL, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,13 +103,13 @@ public class ServiceWatcher implements ServiceConnection {
|
|||||||
* is null.
|
* is null.
|
||||||
* Return true if a new package was found to bind to.
|
* Return true if a new package was found to bind to.
|
||||||
*/
|
*/
|
||||||
private boolean bindBestPackage(String justCheckThisPackage) {
|
private boolean bindBestPackageLocked(String justCheckThisPackage) {
|
||||||
Intent intent = new Intent(mAction);
|
Intent intent = new Intent(mAction);
|
||||||
if (justCheckThisPackage != null) {
|
if (justCheckThisPackage != null) {
|
||||||
intent.setPackage(justCheckThisPackage);
|
intent.setPackage(justCheckThisPackage);
|
||||||
}
|
}
|
||||||
List<ResolveInfo> rInfos = mPm.queryIntentServices(new Intent(mAction),
|
List<ResolveInfo> rInfos = mPm.queryIntentServicesAsUser(new Intent(mAction),
|
||||||
PackageManager.GET_META_DATA);
|
PackageManager.GET_META_DATA, mCurrentUserId);
|
||||||
int bestVersion = Integer.MIN_VALUE;
|
int bestVersion = Integer.MIN_VALUE;
|
||||||
String bestPackage = null;
|
String bestPackage = null;
|
||||||
for (ResolveInfo rInfo : rInfos) {
|
for (ResolveInfo rInfo : rInfos) {
|
||||||
@ -141,36 +146,32 @@ public class ServiceWatcher implements ServiceConnection {
|
|||||||
(bestPackage == null ? "no new best package" : "new best packge: " + bestPackage)));
|
(bestPackage == null ? "no new best package" : "new best packge: " + bestPackage)));
|
||||||
|
|
||||||
if (bestPackage != null) {
|
if (bestPackage != null) {
|
||||||
bindToPackage(bestPackage, bestVersion);
|
bindToPackageLocked(bestPackage, bestVersion);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unbind() {
|
private void unbindLocked() {
|
||||||
String pkg;
|
String pkg;
|
||||||
synchronized (mLock) {
|
pkg = mPackageName;
|
||||||
pkg = mPackageName;
|
mPackageName = null;
|
||||||
mPackageName = null;
|
mVersion = Integer.MIN_VALUE;
|
||||||
mVersion = Integer.MIN_VALUE;
|
|
||||||
}
|
|
||||||
if (pkg != null) {
|
if (pkg != null) {
|
||||||
if (D) Log.d(mTag, "unbinding " + pkg);
|
if (D) Log.d(mTag, "unbinding " + pkg);
|
||||||
mContext.unbindService(this);
|
mContext.unbindService(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindToPackage(String packageName, int version) {
|
private void bindToPackageLocked(String packageName, int version) {
|
||||||
unbind();
|
unbindLocked();
|
||||||
Intent intent = new Intent(mAction);
|
Intent intent = new Intent(mAction);
|
||||||
intent.setPackage(packageName);
|
intent.setPackage(packageName);
|
||||||
synchronized (mLock) {
|
mPackageName = packageName;
|
||||||
mPackageName = packageName;
|
mVersion = version;
|
||||||
mVersion = version;
|
|
||||||
}
|
|
||||||
if (D) Log.d(mTag, "binding " + packageName + " (version " + version + ")");
|
if (D) Log.d(mTag, "binding " + packageName + " (version " + version + ")");
|
||||||
mContext.bindService(intent, this, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
|
mContext.bindService(intent, this, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
|
||||||
| Context.BIND_ALLOW_OOM_MANAGEMENT | Context.BIND_NOT_VISIBLE);
|
| Context.BIND_ALLOW_OOM_MANAGEMENT | Context.BIND_NOT_VISIBLE, mCurrentUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSignatureMatch(Signature[] signatures) {
|
private boolean isSignatureMatch(Signature[] signatures) {
|
||||||
@ -197,31 +198,37 @@ public class ServiceWatcher implements ServiceConnection {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onPackageUpdateFinished(String packageName, int uid) {
|
public void onPackageUpdateFinished(String packageName, int uid) {
|
||||||
if (packageName.equals(mPackageName)) {
|
synchronized (mLock) {
|
||||||
// package updated, make sure to rebind
|
if (packageName.equals(mPackageName)) {
|
||||||
unbind();
|
// package updated, make sure to rebind
|
||||||
|
unbindLocked();
|
||||||
|
}
|
||||||
|
// check the updated package in case it is better
|
||||||
|
bindBestPackageLocked(packageName);
|
||||||
}
|
}
|
||||||
// check the updated package in case it is better
|
|
||||||
bindBestPackage(packageName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPackageAdded(String packageName, int uid) {
|
public void onPackageAdded(String packageName, int uid) {
|
||||||
if (packageName.equals(mPackageName)) {
|
synchronized (mLock) {
|
||||||
// package updated, make sure to rebind
|
if (packageName.equals(mPackageName)) {
|
||||||
unbind();
|
// package updated, make sure to rebind
|
||||||
|
unbindLocked();
|
||||||
|
}
|
||||||
|
// check the new package is case it is better
|
||||||
|
bindBestPackageLocked(packageName);
|
||||||
}
|
}
|
||||||
// check the new package is case it is better
|
|
||||||
bindBestPackage(packageName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPackageRemoved(String packageName, int uid) {
|
public void onPackageRemoved(String packageName, int uid) {
|
||||||
if (packageName.equals(mPackageName)) {
|
synchronized (mLock) {
|
||||||
unbind();
|
if (packageName.equals(mPackageName)) {
|
||||||
// the currently bound package was removed,
|
unbindLocked();
|
||||||
// need to search for a new package
|
// the currently bound package was removed,
|
||||||
bindBestPackage(null);
|
// need to search for a new package
|
||||||
|
bindBestPackageLocked(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -271,4 +278,12 @@ public class ServiceWatcher implements ServiceConnection {
|
|||||||
return mBinder;
|
return mBinder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void switchUser(int userId) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
unbindLocked();
|
||||||
|
mCurrentUserId = userId;
|
||||||
|
bindBestPackageLocked(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import android.location.Address;
|
|||||||
import android.location.GeocoderParams;
|
import android.location.GeocoderParams;
|
||||||
import android.location.IGeocodeProvider;
|
import android.location.IGeocodeProvider;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.os.UserHandle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.server.ServiceWatcher;
|
import com.android.server.ServiceWatcher;
|
||||||
@ -38,8 +39,8 @@ public class GeocoderProxy {
|
|||||||
private final ServiceWatcher mServiceWatcher;
|
private final ServiceWatcher mServiceWatcher;
|
||||||
|
|
||||||
public static GeocoderProxy createAndBind(Context context,
|
public static GeocoderProxy createAndBind(Context context,
|
||||||
List<String> initialPackageNames) {
|
List<String> initialPackageNames, int userId) {
|
||||||
GeocoderProxy proxy = new GeocoderProxy(context, initialPackageNames);
|
GeocoderProxy proxy = new GeocoderProxy(context, initialPackageNames, userId);
|
||||||
if (proxy.bind()) {
|
if (proxy.bind()) {
|
||||||
return proxy;
|
return proxy;
|
||||||
} else {
|
} else {
|
||||||
@ -47,11 +48,11 @@ public class GeocoderProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeocoderProxy(Context context, List<String> initialPackageNames) {
|
public GeocoderProxy(Context context, List<String> initialPackageNames, int userId) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
|
|
||||||
mServiceWatcher = new ServiceWatcher(mContext, TAG, SERVICE_ACTION, initialPackageNames,
|
mServiceWatcher = new ServiceWatcher(mContext, TAG, SERVICE_ACTION, initialPackageNames,
|
||||||
null, null);
|
null, null, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean bind () {
|
private boolean bind () {
|
||||||
|
@ -783,6 +783,11 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
|||||||
sendMessage(SET_REQUEST, 0, new GpsRequest(request, source));
|
sendMessage(SET_REQUEST, 0, new GpsRequest(request, source));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void switchUser(int userId) {
|
||||||
|
// nothing to do here
|
||||||
|
}
|
||||||
|
|
||||||
private void handleSetRequest(ProviderRequest request, WorkSource source) {
|
private void handleSetRequest(ProviderRequest request, WorkSource source) {
|
||||||
if (DEBUG) Log.d(TAG, "setRequest " + request);
|
if (DEBUG) Log.d(TAG, "setRequest " + request);
|
||||||
|
|
||||||
|
@ -38,6 +38,8 @@ public interface LocationProviderInterface {
|
|||||||
public boolean isEnabled();
|
public boolean isEnabled();
|
||||||
public void setRequest(ProviderRequest request, WorkSource source);
|
public void setRequest(ProviderRequest request, WorkSource source);
|
||||||
|
|
||||||
|
public void switchUser(int userId);
|
||||||
|
|
||||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args);
|
public void dump(FileDescriptor fd, PrintWriter pw, String[] args);
|
||||||
|
|
||||||
// --- deprecated (but still supported) ---
|
// --- deprecated (but still supported) ---
|
||||||
|
@ -25,6 +25,7 @@ import android.location.LocationProvider;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.os.UserHandle;
|
||||||
import android.os.WorkSource;
|
import android.os.WorkSource;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@ -54,9 +55,9 @@ public class LocationProviderProxy implements LocationProviderInterface {
|
|||||||
private WorkSource mWorksource = new WorkSource();
|
private WorkSource mWorksource = new WorkSource();
|
||||||
|
|
||||||
public static LocationProviderProxy createAndBind(Context context, String name, String action,
|
public static LocationProviderProxy createAndBind(Context context, String name, String action,
|
||||||
List<String> initialPackageNames, Handler handler) {
|
List<String> initialPackageNames, Handler handler, int userId) {
|
||||||
LocationProviderProxy proxy = new LocationProviderProxy(context, name, action,
|
LocationProviderProxy proxy = new LocationProviderProxy(context, name, action,
|
||||||
initialPackageNames, handler);
|
initialPackageNames, handler, userId);
|
||||||
if (proxy.bind()) {
|
if (proxy.bind()) {
|
||||||
return proxy;
|
return proxy;
|
||||||
} else {
|
} else {
|
||||||
@ -65,11 +66,11 @@ public class LocationProviderProxy implements LocationProviderInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private LocationProviderProxy(Context context, String name, String action,
|
private LocationProviderProxy(Context context, String name, String action,
|
||||||
List<String> initialPackageNames, Handler handler) {
|
List<String> initialPackageNames, Handler handler, int userId) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mName = name;
|
mName = name;
|
||||||
mServiceWatcher = new ServiceWatcher(mContext, TAG, action, initialPackageNames,
|
mServiceWatcher = new ServiceWatcher(mContext, TAG, action, initialPackageNames,
|
||||||
mNewServiceWork, handler);
|
mNewServiceWork, handler, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean bind () {
|
private boolean bind () {
|
||||||
@ -210,6 +211,11 @@ public class LocationProviderProxy implements LocationProviderInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void switchUser(int userId) {
|
||||||
|
mServiceWatcher.switchUser(userId);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||||
pw.append("REMOTE SERVICE");
|
pw.append("REMOTE SERVICE");
|
||||||
|
@ -155,6 +155,11 @@ public class MockProvider implements LocationProviderInterface {
|
|||||||
@Override
|
@Override
|
||||||
public void setRequest(ProviderRequest request, WorkSource source) { }
|
public void setRequest(ProviderRequest request, WorkSource source) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void switchUser(int userId) {
|
||||||
|
// nothing to do here
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sendExtraCommand(String command, Bundle extras) {
|
public boolean sendExtraCommand(String command, Bundle extras) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -96,6 +96,11 @@ public class PassiveProvider implements LocationProviderInterface {
|
|||||||
mReportLocation = request.reportLocation;
|
mReportLocation = request.reportLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void switchUser(int userId) {
|
||||||
|
// nothing to do here
|
||||||
|
}
|
||||||
|
|
||||||
public void updateLocation(Location location) {
|
public void updateLocation(Location location) {
|
||||||
if (mReportLocation) {
|
if (mReportLocation) {
|
||||||
try {
|
try {
|
||||||
|
Reference in New Issue
Block a user