Various location fixes
-Prevent PendingIntents from using LocationRequest SystemApis. We don't track permission removal, so we don't current reset the request if the permission is lost. -Make LocationRequest.getWorkSource() NonNull. Small quality of life change to reduce null checks all over. -Don't spend CPU coarsening location until we actually need to. The vast majority of locations will never need to be coarsened. Don't bother doing so until we actually need to. Bug: 169887240 Test: manual + presubmit Change-Id: I7ad6fe886eaede3ed9f46cebe4246d29d6b6e187
This commit is contained in:
@@ -4171,7 +4171,7 @@ package android.location {
|
||||
method @Deprecated @NonNull public String getProvider();
|
||||
method public int getQuality();
|
||||
method @Deprecated public float getSmallestDisplacement();
|
||||
method @Nullable public android.os.WorkSource getWorkSource();
|
||||
method @NonNull public android.os.WorkSource getWorkSource();
|
||||
method public boolean isHiddenFromAppOps();
|
||||
method public boolean isLocationSettingsIgnored();
|
||||
method public boolean isLowPower();
|
||||
|
||||
@@ -1717,7 +1717,7 @@ package android.location {
|
||||
}
|
||||
|
||||
public final class LocationRequest implements android.os.Parcelable {
|
||||
method @Nullable public android.os.WorkSource getWorkSource();
|
||||
method @NonNull public android.os.WorkSource getWorkSource();
|
||||
method public boolean isHiddenFromAppOps();
|
||||
method public boolean isLocationSettingsIgnored();
|
||||
method public boolean isLowPower();
|
||||
|
||||
@@ -88,6 +88,16 @@ import java.util.function.Consumer;
|
||||
@RequiresFeature(PackageManager.FEATURE_LOCATION)
|
||||
public class LocationManager {
|
||||
|
||||
/**
|
||||
* For apps targeting Android S and above, LocationRequest system APIs may not be used with
|
||||
* PendingIntent location requests.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@ChangeId
|
||||
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
|
||||
public static final long PREVENT_PENDING_INTENT_SYSTEM_API_USAGE = 169887240L;
|
||||
|
||||
/**
|
||||
* For apps targeting Android S and above, location clients may receive historical locations
|
||||
* (from before the present time) under some circumstances.
|
||||
|
||||
@@ -250,7 +250,7 @@ public final class LocationRequest implements Parcelable {
|
||||
boolean hiddenFromAppOps,
|
||||
boolean locationSettingsIgnored,
|
||||
boolean lowPower,
|
||||
@Nullable WorkSource workSource) {
|
||||
WorkSource workSource) {
|
||||
Preconditions.checkArgument(intervalMillis != PASSIVE_INTERVAL || quality == POWER_NONE);
|
||||
Preconditions.checkArgument(minUpdateIntervalMillis <= intervalMillis);
|
||||
|
||||
@@ -265,7 +265,7 @@ public final class LocationRequest implements Parcelable {
|
||||
mHideFromAppOps = hiddenFromAppOps;
|
||||
mLowPower = lowPower;
|
||||
mLocationSettingsIgnored = locationSettingsIgnored;
|
||||
mWorkSource = workSource;
|
||||
mWorkSource = Objects.requireNonNull(workSource);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -645,12 +645,15 @@ public final class LocationRequest implements Parcelable {
|
||||
@SystemApi
|
||||
@Deprecated
|
||||
public void setWorkSource(@Nullable WorkSource workSource) {
|
||||
if (workSource == null) {
|
||||
workSource = new WorkSource();
|
||||
}
|
||||
mWorkSource = workSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the work source used for power blame for this request. If null, the system is free to
|
||||
* assign power blame as it deems most appropriate.
|
||||
* Returns the work source used for power blame for this request. If empty, the system is free
|
||||
* to assign power blame as it deems most appropriate.
|
||||
*
|
||||
* @return the work source used for power blame for this request
|
||||
*
|
||||
@@ -658,7 +661,7 @@ public final class LocationRequest implements Parcelable {
|
||||
*/
|
||||
@TestApi
|
||||
@SystemApi
|
||||
public @Nullable WorkSource getWorkSource() {
|
||||
public @NonNull WorkSource getWorkSource() {
|
||||
return mWorkSource;
|
||||
}
|
||||
|
||||
@@ -1062,9 +1065,9 @@ public final class LocationRequest implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the work source to use for power blame for this location request. Defaults to null,
|
||||
* which implies the system is free to assign power blame as it determines best for this
|
||||
* request (which usually means blaming the owner of the location listener).
|
||||
* Sets the work source to use for power blame for this location request. Defaults to an
|
||||
* empty WorkSource, which implies the system is free to assign power blame as it determines
|
||||
* best for this request (which usually means blaming the owner of the location listener).
|
||||
*
|
||||
* <p>Permissions enforcement occurs when resulting location request is actually used, not
|
||||
* when this method is invoked.
|
||||
@@ -1108,7 +1111,7 @@ public final class LocationRequest implements Parcelable {
|
||||
mHiddenFromAppOps,
|
||||
mLocationSettingsIgnored,
|
||||
mLowPower,
|
||||
mWorkSource);
|
||||
new WorkSource(mWorkSource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4111,7 +4111,7 @@ package android.location {
|
||||
method @Deprecated @NonNull public String getProvider();
|
||||
method public int getQuality();
|
||||
method @Deprecated public float getSmallestDisplacement();
|
||||
method @Nullable public android.os.WorkSource getWorkSource();
|
||||
method @NonNull public android.os.WorkSource getWorkSource();
|
||||
method public boolean isHiddenFromAppOps();
|
||||
method public boolean isLocationSettingsIgnored();
|
||||
method public boolean isLowPower();
|
||||
|
||||
@@ -111,7 +111,7 @@ public class LocationFudger {
|
||||
*/
|
||||
public Location createCoarse(Location fine) {
|
||||
synchronized (this) {
|
||||
if (fine == mCachedFineLocation) {
|
||||
if (fine == mCachedFineLocation || fine == mCachedCoarseLocation) {
|
||||
return mCachedCoarseLocation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
package com.android.server.location;
|
||||
|
||||
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
|
||||
import static android.app.compat.CompatChanges.isChangeEnabled;
|
||||
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
|
||||
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static android.location.LocationManager.FUSED_PROVIDER;
|
||||
import static android.location.LocationManager.GPS_PROVIDER;
|
||||
import static android.location.LocationManager.NETWORK_PROVIDER;
|
||||
import static android.location.LocationManager.PREVENT_PENDING_INTENT_SYSTEM_API_USAGE;
|
||||
import static android.location.LocationRequest.LOW_POWER_EXCEPTIONS;
|
||||
|
||||
import static com.android.server.location.LocationPermissions.PERMISSION_COARSE;
|
||||
@@ -75,7 +77,6 @@ import android.os.WorkSource.WorkChain;
|
||||
import android.stats.location.LocationStatsEnums;
|
||||
import android.util.IndentingPrintWriter;
|
||||
import android.util.Log;
|
||||
import android.util.TimeUtils;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.location.ProviderProperties;
|
||||
@@ -570,7 +571,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
new IllegalArgumentException());
|
||||
}
|
||||
|
||||
request = validateLocationRequest(request);
|
||||
request = validateLocationRequest(request, identity);
|
||||
|
||||
LocationProviderManager manager = getLocationProviderManager(provider);
|
||||
Preconditions.checkArgument(manager != null,
|
||||
@@ -592,7 +593,21 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
// clients in the system process must have an attribution tag set
|
||||
Preconditions.checkArgument(identity.getPid() != Process.myPid() || attributionTag != null);
|
||||
|
||||
request = validateLocationRequest(request);
|
||||
// pending intents requests may not use system apis because we do not keep track if clients
|
||||
// lose the relevant permissions, and thus should not get the benefit of those apis. its
|
||||
// simplest to ensure these apis are simply never set for pending intent requests. the same
|
||||
// does not apply for listener requests since those will have the process (including the
|
||||
// listener) killed on permission removal
|
||||
boolean usesSystemApi = request.isLowPower()
|
||||
|| request.isHiddenFromAppOps()
|
||||
|| request.isLocationSettingsIgnored()
|
||||
|| !request.getWorkSource().isEmpty();
|
||||
if (usesSystemApi
|
||||
&& isChangeEnabled(PREVENT_PENDING_INTENT_SYSTEM_API_USAGE, identity.getUid())) {
|
||||
throw new SecurityException("PendingIntent location requests may not use system APIs");
|
||||
}
|
||||
|
||||
request = validateLocationRequest(request, identity);
|
||||
|
||||
LocationProviderManager manager = getLocationProviderManager(provider);
|
||||
Preconditions.checkArgument(manager != null,
|
||||
@@ -601,9 +616,9 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
manager.registerLocationRequest(request, identity, permissionLevel, pendingIntent);
|
||||
}
|
||||
|
||||
private LocationRequest validateLocationRequest(LocationRequest request) {
|
||||
WorkSource workSource = request.getWorkSource();
|
||||
if (workSource != null && !workSource.isEmpty()) {
|
||||
private LocationRequest validateLocationRequest(LocationRequest request,
|
||||
CallerIdentity identity) {
|
||||
if (!request.getWorkSource().isEmpty()) {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
permission.UPDATE_DEVICE_STATS,
|
||||
"setting a work source requires " + permission.UPDATE_DEVICE_STATS);
|
||||
@@ -634,23 +649,25 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
if (request.getWorkSource() != null) {
|
||||
if (request.getWorkSource().isEmpty()) {
|
||||
sanitized.setWorkSource(null);
|
||||
} else if (request.getWorkSource().getPackageName(0) == null) {
|
||||
Log.w(TAG, "received (and ignoring) illegal worksource with no package name");
|
||||
sanitized.setWorkSource(null);
|
||||
} else {
|
||||
List<WorkChain> workChains = request.getWorkSource().getWorkChains();
|
||||
if (workChains != null && !workChains.isEmpty() && workChains.get(
|
||||
0).getAttributionTag() == null) {
|
||||
Log.w(TAG,
|
||||
"received (and ignoring) illegal worksource with no attribution tag");
|
||||
sanitized.setWorkSource(null);
|
||||
}
|
||||
WorkSource workSource = new WorkSource(request.getWorkSource());
|
||||
if (workSource.size() > 0 && workSource.getPackageName(0) == null) {
|
||||
Log.w(TAG, "received (and ignoring) illegal worksource with no package name");
|
||||
workSource.clear();
|
||||
} else {
|
||||
List<WorkChain> workChains = workSource.getWorkChains();
|
||||
if (workChains != null && !workChains.isEmpty()
|
||||
&& workChains.get(0).getAttributionTag() == null) {
|
||||
Log.w(TAG,
|
||||
"received (and ignoring) illegal worksource with no attribution tag");
|
||||
workSource.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (workSource.isEmpty()) {
|
||||
identity.addToWorkSource(workSource);
|
||||
}
|
||||
sanitized.setWorkSource(workSource);
|
||||
|
||||
return sanitized.build();
|
||||
}
|
||||
|
||||
@@ -684,15 +701,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
return null;
|
||||
}
|
||||
|
||||
Location location = manager.getLastLocation(identity, permissionLevel, false);
|
||||
|
||||
// lastly - note app ops
|
||||
if (!mInjector.getAppOpsHelper().noteOpNoThrow(LocationPermissions.asAppOp(permissionLevel),
|
||||
identity)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return location;
|
||||
return manager.getLastLocation(identity, permissionLevel, false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -710,7 +719,7 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
// clients in the system process must have an attribution tag set
|
||||
Preconditions.checkState(identity.getPid() != Process.myPid() || attributionTag != null);
|
||||
|
||||
request = validateLocationRequest(request);
|
||||
request = validateLocationRequest(request, identity);
|
||||
|
||||
LocationProviderManager manager = getLocationProviderManager(provider);
|
||||
Preconditions.checkArgument(manager != null,
|
||||
@@ -727,7 +736,6 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
return null;
|
||||
}
|
||||
|
||||
// use fine permission level to avoid creating unnecessary coarse locations
|
||||
Location location = gpsManager.getLastLocationUnsafe(UserHandle.USER_ALL,
|
||||
PERMISSION_FINE, false, Long.MAX_VALUE);
|
||||
if (location == null) {
|
||||
@@ -1116,9 +1124,8 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
return;
|
||||
}
|
||||
|
||||
ipw.print("Location Manager State:");
|
||||
ipw.println("Location Manager State:");
|
||||
ipw.increaseIndent();
|
||||
ipw.println("Elapsed Realtime: " + TimeUtils.formatDuration(SystemClock.elapsedRealtime()));
|
||||
|
||||
ipw.println("User Info:");
|
||||
ipw.increaseIndent();
|
||||
|
||||
@@ -31,6 +31,7 @@ import static android.os.PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF
|
||||
import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF;
|
||||
|
||||
import static com.android.internal.location.ProviderRequest.EMPTY_REQUEST;
|
||||
import static com.android.internal.location.ProviderRequest.INTERVAL_DISABLED;
|
||||
import static com.android.server.location.LocationManagerService.D;
|
||||
import static com.android.server.location.LocationManagerService.TAG;
|
||||
import static com.android.server.location.LocationPermissions.PERMISSION_COARSE;
|
||||
@@ -238,8 +239,7 @@ class LocationProviderManager extends
|
||||
protected abstract class Registration extends RemoteListenerRegistration<LocationRequest,
|
||||
LocationTransport, LocationListenerOperation> {
|
||||
|
||||
@PermissionLevel protected final int mPermissionLevel;
|
||||
private final WorkSource mWorkSource;
|
||||
private final @PermissionLevel int mPermissionLevel;
|
||||
|
||||
// we cache these values because checking/calculating on the fly is more expensive
|
||||
private boolean mPermitted;
|
||||
@@ -247,22 +247,17 @@ class LocationProviderManager extends
|
||||
private LocationRequest mProviderLocationRequest;
|
||||
private boolean mIsUsingHighPower;
|
||||
|
||||
@Nullable private Location mLastLocation = null;
|
||||
private @Nullable Location mLastLocation = null;
|
||||
|
||||
protected Registration(LocationRequest request, CallerIdentity identity,
|
||||
LocationTransport transport, @PermissionLevel int permissionLevel) {
|
||||
super(Objects.requireNonNull(request), identity, transport);
|
||||
|
||||
Preconditions.checkArgument(permissionLevel > PERMISSION_NONE);
|
||||
Preconditions.checkArgument(!request.getWorkSource().isEmpty());
|
||||
|
||||
mPermissionLevel = permissionLevel;
|
||||
|
||||
if (request.getWorkSource() != null && !request.getWorkSource().isEmpty()) {
|
||||
mWorkSource = request.getWorkSource();
|
||||
} else {
|
||||
mWorkSource = identity.addToWorkSource(null);
|
||||
}
|
||||
|
||||
mProviderLocationRequest = super.getRequest();
|
||||
mProviderLocationRequest = request;
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@@ -376,6 +371,10 @@ class LocationProviderManager extends
|
||||
return mLastLocation;
|
||||
}
|
||||
|
||||
public @PermissionLevel int getPermissionLevel() {
|
||||
return mPermissionLevel;
|
||||
}
|
||||
|
||||
public final boolean isForeground() {
|
||||
return mForeground;
|
||||
}
|
||||
@@ -389,10 +388,6 @@ class LocationProviderManager extends
|
||||
return LocationProviderManager.this;
|
||||
}
|
||||
|
||||
protected final WorkSource getWorkSource() {
|
||||
return mWorkSource;
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private void onHighPowerUsageChanged() {
|
||||
boolean isUsingHighPower = isUsingHighPower();
|
||||
@@ -609,7 +604,7 @@ class LocationProviderManager extends
|
||||
mWakeLock = Objects.requireNonNull(mContext.getSystemService(PowerManager.class))
|
||||
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
|
||||
mWakeLock.setReferenceCounted(true);
|
||||
mWakeLock.setWorkSource(getWorkSource());
|
||||
mWakeLock.setWorkSource(request.getWorkSource());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -628,7 +623,7 @@ class LocationProviderManager extends
|
||||
onAlarm();
|
||||
} else if (mExpirationRealtimeMs < Long.MAX_VALUE) {
|
||||
mAlarmHelper.setDelayedAlarm(mExpirationRealtimeMs - registerTimeMs, this,
|
||||
getWorkSource());
|
||||
getRequest().getWorkSource());
|
||||
}
|
||||
|
||||
// start listening for provider enabled/disabled events
|
||||
@@ -690,7 +685,7 @@ class LocationProviderManager extends
|
||||
if (maxLocationAgeMs > MIN_REQUEST_DELAY_MS) {
|
||||
Location lastLocation = getLastLocationUnsafe(
|
||||
getIdentity().getUserId(),
|
||||
PERMISSION_FINE, // acceptLocationChange() handles coarsening this
|
||||
getPermissionLevel(),
|
||||
getRequest().isLocationSettingsIgnored(),
|
||||
maxLocationAgeMs);
|
||||
if (lastLocation != null) {
|
||||
@@ -732,18 +727,8 @@ class LocationProviderManager extends
|
||||
return null;
|
||||
}
|
||||
|
||||
Location location;
|
||||
switch (mPermissionLevel) {
|
||||
case PERMISSION_FINE:
|
||||
location = fineLocation;
|
||||
break;
|
||||
case PERMISSION_COARSE:
|
||||
location = mLocationFudger.createCoarse(fineLocation);
|
||||
break;
|
||||
default:
|
||||
// shouldn't be possible to have a client added without location permissions
|
||||
throw new AssertionError();
|
||||
}
|
||||
Location location = Objects.requireNonNull(
|
||||
getPermittedLocation(fineLocation, getPermissionLevel()));
|
||||
|
||||
Location lastDeliveredLocation = getLastDeliveredLocation();
|
||||
if (lastDeliveredLocation != null) {
|
||||
@@ -765,7 +750,7 @@ class LocationProviderManager extends
|
||||
}
|
||||
|
||||
// note app ops
|
||||
if (!mAppOpsHelper.noteOpNoThrow(LocationPermissions.asAppOp(mPermissionLevel),
|
||||
if (!mAppOpsHelper.noteOpNoThrow(LocationPermissions.asAppOp(getPermissionLevel()),
|
||||
getIdentity())) {
|
||||
if (D) {
|
||||
Log.w(TAG, "noteOp denied for " + getIdentity());
|
||||
@@ -962,7 +947,7 @@ class LocationProviderManager extends
|
||||
}
|
||||
|
||||
protected final class GetCurrentLocationListenerRegistration extends Registration implements
|
||||
IBinder.DeathRecipient, ProviderEnabledListener, OnAlarmListener {
|
||||
IBinder.DeathRecipient, OnAlarmListener {
|
||||
|
||||
private volatile LocationTransport mTransport;
|
||||
|
||||
@@ -974,11 +959,6 @@ class LocationProviderManager extends
|
||||
mTransport = transport;
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
void deliverLocation(@Nullable Location location) {
|
||||
executeSafely(getExecutor(), () -> mTransport, acceptLocationChange(location));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onListenerUnregister() {
|
||||
mTransport = null;
|
||||
@@ -1001,29 +981,13 @@ class LocationProviderManager extends
|
||||
onAlarm();
|
||||
} else if (mExpirationRealtimeMs < Long.MAX_VALUE) {
|
||||
mAlarmHelper.setDelayedAlarm(mExpirationRealtimeMs - registerTimeMs, this,
|
||||
getWorkSource());
|
||||
}
|
||||
|
||||
// if this request is ignoring location settings, then we don't want to immediately fail
|
||||
// it if the provider is disabled or becomes disabled.
|
||||
if (!getRequest().isLocationSettingsIgnored()) {
|
||||
// start listening for provider enabled/disabled events
|
||||
addEnabledListener(this);
|
||||
|
||||
// if the provider is currently disabled fail immediately
|
||||
int userId = getIdentity().getUserId();
|
||||
if (!isEnabled(userId)) {
|
||||
deliverLocation(null);
|
||||
}
|
||||
getRequest().getWorkSource());
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@Override
|
||||
protected void onProviderListenerUnregister() {
|
||||
// stop listening for provider enabled/disabled events
|
||||
removeEnabledListener(this);
|
||||
|
||||
// remove alarm for expiration
|
||||
if (mExpirationRealtimeMs < Long.MAX_VALUE) {
|
||||
mAlarmHelper.cancel(this);
|
||||
@@ -1032,6 +996,38 @@ class LocationProviderManager extends
|
||||
((IBinder) getKey()).unlinkToDeath(this, 0);
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@Override
|
||||
protected LocationListenerOperation onProviderListenerActive() {
|
||||
Location lastLocation = getLastLocationUnsafe(
|
||||
getIdentity().getUserId(),
|
||||
getPermissionLevel(),
|
||||
getRequest().isLocationSettingsIgnored(),
|
||||
MAX_CURRENT_LOCATION_AGE_MS);
|
||||
if (lastLocation != null) {
|
||||
return acceptLocationChange(lastLocation);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@Override
|
||||
protected LocationListenerOperation onProviderListenerInactive() {
|
||||
if (!getRequest().isLocationSettingsIgnored()) {
|
||||
// if we go inactive for any reason, fail immediately
|
||||
return acceptLocationChange(null);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
void deliverNull() {
|
||||
synchronized (mLock) {
|
||||
executeSafely(getExecutor(), () -> mTransport, acceptLocationChange(null));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAlarm() {
|
||||
if (D) {
|
||||
@@ -1041,9 +1037,10 @@ class LocationProviderManager extends
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
deliverLocation(null);
|
||||
// no need to remove alarm after it's fired
|
||||
mExpirationRealtimeMs = Long.MAX_VALUE;
|
||||
|
||||
deliverNull();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1062,29 +1059,16 @@ class LocationProviderManager extends
|
||||
}
|
||||
|
||||
// lastly - note app ops
|
||||
Location location;
|
||||
if (fineLocation == null) {
|
||||
location = null;
|
||||
} else if (!mAppOpsHelper.noteOpNoThrow(LocationPermissions.asAppOp(mPermissionLevel),
|
||||
if (!mAppOpsHelper.noteOpNoThrow(LocationPermissions.asAppOp(getPermissionLevel()),
|
||||
getIdentity())) {
|
||||
if (D) {
|
||||
Log.w(TAG, "noteOp denied for " + getIdentity());
|
||||
}
|
||||
location = null;
|
||||
} else {
|
||||
switch (mPermissionLevel) {
|
||||
case PERMISSION_FINE:
|
||||
location = fineLocation;
|
||||
break;
|
||||
case PERMISSION_COARSE:
|
||||
location = mLocationFudger.createCoarse(fineLocation);
|
||||
break;
|
||||
default:
|
||||
// shouldn't be possible to have a client added without location permissions
|
||||
throw new AssertionError();
|
||||
}
|
||||
fineLocation = null;
|
||||
}
|
||||
|
||||
Location location = getPermittedLocation(fineLocation, getPermissionLevel());
|
||||
|
||||
return new LocationListenerOperation() {
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
@@ -1119,22 +1103,6 @@ class LocationProviderManager extends
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderEnabledChanged(String provider, int userId, boolean enabled) {
|
||||
Preconditions.checkState(mName.equals(provider));
|
||||
|
||||
if (userId != getIdentity().getUserId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if the provider is disabled we give up on current location immediately
|
||||
if (!getRequest().isLocationSettingsIgnored() && !enabled) {
|
||||
synchronized (mLock) {
|
||||
deliverLocation(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void binderDied() {
|
||||
try {
|
||||
@@ -1449,24 +1417,34 @@ class LocationProviderManager extends
|
||||
}
|
||||
}
|
||||
|
||||
Location location = getLastLocationUnsafe(identity.getUserId(), permissionLevel,
|
||||
ignoreLocationSettings, Long.MAX_VALUE);
|
||||
// lastly - note app ops
|
||||
if (!mAppOpsHelper.noteOpNoThrow(LocationPermissions.asAppOp(permissionLevel),
|
||||
identity)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// we don't note op here because we don't know what the client intends to do with the
|
||||
// location, the client is responsible for noting if necessary
|
||||
Location location = getPermittedLocation(
|
||||
getLastLocationUnsafe(
|
||||
identity.getUserId(),
|
||||
permissionLevel,
|
||||
ignoreLocationSettings,
|
||||
Long.MAX_VALUE),
|
||||
permissionLevel);
|
||||
|
||||
if (identity.getPid() == Process.myPid() && location != null) {
|
||||
if (location != null && identity.getPid() == Process.myPid()) {
|
||||
// if delivering to the same process, make a copy of the location first (since
|
||||
// location is mutable)
|
||||
return new Location(location);
|
||||
} else {
|
||||
return location;
|
||||
location = new Location(location);
|
||||
}
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function does not perform any permissions or safety checks, by calling it you are
|
||||
* committing to performing all applicable checks yourself.
|
||||
* committing to performing all applicable checks yourself. This always returns a "fine"
|
||||
* location, even if the permissionLevel is coarse. You are responsible for coarsening the
|
||||
* location if necessary.
|
||||
*/
|
||||
@Nullable
|
||||
public Location getLastLocationUnsafe(int userId, @PermissionLevel int permissionLevel,
|
||||
@@ -1535,11 +1513,10 @@ class LocationProviderManager extends
|
||||
mLastLocations.put(userId, lastLocation);
|
||||
}
|
||||
|
||||
Location coarseLocation = mLocationFudger.createCoarse(location);
|
||||
if (isEnabled(userId)) {
|
||||
lastLocation.set(location, coarseLocation);
|
||||
lastLocation.set(location);
|
||||
}
|
||||
lastLocation.setBypass(location, coarseLocation);
|
||||
lastLocation.setBypass(location);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1560,51 +1537,26 @@ class LocationProviderManager extends
|
||||
permissionLevel);
|
||||
|
||||
synchronized (mLock) {
|
||||
// shortcut various failure conditions so that we can return immediately rather than
|
||||
// waiting for location to timeout
|
||||
if (mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
|
||||
identity.getPackageName())) {
|
||||
registration.deliverLocation(null);
|
||||
return null;
|
||||
}
|
||||
if (!request.isLocationSettingsIgnored()) {
|
||||
if (!isEnabled(identity.getUserId())) {
|
||||
registration.deliverLocation(null);
|
||||
return null;
|
||||
}
|
||||
if (!identity.isSystem() && !mUserHelper.isCurrentUserId(identity.getUserId())) {
|
||||
registration.deliverLocation(null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Location lastLocation = getLastLocationUnsafe(
|
||||
identity.getUserId(),
|
||||
permissionLevel,
|
||||
request.isLocationSettingsIgnored(),
|
||||
MAX_CURRENT_LOCATION_AGE_MS);
|
||||
if (lastLocation != null) {
|
||||
registration.deliverLocation(lastLocation);
|
||||
return null;
|
||||
}
|
||||
|
||||
// if last location isn't good enough then we add a location request
|
||||
long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
addRegistration(callback.asBinder(), registration);
|
||||
if (!registration.isActive()) {
|
||||
// if the registration never activated, fail it immediately
|
||||
registration.deliverNull();
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
}
|
||||
|
||||
ICancellationSignal cancelTransport = CancellationSignal.createTransport();
|
||||
CancellationSignal cancellationSignal = CancellationSignal.fromTransport(cancelTransport);
|
||||
cancellationSignal.setOnCancelListener(SingleUseCallback.wrap(
|
||||
() -> {
|
||||
synchronized (mLock) {
|
||||
removeRegistration(callback.asBinder(), registration);
|
||||
}
|
||||
}));
|
||||
CancellationSignal.fromTransport(cancelTransport)
|
||||
.setOnCancelListener(SingleUseCallback.wrap(
|
||||
() -> {
|
||||
synchronized (mLock) {
|
||||
removeRegistration(callback.asBinder(), registration);
|
||||
}
|
||||
}));
|
||||
return cancelTransport;
|
||||
}
|
||||
|
||||
@@ -1619,16 +1571,16 @@ class LocationProviderManager extends
|
||||
|
||||
public void registerLocationRequest(LocationRequest request, CallerIdentity identity,
|
||||
@PermissionLevel int permissionLevel, ILocationListener listener) {
|
||||
LocationListenerRegistration registration = new LocationListenerRegistration(
|
||||
request,
|
||||
identity,
|
||||
new LocationListenerTransport(listener),
|
||||
permissionLevel);
|
||||
|
||||
synchronized (mLock) {
|
||||
long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
addRegistration(
|
||||
listener.asBinder(),
|
||||
new LocationListenerRegistration(
|
||||
request,
|
||||
identity,
|
||||
new LocationListenerTransport(listener),
|
||||
permissionLevel));
|
||||
addRegistration(listener.asBinder(), registration);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
@@ -1637,16 +1589,16 @@ class LocationProviderManager extends
|
||||
|
||||
public void registerLocationRequest(LocationRequest request, CallerIdentity callerIdentity,
|
||||
@PermissionLevel int permissionLevel, PendingIntent pendingIntent) {
|
||||
LocationPendingIntentRegistration registration = new LocationPendingIntentRegistration(
|
||||
request,
|
||||
callerIdentity,
|
||||
new LocationPendingIntentTransport(mContext, pendingIntent),
|
||||
permissionLevel);
|
||||
|
||||
synchronized (mLock) {
|
||||
long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
addRegistration(
|
||||
pendingIntent,
|
||||
new LocationPendingIntentRegistration(
|
||||
request,
|
||||
callerIdentity,
|
||||
new LocationPendingIntentTransport(mContext, pendingIntent),
|
||||
permissionLevel));
|
||||
addRegistration(pendingIntent, registration);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
@@ -1897,7 +1849,7 @@ class LocationProviderManager extends
|
||||
Preconditions.checkState(Thread.holdsLock(mLock));
|
||||
}
|
||||
|
||||
long intervalMs = Long.MAX_VALUE;
|
||||
long intervalMs = INTERVAL_DISABLED;
|
||||
boolean locationSettingsIgnored = false;
|
||||
boolean lowPower = true;
|
||||
ArrayList<LocationRequest> locationRequests = new ArrayList<>(registrations.size());
|
||||
@@ -1916,12 +1868,18 @@ class LocationProviderManager extends
|
||||
locationRequests.add(request);
|
||||
}
|
||||
|
||||
if (intervalMs == INTERVAL_DISABLED) {
|
||||
return EMPTY_REQUEST;
|
||||
}
|
||||
|
||||
// calculate who to blame for power in a somewhat arbitrary fashion. we pick a threshold
|
||||
// interval slightly higher that the minimum interval, and spread the blame across all
|
||||
// contributing registrations under that threshold (since worksource does not allow us to
|
||||
// represent differing power blame ratios).
|
||||
long thresholdIntervalMs = (intervalMs + 1000) * 3 / 2;
|
||||
if (thresholdIntervalMs < 0 || thresholdIntervalMs >= PASSIVE_INTERVAL) {
|
||||
long thresholdIntervalMs;
|
||||
try {
|
||||
thresholdIntervalMs = Math.multiplyExact(Math.addExact(intervalMs, 1000) / 2, 3);
|
||||
} catch (ArithmeticException e) {
|
||||
// check for and handle overflow by setting to one below the passive interval so passive
|
||||
// requests are automatically skipped
|
||||
thresholdIntervalMs = PASSIVE_INTERVAL - 1;
|
||||
@@ -1930,7 +1888,7 @@ class LocationProviderManager extends
|
||||
WorkSource workSource = new WorkSource();
|
||||
for (Registration registration : registrations) {
|
||||
if (registration.getRequest().getIntervalMillis() <= thresholdIntervalMs) {
|
||||
workSource.add(registration.getWorkSource());
|
||||
workSource.add(registration.getRequest().getWorkSource());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1963,7 +1921,7 @@ class LocationProviderManager extends
|
||||
// location for our calculations instead. this prevents spammy add/remove behavior
|
||||
last = getLastLocationUnsafe(
|
||||
registration.getIdentity().getUserId(),
|
||||
PERMISSION_FINE,
|
||||
registration.getPermissionLevel(),
|
||||
false,
|
||||
locationRequest.getIntervalMillis());
|
||||
}
|
||||
@@ -2256,6 +2214,20 @@ class LocationProviderManager extends
|
||||
updateRegistrations(registration -> registration.getIdentity().getUserId() == userId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Location getPermittedLocation(@Nullable Location fineLocation,
|
||||
@PermissionLevel int permissionLevel) {
|
||||
switch (permissionLevel) {
|
||||
case PERMISSION_FINE:
|
||||
return fineLocation;
|
||||
case PERMISSION_COARSE:
|
||||
return fineLocation != null ? mLocationFudger.createCoarse(fineLocation) : null;
|
||||
default:
|
||||
// shouldn't be possible to have a client added without location permissions
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
public void dump(FileDescriptor fd, IndentingPrintWriter ipw, String[] args) {
|
||||
synchronized (mLock) {
|
||||
ipw.print(mName);
|
||||
@@ -2306,10 +2278,14 @@ class LocationProviderManager extends
|
||||
public void clearMock() {
|
||||
if (mFineLocation != null && mFineLocation.isFromMockProvider()) {
|
||||
mFineLocation = null;
|
||||
}
|
||||
if (mCoarseLocation != null && mCoarseLocation.isFromMockProvider()) {
|
||||
mCoarseLocation = null;
|
||||
}
|
||||
if (mFineBypassLocation != null && mFineBypassLocation.isFromMockProvider()) {
|
||||
mFineBypassLocation = null;
|
||||
}
|
||||
if (mCoarseBypassLocation != null && mCoarseBypassLocation.isFromMockProvider()) {
|
||||
mCoarseBypassLocation = null;
|
||||
}
|
||||
}
|
||||
@@ -2340,14 +2316,14 @@ class LocationProviderManager extends
|
||||
}
|
||||
}
|
||||
|
||||
public void set(Location fineLocation, Location coarseLocation) {
|
||||
mFineLocation = calculateNextFine(mFineLocation, fineLocation);
|
||||
mCoarseLocation = calculateNextCoarse(mCoarseLocation, coarseLocation);
|
||||
public void set(Location location) {
|
||||
mFineLocation = calculateNextFine(mFineLocation, location);
|
||||
mCoarseLocation = calculateNextCoarse(mCoarseLocation, location);
|
||||
}
|
||||
|
||||
public void setBypass(Location fineLocation, Location coarseLocation) {
|
||||
mFineBypassLocation = calculateNextFine(mFineBypassLocation, fineLocation);
|
||||
mCoarseBypassLocation = calculateNextCoarse(mCoarseBypassLocation, coarseLocation);
|
||||
public void setBypass(Location location) {
|
||||
mFineBypassLocation = calculateNextFine(mFineBypassLocation, location);
|
||||
mCoarseBypassLocation = calculateNextCoarse(mCoarseBypassLocation, location);
|
||||
}
|
||||
|
||||
private Location calculateNextFine(@Nullable Location oldFine, Location newFine) {
|
||||
@@ -2369,8 +2345,8 @@ class LocationProviderManager extends
|
||||
}
|
||||
|
||||
// update last coarse interval only if enough time has passed
|
||||
if (newCoarse.getElapsedRealtimeNanos() - MIN_COARSE_INTERVAL_MS
|
||||
> oldCoarse.getElapsedRealtimeNanos()) {
|
||||
if (newCoarse.getElapsedRealtimeMillis() - MIN_COARSE_INTERVAL_MS
|
||||
> oldCoarse.getElapsedRealtimeMillis()) {
|
||||
return newCoarse;
|
||||
} else {
|
||||
return oldCoarse;
|
||||
|
||||
@@ -66,6 +66,7 @@ import android.os.IRemoteCallback;
|
||||
import android.os.PowerManager;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.WorkSource;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -111,6 +112,7 @@ public class LocationProviderManagerTest {
|
||||
private static final CallerIdentity IDENTITY = CallerIdentity.forTest(CURRENT_USER, 1,
|
||||
"mypackage",
|
||||
"attribution");
|
||||
private static final WorkSource WORK_SOURCE = new WorkSource(IDENTITY.getUid());
|
||||
|
||||
private Random mRandom;
|
||||
|
||||
@@ -333,7 +335,7 @@ public class LocationProviderManagerTest {
|
||||
@Test
|
||||
public void testPassive_Listener() throws Exception {
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = new LocationRequest.Builder(0).build();
|
||||
LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
|
||||
mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
Location loc = createLocation(NAME, mRandom);
|
||||
@@ -358,8 +360,11 @@ public class LocationProviderManagerTest {
|
||||
ArgumentCaptor<Location> locationCaptor = ArgumentCaptor.forClass(Location.class);
|
||||
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
mManager.registerLocationRequest(new LocationRequest.Builder(0).build(), IDENTITY,
|
||||
PERMISSION_FINE, listener);
|
||||
mManager.registerLocationRequest(
|
||||
new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build(),
|
||||
IDENTITY,
|
||||
PERMISSION_FINE,
|
||||
listener);
|
||||
|
||||
Location loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
@@ -402,8 +407,11 @@ public class LocationProviderManagerTest {
|
||||
"attribution");
|
||||
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
mManager.registerLocationRequest(new LocationRequest.Builder(0).build(), identity,
|
||||
PERMISSION_FINE, listener);
|
||||
mManager.registerLocationRequest(
|
||||
new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build(),
|
||||
identity,
|
||||
PERMISSION_FINE,
|
||||
listener);
|
||||
|
||||
Location loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
@@ -415,8 +423,11 @@ public class LocationProviderManagerTest {
|
||||
@Test
|
||||
public void testRegisterListener_Unregister() throws Exception {
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
mManager.registerLocationRequest(new LocationRequest.Builder(0).build(), IDENTITY,
|
||||
PERMISSION_FINE, listener);
|
||||
mManager.registerLocationRequest(
|
||||
new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build(),
|
||||
IDENTITY,
|
||||
PERMISSION_FINE,
|
||||
listener);
|
||||
mManager.unregisterLocationRequest(listener);
|
||||
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
@@ -433,8 +444,11 @@ public class LocationProviderManagerTest {
|
||||
"attribution");
|
||||
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
mManager.registerLocationRequest(new LocationRequest.Builder(0).build(), identity,
|
||||
PERMISSION_FINE, listener);
|
||||
mManager.registerLocationRequest(
|
||||
new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build(),
|
||||
identity,
|
||||
PERMISSION_FINE,
|
||||
listener);
|
||||
|
||||
CountDownLatch blocker = new CountDownLatch(1);
|
||||
IN_PROCESS_EXECUTOR.execute(() -> {
|
||||
@@ -455,7 +469,10 @@ public class LocationProviderManagerTest {
|
||||
@Test
|
||||
public void testRegisterListener_NumUpdates() throws Exception {
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = new LocationRequest.Builder(0).setMaxUpdates(5).build();
|
||||
LocationRequest request = new LocationRequest.Builder(0)
|
||||
.setMaxUpdates(5)
|
||||
.setWorkSource(WORK_SOURCE)
|
||||
.build();
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
@@ -472,7 +489,10 @@ public class LocationProviderManagerTest {
|
||||
@Test
|
||||
public void testRegisterListener_ExpiringAlarm() throws Exception {
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = new LocationRequest.Builder(0).setDurationMillis(5000).build();
|
||||
LocationRequest request = new LocationRequest.Builder(0)
|
||||
.setDurationMillis(5000)
|
||||
.setWorkSource(WORK_SOURCE)
|
||||
.build();
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
mInjector.getAlarmHelper().incrementAlarmTime(5000);
|
||||
@@ -484,7 +504,10 @@ public class LocationProviderManagerTest {
|
||||
@Test
|
||||
public void testRegisterListener_ExpiringNoAlarm() throws Exception {
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = new LocationRequest.Builder(0).setDurationMillis(25).build();
|
||||
LocationRequest request = new LocationRequest.Builder(0)
|
||||
.setDurationMillis(25)
|
||||
.setWorkSource(WORK_SOURCE)
|
||||
.build();
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
Thread.sleep(25);
|
||||
@@ -497,8 +520,10 @@ public class LocationProviderManagerTest {
|
||||
@Test
|
||||
public void testRegisterListener_FastestInterval() throws Exception {
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = new LocationRequest.Builder(5000).setMinUpdateIntervalMillis(
|
||||
5000).build();
|
||||
LocationRequest request = new LocationRequest.Builder(5000)
|
||||
.setMinUpdateIntervalMillis(5000)
|
||||
.setWorkSource(WORK_SOURCE)
|
||||
.build();
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
@@ -511,8 +536,10 @@ public class LocationProviderManagerTest {
|
||||
@Test
|
||||
public void testRegisterListener_SmallestDisplacement() throws Exception {
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = new LocationRequest.Builder(5000).setMinUpdateDistanceMeters(
|
||||
1f).build();
|
||||
LocationRequest request = new LocationRequest.Builder(5000)
|
||||
.setMinUpdateDistanceMeters(1f)
|
||||
.setWorkSource(WORK_SOURCE)
|
||||
.build();
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
Location loc = createLocation(NAME, mRandom);
|
||||
@@ -526,7 +553,7 @@ public class LocationProviderManagerTest {
|
||||
@Test
|
||||
public void testRegisterListener_NoteOpFailure() throws Exception {
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = new LocationRequest.Builder(0).build();
|
||||
LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
mInjector.getAppOpsHelper().setAppOpAllowed(OP_FINE_LOCATION, IDENTITY.getPackageName(),
|
||||
@@ -544,8 +571,11 @@ public class LocationProviderManagerTest {
|
||||
"attribution");
|
||||
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
mManager.registerLocationRequest(new LocationRequest.Builder(0).build(), identity,
|
||||
PERMISSION_FINE, listener);
|
||||
mManager.registerLocationRequest(
|
||||
new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build(),
|
||||
identity,
|
||||
PERMISSION_FINE,
|
||||
listener);
|
||||
|
||||
CountDownLatch blocker = new CountDownLatch(1);
|
||||
IN_PROCESS_EXECUTOR.execute(() -> {
|
||||
@@ -572,8 +602,8 @@ public class LocationProviderManagerTest {
|
||||
ArgumentCaptor<Location> locationCaptor = ArgumentCaptor.forClass(Location.class);
|
||||
|
||||
ILocationCallback listener = createMockGetCurrentLocationListener();
|
||||
LocationRequest locationRequest = new LocationRequest.Builder(0).build();
|
||||
mManager.getCurrentLocation(locationRequest, IDENTITY, PERMISSION_FINE, listener);
|
||||
LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
|
||||
mManager.getCurrentLocation(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
Location loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
@@ -586,8 +616,8 @@ public class LocationProviderManagerTest {
|
||||
@Test
|
||||
public void testGetCurrentLocation_Cancel() throws Exception {
|
||||
ILocationCallback listener = createMockGetCurrentLocationListener();
|
||||
LocationRequest locationRequest = new LocationRequest.Builder(0).build();
|
||||
ICancellationSignal cancellationSignal = mManager.getCurrentLocation(locationRequest,
|
||||
LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
|
||||
ICancellationSignal cancellationSignal = mManager.getCurrentLocation(request,
|
||||
IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
cancellationSignal.cancel();
|
||||
@@ -599,8 +629,8 @@ public class LocationProviderManagerTest {
|
||||
@Test
|
||||
public void testGetCurrentLocation_ProviderDisabled() throws Exception {
|
||||
ILocationCallback listener = createMockGetCurrentLocationListener();
|
||||
LocationRequest locationRequest = new LocationRequest.Builder(0).build();
|
||||
mManager.getCurrentLocation(locationRequest, IDENTITY, PERMISSION_FINE, listener);
|
||||
LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
|
||||
mManager.getCurrentLocation(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
mProvider.setProviderAllowed(false);
|
||||
mProvider.setProviderAllowed(true);
|
||||
@@ -613,8 +643,8 @@ public class LocationProviderManagerTest {
|
||||
mProvider.setProviderAllowed(false);
|
||||
|
||||
ILocationCallback listener = createMockGetCurrentLocationListener();
|
||||
LocationRequest locationRequest = new LocationRequest.Builder(0).build();
|
||||
mManager.getCurrentLocation(locationRequest, IDENTITY, PERMISSION_FINE, listener);
|
||||
LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
|
||||
mManager.getCurrentLocation(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
mProvider.setProviderAllowed(true);
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
@@ -629,8 +659,8 @@ public class LocationProviderManagerTest {
|
||||
mProvider.setProviderLocation(loc);
|
||||
|
||||
ILocationCallback listener = createMockGetCurrentLocationListener();
|
||||
LocationRequest locationRequest = new LocationRequest.Builder(0).build();
|
||||
mManager.getCurrentLocation(locationRequest, IDENTITY, PERMISSION_FINE, listener);
|
||||
LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
|
||||
mManager.getCurrentLocation(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
verify(listener, times(1)).onLocation(locationCaptor.capture());
|
||||
assertThat(locationCaptor.getValue()).isEqualTo(loc);
|
||||
@@ -639,8 +669,8 @@ public class LocationProviderManagerTest {
|
||||
@Test
|
||||
public void testGetCurrentLocation_Timeout() throws Exception {
|
||||
ILocationCallback listener = createMockGetCurrentLocationListener();
|
||||
LocationRequest locationRequest = new LocationRequest.Builder(0).build();
|
||||
mManager.getCurrentLocation(locationRequest, IDENTITY, PERMISSION_FINE, listener);
|
||||
LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
|
||||
mManager.getCurrentLocation(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
mInjector.getAlarmHelper().incrementAlarmTime(60000);
|
||||
verify(listener, times(1)).onLocation(isNull());
|
||||
@@ -654,7 +684,7 @@ public class LocationProviderManagerTest {
|
||||
IDENTITY.getPackageName())).isFalse();
|
||||
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = new LocationRequest.Builder(0).build();
|
||||
LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
|
||||
@@ -683,7 +713,8 @@ public class LocationProviderManagerTest {
|
||||
assertThat(mProvider.getRequest().getLocationRequests()).isEmpty();
|
||||
|
||||
ILocationListener listener1 = createMockLocationListener();
|
||||
LocationRequest request1 = new LocationRequest.Builder(5).build();
|
||||
LocationRequest request1 = new LocationRequest.Builder(5).setWorkSource(
|
||||
WORK_SOURCE).build();
|
||||
mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
|
||||
|
||||
assertThat(mProvider.getRequest().isActive()).isTrue();
|
||||
@@ -694,7 +725,10 @@ public class LocationProviderManagerTest {
|
||||
assertThat(mProvider.getRequest().getWorkSource()).isNotNull();
|
||||
|
||||
ILocationListener listener2 = createMockLocationListener();
|
||||
LocationRequest request2 = new LocationRequest.Builder(1).setLowPower(true).build();
|
||||
LocationRequest request2 = new LocationRequest.Builder(1)
|
||||
.setLowPower(true)
|
||||
.setWorkSource(WORK_SOURCE)
|
||||
.build();
|
||||
mManager.registerLocationRequest(request2, IDENTITY, PERMISSION_FINE, listener2);
|
||||
|
||||
assertThat(mProvider.getRequest().isActive()).isTrue();
|
||||
@@ -725,7 +759,9 @@ public class LocationProviderManagerTest {
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
|
||||
ILocationListener listener1 = createMockLocationListener();
|
||||
LocationRequest request1 = new LocationRequest.Builder(60000).build();
|
||||
LocationRequest request1 = new LocationRequest.Builder(60000)
|
||||
.setWorkSource(WORK_SOURCE)
|
||||
.build();
|
||||
mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
|
||||
|
||||
verify(listener1).onLocationChanged(any(Location.class), nullable(IRemoteCallback.class));
|
||||
@@ -742,7 +778,9 @@ public class LocationProviderManagerTest {
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
|
||||
ILocationListener listener1 = createMockLocationListener();
|
||||
LocationRequest request1 = new LocationRequest.Builder(60000).build();
|
||||
LocationRequest request1 = new LocationRequest.Builder(60000)
|
||||
.setWorkSource(WORK_SOURCE)
|
||||
.build();
|
||||
|
||||
mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
|
||||
assertThat(mProvider.getRequest().isActive()).isFalse();
|
||||
@@ -757,7 +795,9 @@ public class LocationProviderManagerTest {
|
||||
@Test
|
||||
public void testProviderRequest_BackgroundThrottle() {
|
||||
ILocationListener listener1 = createMockLocationListener();
|
||||
LocationRequest request1 = new LocationRequest.Builder(5).build();
|
||||
LocationRequest request1 = new LocationRequest.Builder(5)
|
||||
.setWorkSource(WORK_SOURCE)
|
||||
.build();
|
||||
mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
|
||||
|
||||
assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5);
|
||||
@@ -773,7 +813,9 @@ public class LocationProviderManagerTest {
|
||||
Collections.singleton(IDENTITY.getPackageName()));
|
||||
|
||||
ILocationListener listener1 = createMockLocationListener();
|
||||
LocationRequest request1 = new LocationRequest.Builder(5).build();
|
||||
LocationRequest request1 = new LocationRequest.Builder(5)
|
||||
.setWorkSource(WORK_SOURCE)
|
||||
.build();
|
||||
mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
|
||||
|
||||
assertThat(mProvider.getRequest().isActive()).isTrue();
|
||||
@@ -781,8 +823,10 @@ public class LocationProviderManagerTest {
|
||||
assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse();
|
||||
|
||||
ILocationListener listener2 = createMockLocationListener();
|
||||
LocationRequest request2 = new LocationRequest.Builder(1).setLocationSettingsIgnored(
|
||||
true).build();
|
||||
LocationRequest request2 = new LocationRequest.Builder(1)
|
||||
.setLocationSettingsIgnored(true)
|
||||
.setWorkSource(WORK_SOURCE)
|
||||
.build();
|
||||
mManager.registerLocationRequest(request2, IDENTITY, PERMISSION_FINE, listener2);
|
||||
|
||||
assertThat(mProvider.getRequest().isActive()).isTrue();
|
||||
@@ -796,12 +840,16 @@ public class LocationProviderManagerTest {
|
||||
Collections.singleton(IDENTITY.getPackageName()));
|
||||
|
||||
ILocationListener listener1 = createMockLocationListener();
|
||||
LocationRequest request1 = new LocationRequest.Builder(1).build();
|
||||
LocationRequest request1 = new LocationRequest.Builder(1)
|
||||
.setWorkSource(WORK_SOURCE)
|
||||
.build();
|
||||
mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
|
||||
|
||||
ILocationListener listener2 = createMockLocationListener();
|
||||
LocationRequest request2 = new LocationRequest.Builder(5).setLocationSettingsIgnored(
|
||||
true).build();
|
||||
LocationRequest request2 = new LocationRequest.Builder(5)
|
||||
.setLocationSettingsIgnored(true)
|
||||
.setWorkSource(WORK_SOURCE)
|
||||
.build();
|
||||
mManager.registerLocationRequest(request2, IDENTITY, PERMISSION_FINE, listener2);
|
||||
|
||||
mInjector.getSettingsHelper().setLocationEnabled(false, IDENTITY.getUserId());
|
||||
@@ -818,8 +866,10 @@ public class LocationProviderManagerTest {
|
||||
Collections.singleton(IDENTITY.getPackageName()));
|
||||
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = new LocationRequest.Builder(1).setLocationSettingsIgnored(
|
||||
true).build();
|
||||
LocationRequest request = new LocationRequest.Builder(1)
|
||||
.setLocationSettingsIgnored(true)
|
||||
.setWorkSource(WORK_SOURCE)
|
||||
.build();
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
mInjector.getSettingsHelper().setIgnoreSettingsPackageWhitelist(Collections.emptySet());
|
||||
@@ -835,8 +885,10 @@ public class LocationProviderManagerTest {
|
||||
Collections.singleton(IDENTITY.getPackageName()));
|
||||
|
||||
ILocationListener listener1 = createMockLocationListener();
|
||||
LocationRequest request1 = new LocationRequest.Builder(5).setLocationSettingsIgnored(
|
||||
true).build();
|
||||
LocationRequest request1 = new LocationRequest.Builder(5)
|
||||
.setLocationSettingsIgnored(true)
|
||||
.setWorkSource(WORK_SOURCE)
|
||||
.build();
|
||||
mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
|
||||
|
||||
assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5);
|
||||
@@ -851,7 +903,7 @@ public class LocationProviderManagerTest {
|
||||
LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF);
|
||||
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = new LocationRequest.Builder(5).build();
|
||||
LocationRequest request = new LocationRequest.Builder(5).setWorkSource(WORK_SOURCE).build();
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
assertThat(mProvider.getRequest().isActive()).isTrue();
|
||||
|
||||
Reference in New Issue
Block a user