Merge "Extract LocationProviderManager"
This commit is contained in:
committed by
Android (Google) Code Review
commit
275fd7ede6
@@ -21,6 +21,8 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.location.util.identity.CallerIdentity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Location manager local system service interface.
|
||||
*
|
||||
@@ -28,6 +30,16 @@ import android.location.util.identity.CallerIdentity;
|
||||
*/
|
||||
public abstract class LocationManagerInternal {
|
||||
|
||||
/**
|
||||
* Listener for changes in provider enabled state.
|
||||
*/
|
||||
public interface ProviderEnabledListener {
|
||||
/**
|
||||
* Called when the provider enabled state changes for a particular user.
|
||||
*/
|
||||
void onProviderEnabledChanged(String provider, int userId, boolean enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given provider is enabled for the given user.
|
||||
*
|
||||
@@ -37,6 +49,24 @@ public abstract class LocationManagerInternal {
|
||||
*/
|
||||
public abstract boolean isProviderEnabledForUser(@NonNull String provider, int userId);
|
||||
|
||||
/**
|
||||
* Adds a provider enabled listener. The given provider must exist.
|
||||
*
|
||||
* @param provider The provider to listen for changes
|
||||
* @param listener The listener
|
||||
*/
|
||||
public abstract void addProviderEnabledListener(String provider,
|
||||
ProviderEnabledListener listener);
|
||||
|
||||
/**
|
||||
* Removes a provider enabled listener. The given provider must exist.
|
||||
*
|
||||
* @param provider The provider to listen for changes
|
||||
* @param listener The listener
|
||||
*/
|
||||
public abstract void removeProviderEnabledListener(String provider,
|
||||
ProviderEnabledListener listener);
|
||||
|
||||
/**
|
||||
* Returns true if the given identity is a location provider.
|
||||
*
|
||||
@@ -52,4 +82,10 @@ public abstract class LocationManagerInternal {
|
||||
*/
|
||||
// TODO: there is no reason for this to exist as part of any API. move all the logic into gnss
|
||||
public abstract void sendNiResponse(int notifId, int userResponse);
|
||||
|
||||
/**
|
||||
* Should only be used by GNSS code.
|
||||
*/
|
||||
// TODO: there is no reason for this to exist as part of any API. create a real batching API
|
||||
public abstract void reportGnssBatchLocations(List<Location> locations);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@ import android.util.TimeUtils;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
/**
|
||||
* A data object that contains quality of service parameters for requests
|
||||
@@ -150,8 +152,6 @@ public final class LocationRequest implements Parcelable {
|
||||
|
||||
@UnsupportedAppUsage
|
||||
private String mProvider;
|
||||
// if true, client requests coarse location, if false, client requests fine location
|
||||
private boolean mCoarseLocation;
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
|
||||
private int mQuality;
|
||||
@UnsupportedAppUsage
|
||||
@@ -257,7 +257,6 @@ public final class LocationRequest implements Parcelable {
|
||||
public LocationRequest() {
|
||||
this(
|
||||
/* provider= */ LocationManager.FUSED_PROVIDER,
|
||||
/* coarseLocation= */ false,
|
||||
/* quality= */ POWER_LOW,
|
||||
/* interval= */ DEFAULT_INTERVAL_MS,
|
||||
/* fastestInterval= */ (long) (DEFAULT_INTERVAL_MS / FASTEST_INTERVAL_FACTOR),
|
||||
@@ -276,7 +275,6 @@ public final class LocationRequest implements Parcelable {
|
||||
public LocationRequest(LocationRequest src) {
|
||||
this(
|
||||
src.mProvider,
|
||||
src.mCoarseLocation,
|
||||
src.mQuality,
|
||||
src.mInterval,
|
||||
src.mFastestInterval,
|
||||
@@ -293,7 +291,6 @@ public final class LocationRequest implements Parcelable {
|
||||
|
||||
private LocationRequest(
|
||||
@NonNull String provider,
|
||||
boolean coarseLocation,
|
||||
int quality,
|
||||
long intervalMs,
|
||||
long fastestIntervalMs,
|
||||
@@ -310,7 +307,6 @@ public final class LocationRequest implements Parcelable {
|
||||
checkQuality(quality);
|
||||
|
||||
mProvider = provider;
|
||||
mCoarseLocation = coarseLocation;
|
||||
mQuality = quality;
|
||||
mInterval = intervalMs;
|
||||
mFastestInterval = fastestIntervalMs;
|
||||
@@ -326,20 +322,6 @@ public final class LocationRequest implements Parcelable {
|
||||
mWorkSource = workSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public boolean isCoarse() {
|
||||
return mCoarseLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public void setCoarse(boolean coarse) {
|
||||
mCoarseLocation = coarse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the quality of the request.
|
||||
*
|
||||
@@ -720,7 +702,6 @@ public final class LocationRequest implements Parcelable {
|
||||
public LocationRequest createFromParcel(Parcel in) {
|
||||
return new LocationRequest(
|
||||
/* provider= */ in.readString(),
|
||||
/* coarseLocation= */ in.readBoolean(),
|
||||
/* quality= */ in.readInt(),
|
||||
/* interval= */ in.readLong(),
|
||||
/* fastestInterval= */ in.readLong(),
|
||||
@@ -749,7 +730,6 @@ public final class LocationRequest implements Parcelable {
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeString(mProvider);
|
||||
parcel.writeBoolean(mCoarseLocation);
|
||||
parcel.writeInt(mQuality);
|
||||
parcel.writeLong(mInterval);
|
||||
parcel.writeLong(mFastestInterval);
|
||||
@@ -784,6 +764,36 @@ public final class LocationRequest implements Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LocationRequest that = (LocationRequest) o;
|
||||
return mQuality == that.mQuality
|
||||
&& mInterval == that.mInterval
|
||||
&& mFastestInterval == that.mFastestInterval
|
||||
&& mExplicitFastestInterval == that.mExplicitFastestInterval
|
||||
&& mExpireAt == that.mExpireAt
|
||||
&& mExpireIn == that.mExpireIn
|
||||
&& mNumUpdates == that.mNumUpdates
|
||||
&& Float.compare(that.mSmallestDisplacement, mSmallestDisplacement) == 0
|
||||
&& mHideFromAppOps == that.mHideFromAppOps
|
||||
&& mLocationSettingsIgnored == that.mLocationSettingsIgnored
|
||||
&& mLowPowerMode == that.mLowPowerMode
|
||||
&& mProvider.equals(that.mProvider)
|
||||
&& Objects.equals(mWorkSource, that.mWorkSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mProvider, mInterval, mWorkSource);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
@@ -794,7 +804,7 @@ public final class LocationRequest implements Parcelable {
|
||||
if (mQuality != POWER_NONE) {
|
||||
s.append(" interval=");
|
||||
TimeUtils.formatDuration(mInterval, s);
|
||||
if (mExplicitFastestInterval) {
|
||||
if (mExplicitFastestInterval && mFastestInterval != mInterval) {
|
||||
s.append(" fastestInterval=");
|
||||
TimeUtils.formatDuration(mFastestInterval, s);
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ public class LocationFudger {
|
||||
public Location createCoarse(Location fine) {
|
||||
synchronized (this) {
|
||||
if (fine == mCachedFineLocation) {
|
||||
return new Location(mCachedCoarseLocation);
|
||||
return mCachedCoarseLocation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ public class LocationFudger {
|
||||
mCachedCoarseLocation = coarse;
|
||||
}
|
||||
|
||||
return new Location(mCachedCoarseLocation);
|
||||
return mCachedCoarseLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.location;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.location.util.identity.CallerIdentity;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* Shared utilities for LocationManagerService and GnssManager.
|
||||
*/
|
||||
public class LocationManagerServiceUtils {
|
||||
|
||||
/**
|
||||
* Skeleton class of listener that can be linked to a binder.
|
||||
*/
|
||||
public abstract static class LinkedListenerBase implements IBinder.DeathRecipient {
|
||||
protected final CallerIdentity mCallerIdentity;
|
||||
|
||||
LinkedListenerBase(@NonNull CallerIdentity callerIdentity) {
|
||||
mCallerIdentity = callerIdentity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return mCallerIdentity.toString();
|
||||
}
|
||||
|
||||
public CallerIdentity getCallerIdentity() {
|
||||
return mCallerIdentity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link listener (i.e. callback) to a binder, so that it will be called upon binder's death.
|
||||
*/
|
||||
public boolean linkToListenerDeathNotificationLocked(IBinder binder) {
|
||||
try {
|
||||
binder.linkToDeath(this, 0 /* flags */);
|
||||
return true;
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink death listener (i.e. callback) from binder.
|
||||
*/
|
||||
public void unlinkFromListenerDeathNotificationLocked(IBinder binder) {
|
||||
try {
|
||||
binder.unlinkToDeath(this, 0 /* flags */);
|
||||
} catch (NoSuchElementException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -40,9 +40,8 @@ public class MockProvider extends AbstractLocationProvider {
|
||||
|
||||
public MockProvider(ProviderProperties properties, CallerIdentity identity) {
|
||||
// using a direct executor is ok because this class has no locks that could deadlock
|
||||
super(DIRECT_EXECUTOR);
|
||||
super(DIRECT_EXECUTOR, identity);
|
||||
setProperties(properties);
|
||||
setIdentity(identity);
|
||||
}
|
||||
|
||||
/** Sets the allowed state of this mock provider. */
|
||||
|
||||
@@ -241,7 +241,6 @@ public class MockableLocationProvider extends AbstractLocationProvider {
|
||||
if (getState().properties != null) {
|
||||
pw.println("properties=" + getState().properties);
|
||||
}
|
||||
pw.println("request=" + mRequest);
|
||||
}
|
||||
|
||||
if (provider != null) {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.location;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Binder;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.server.location.util.Injector;
|
||||
|
||||
class PassiveLocationProviderManager extends LocationProviderManager {
|
||||
|
||||
PassiveLocationProviderManager(Context context, Injector injector) {
|
||||
super(context, injector, LocationManager.PASSIVE_PROVIDER, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRealProvider(AbstractLocationProvider provider) {
|
||||
Preconditions.checkArgument(provider instanceof PassiveProvider);
|
||||
super.setRealProvider(provider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMockProvider(@Nullable MockProvider provider) {
|
||||
if (provider != null) {
|
||||
throw new IllegalArgumentException("Cannot mock the passive provider");
|
||||
}
|
||||
}
|
||||
|
||||
public void updateLocation(Location location) {
|
||||
synchronized (mLock) {
|
||||
PassiveProvider passiveProvider = (PassiveProvider) mProvider.getProvider();
|
||||
Preconditions.checkState(passiveProvider != null);
|
||||
|
||||
long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
passiveProvider.updateLocation(location);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,17 +16,21 @@
|
||||
|
||||
package com.android.server.location.gnss;
|
||||
|
||||
import static android.location.LocationManager.GPS_PROVIDER;
|
||||
|
||||
import static com.android.server.location.LocationPermissions.PERMISSION_FINE;
|
||||
import static com.android.server.location.gnss.GnssManagerService.TAG;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.location.LocationManagerInternal;
|
||||
import android.location.LocationManagerInternal.ProviderEnabledListener;
|
||||
import android.location.util.identity.CallerIdentity;
|
||||
import android.os.IBinder;
|
||||
import android.os.IInterface;
|
||||
import android.os.Process;
|
||||
import android.util.ArraySet;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.location.listeners.BinderListenerRegistration;
|
||||
import com.android.server.location.listeners.ListenerMultiplexer;
|
||||
@@ -161,8 +165,8 @@ public abstract class GnssListenerMultiplexer<TRequest, TListener extends IInter
|
||||
protected final LocationManagerInternal mLocationManagerInternal;
|
||||
|
||||
private final UserListener mUserChangedListener = this::onUserChanged;
|
||||
private final SettingsHelper.UserSettingChangedListener mLocationEnabledChangedListener =
|
||||
this::onLocationEnabledChanged;
|
||||
private final ProviderEnabledListener mProviderEnabledChangedListener =
|
||||
this::onProviderEnabledChanged;
|
||||
private final SettingsHelper.GlobalSettingChangedListener
|
||||
mBackgroundThrottlePackageWhitelistChangedListener =
|
||||
this::onBackgroundThrottlePackageWhitelistChanged;
|
||||
@@ -233,12 +237,11 @@ public abstract class GnssListenerMultiplexer<TRequest, TListener extends IInter
|
||||
}
|
||||
|
||||
CallerIdentity identity = registration.getIdentity();
|
||||
// TODO: this should be checking if the gps provider is enabled, not if location is enabled,
|
||||
// but this is the same for now.
|
||||
return registration.isPermitted()
|
||||
&& (registration.isForeground() || isBackgroundRestrictionExempt(identity))
|
||||
&& mUserInfoHelper.isCurrentUserId(identity.getUserId())
|
||||
&& mSettingsHelper.isLocationEnabled(identity.getUserId())
|
||||
&& mLocationManagerInternal.isProviderEnabledForUser(GPS_PROVIDER,
|
||||
identity.getUserId())
|
||||
&& !mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
|
||||
identity.getPackageName());
|
||||
}
|
||||
@@ -263,7 +266,8 @@ public abstract class GnssListenerMultiplexer<TRequest, TListener extends IInter
|
||||
}
|
||||
|
||||
mUserInfoHelper.addListener(mUserChangedListener);
|
||||
mSettingsHelper.addOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
|
||||
mLocationManagerInternal.addProviderEnabledListener(GPS_PROVIDER,
|
||||
mProviderEnabledChangedListener);
|
||||
mSettingsHelper.addOnBackgroundThrottlePackageWhitelistChangedListener(
|
||||
mBackgroundThrottlePackageWhitelistChangedListener);
|
||||
mSettingsHelper.addOnLocationPackageBlacklistChangedListener(
|
||||
@@ -279,7 +283,8 @@ public abstract class GnssListenerMultiplexer<TRequest, TListener extends IInter
|
||||
}
|
||||
|
||||
mUserInfoHelper.removeListener(mUserChangedListener);
|
||||
mSettingsHelper.removeOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
|
||||
mLocationManagerInternal.removeProviderEnabledListener(GPS_PROVIDER,
|
||||
mProviderEnabledChangedListener);
|
||||
mSettingsHelper.removeOnBackgroundThrottlePackageWhitelistChangedListener(
|
||||
mBackgroundThrottlePackageWhitelistChangedListener);
|
||||
mSettingsHelper.removeOnLocationPackageBlacklistChangedListener(
|
||||
@@ -294,7 +299,8 @@ public abstract class GnssListenerMultiplexer<TRequest, TListener extends IInter
|
||||
}
|
||||
}
|
||||
|
||||
private void onLocationEnabledChanged(int userId) {
|
||||
private void onProviderEnabledChanged(String provider, int userId, boolean enabled) {
|
||||
Preconditions.checkState(GPS_PROVIDER.equals(provider));
|
||||
updateRegistrations(registration -> registration.getIdentity().getUserId() == userId);
|
||||
}
|
||||
|
||||
|
||||
@@ -104,18 +104,18 @@ public abstract class ListenerMultiplexer<TKey, TRequest, TListener,
|
||||
* should return true if a matching call to {@link #unregisterWithService()} is required to
|
||||
* unregister (ie, if registration succeeds).
|
||||
*
|
||||
* @see #reregisterWithService(Object)
|
||||
* @see #reregisterWithService(Object, Object)
|
||||
*/
|
||||
protected abstract boolean registerWithService(TMergedRequest mergedRequest);
|
||||
protected abstract boolean registerWithService(TMergedRequest newRequest);
|
||||
|
||||
/**
|
||||
* Invoked when the service already has a request, and it is being replaced with a new request.
|
||||
* The default implementation unregisters first, then registers with the new merged request, but
|
||||
* this may be overridden by subclasses in order to reregister more efficiently.
|
||||
*/
|
||||
protected boolean reregisterWithService(TMergedRequest mergedRequest) {
|
||||
protected boolean reregisterWithService(TMergedRequest oldRequest, TMergedRequest newRequest) {
|
||||
unregisterWithService();
|
||||
return registerWithService(mergedRequest);
|
||||
return registerWithService(newRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -368,6 +368,7 @@ public abstract class ListenerMultiplexer<TKey, TRequest, TListener,
|
||||
mCurrentRequest = null;
|
||||
if (mServiceRegistered) {
|
||||
mServiceRegistered = false;
|
||||
mCurrentRequest = null;
|
||||
unregisterWithService();
|
||||
}
|
||||
return;
|
||||
@@ -376,11 +377,15 @@ public abstract class ListenerMultiplexer<TKey, TRequest, TListener,
|
||||
TMergedRequest merged = mergeRequests(actives);
|
||||
if (!mServiceRegistered || !Objects.equals(merged, mCurrentRequest)) {
|
||||
if (mServiceRegistered) {
|
||||
mServiceRegistered = reregisterWithService(merged);
|
||||
mServiceRegistered = reregisterWithService(mCurrentRequest, merged);
|
||||
} else {
|
||||
mServiceRegistered = registerWithService(merged);
|
||||
}
|
||||
mCurrentRequest = merged;
|
||||
if (mServiceRegistered) {
|
||||
mCurrentRequest = merged;
|
||||
} else {
|
||||
mCurrentRequest = null;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
@@ -388,29 +393,6 @@ public abstract class ListenerMultiplexer<TKey, TRequest, TListener,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates the given predicate for all registrations, and forces an {@link #updateService()}
|
||||
* if any predicate returns true for an active registration. The predicate will always be
|
||||
* evaluated for all registrations, even inactive registrations, or if it has already returned
|
||||
* true for a prior registration.
|
||||
*/
|
||||
protected final void updateService(Predicate<TRegistration> predicate) {
|
||||
synchronized (mRegistrations) {
|
||||
boolean updateService = false;
|
||||
final int size = mRegistrations.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
TRegistration registration = mRegistrations.valueAt(i);
|
||||
if (predicate.test(registration) && registration.isActive()) {
|
||||
updateService = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (updateService) {
|
||||
updateService();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins buffering calls to {@link #updateService()} until {@link UpdateServiceLock#close()}
|
||||
* is called. This is useful to prevent extra work when combining multiple calls (for example,
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.annotation.Nullable;
|
||||
import android.location.util.identity.CallerIdentity;
|
||||
import android.os.Process;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.listeners.ListenerExecutor;
|
||||
import com.android.server.FgThread;
|
||||
|
||||
@@ -39,6 +40,9 @@ import java.util.concurrent.Executor;
|
||||
*/
|
||||
public class ListenerRegistration<TRequest, TListener> implements ListenerExecutor {
|
||||
|
||||
@VisibleForTesting
|
||||
public static final Executor IN_PROCESS_EXECUTOR = FgThread.getExecutor();
|
||||
|
||||
private final Executor mExecutor;
|
||||
private final @Nullable TRequest mRequest;
|
||||
private final CallerIdentity mIdentity;
|
||||
@@ -55,9 +59,9 @@ public class ListenerRegistration<TRequest, TListener> implements ListenerExecut
|
||||
// there's a slight loophole here for pending intents - pending intent callbacks can
|
||||
// always be run on the direct executor since they're always asynchronous, but honestly
|
||||
// you shouldn't be using pending intent callbacks within the same process anyways
|
||||
mExecutor = FgThread.getExecutor();
|
||||
mExecutor = IN_PROCESS_EXECUTOR;
|
||||
} else {
|
||||
mExecutor = DIRECT_EXECUTOR;
|
||||
mExecutor = DIRECT_EXECUTOR;
|
||||
}
|
||||
|
||||
mRequest = request;
|
||||
@@ -73,7 +77,7 @@ public class ListenerRegistration<TRequest, TListener> implements ListenerExecut
|
||||
/**
|
||||
* Returns the request associated with this listener, or null if one wasn't supplied.
|
||||
*/
|
||||
public final @Nullable TRequest getRequest() {
|
||||
public @Nullable TRequest getRequest() {
|
||||
return mRequest;
|
||||
}
|
||||
|
||||
@@ -107,7 +111,7 @@ public class ListenerRegistration<TRequest, TListener> implements ListenerExecut
|
||||
*/
|
||||
protected void onInactive() {}
|
||||
|
||||
final boolean isActive() {
|
||||
public final boolean isActive() {
|
||||
return mActive;
|
||||
}
|
||||
|
||||
@@ -120,7 +124,7 @@ public class ListenerRegistration<TRequest, TListener> implements ListenerExecut
|
||||
return false;
|
||||
}
|
||||
|
||||
final boolean isRegistered() {
|
||||
public final boolean isRegistered() {
|
||||
return mListener != null;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ public abstract class RemovableListenerRegistration<TRequest, TListener> extends
|
||||
protected RemovableListenerRegistration(String tag, @Nullable TRequest request,
|
||||
CallerIdentity callerIdentity, TListener listener) {
|
||||
super(request, callerIdentity, listener);
|
||||
mTag = tag;
|
||||
mTag = Objects.requireNonNull(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.frameworks.mockingservicestests">
|
||||
|
||||
<uses-sdk android:targetSdkVersion="30" />
|
||||
|
||||
<uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/>
|
||||
<uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/>
|
||||
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
|
||||
|
||||
@@ -0,0 +1,971 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.location;
|
||||
|
||||
import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
|
||||
import static android.app.AlarmManager.WINDOW_EXACT;
|
||||
import static android.app.AppOpsManager.OP_FINE_LOCATION;
|
||||
import static android.app.AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION;
|
||||
import static android.app.AppOpsManager.OP_MONITOR_LOCATION;
|
||||
import static android.location.Criteria.ACCURACY_COARSE;
|
||||
import static android.location.Criteria.ACCURACY_FINE;
|
||||
import static android.location.Criteria.POWER_HIGH;
|
||||
import static android.location.LocationManager.PASSIVE_PROVIDER;
|
||||
|
||||
import static androidx.test.ext.truth.location.LocationSubject.assertThat;
|
||||
|
||||
import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
|
||||
import static com.android.server.location.LocationPermissions.PERMISSION_COARSE;
|
||||
import static com.android.server.location.LocationPermissions.PERMISSION_FINE;
|
||||
import static com.android.server.location.LocationUtils.createLocation;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
import static org.mockito.Mockito.after;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.timeout;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.AlarmManager.OnAlarmListener;
|
||||
import android.content.Context;
|
||||
import android.location.ILocationCallback;
|
||||
import android.location.ILocationListener;
|
||||
import android.location.Location;
|
||||
import android.location.LocationManagerInternal;
|
||||
import android.location.LocationManagerInternal.ProviderEnabledListener;
|
||||
import android.location.LocationRequest;
|
||||
import android.location.util.identity.CallerIdentity;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Handler;
|
||||
import android.os.ICancellationSignal;
|
||||
import android.os.IRemoteCallback;
|
||||
import android.os.PowerManager;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.WorkSource;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.internal.location.ProviderProperties;
|
||||
import com.android.internal.location.ProviderRequest;
|
||||
import com.android.server.FgThread;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.location.listeners.ListenerRegistration;
|
||||
import com.android.server.location.util.FakeUserInfoHelper;
|
||||
import com.android.server.location.util.TestInjector;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class LocationProviderManagerTest {
|
||||
|
||||
private static final String TAG = "LocationProviderManagerTest";
|
||||
|
||||
private static final long TIMEOUT_MS = 1000;
|
||||
|
||||
private static final int CURRENT_USER = FakeUserInfoHelper.DEFAULT_USERID;
|
||||
private static final int OTHER_USER = CURRENT_USER + 10;
|
||||
|
||||
private static final String NAME = "test";
|
||||
private static final ProviderProperties PROPERTIES = new ProviderProperties(false, false, false,
|
||||
false, true, true, true, POWER_HIGH, ACCURACY_FINE);
|
||||
private static final CallerIdentity IDENTITY = CallerIdentity.forTest(CURRENT_USER, 1,
|
||||
"mypackage",
|
||||
"attribution");
|
||||
|
||||
private Random mRandom;
|
||||
|
||||
@Mock
|
||||
private LocationManagerInternal mInternal;
|
||||
@Mock
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private AlarmManager mAlarmManager;
|
||||
@Mock
|
||||
private PowerManager mPowerManager;
|
||||
@Mock
|
||||
private PowerManager.WakeLock mWakeLock;
|
||||
|
||||
private TestInjector mInjector;
|
||||
private PassiveLocationProviderManager mPassive;
|
||||
private TestProvider mProvider;
|
||||
|
||||
private LocationProviderManager mManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
initMocks(this);
|
||||
|
||||
long seed = System.currentTimeMillis();
|
||||
Log.i(TAG, "location random seed: " + seed);
|
||||
|
||||
mRandom = new Random(seed);
|
||||
|
||||
LocalServices.addService(LocationManagerInternal.class, mInternal);
|
||||
|
||||
doReturn("android").when(mContext).getPackageName();
|
||||
doReturn(mAlarmManager).when(mContext).getSystemService(AlarmManager.class);
|
||||
doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
|
||||
doReturn(mWakeLock).when(mPowerManager).newWakeLock(anyInt(), anyString());
|
||||
|
||||
mInjector = new TestInjector();
|
||||
mInjector.getUserInfoHelper().startUser(OTHER_USER);
|
||||
|
||||
mPassive = new PassiveLocationProviderManager(mContext, mInjector);
|
||||
mPassive.startManager();
|
||||
mPassive.setRealProvider(new PassiveProvider(mContext));
|
||||
|
||||
mProvider = new TestProvider(PROPERTIES, IDENTITY);
|
||||
mProvider.setProviderAllowed(true);
|
||||
|
||||
mManager = new LocationProviderManager(mContext, mInjector, NAME, mPassive);
|
||||
mManager.startManager();
|
||||
mManager.setRealProvider(mProvider);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
LocalServices.removeServiceForTest(LocationManagerInternal.class);
|
||||
|
||||
// some test failures may leave the fg thread stuck, interrupt until we get out of it
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
FgThread.getExecutor().execute(latch::countDown);
|
||||
int count = 0;
|
||||
while (++count < 10 && !latch.await(10, TimeUnit.MILLISECONDS)) {
|
||||
FgThread.get().getLooper().getThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProperties() {
|
||||
assertThat(mManager.getName()).isEqualTo(NAME);
|
||||
assertThat(mManager.getProperties()).isEqualTo(PROPERTIES);
|
||||
assertThat(mManager.getIdentity()).isEqualTo(IDENTITY);
|
||||
assertThat(mManager.hasProvider()).isTrue();
|
||||
|
||||
ProviderProperties newProperties = new ProviderProperties(true, true, true,
|
||||
true, false, false, false, POWER_HIGH, ACCURACY_COARSE);
|
||||
mProvider.setProperties(newProperties);
|
||||
assertThat(mManager.getProperties()).isEqualTo(newProperties);
|
||||
|
||||
CallerIdentity newIdentity = CallerIdentity.forTest(OTHER_USER, 1, "otherpackage",
|
||||
"otherattribution");
|
||||
mProvider.setIdentity(newIdentity);
|
||||
assertThat(mManager.getIdentity()).isEqualTo(newIdentity);
|
||||
|
||||
mManager.setRealProvider(null);
|
||||
assertThat(mManager.hasProvider()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveProvider() {
|
||||
mManager.setRealProvider(null);
|
||||
assertThat(mManager.hasProvider()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEnabled() {
|
||||
assertThat(mManager.isEnabled(CURRENT_USER)).isTrue();
|
||||
|
||||
mInjector.getSettingsHelper().setLocationEnabled(false, CURRENT_USER);
|
||||
assertThat(mManager.isEnabled(CURRENT_USER)).isFalse();
|
||||
|
||||
mInjector.getSettingsHelper().setLocationEnabled(true, CURRENT_USER);
|
||||
mProvider.setAllowed(false);
|
||||
assertThat(mManager.isEnabled(CURRENT_USER)).isFalse();
|
||||
|
||||
mProvider.setAllowed(true);
|
||||
mInjector.getUserInfoHelper().setCurrentUserId(OTHER_USER);
|
||||
assertThat(mManager.isEnabled(CURRENT_USER)).isFalse();
|
||||
assertThat(mManager.isEnabled(OTHER_USER)).isTrue();
|
||||
|
||||
mInjector.getUserInfoHelper().setCurrentUserId(CURRENT_USER);
|
||||
assertThat(mManager.isEnabled(CURRENT_USER)).isTrue();
|
||||
assertThat(mManager.isEnabled(OTHER_USER)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEnabledListener() {
|
||||
ProviderEnabledListener listener = mock(ProviderEnabledListener.class);
|
||||
mManager.addEnabledListener(listener);
|
||||
verify(listener, never()).onProviderEnabledChanged(anyString(), anyInt(), anyBoolean());
|
||||
|
||||
mInjector.getSettingsHelper().setLocationEnabled(false, CURRENT_USER);
|
||||
verify(listener, timeout(TIMEOUT_MS).times(1)).onProviderEnabledChanged(NAME, CURRENT_USER,
|
||||
false);
|
||||
|
||||
mInjector.getSettingsHelper().setLocationEnabled(true, CURRENT_USER);
|
||||
verify(listener, timeout(TIMEOUT_MS).times(1)).onProviderEnabledChanged(NAME, CURRENT_USER,
|
||||
true);
|
||||
|
||||
mProvider.setAllowed(false);
|
||||
verify(listener, timeout(TIMEOUT_MS).times(2)).onProviderEnabledChanged(NAME, CURRENT_USER,
|
||||
false);
|
||||
|
||||
mProvider.setAllowed(true);
|
||||
verify(listener, timeout(TIMEOUT_MS).times(2)).onProviderEnabledChanged(NAME, CURRENT_USER,
|
||||
true);
|
||||
|
||||
mInjector.getUserInfoHelper().setCurrentUserId(OTHER_USER);
|
||||
verify(listener, timeout(TIMEOUT_MS).times(3)).onProviderEnabledChanged(NAME, CURRENT_USER,
|
||||
false);
|
||||
verify(listener, timeout(TIMEOUT_MS).times(1)).onProviderEnabledChanged(NAME, OTHER_USER,
|
||||
true);
|
||||
|
||||
mInjector.getUserInfoHelper().setCurrentUserId(CURRENT_USER);
|
||||
verify(listener, timeout(TIMEOUT_MS).times(3)).onProviderEnabledChanged(NAME, CURRENT_USER,
|
||||
true);
|
||||
verify(listener, timeout(TIMEOUT_MS).times(1)).onProviderEnabledChanged(NAME, OTHER_USER,
|
||||
false);
|
||||
|
||||
mManager.removeEnabledListener(listener);
|
||||
mInjector.getSettingsHelper().setLocationEnabled(false, CURRENT_USER);
|
||||
verifyNoMoreInteractions(listener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLastLocation_Fine() {
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0, false);
|
||||
assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isNull();
|
||||
|
||||
Location loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isEqualTo(loc);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLastLocation_Coarse() {
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0, false);
|
||||
assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isNull();
|
||||
|
||||
Location loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
Location coarse = mManager.getLastLocation(request, IDENTITY, PERMISSION_COARSE);
|
||||
assertThat(coarse).isNotEqualTo(loc);
|
||||
assertThat(coarse).isNearby(loc, 5000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLastLocation_Bypass() {
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0, false);
|
||||
LocationRequest bypassRequest = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0,
|
||||
false).setLocationSettingsIgnored(true);
|
||||
assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isNull();
|
||||
assertThat(mManager.getLastLocation(bypassRequest, IDENTITY, PERMISSION_FINE)).isNull();
|
||||
|
||||
Location loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isEqualTo(loc);
|
||||
assertThat(mManager.getLastLocation(bypassRequest, IDENTITY, PERMISSION_FINE)).isEqualTo(
|
||||
loc);
|
||||
|
||||
mProvider.setProviderAllowed(false);
|
||||
assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isNull();
|
||||
assertThat(mManager.getLastLocation(bypassRequest, IDENTITY, PERMISSION_FINE)).isEqualTo(
|
||||
loc);
|
||||
|
||||
loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isNull();
|
||||
assertThat(mManager.getLastLocation(bypassRequest, IDENTITY, PERMISSION_FINE)).isEqualTo(
|
||||
loc);
|
||||
|
||||
mProvider.setProviderAllowed(true);
|
||||
assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isNull();
|
||||
assertThat(mManager.getLastLocation(bypassRequest, IDENTITY, PERMISSION_FINE)).isEqualTo(
|
||||
loc);
|
||||
|
||||
loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isEqualTo(loc);
|
||||
assertThat(mManager.getLastLocation(bypassRequest, IDENTITY, PERMISSION_FINE)).isEqualTo(
|
||||
loc);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLastLocation_ClearOnMockRemoval() {
|
||||
MockProvider mockProvider = new MockProvider(PROPERTIES, IDENTITY);
|
||||
mockProvider.setAllowed(true);
|
||||
mManager.setMockProvider(mockProvider);
|
||||
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0, false);
|
||||
Location loc = createLocation(NAME, mRandom);
|
||||
mockProvider.setProviderLocation(loc);
|
||||
assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isEqualTo(loc);
|
||||
|
||||
mManager.setMockProvider(null);
|
||||
assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInjectLastLocation() {
|
||||
Location loc1 = createLocation(NAME, mRandom);
|
||||
mManager.injectLastLocation(loc1, CURRENT_USER);
|
||||
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0, false);
|
||||
assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isEqualTo(loc1);
|
||||
|
||||
Location loc2 = createLocation(NAME, mRandom);
|
||||
mManager.injectLastLocation(loc2, CURRENT_USER);
|
||||
|
||||
assertThat(mManager.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isEqualTo(loc1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPassive_Listener() throws Exception {
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(PASSIVE_PROVIDER, 0,
|
||||
0, false);
|
||||
mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
Location loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
|
||||
ArgumentCaptor<Location> locationCaptor = ArgumentCaptor.forClass(Location.class);
|
||||
verify(listener).onLocationChanged(locationCaptor.capture(),
|
||||
nullable(IRemoteCallback.class));
|
||||
assertThat(locationCaptor.getValue()).isEqualTo(loc);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPassive_LastLocation() {
|
||||
Location loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(PASSIVE_PROVIDER, 0,
|
||||
0, false);
|
||||
assertThat(mPassive.getLastLocation(request, IDENTITY, PERMISSION_FINE)).isEqualTo(loc);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterListener() throws Exception {
|
||||
ArgumentCaptor<Location> locationCaptor = ArgumentCaptor.forClass(Location.class);
|
||||
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
mManager.registerLocationRequest(
|
||||
LocationRequest.createFromDeprecatedProvider(NAME, 0, 0, false), IDENTITY,
|
||||
PERMISSION_FINE, listener);
|
||||
|
||||
Location loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
verify(listener, times(1)).onLocationChanged(locationCaptor.capture(),
|
||||
nullable(IRemoteCallback.class));
|
||||
assertThat(locationCaptor.getValue()).isEqualTo(loc);
|
||||
|
||||
mInjector.getSettingsHelper().setLocationEnabled(false, CURRENT_USER);
|
||||
verify(listener, timeout(TIMEOUT_MS).times(1)).onProviderEnabledChanged(NAME, false);
|
||||
loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
verify(listener, times(1)).onLocationChanged(any(Location.class),
|
||||
nullable(IRemoteCallback.class));
|
||||
|
||||
mInjector.getSettingsHelper().setLocationEnabled(true, CURRENT_USER);
|
||||
verify(listener, timeout(TIMEOUT_MS).times(1)).onProviderEnabledChanged(NAME, true);
|
||||
|
||||
mProvider.setAllowed(false);
|
||||
verify(listener, timeout(TIMEOUT_MS).times(2)).onProviderEnabledChanged(NAME, false);
|
||||
loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
verify(listener, times(1)).onLocationChanged(any(Location.class),
|
||||
nullable(IRemoteCallback.class));
|
||||
|
||||
mProvider.setAllowed(true);
|
||||
verify(listener, timeout(TIMEOUT_MS).times(2)).onProviderEnabledChanged(NAME, true);
|
||||
|
||||
mInjector.getUserInfoHelper().setCurrentUserId(OTHER_USER);
|
||||
verify(listener, timeout(TIMEOUT_MS).times(3)).onProviderEnabledChanged(NAME, false);
|
||||
loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
verify(listener, times(1)).onLocationChanged(any(Location.class),
|
||||
nullable(IRemoteCallback.class));
|
||||
|
||||
mInjector.getUserInfoHelper().setCurrentUserId(CURRENT_USER);
|
||||
verify(listener, timeout(TIMEOUT_MS).times(3)).onProviderEnabledChanged(NAME, true);
|
||||
|
||||
loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
verify(listener, times(2)).onLocationChanged(locationCaptor.capture(),
|
||||
nullable(IRemoteCallback.class));
|
||||
assertThat(locationCaptor.getValue()).isEqualTo(loc);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterListener_SameProcess() throws Exception {
|
||||
ArgumentCaptor<Location> locationCaptor = ArgumentCaptor.forClass(Location.class);
|
||||
|
||||
CallerIdentity identity = CallerIdentity.forTest(CURRENT_USER, Process.myPid(), "mypackage",
|
||||
"attribution");
|
||||
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
mManager.registerLocationRequest(
|
||||
LocationRequest.createFromDeprecatedProvider(NAME, 0, 0, false), identity,
|
||||
PERMISSION_FINE, listener);
|
||||
|
||||
Location loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
verify(listener, timeout(TIMEOUT_MS).times(1)).onLocationChanged(locationCaptor.capture(),
|
||||
nullable(IRemoteCallback.class));
|
||||
assertThat(locationCaptor.getValue()).isEqualTo(loc);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterListener_Unregister() throws Exception {
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
mManager.registerLocationRequest(
|
||||
LocationRequest.createFromDeprecatedProvider(NAME, 0, 0, false), IDENTITY,
|
||||
PERMISSION_FINE, listener);
|
||||
mManager.unregisterLocationRequest(listener);
|
||||
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
verify(listener, never()).onLocationChanged(any(Location.class),
|
||||
nullable(IRemoteCallback.class));
|
||||
|
||||
mInjector.getSettingsHelper().setLocationEnabled(false, CURRENT_USER);
|
||||
verify(listener, after(TIMEOUT_MS).never()).onProviderEnabledChanged(NAME, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterListener_Unregister_SameProcess() throws Exception {
|
||||
CallerIdentity identity = CallerIdentity.forTest(CURRENT_USER, Process.myPid(), "mypackage",
|
||||
"attribution");
|
||||
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
mManager.registerLocationRequest(
|
||||
LocationRequest.createFromDeprecatedProvider(NAME, 0, 0, false), identity,
|
||||
PERMISSION_FINE, listener);
|
||||
|
||||
CountDownLatch blocker = new CountDownLatch(1);
|
||||
ListenerRegistration.IN_PROCESS_EXECUTOR.execute(() -> {
|
||||
try {
|
||||
blocker.await();
|
||||
} catch (InterruptedException e) {
|
||||
// do nothing
|
||||
}
|
||||
});
|
||||
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
mManager.unregisterLocationRequest(listener);
|
||||
blocker.countDown();
|
||||
verify(listener, after(TIMEOUT_MS).never()).onLocationChanged(any(Location.class),
|
||||
nullable(IRemoteCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterListener_NumUpdates() throws Exception {
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0,
|
||||
false).setNumUpdates(5);
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
|
||||
verify(listener, times(5)).onLocationChanged(any(Location.class),
|
||||
nullable(IRemoteCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterListener_ExpiringAlarm() throws Exception {
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0,
|
||||
false).setExpireIn(5000);
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
long baseTimeMs = SystemClock.elapsedRealtime();
|
||||
|
||||
ArgumentCaptor<Long> timeoutCapture = ArgumentCaptor.forClass(Long.class);
|
||||
ArgumentCaptor<OnAlarmListener> listenerCapture = ArgumentCaptor.forClass(
|
||||
OnAlarmListener.class);
|
||||
verify(mAlarmManager).set(eq(ELAPSED_REALTIME_WAKEUP), timeoutCapture.capture(),
|
||||
eq(WINDOW_EXACT), eq(0L), listenerCapture.capture(), any(Handler.class),
|
||||
any(WorkSource.class));
|
||||
|
||||
assertThat(timeoutCapture.getValue()).isAtLeast(baseTimeMs + 4000);
|
||||
assertThat(timeoutCapture.getValue()).isAtMost(baseTimeMs + 5000);
|
||||
listenerCapture.getValue().onAlarm();
|
||||
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
verify(listener, never()).onLocationChanged(any(Location.class),
|
||||
nullable(IRemoteCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterListener_ExpiringNoAlarm() throws Exception {
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0,
|
||||
false).setExpireIn(25);
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
Thread.sleep(25);
|
||||
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
verify(listener, never()).onLocationChanged(any(Location.class),
|
||||
nullable(IRemoteCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterListener_AlreadyExpired() throws Exception {
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0,
|
||||
false).setExpireIn(-1);
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
verify(listener, never()).onLocationChanged(any(Location.class),
|
||||
nullable(IRemoteCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterListener_FastestInterval() throws Exception {
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 5000, 0,
|
||||
false).setFastestInterval(5000);
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
|
||||
verify(listener, times(1)).onLocationChanged(any(Location.class),
|
||||
nullable(IRemoteCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterListener_SmallestDisplacement() throws Exception {
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 5000, 0,
|
||||
false).setSmallestDisplacement(1f);
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
Location loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
mProvider.setProviderLocation(loc);
|
||||
|
||||
verify(listener, times(1)).onLocationChanged(any(Location.class),
|
||||
nullable(IRemoteCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterListener_NoteOpFailure() throws Exception {
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0, false);
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
mInjector.getAppOpsHelper().setAppOpAllowed(OP_FINE_LOCATION, IDENTITY.getPackageName(),
|
||||
false);
|
||||
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
|
||||
verify(listener, never()).onLocationChanged(any(Location.class),
|
||||
nullable(IRemoteCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterListener_Wakelock() throws Exception {
|
||||
CallerIdentity identity = CallerIdentity.forTest(CURRENT_USER, Process.myPid(), "mypackage",
|
||||
"attribution");
|
||||
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
mManager.registerLocationRequest(
|
||||
LocationRequest.createFromDeprecatedProvider(NAME, 0, 0, false), identity,
|
||||
PERMISSION_FINE, listener);
|
||||
|
||||
CountDownLatch blocker = new CountDownLatch(1);
|
||||
ListenerRegistration.IN_PROCESS_EXECUTOR.execute(() -> {
|
||||
try {
|
||||
blocker.await();
|
||||
} catch (InterruptedException e) {
|
||||
// do nothing
|
||||
}
|
||||
});
|
||||
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
verify(mWakeLock).acquire(anyLong());
|
||||
verify(mWakeLock, never()).release();
|
||||
|
||||
blocker.countDown();
|
||||
verify(listener, timeout(TIMEOUT_MS)).onLocationChanged(any(Location.class),
|
||||
nullable(IRemoteCallback.class));
|
||||
verify(mWakeLock).acquire(anyLong());
|
||||
verify(mWakeLock, timeout(TIMEOUT_MS)).release();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCurrentLocation() throws Exception {
|
||||
ArgumentCaptor<Location> locationCaptor = ArgumentCaptor.forClass(Location.class);
|
||||
|
||||
ILocationCallback listener = createMockGetCurrentLocationListener();
|
||||
LocationRequest locationRequest = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0,
|
||||
false);
|
||||
ICancellationSignal cancellationSignal = CancellationSignal.createTransport();
|
||||
mManager.getCurrentLocation(locationRequest, IDENTITY,
|
||||
PERMISSION_FINE, cancellationSignal, listener);
|
||||
|
||||
Location loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
|
||||
verify(listener, times(1)).onLocation(locationCaptor.capture());
|
||||
assertThat(locationCaptor.getValue()).isEqualTo(loc);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCurrentLocation_Cancel() throws Exception {
|
||||
ILocationCallback listener = createMockGetCurrentLocationListener();
|
||||
LocationRequest locationRequest = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0,
|
||||
false);
|
||||
ICancellationSignal cancellationSignal = CancellationSignal.createTransport();
|
||||
mManager.getCurrentLocation(locationRequest, IDENTITY,
|
||||
PERMISSION_FINE, cancellationSignal, listener);
|
||||
|
||||
cancellationSignal.cancel();
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
|
||||
verify(listener, never()).onLocation(nullable(Location.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCurrentLocation_ProviderDisabled() throws Exception {
|
||||
ILocationCallback listener = createMockGetCurrentLocationListener();
|
||||
LocationRequest locationRequest = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0,
|
||||
false);
|
||||
ICancellationSignal cancellationSignal = CancellationSignal.createTransport();
|
||||
mManager.getCurrentLocation(locationRequest, IDENTITY,
|
||||
PERMISSION_FINE, cancellationSignal, listener);
|
||||
|
||||
mProvider.setProviderAllowed(false);
|
||||
mProvider.setProviderAllowed(true);
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
verify(listener, times(1)).onLocation(isNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCurrentLocation_ProviderAlreadyDisabled() throws Exception {
|
||||
mProvider.setProviderAllowed(false);
|
||||
|
||||
ILocationCallback listener = createMockGetCurrentLocationListener();
|
||||
LocationRequest locationRequest = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0,
|
||||
false);
|
||||
ICancellationSignal cancellationSignal = CancellationSignal.createTransport();
|
||||
mManager.getCurrentLocation(locationRequest, IDENTITY,
|
||||
PERMISSION_FINE, cancellationSignal, listener);
|
||||
|
||||
mProvider.setProviderAllowed(true);
|
||||
mProvider.setProviderLocation(createLocation(NAME, mRandom));
|
||||
verify(listener, times(1)).onLocation(isNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCurrentLocation_LastLocation() throws Exception {
|
||||
ArgumentCaptor<Location> locationCaptor = ArgumentCaptor.forClass(Location.class);
|
||||
|
||||
Location loc = createLocation(NAME, mRandom);
|
||||
mProvider.setProviderLocation(loc);
|
||||
|
||||
ILocationCallback listener = createMockGetCurrentLocationListener();
|
||||
LocationRequest locationRequest = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0,
|
||||
false);
|
||||
ICancellationSignal cancellationSignal = CancellationSignal.createTransport();
|
||||
mManager.getCurrentLocation(locationRequest, IDENTITY,
|
||||
PERMISSION_FINE, cancellationSignal, listener);
|
||||
|
||||
verify(listener, times(1)).onLocation(locationCaptor.capture());
|
||||
assertThat(locationCaptor.getValue()).isEqualTo(loc);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCurrentLocation_Timeout() throws Exception {
|
||||
ILocationCallback listener = createMockGetCurrentLocationListener();
|
||||
LocationRequest locationRequest = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0,
|
||||
false);
|
||||
ICancellationSignal cancellationSignal = CancellationSignal.createTransport();
|
||||
mManager.getCurrentLocation(locationRequest, IDENTITY,
|
||||
PERMISSION_FINE, cancellationSignal, listener);
|
||||
|
||||
ArgumentCaptor<OnAlarmListener> listenerCapture = ArgumentCaptor.forClass(
|
||||
OnAlarmListener.class);
|
||||
verify(mAlarmManager).set(eq(ELAPSED_REALTIME_WAKEUP), anyLong(),
|
||||
eq(WINDOW_EXACT), eq(0L), listenerCapture.capture(), any(Handler.class),
|
||||
any(WorkSource.class));
|
||||
listenerCapture.getValue().onAlarm();
|
||||
|
||||
verify(listener, times(1)).onLocation(isNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocationMonitoring() {
|
||||
assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
|
||||
IDENTITY.getPackageName())).isFalse();
|
||||
assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
|
||||
IDENTITY.getPackageName())).isFalse();
|
||||
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 0, 0, false);
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
|
||||
IDENTITY.getPackageName())).isTrue();
|
||||
assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
|
||||
IDENTITY.getPackageName())).isTrue();
|
||||
|
||||
mInjector.getAppForegroundHelper().setAppForeground(IDENTITY.getUid(), false);
|
||||
|
||||
assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
|
||||
IDENTITY.getPackageName())).isTrue();
|
||||
assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
|
||||
IDENTITY.getPackageName())).isFalse();
|
||||
|
||||
mManager.unregisterLocationRequest(listener);
|
||||
|
||||
assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
|
||||
IDENTITY.getPackageName())).isFalse();
|
||||
assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
|
||||
IDENTITY.getPackageName())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderRequest() {
|
||||
assertThat(mProvider.getRequest().reportLocation).isFalse();
|
||||
assertThat(mProvider.getRequest().locationRequests).isEmpty();
|
||||
|
||||
ILocationListener listener1 = createMockLocationListener();
|
||||
LocationRequest request1 = LocationRequest.createFromDeprecatedProvider(NAME, 5, 0, false);
|
||||
mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
|
||||
|
||||
assertThat(mProvider.getRequest().reportLocation).isTrue();
|
||||
assertThat(mProvider.getRequest().locationRequests).containsExactly(request1);
|
||||
assertThat(mProvider.getRequest().locationSettingsIgnored).isFalse();
|
||||
assertThat(mProvider.getRequest().interval).isEqualTo(5);
|
||||
assertThat(mProvider.getRequest().lowPowerMode).isFalse();
|
||||
assertThat(mProvider.getRequest().workSource).isNotNull();
|
||||
|
||||
ILocationListener listener2 = createMockLocationListener();
|
||||
LocationRequest request2 = LocationRequest.createFromDeprecatedProvider(NAME, 1, 0,
|
||||
false).setLowPowerMode(true);
|
||||
mManager.registerLocationRequest(request2, IDENTITY, PERMISSION_FINE, listener2);
|
||||
|
||||
assertThat(mProvider.getRequest().reportLocation).isTrue();
|
||||
assertThat(mProvider.getRequest().locationRequests).containsExactly(request1, request2);
|
||||
assertThat(mProvider.getRequest().locationSettingsIgnored).isFalse();
|
||||
assertThat(mProvider.getRequest().interval).isEqualTo(1);
|
||||
assertThat(mProvider.getRequest().lowPowerMode).isFalse();
|
||||
assertThat(mProvider.getRequest().workSource).isNotNull();
|
||||
|
||||
mManager.unregisterLocationRequest(listener1);
|
||||
|
||||
assertThat(mProvider.getRequest().reportLocation).isTrue();
|
||||
assertThat(mProvider.getRequest().locationRequests).containsExactly(request2);
|
||||
assertThat(mProvider.getRequest().locationSettingsIgnored).isFalse();
|
||||
assertThat(mProvider.getRequest().interval).isEqualTo(1);
|
||||
assertThat(mProvider.getRequest().lowPowerMode).isTrue();
|
||||
assertThat(mProvider.getRequest().workSource).isNotNull();
|
||||
|
||||
mManager.unregisterLocationRequest(listener2);
|
||||
|
||||
assertThat(mProvider.getRequest().reportLocation).isFalse();
|
||||
assertThat(mProvider.getRequest().locationRequests).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderRequest_BackgroundThrottle() {
|
||||
ILocationListener listener1 = createMockLocationListener();
|
||||
LocationRequest request1 = LocationRequest.createFromDeprecatedProvider(NAME, 5, 0, false);
|
||||
mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
|
||||
|
||||
assertThat(mProvider.getRequest().interval).isEqualTo(5);
|
||||
|
||||
mInjector.getAppForegroundHelper().setAppForeground(IDENTITY.getUid(), false);
|
||||
assertThat(mProvider.getRequest().interval).isEqualTo(
|
||||
mInjector.getSettingsHelper().getBackgroundThrottleIntervalMs());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderRequest_IgnoreLocationSettings() {
|
||||
mInjector.getSettingsHelper().setIgnoreSettingsPackageWhitelist(
|
||||
Collections.singleton(IDENTITY.getPackageName()));
|
||||
|
||||
ILocationListener listener1 = createMockLocationListener();
|
||||
LocationRequest request1 = LocationRequest.createFromDeprecatedProvider(NAME, 5, 0, false);
|
||||
mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
|
||||
|
||||
assertThat(mProvider.getRequest().reportLocation).isTrue();
|
||||
assertThat(mProvider.getRequest().interval).isEqualTo(5);
|
||||
assertThat(mProvider.getRequest().locationSettingsIgnored).isFalse();
|
||||
|
||||
ILocationListener listener2 = createMockLocationListener();
|
||||
LocationRequest request2 = LocationRequest.createFromDeprecatedProvider(NAME, 1, 0,
|
||||
false).setLocationSettingsIgnored(true);
|
||||
mManager.registerLocationRequest(request2, IDENTITY, PERMISSION_FINE, listener2);
|
||||
|
||||
assertThat(mProvider.getRequest().reportLocation).isTrue();
|
||||
assertThat(mProvider.getRequest().interval).isEqualTo(1);
|
||||
assertThat(mProvider.getRequest().locationSettingsIgnored).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderRequest_IgnoreLocationSettings_ProviderDisabled() {
|
||||
mInjector.getSettingsHelper().setIgnoreSettingsPackageWhitelist(
|
||||
Collections.singleton(IDENTITY.getPackageName()));
|
||||
|
||||
ILocationListener listener1 = createMockLocationListener();
|
||||
LocationRequest request1 = LocationRequest.createFromDeprecatedProvider(NAME, 1, 0, false);
|
||||
mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
|
||||
|
||||
ILocationListener listener2 = createMockLocationListener();
|
||||
LocationRequest request2 = LocationRequest.createFromDeprecatedProvider(NAME, 5, 0,
|
||||
false).setLocationSettingsIgnored(true);
|
||||
mManager.registerLocationRequest(request2, IDENTITY, PERMISSION_FINE, listener2);
|
||||
|
||||
mInjector.getSettingsHelper().setLocationEnabled(false, IDENTITY.getUserId());
|
||||
|
||||
assertThat(mProvider.getRequest().reportLocation).isTrue();
|
||||
assertThat(mProvider.getRequest().locationRequests).containsExactly(request2);
|
||||
assertThat(mProvider.getRequest().interval).isEqualTo(5);
|
||||
assertThat(mProvider.getRequest().locationSettingsIgnored).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderRequest_IgnoreLocationSettings_NoAllowlist() {
|
||||
mInjector.getSettingsHelper().setIgnoreSettingsPackageWhitelist(
|
||||
Collections.singleton(IDENTITY.getPackageName()));
|
||||
|
||||
ILocationListener listener = createMockLocationListener();
|
||||
LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 1, 0,
|
||||
false).setLocationSettingsIgnored(true);
|
||||
mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
|
||||
|
||||
mInjector.getSettingsHelper().setIgnoreSettingsPackageWhitelist(Collections.emptySet());
|
||||
|
||||
assertThat(mProvider.getRequest().reportLocation).isTrue();
|
||||
assertThat(mProvider.getRequest().interval).isEqualTo(1);
|
||||
assertThat(mProvider.getRequest().locationSettingsIgnored).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderRequest_BackgroundThrottle_IgnoreLocationSettings() {
|
||||
mInjector.getSettingsHelper().setIgnoreSettingsPackageWhitelist(
|
||||
Collections.singleton(IDENTITY.getPackageName()));
|
||||
|
||||
ILocationListener listener1 = createMockLocationListener();
|
||||
LocationRequest request1 = LocationRequest.createFromDeprecatedProvider(NAME, 5, 0,
|
||||
false).setLocationSettingsIgnored(true);
|
||||
mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
|
||||
|
||||
assertThat(mProvider.getRequest().interval).isEqualTo(5);
|
||||
|
||||
mInjector.getAppForegroundHelper().setAppForeground(IDENTITY.getUid(), false);
|
||||
assertThat(mProvider.getRequest().interval).isEqualTo(5);
|
||||
}
|
||||
|
||||
private ILocationListener createMockLocationListener() {
|
||||
return spy(new ILocationListener.Stub() {
|
||||
@Override
|
||||
public void onLocationChanged(Location location, IRemoteCallback onCompleteCallback) {
|
||||
if (onCompleteCallback != null) {
|
||||
try {
|
||||
onCompleteCallback.sendResult(null);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderEnabledChanged(String provider, boolean enabled) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private ILocationCallback createMockGetCurrentLocationListener() {
|
||||
return spy(new ILocationCallback.Stub() {
|
||||
@Override
|
||||
public void onLocation(Location location) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static class TestProvider extends AbstractLocationProvider {
|
||||
|
||||
private ProviderRequest mProviderRequest = ProviderRequest.EMPTY_REQUEST;
|
||||
|
||||
TestProvider(ProviderProperties properties, CallerIdentity identity) {
|
||||
super(DIRECT_EXECUTOR, identity);
|
||||
setProperties(properties);
|
||||
}
|
||||
|
||||
public void setProviderAllowed(boolean allowed) {
|
||||
setAllowed(allowed);
|
||||
}
|
||||
|
||||
public void setProviderLocation(Location l) {
|
||||
reportLocation(new Location(l));
|
||||
}
|
||||
|
||||
public ProviderRequest getRequest() {
|
||||
return mProviderRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetRequest(ProviderRequest request) {
|
||||
mProviderRequest = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onExtraCommand(int uid, int pid, String command, Bundle extras) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user