From 49983fcbbd085bd55dd8ef14d146120ec95cf256 Mon Sep 17 00:00:00 2001 From: Soonil Nagarkar Date: Thu, 24 Dec 2020 14:02:44 -0800 Subject: Copy LocationProviderBase API into SystemApi surface This allows third party location providers to link against the standard API surface. This replaces the LocationProviderBase implementation in the com.android.location.providers API. Both will temporarily coexist until third party applications can be migrated, and then old version will be removed. Only the LocationProviderBase API is migrated right now as its the only API that has undergone changes. This also restores some old, unused classes which should not have been remove from the API surface. Clients that support older API version will still need to link against these classes. Bug: 176115245 Test: builds Change-Id: I2d688447e1f59e441f5c48ff36d3f0dd8b5dc7f6 --- .../java/android/location/ILocationManager.aidl | 2 +- .../java/android/location/LocationManager.java | 32 +- .../java/android/location/LocationProvider.java | 14 +- .../java/android/location/ProviderProperties.aidl | 19 - .../java/android/location/ProviderProperties.java | 295 --------------- .../location/provider/ILocationProvider.aidl | 35 ++ .../provider/ILocationProviderManager.aidl | 33 ++ .../location/provider/LocationProviderBase.java | 307 +++++++++++++++ .../location/provider/ProviderProperties.aidl | 19 + .../location/provider/ProviderProperties.java | 414 +++++++++++++++++++++ .../android/location/provider/ProviderRequest.aidl | 19 + .../android/location/provider/ProviderRequest.java | 320 ++++++++++++++++ .../internal/location/ILocationProvider.aidl | 42 --- .../location/ILocationProviderManager.aidl | 33 -- .../android/internal/location/ProviderRequest.aidl | 19 - .../android/internal/location/ProviderRequest.java | 342 ----------------- 16 files changed, 1181 insertions(+), 764 deletions(-) delete mode 100644 location/java/android/location/ProviderProperties.aidl delete mode 100644 location/java/android/location/ProviderProperties.java create mode 100644 location/java/android/location/provider/ILocationProvider.aidl create mode 100644 location/java/android/location/provider/ILocationProviderManager.aidl create mode 100644 location/java/android/location/provider/LocationProviderBase.java create mode 100644 location/java/android/location/provider/ProviderProperties.aidl create mode 100644 location/java/android/location/provider/ProviderProperties.java create mode 100644 location/java/android/location/provider/ProviderRequest.aidl create mode 100644 location/java/android/location/provider/ProviderRequest.java delete mode 100644 location/java/com/android/internal/location/ILocationProvider.aidl delete mode 100644 location/java/com/android/internal/location/ILocationProviderManager.aidl delete mode 100644 location/java/com/android/internal/location/ProviderRequest.aidl delete mode 100644 location/java/com/android/internal/location/ProviderRequest.java (limited to 'location/java') diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index c50904cad4e2..afae50203cd3 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -36,7 +36,7 @@ import android.location.LastLocationRequest; import android.location.Location; import android.location.LocationRequest; import android.location.LocationTime; -import android.location.ProviderProperties; +import android.location.provider.ProviderProperties; import android.os.Bundle; import android.os.ICancellationSignal; diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 1d3e8ebaa0ab..2dc9eb44236f 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -49,6 +49,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; +import android.location.provider.ProviderProperties; import android.os.Build; import android.os.Bundle; import android.os.CancellationSignal; @@ -1803,7 +1804,6 @@ public class LocationManager { } try { - ProviderProperties properties = mService.getProviderProperties(provider); return new LocationProvider(provider, properties); } catch (IllegalArgumentException e) { @@ -1931,11 +1931,35 @@ public class LocationManager { boolean supportsSpeed, boolean supportsBearing, @ProviderProperties.PowerUsage int powerUsage, @ProviderProperties.Accuracy int accuracy) { + addTestProvider(provider, new ProviderProperties.Builder() + .setHasNetworkRequirement(requiresNetwork) + .setHasSatelliteRequirement(requiresSatellite) + .setHasCellRequirement(requiresCell) + .setHasMonetaryCost(hasMonetaryCost) + .setHasAltitudeSupport(supportsAltitude) + .setHasSpeedSupport(supportsSpeed) + .setHasBearingSupport(supportsBearing) + .setPowerUsage(powerUsage) + .setAccuracy(accuracy) + .build()); + } + + /** + * Creates a test location provider and adds it to the set of active providers. This provider + * will replace any provider with the same name that exists prior to this call. + * + * @param provider the provider name + * + * @throws IllegalArgumentException if provider is null + * @throws IllegalArgumentException if properties is null + * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION + * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED + * allowed} for your app. + */ + public void addTestProvider(@NonNull String provider, @NonNull ProviderProperties properties) { Preconditions.checkArgument(provider != null, "invalid null provider"); + Preconditions.checkArgument(properties != null, "invalid null properties"); - ProviderProperties properties = new ProviderProperties(requiresNetwork, - requiresSatellite, requiresCell, hasMonetaryCost, supportsAltitude, supportsSpeed, - supportsBearing, powerUsage, accuracy); try { mService.addTestProvider(provider, properties, mContext.getOpPackageName(), mContext.getFeatureId()); diff --git a/location/java/android/location/LocationProvider.java b/location/java/android/location/LocationProvider.java index 6d2bfed99fb7..60b251ea990d 100644 --- a/location/java/android/location/LocationProvider.java +++ b/location/java/android/location/LocationProvider.java @@ -17,6 +17,7 @@ package android.location; import android.annotation.Nullable; +import android.location.provider.ProviderProperties; /** * Information about the properties of a location provider. @@ -200,10 +201,8 @@ public class LocationProvider { } /** - * Returns the power requirement for this provider. - * - * @return the power requirement for this provider, as one of the - * constants ProviderProperties.POWER_USAGE_*. + * Returns the power requirement for this provider, one of the ProviderProperties.POWER_USAGE_* + * constants. */ public int getPowerRequirement() { if (mProperties == null) { @@ -214,11 +213,8 @@ public class LocationProvider { } /** - * Returns a constant describing horizontal accuracy of this provider. - * If the provider returns finer grain or exact location, - * {@link ProviderProperties#ACCURACY_FINE} is returned, otherwise if the - * location is only approximate then {@link ProviderProperties#ACCURACY_COARSE} - * is returned. + * Returns the rough accuracy of this provider, one of the ProviderProperties.ACCURACY_* + * constants. */ public int getAccuracy() { if (mProperties == null) { diff --git a/location/java/android/location/ProviderProperties.aidl b/location/java/android/location/ProviderProperties.aidl deleted file mode 100644 index 8b1d79f90233..000000000000 --- a/location/java/android/location/ProviderProperties.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2012, 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 android.location; - -parcelable ProviderProperties; diff --git a/location/java/android/location/ProviderProperties.java b/location/java/android/location/ProviderProperties.java deleted file mode 100644 index 8fa8c984b172..000000000000 --- a/location/java/android/location/ProviderProperties.java +++ /dev/null @@ -1,295 +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 android.location; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.os.Parcel; -import android.os.Parcelable; - -import com.android.internal.util.Preconditions; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.Objects; - -/** - * Location provider properties. - */ -public final class ProviderProperties implements Parcelable { - - /** - * A constant indicating low power usage. - */ - public static final int POWER_USAGE_LOW = 1; - - /** - * A constant indicating a medium power usage. - */ - public static final int POWER_USAGE_MEDIUM = 2; - - /** - * A constant indicating high power usage. - */ - public static final int POWER_USAGE_HIGH = 3; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = "POWER_USAGE_", value = {POWER_USAGE_LOW, POWER_USAGE_MEDIUM, - POWER_USAGE_HIGH}) - public @interface PowerUsage {} - - /** - * A constant indicating a finer location accuracy. - */ - public static final int ACCURACY_FINE = 1; - - /** - * A constant indicating a coarser location accuracy. - */ - public static final int ACCURACY_COARSE = 2; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = "ACCURACY_", value = {ACCURACY_FINE, ACCURACY_COARSE}) - public @interface Accuracy {} - - private final boolean mHasNetworkRequirement; - private final boolean mHasSatelliteRequirement; - private final boolean mHasCellRequirement; - private final boolean mHasMonetaryCost; - private final boolean mHasAltitudeSupport; - private final boolean mHasSpeedSupport; - private final boolean mHasBearingSupport; - private final @PowerUsage int mPowerUsage; - private final @Accuracy int mAccuracy; - - /** - * @hide - */ - public ProviderProperties(boolean hasNetworkRequirement, boolean hasSatelliteRequirement, - boolean hasCellRequirement, boolean hasMonetaryCost, boolean hasAltitudeSupport, - boolean hasSpeedSupport, boolean hasBearingSupport, - @PowerUsage int powerUsage, @Accuracy int accuracy) { - mHasNetworkRequirement = hasNetworkRequirement; - mHasSatelliteRequirement = hasSatelliteRequirement; - mHasCellRequirement = hasCellRequirement; - mHasMonetaryCost = hasMonetaryCost; - mHasAltitudeSupport = hasAltitudeSupport; - mHasSpeedSupport = hasSpeedSupport; - mHasBearingSupport = hasBearingSupport; - mPowerUsage = Preconditions.checkArgumentInRange(powerUsage, POWER_USAGE_LOW, - POWER_USAGE_HIGH, "powerUsage"); - mAccuracy = Preconditions.checkArgumentInRange(accuracy, ACCURACY_FINE, - ACCURACY_COARSE, "locationAccuracy"); - } - - /** - * True if provider requires access to a data network (e.g., the Internet). - */ - public boolean hasNetworkRequirement() { - return mHasNetworkRequirement; - } - - /** - * True if the provider requires access to a satellite-based positioning system (e.g., GPS). - */ - public boolean hasSatelliteRequirement() { - return mHasSatelliteRequirement; - } - - /** - * True if the provider requires access to a cellular network (e.g., for cell tower IDs). - */ - public boolean hasCellRequirement() { - return mHasCellRequirement; - } - - /** - * True if this provider may result in a monetary charge to the user. Network usage is not - * considered a monetary cost. - */ - public boolean hasMonetaryCost() { - return mHasMonetaryCost; - } - - /** - * True if the provider is able to provide altitude under at least some conditions. - */ - public boolean hasAltitudeSupport() { - return mHasAltitudeSupport; - } - - /** - * True if the provider is able to provide speed under at least some conditions. - */ - public boolean hasSpeedSupport() { - return mHasSpeedSupport; - } - - /** - * True if the provider is able to provide bearing under at least some conditions. - */ - public boolean hasBearingSupport() { - return mHasBearingSupport; - } - - /** - * Power usage for this provider. - */ - public @PowerUsage int getPowerUsage() { - return mPowerUsage; - } - - /** - * Rough location accuracy for this provider, primarily with respect to horizontal location - * accuracy. - */ - public @Accuracy int getAccuracy() { - return mAccuracy; - } - - public static final @NonNull Creator CREATOR = - new Creator() { - @Override - public ProviderProperties createFromParcel(Parcel in) { - return new ProviderProperties( - /* hasNetworkRequirement= */ in.readBoolean(), - /* hasSatelliteRequirement= */ in.readBoolean(), - /* hasCellRequirement= */ in.readBoolean(), - /* hasMonetaryCost= */ in.readBoolean(), - /* hasAltitudeSupport= */ in.readBoolean(), - /* hasSpeedSupport= */ in.readBoolean(), - /* hasBearingSupport= */ in.readBoolean(), - /* powerUsage= */ in.readInt(), - /* accuracy= */ in.readInt()); - } - - @Override - public ProviderProperties[] newArray(int size) { - return new ProviderProperties[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(@NonNull Parcel parcel, int flags) { - parcel.writeBoolean(mHasNetworkRequirement); - parcel.writeBoolean(mHasSatelliteRequirement); - parcel.writeBoolean(mHasCellRequirement); - parcel.writeBoolean(mHasMonetaryCost); - parcel.writeBoolean(mHasAltitudeSupport); - parcel.writeBoolean(mHasSpeedSupport); - parcel.writeBoolean(mHasBearingSupport); - parcel.writeInt(mPowerUsage); - parcel.writeInt(mAccuracy); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof ProviderProperties)) { - return false; - } - ProviderProperties that = (ProviderProperties) o; - return mHasNetworkRequirement == that.mHasNetworkRequirement - && mHasSatelliteRequirement == that.mHasSatelliteRequirement - && mHasCellRequirement == that.mHasCellRequirement - && mHasMonetaryCost == that.mHasMonetaryCost - && mHasAltitudeSupport == that.mHasAltitudeSupport - && mHasSpeedSupport == that.mHasSpeedSupport - && mHasBearingSupport == that.mHasBearingSupport - && mPowerUsage == that.mPowerUsage - && mAccuracy == that.mAccuracy; - } - - @Override - public int hashCode() { - return Objects.hash(mHasNetworkRequirement, mHasSatelliteRequirement, mHasCellRequirement, - mHasMonetaryCost, mHasAltitudeSupport, mHasSpeedSupport, mHasBearingSupport, - mPowerUsage, mAccuracy); - } - - @Override - public String toString() { - StringBuilder b = new StringBuilder("ProviderProperties["); - b.append("power=").append(powerToString(mPowerUsage)).append(", "); - b.append("accuracy=").append(accuracyToString(mAccuracy)); - if (mHasNetworkRequirement || mHasSatelliteRequirement || mHasCellRequirement) { - b.append(", requires="); - if (mHasNetworkRequirement) { - b.append("network,"); - } - if (mHasSatelliteRequirement) { - b.append("satellite,"); - } - if (mHasCellRequirement) { - b.append("cell,"); - } - b.setLength(b.length() - 1); - } - if (mHasMonetaryCost) { - b.append(", hasMonetaryCost"); - } - if (mHasBearingSupport || mHasSpeedSupport || mHasAltitudeSupport) { - b.append(", supports=["); - if (mHasBearingSupport) { - b.append("bearing,"); - } - if (mHasSpeedSupport) { - b.append("speed,"); - } - if (mHasAltitudeSupport) { - b.append("altitude,"); - } - b.setLength(b.length() - 1); - b.append("]"); - } - b.append("]"); - return b.toString(); - } - - private static String powerToString(@PowerUsage int power) { - switch (power) { - case POWER_USAGE_LOW: - return "Low"; - case POWER_USAGE_MEDIUM: - return "Medium"; - case POWER_USAGE_HIGH: - return "High"; - default: - throw new AssertionError(); - } - } - - private static String accuracyToString(@Accuracy int accuracy) { - switch (accuracy) { - case ACCURACY_COARSE: - return "Coarse"; - case ACCURACY_FINE: - return "Fine"; - default: - throw new AssertionError(); - } - } -} diff --git a/location/java/android/location/provider/ILocationProvider.aidl b/location/java/android/location/provider/ILocationProvider.aidl new file mode 100644 index 000000000000..f9995d5cf8b8 --- /dev/null +++ b/location/java/android/location/provider/ILocationProvider.aidl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2009 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 android.location.provider; + +import android.os.Bundle; + +import android.location.provider.ILocationProviderManager; +import android.location.provider.ProviderRequest; + +/** + * Binder interface for services that implement location providers. Do not implement this directly, + * extend {@link LocationProviderBase} instead. + * @hide + */ +interface ILocationProvider { + + oneway void setLocationProviderManager(in ILocationProviderManager manager); + oneway void setRequest(in ProviderRequest request); + oneway void flush(); + oneway void sendExtraCommand(String command, in Bundle extras); +} diff --git a/location/java/android/location/provider/ILocationProviderManager.aidl b/location/java/android/location/provider/ILocationProviderManager.aidl new file mode 100644 index 000000000000..e3f51d9a23e1 --- /dev/null +++ b/location/java/android/location/provider/ILocationProviderManager.aidl @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2009 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 android.location.provider; + +import android.location.LocationResult; +import android.location.provider.ProviderProperties; + +/** + * Binder interface for manager of all location providers. + * @hide + */ +interface ILocationProviderManager { + void onInitialize(boolean allowed, in ProviderProperties properties, @nullable String packageName, @nullable String attributionTag); + void onSetAllowed(boolean allowed); + void onSetProperties(in ProviderProperties properties); + + void onReportLocation(in LocationResult locationResult); + void onFlushComplete(); +} diff --git a/location/java/android/location/provider/LocationProviderBase.java b/location/java/android/location/provider/LocationProviderBase.java new file mode 100644 index 000000000000..1306ea2c0204 --- /dev/null +++ b/location/java/android/location/provider/LocationProviderBase.java @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2010 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 android.location.provider; + +import static android.location.Location.EXTRA_NO_GPS_LOCATION; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SuppressLint; +import android.annotation.SystemApi; +import android.content.Context; +import android.content.Intent; +import android.location.Location; +import android.location.LocationResult; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import java.util.Objects; + +/** + * Base class for location providers outside the system server. + * + * Location providers should be wrapped in a non-exported service which returns the result of + * {@link #getBinder()} from the service's {@link android.app.Service#onBind(Intent)} method. The + * service should not be exported so that components other than the system server cannot bind to it. + * Alternatively, the service may be guarded by a permission that only system server can obtain. The + * service may specify metadata on its capabilities: + * + *
    + *
  • + * "serviceVersion": An integer version code to help tie break if multiple services are + * capable of implementing the same location provider. All else equal, the service with the + * highest version code will be chosen. Assumed to be 0 if not specified. + *
  • + *
  • + * "serviceIsMultiuser": A boolean property, indicating if the service wishes to take + * responsibility for handling changes to the current user on the device. If true, the + * service will always be bound from the system user. If false, the service will always be + * bound from the current user. If the current user changes, the old binding will be + * released, and a new binding established under the new user. Assumed to be false if not + * specified. + *
  • + *
+ * + *

The service should have an intent filter in place for the location provider it wishes to + * implements. Defaults for some providers are specified as constants in this class. + * + * @hide + */ +@SystemApi +public abstract class LocationProviderBase { + + /** + * Callback to be invoked when a flush operation is complete and all flushed locations have been + * reported. + */ + public interface OnFlushCompleteCallback { + + /** + * Should be invoked once the flush is complete. + */ + void onFlushComplete(); + } + + /** + * The action the wrapping service should have in its intent filter to implement the + * {@link android.location.LocationManager#NETWORK_PROVIDER}. + */ + @SuppressLint("ActionValue") + public static final String ACTION_NETWORK_PROVIDER = + "com.android.location.service.v3.NetworkLocationProvider"; + + /** + * The action the wrapping service should have in its intent filter to implement the + * {@link android.location.LocationManager#FUSED_PROVIDER}. + */ + @SuppressLint("ActionValue") + public static final String ACTION_FUSED_PROVIDER = + "com.android.location.service.FusedLocationProvider"; + + private final String mTag; + private final @Nullable String mPackageName; + private final @Nullable String mAttributionTag; + private final IBinder mBinder; + + // write locked on mBinder, read lock is optional depending on atomicity requirements + private @Nullable volatile ILocationProviderManager mManager; + private volatile ProviderProperties mProperties; + private volatile boolean mAllowed; + + public LocationProviderBase(@NonNull Context context, @NonNull String tag, + @NonNull ProviderProperties properties) { + mTag = tag; + mPackageName = context.getPackageName(); + mAttributionTag = context.getAttributionTag(); + mBinder = new Service(); + + mManager = null; + mProperties = Objects.requireNonNull(properties); + mAllowed = true; + } + + /** + * Returns the IBinder instance that should be returned from the + * {@link android.app.Service#onBind(Intent)} method of the wrapping service. + */ + public final @Nullable IBinder getBinder() { + return mBinder; + } + + /** + * Sets whether this provider is currently allowed or not. Note that this is specific to the + * provider only, and is unrelated to global location settings. This is a hint to the location + * manager that this provider will be unable to fulfill incoming requests. Setting a provider + * as not allowed will result in the provider being disabled. Setting a provider as allowed + * means that the provider may be in either the enabled or disabled state. + * + *

Some guidelines: providers should set their own allowed/disallowed status based only on + * state "owned" by that provider. For instance, providers should not take into account the + * state of the location master setting when setting themselves allowed or disallowed, as this + * state is not owned by a particular provider. If a provider requires some additional user + * consent that is particular to the provider, this should be use to set the allowed/disallowed + * state. If the provider proxies to another provider, the child provider's allowed/disallowed + * state should be taken into account in the parent's allowed state. For most providers, it is + * expected that they will be always allowed. + */ + public void setAllowed(boolean allowed) { + synchronized (mBinder) { + if (mAllowed == allowed) { + return; + } + + mAllowed = allowed; + } + + ILocationProviderManager manager = mManager; + if (manager != null) { + try { + manager.onSetAllowed(mAllowed); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (RuntimeException e) { + Log.w(mTag, e); + } + } + } + + /** + * Returns true if this provider is allowed. Providers start as allowed on construction. + */ + public boolean isAllowed() { + return mAllowed; + } + + /** + * Sets the provider properties that may be queried by clients. Generally speaking, providers + * should try to avoid changing their properties after construction. + */ + public void setProperties(@NonNull ProviderProperties properties) { + synchronized (mBinder) { + mProperties = Objects.requireNonNull(properties); + } + + ILocationProviderManager manager = mManager; + if (manager != null) { + try { + manager.onSetProperties(mProperties); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (RuntimeException e) { + Log.w(mTag, e); + } + } + } + + /** + * Returns the currently set properties of the provider. + */ + public @NonNull ProviderProperties getProperties() { + return mProperties; + } + + /** + * Reports a new location from this provider. + */ + public void reportLocation(@NonNull Location location) { + reportLocation(LocationResult.create(location)); + } + + /** + * Reports a new location result from this provider. + * + *

May only be used from Android S onwards. + */ + public void reportLocation(@NonNull LocationResult locationResult) { + ILocationProviderManager manager = mManager; + if (manager != null) { + locationResult = locationResult.map(location -> { + // remove deprecated extras to save on serialization costs + Bundle extras = location.getExtras(); + if (extras != null && (extras.containsKey(EXTRA_NO_GPS_LOCATION) + || extras.containsKey("coarseLocation"))) { + location = new Location(location); + extras = location.getExtras(); + extras.remove(EXTRA_NO_GPS_LOCATION); + extras.remove("coarseLocation"); + if (extras.isEmpty()) { + location.setExtras(null); + } + } + return location; + }); + + try { + manager.onReportLocation(locationResult); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (RuntimeException e) { + Log.w(mTag, e); + } + } + } + + /** + * Set the current {@link ProviderRequest} for this provider. Each call to this method overrides + * any prior ProviderRequests. The provider should immediately attempt to provide locations (or + * not provide locations) according to the parameters of the provider request. + */ + public abstract void onSetRequest(@NonNull ProviderRequest request); + + /** + * Requests a flush of any pending batched locations. The callback must always be invoked once + * per invocation, and should be invoked after {@link #reportLocation(LocationResult)} has been + * invoked with any flushed locations. The callback may be invoked immediately if no locations + * are flushed. + */ + public abstract void onFlush(@NonNull OnFlushCompleteCallback callback); + + /** + * Implements optional custom commands. + */ + public abstract void onSendExtraCommand(@NonNull String command, @Nullable Bundle extras); + + private final class Service extends ILocationProvider.Stub { + + Service() {} + + @Override + public void setLocationProviderManager(ILocationProviderManager manager) { + synchronized (mBinder) { + try { + manager.onInitialize(mAllowed, mProperties, mPackageName, mAttributionTag); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (RuntimeException e) { + Log.w(mTag, e); + } + + mManager = manager; + } + } + + @Override + public void setRequest(ProviderRequest request) { + onSetRequest(request); + } + + @Override + public void flush() { + onFlush(this::onFlushComplete); + } + + private void onFlushComplete() { + ILocationProviderManager manager = mManager; + if (manager != null) { + try { + manager.onFlushComplete(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (RuntimeException e) { + Log.w(mTag, e); + } + } + } + + @Override + public void sendExtraCommand(String command, Bundle extras) { + onSendExtraCommand(command, extras); + } + } +} diff --git a/location/java/android/location/provider/ProviderProperties.aidl b/location/java/android/location/provider/ProviderProperties.aidl new file mode 100644 index 000000000000..fd5a614b4fc8 --- /dev/null +++ b/location/java/android/location/provider/ProviderProperties.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2012, 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 android.location.provider; + +parcelable ProviderProperties; diff --git a/location/java/android/location/provider/ProviderProperties.java b/location/java/android/location/provider/ProviderProperties.java new file mode 100644 index 000000000000..793401251de8 --- /dev/null +++ b/location/java/android/location/provider/ProviderProperties.java @@ -0,0 +1,414 @@ +/* + * Copyright (C) 2021 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 android.location.provider; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.Preconditions; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Objects; + +/** + * Location provider properties. + */ +public final class ProviderProperties implements Parcelable { + + /** + * A constant indicating low power usage. + */ + public static final int POWER_USAGE_LOW = 1; + + /** + * A constant indicating a medium power usage. + */ + public static final int POWER_USAGE_MEDIUM = 2; + + /** + * A constant indicating high power usage. + */ + public static final int POWER_USAGE_HIGH = 3; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "POWER_USAGE_", value = {POWER_USAGE_LOW, POWER_USAGE_MEDIUM, + POWER_USAGE_HIGH}) + public @interface PowerUsage {} + + /** + * A constant indicating a finer location accuracy. + */ + public static final int ACCURACY_FINE = 1; + + /** + * A constant indicating a coarser location accuracy. + */ + public static final int ACCURACY_COARSE = 2; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "ACCURACY_", value = {ACCURACY_FINE, ACCURACY_COARSE}) + public @interface Accuracy {} + + private final boolean mHasNetworkRequirement; + private final boolean mHasSatelliteRequirement; + private final boolean mHasCellRequirement; + private final boolean mHasMonetaryCost; + private final boolean mHasAltitudeSupport; + private final boolean mHasSpeedSupport; + private final boolean mHasBearingSupport; + private final @PowerUsage int mPowerUsage; + private final @Accuracy int mAccuracy; + + private ProviderProperties(boolean hasNetworkRequirement, boolean hasSatelliteRequirement, + boolean hasCellRequirement, boolean hasMonetaryCost, boolean hasAltitudeSupport, + boolean hasSpeedSupport, boolean hasBearingSupport, + @PowerUsage int powerUsage, @Accuracy int accuracy) { + mHasNetworkRequirement = hasNetworkRequirement; + mHasSatelliteRequirement = hasSatelliteRequirement; + mHasCellRequirement = hasCellRequirement; + mHasMonetaryCost = hasMonetaryCost; + mHasAltitudeSupport = hasAltitudeSupport; + mHasSpeedSupport = hasSpeedSupport; + mHasBearingSupport = hasBearingSupport; + mPowerUsage = powerUsage; + mAccuracy = accuracy; + } + + /** + * True if provider requires access to a data network (e.g., the Internet). + */ + public boolean hasNetworkRequirement() { + return mHasNetworkRequirement; + } + + /** + * True if the provider requires access to a satellite-based positioning system (e.g., GPS). + */ + public boolean hasSatelliteRequirement() { + return mHasSatelliteRequirement; + } + + /** + * True if the provider requires access to a cellular network (e.g., for cell tower IDs). + */ + public boolean hasCellRequirement() { + return mHasCellRequirement; + } + + /** + * True if this provider may result in a monetary charge to the user. Network usage is not + * considered a monetary cost. + */ + public boolean hasMonetaryCost() { + return mHasMonetaryCost; + } + + /** + * True if the provider is able to provide altitude under at least some conditions. + */ + public boolean hasAltitudeSupport() { + return mHasAltitudeSupport; + } + + /** + * True if the provider is able to provide speed under at least some conditions. + */ + public boolean hasSpeedSupport() { + return mHasSpeedSupport; + } + + /** + * True if the provider is able to provide bearing under at least some conditions. + */ + public boolean hasBearingSupport() { + return mHasBearingSupport; + } + + /** + * Power usage for this provider. + */ + public @PowerUsage int getPowerUsage() { + return mPowerUsage; + } + + /** + * Rough location accuracy for this provider, primarily with respect to horizontal location + * accuracy. + */ + public @Accuracy int getAccuracy() { + return mAccuracy; + } + + public static final @NonNull Creator CREATOR = + new Creator() { + @Override + public ProviderProperties createFromParcel(Parcel in) { + return new ProviderProperties( + /* hasNetworkRequirement= */ in.readBoolean(), + /* hasSatelliteRequirement= */ in.readBoolean(), + /* hasCellRequirement= */ in.readBoolean(), + /* hasMonetaryCost= */ in.readBoolean(), + /* hasAltitudeSupport= */ in.readBoolean(), + /* hasSpeedSupport= */ in.readBoolean(), + /* hasBearingSupport= */ in.readBoolean(), + /* powerUsage= */ in.readInt(), + /* accuracy= */ in.readInt()); + } + + @Override + public ProviderProperties[] newArray(int size) { + return new ProviderProperties[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel parcel, int flags) { + parcel.writeBoolean(mHasNetworkRequirement); + parcel.writeBoolean(mHasSatelliteRequirement); + parcel.writeBoolean(mHasCellRequirement); + parcel.writeBoolean(mHasMonetaryCost); + parcel.writeBoolean(mHasAltitudeSupport); + parcel.writeBoolean(mHasSpeedSupport); + parcel.writeBoolean(mHasBearingSupport); + parcel.writeInt(mPowerUsage); + parcel.writeInt(mAccuracy); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ProviderProperties)) { + return false; + } + ProviderProperties that = (ProviderProperties) o; + return mHasNetworkRequirement == that.mHasNetworkRequirement + && mHasSatelliteRequirement == that.mHasSatelliteRequirement + && mHasCellRequirement == that.mHasCellRequirement + && mHasMonetaryCost == that.mHasMonetaryCost + && mHasAltitudeSupport == that.mHasAltitudeSupport + && mHasSpeedSupport == that.mHasSpeedSupport + && mHasBearingSupport == that.mHasBearingSupport + && mPowerUsage == that.mPowerUsage + && mAccuracy == that.mAccuracy; + } + + @Override + public int hashCode() { + return Objects.hash(mHasNetworkRequirement, mHasSatelliteRequirement, mHasCellRequirement, + mHasMonetaryCost, mHasAltitudeSupport, mHasSpeedSupport, mHasBearingSupport, + mPowerUsage, mAccuracy); + } + + @Override + public String toString() { + StringBuilder b = new StringBuilder("ProviderProperties["); + b.append("powerUsage=").append(powerToString(mPowerUsage)).append(", "); + b.append("accuracy=").append(accuracyToString(mAccuracy)); + if (mHasNetworkRequirement || mHasSatelliteRequirement || mHasCellRequirement) { + b.append(", requires="); + if (mHasNetworkRequirement) { + b.append("network,"); + } + if (mHasSatelliteRequirement) { + b.append("satellite,"); + } + if (mHasCellRequirement) { + b.append("cell,"); + } + b.setLength(b.length() - 1); + } + if (mHasMonetaryCost) { + b.append(", hasMonetaryCost"); + } + if (mHasBearingSupport || mHasSpeedSupport || mHasAltitudeSupport) { + b.append(", supports=["); + if (mHasBearingSupport) { + b.append("bearing,"); + } + if (mHasSpeedSupport) { + b.append("speed,"); + } + if (mHasAltitudeSupport) { + b.append("altitude,"); + } + b.setLength(b.length() - 1); + b.append("]"); + } + b.append("]"); + return b.toString(); + } + + private static String powerToString(@PowerUsage int power) { + switch (power) { + case POWER_USAGE_LOW: + return "Low"; + case POWER_USAGE_MEDIUM: + return "Medium"; + case POWER_USAGE_HIGH: + return "High"; + default: + throw new AssertionError(); + } + } + + private static String accuracyToString(@Accuracy int accuracy) { + switch (accuracy) { + case ACCURACY_COARSE: + return "Coarse"; + case ACCURACY_FINE: + return "Fine"; + default: + throw new AssertionError(); + } + } + + /** + * Builder for ProviderProperties. + */ + public static final class Builder { + + private boolean mHasNetworkRequirement; + private boolean mHasSatelliteRequirement; + private boolean mHasCellRequirement; + private boolean mHasMonetaryCost; + private boolean mHasAltitudeSupport; + private boolean mHasSpeedSupport; + private boolean mHasBearingSupport; + private @PowerUsage int mPowerUsage; + private @Accuracy int mAccuracy; + + public Builder() { + mHasNetworkRequirement = false; + mHasSatelliteRequirement = false; + mHasCellRequirement = false; + mHasMonetaryCost = false; + mHasAltitudeSupport = false; + mHasSpeedSupport = false; + mHasBearingSupport = false; + mPowerUsage = POWER_USAGE_HIGH; + mAccuracy = ACCURACY_COARSE; + } + + public Builder(@NonNull ProviderProperties providerProperties) { + mHasNetworkRequirement = providerProperties.mHasNetworkRequirement; + mHasSatelliteRequirement = providerProperties.mHasSatelliteRequirement; + mHasCellRequirement = providerProperties.mHasCellRequirement; + mHasMonetaryCost = providerProperties.mHasMonetaryCost; + mHasAltitudeSupport = providerProperties.mHasAltitudeSupport; + mHasSpeedSupport = providerProperties.mHasSpeedSupport; + mHasBearingSupport = providerProperties.mHasBearingSupport; + mPowerUsage = providerProperties.mPowerUsage; + mAccuracy = providerProperties.mAccuracy; + } + + /** + * Sets whether a provider requires network access. False by default. + */ + public @NonNull Builder setHasNetworkRequirement(boolean requiresNetwork) { + mHasNetworkRequirement = requiresNetwork; + return this; + } + + /** + * Sets whether a provider requires satellite access. False by default. + */ + public @NonNull Builder setHasSatelliteRequirement(boolean requiresSatellite) { + mHasSatelliteRequirement = requiresSatellite; + return this; + } + + /** + * Sets whether a provider requires cell tower access. False by default. + */ + public @NonNull Builder setHasCellRequirement(boolean requiresCell) { + mHasCellRequirement = requiresCell; + return this; + } + + /** + * Sets whether a provider has a monetary cost. False by default. + */ + public @NonNull Builder setHasMonetaryCost(boolean monetaryCost) { + mHasMonetaryCost = monetaryCost; + return this; + } + + /** + * Sets whether a provider can provide altitude information. False by default. + */ + public @NonNull Builder setHasAltitudeSupport(boolean supportsAltitude) { + mHasAltitudeSupport = supportsAltitude; + return this; + } + + /** + * Sets whether a provider can provide speed information. False by default. + */ + public @NonNull Builder setHasSpeedSupport(boolean supportsSpeed) { + mHasSpeedSupport = supportsSpeed; + return this; + } + + /** + * Sets whether a provider can provide bearing information. False by default. + */ + public @NonNull Builder setHasBearingSupport(boolean supportsBearing) { + mHasBearingSupport = supportsBearing; + return this; + } + + /** + * Sets a very rough bucket of provider power usage. {@link #POWER_USAGE_HIGH} by default. + */ + public @NonNull Builder setPowerUsage(@PowerUsage int powerUsage) { + mPowerUsage = Preconditions.checkArgumentInRange(powerUsage, POWER_USAGE_LOW, + POWER_USAGE_HIGH, "powerUsage"); + return this; + } + + /** + * Sets a very rough bucket of provider location accuracy. {@link #ACCURACY_COARSE} by + * default. + */ + public @NonNull Builder setAccuracy(@Accuracy int accuracy) { + mAccuracy = Preconditions.checkArgumentInRange(accuracy, ACCURACY_FINE, + ACCURACY_COARSE, "accuracy"); + return this; + } + + /** + * Builds a new ProviderProperties. + */ + public @NonNull ProviderProperties build() { + return new ProviderProperties(mHasNetworkRequirement, mHasSatelliteRequirement, + mHasCellRequirement, mHasMonetaryCost, mHasAltitudeSupport, mHasSpeedSupport, + mHasBearingSupport, mPowerUsage, mAccuracy); + } + } +} diff --git a/location/java/android/location/provider/ProviderRequest.aidl b/location/java/android/location/provider/ProviderRequest.aidl new file mode 100644 index 000000000000..b98f3018fe2b --- /dev/null +++ b/location/java/android/location/provider/ProviderRequest.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2012 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 android.location.provider; + +parcelable ProviderRequest; diff --git a/location/java/android/location/provider/ProviderRequest.java b/location/java/android/location/provider/ProviderRequest.java new file mode 100644 index 000000000000..e543b040a2d4 --- /dev/null +++ b/location/java/android/location/provider/ProviderRequest.java @@ -0,0 +1,320 @@ +/* + * 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 android.location.provider; + +import static android.location.LocationRequest.QUALITY_BALANCED_POWER_ACCURACY; +import static android.location.LocationRequest.QUALITY_HIGH_ACCURACY; +import static android.location.LocationRequest.QUALITY_LOW_POWER; + +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.location.LocationRequest; +import android.location.LocationRequest.Quality; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.WorkSource; +import android.util.TimeUtils; + +import com.android.internal.util.Preconditions; + +import java.util.Objects; + +/** + * Location provider request. + * @hide + */ +@SystemApi +public final class ProviderRequest implements Parcelable { + + public static final long INTERVAL_DISABLED = Long.MAX_VALUE; + + public static final @NonNull ProviderRequest EMPTY_REQUEST = new ProviderRequest( + INTERVAL_DISABLED, QUALITY_BALANCED_POWER_ACCURACY, 0, false, false, new WorkSource()); + + private final long mIntervalMillis; + private final @Quality int mQuality; + private final long mMaxUpdateDelayMillis; + private final boolean mLowPower; + private final boolean mLocationSettingsIgnored; + private final WorkSource mWorkSource; + + private ProviderRequest( + long intervalMillis, + @Quality int quality, + long maxUpdateDelayMillis, + boolean lowPower, + boolean locationSettingsIgnored, + @NonNull WorkSource workSource) { + mIntervalMillis = intervalMillis; + mQuality = quality; + mMaxUpdateDelayMillis = maxUpdateDelayMillis; + mLowPower = lowPower; + mLocationSettingsIgnored = locationSettingsIgnored; + mWorkSource = Objects.requireNonNull(workSource); + } + + /** + * True if this is an active request with a valid location reporting interval, false if this + * request is inactive and does not require any locations to be reported. + */ + public boolean isActive() { + return mIntervalMillis != INTERVAL_DISABLED; + } + + /** + * The interval at which a provider should report location. Will return + * {@link #INTERVAL_DISABLED} for an inactive request. + */ + public @IntRange(from = 0) long getIntervalMillis() { + return mIntervalMillis; + } + + /** + * The quality hint for this location request. The quality hint informs the provider how it + * should attempt to manage any accuracy vs power tradeoffs while attempting to satisfy this + * provider request. + */ + public @Quality int getQuality() { + return mQuality; + } + + /** + * The maximum time any location update may be delayed, and thus grouped with following updates + * to enable location batching. If the maximum update delay is equal to or greater than + * twice the interval, then the provider may provide batched results if possible. The maximum + * batch size a provider is allowed to return is the maximum update delay divided by the + * interval. + */ + public @IntRange(from = 0) long getMaxUpdateDelayMillis() { + return mMaxUpdateDelayMillis; + } + + /** + * Whether any applicable hardware low power modes should be used to satisfy this request. + */ + public boolean isLowPower() { + return mLowPower; + } + + /** + * Whether the provider should ignore all location settings, user consents, power restrictions + * or any other restricting factors and always satisfy this request to the best of their + * ability. This should only be used in case of a user initiated emergency. + */ + public boolean isLocationSettingsIgnored() { + return mLocationSettingsIgnored; + } + + /** + * The power blame for this provider request. + */ + public @NonNull WorkSource getWorkSource() { + return mWorkSource; + } + + public static final @NonNull Creator CREATOR = new Creator() { + @Override + public ProviderRequest createFromParcel(Parcel in) { + long intervalMillis = in.readLong(); + if (intervalMillis == INTERVAL_DISABLED) { + return EMPTY_REQUEST; + } else { + return new ProviderRequest( + intervalMillis, + /* quality= */ in.readInt(), + /* maxUpdateDelayMillis= */ in.readLong(), + /* lowPower= */ in.readBoolean(), + /* locationSettingsIgnored= */ in.readBoolean(), + /* workSource= */ in.readTypedObject(WorkSource.CREATOR)); + } + } + + @Override + public ProviderRequest[] newArray(int size) { + return new ProviderRequest[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel parcel, int flags) { + parcel.writeLong(mIntervalMillis); + if (mIntervalMillis != INTERVAL_DISABLED) { + parcel.writeInt(mQuality); + parcel.writeLong(mMaxUpdateDelayMillis); + parcel.writeBoolean(mLowPower); + parcel.writeBoolean(mLocationSettingsIgnored); + parcel.writeTypedObject(mWorkSource, flags); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + ProviderRequest that = (ProviderRequest) o; + if (mIntervalMillis == INTERVAL_DISABLED) { + return that.mIntervalMillis == INTERVAL_DISABLED; + } else { + return mIntervalMillis == that.mIntervalMillis + && mQuality == that.mQuality + && mMaxUpdateDelayMillis == that.mMaxUpdateDelayMillis + && mLowPower == that.mLowPower + && mLocationSettingsIgnored == that.mLocationSettingsIgnored + && mWorkSource.equals(that.mWorkSource); + } + } + + @Override + public int hashCode() { + return Objects.hash(mIntervalMillis, mQuality, mWorkSource); + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append("ProviderRequest["); + if (mIntervalMillis != INTERVAL_DISABLED) { + s.append("@"); + TimeUtils.formatDuration(mIntervalMillis, s); + if (mQuality != QUALITY_BALANCED_POWER_ACCURACY) { + if (mQuality == QUALITY_HIGH_ACCURACY) { + s.append(", HIGH_ACCURACY"); + } else if (mQuality == QUALITY_LOW_POWER) { + s.append(", LOW_POWER"); + } + } + if (mMaxUpdateDelayMillis / 2 > mIntervalMillis) { + s.append(", maxUpdateDelay="); + TimeUtils.formatDuration(mMaxUpdateDelayMillis, s); + } + if (mLowPower) { + s.append(", lowPower"); + } + if (mLocationSettingsIgnored) { + s.append(", locationSettingsIgnored"); + } + if (!mWorkSource.isEmpty()) { + s.append(", ").append(mWorkSource); + } + } else { + s.append("OFF"); + } + s.append(']'); + return s.toString(); + } + + /** + * A Builder for {@link ProviderRequest}s. + */ + public static final class Builder { + private long mIntervalMillis = INTERVAL_DISABLED; + private int mQuality = QUALITY_BALANCED_POWER_ACCURACY; + private long mMaxUpdateDelayMillis = 0; + private boolean mLowPower; + private boolean mLocationSettingsIgnored; + private WorkSource mWorkSource = new WorkSource(); + + /** + * Sets the request interval. Use {@link #INTERVAL_DISABLED} for an inactive request. + * Defaults to {@link #INTERVAL_DISABLED}. + */ + public @NonNull Builder setIntervalMillis(@IntRange(from = 0) long intervalMillis) { + mIntervalMillis = Preconditions.checkArgumentInRange(intervalMillis, 0, Long.MAX_VALUE, + "intervalMillis"); + return this; + } + + /** + * Sets the request quality. The quality is a hint to providers on how they should weigh + * power vs accuracy tradeoffs. High accuracy locations may cost more power to produce, and + * lower accuracy locations may cost less power to produce. Defaults to + * {@link LocationRequest#QUALITY_BALANCED_POWER_ACCURACY}. + */ + public @NonNull Builder setQuality(@Quality int quality) { + Preconditions.checkArgument( + quality == QUALITY_LOW_POWER || quality == QUALITY_BALANCED_POWER_ACCURACY + || quality == QUALITY_HIGH_ACCURACY); + mQuality = quality; + return this; + } + + /** + * Sets the maximum time any location update may be delayed, and thus grouped with following + * updates to enable location batching. If the maximum update delay is equal to or greater + * than twice the interval, then location providers may provide batched results. Defaults to + * 0. + */ + public @NonNull Builder setMaxUpdateDelayMillis( + @IntRange(from = 0) long maxUpdateDelayMillis) { + mMaxUpdateDelayMillis = Preconditions.checkArgumentInRange(maxUpdateDelayMillis, 0, + Long.MAX_VALUE, "maxUpdateDelayMillis"); + return this; + } + + /** + * Sets whether hardware low power mode should be used. False by default. + */ + public @NonNull Builder setLowPower(boolean lowPower) { + mLowPower = lowPower; + return this; + } + + /** + * Sets whether location settings should be ignored. False by default. + */ + public @NonNull Builder setLocationSettingsIgnored(boolean locationSettingsIgnored) { + this.mLocationSettingsIgnored = locationSettingsIgnored; + return this; + } + + /** + * Sets the work source for power blame. Empty by default. + */ + public @NonNull Builder setWorkSource(@NonNull WorkSource workSource) { + mWorkSource = Objects.requireNonNull(workSource); + return this; + } + + /** + * Builds a ProviderRequest. + */ + public @NonNull ProviderRequest build() { + if (mIntervalMillis == INTERVAL_DISABLED) { + return EMPTY_REQUEST; + } else { + return new ProviderRequest( + mIntervalMillis, + mQuality, + mMaxUpdateDelayMillis, + mLowPower, + mLocationSettingsIgnored, + mWorkSource); + } + } + } +} diff --git a/location/java/com/android/internal/location/ILocationProvider.aidl b/location/java/com/android/internal/location/ILocationProvider.aidl deleted file mode 100644 index dac08ff77938..000000000000 --- a/location/java/com/android/internal/location/ILocationProvider.aidl +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.location; - -import android.os.Bundle; -import android.os.WorkSource; - -import com.android.internal.location.ILocationProviderManager; -import com.android.internal.location.ProviderRequest; - -/** - * Binder interface for services that implement location providers. Do not implement this directly, - * extend {@link LocationProviderBase} instead. - * @hide - */ -interface ILocationProvider { - - @UnsupportedAppUsage(maxTargetSdk = 30, publicAlternatives = "{@code Do not use}") - oneway void setLocationProviderManager(in ILocationProviderManager manager); - - @UnsupportedAppUsage(maxTargetSdk = 30, publicAlternatives = "{@code Do not use}") - oneway void setRequest(in ProviderRequest request, in WorkSource ws); - - oneway void flush(); - - @UnsupportedAppUsage(maxTargetSdk = 30, publicAlternatives = "{@code Do not use}") - oneway void sendExtraCommand(String command, in Bundle extras); -} diff --git a/location/java/com/android/internal/location/ILocationProviderManager.aidl b/location/java/com/android/internal/location/ILocationProviderManager.aidl deleted file mode 100644 index a5b22b2c07d3..000000000000 --- a/location/java/com/android/internal/location/ILocationProviderManager.aidl +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2009 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.internal.location; - -import android.location.LocationResult; -import android.location.ProviderProperties; - -/** - * Binder interface for manager of all location providers. - * @hide - */ -interface ILocationProviderManager { - void onInitialize(boolean allowed, in ProviderProperties properties, @nullable String packageName, @nullable String attributionTag); - void onSetAllowed(boolean allowed); - void onSetProperties(in ProviderProperties properties); - - void onReportLocation(in LocationResult locationResult); - void onFlushComplete(); -} diff --git a/location/java/com/android/internal/location/ProviderRequest.aidl b/location/java/com/android/internal/location/ProviderRequest.aidl deleted file mode 100644 index 4e1ea955c2e5..000000000000 --- a/location/java/com/android/internal/location/ProviderRequest.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2012 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.internal.location; - -parcelable ProviderRequest; diff --git a/location/java/com/android/internal/location/ProviderRequest.java b/location/java/com/android/internal/location/ProviderRequest.java deleted file mode 100644 index 545ea528826b..000000000000 --- a/location/java/com/android/internal/location/ProviderRequest.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (C) 2012 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.internal.location; - -import static android.location.LocationRequest.QUALITY_BALANCED_POWER_ACCURACY; -import static android.location.LocationRequest.QUALITY_HIGH_ACCURACY; -import static android.location.LocationRequest.QUALITY_LOW_POWER; - -import android.annotation.IntRange; -import android.annotation.NonNull; -import android.compat.annotation.UnsupportedAppUsage; -import android.location.LocationRequest; -import android.location.LocationRequest.Quality; -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; -import android.os.WorkSource; -import android.util.TimeUtils; - -import com.android.internal.util.Preconditions; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -/** - * Location provider request. - * @hide - */ -public final class ProviderRequest implements Parcelable { - - public static final long INTERVAL_DISABLED = Long.MAX_VALUE; - - public static final ProviderRequest EMPTY_REQUEST = new ProviderRequest( - INTERVAL_DISABLED, QUALITY_BALANCED_POWER_ACCURACY, 0, false, false, new WorkSource()); - - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@link " - + "ProviderRequest}") - public final boolean reportLocation; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@link " - + "ProviderRequest}") - public final long interval; - private final @Quality int mQuality; - private final long mMaxUpdateDelayMillis; - private final boolean mLowPower; - private final boolean mLocationSettingsIgnored; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@link " - + "ProviderRequest}") - public final List locationRequests; - private final WorkSource mWorkSource; - - private ProviderRequest( - long intervalMillis, - @Quality int quality, - long maxUpdateDelayMillis, - boolean lowPower, - boolean locationSettingsIgnored, - @NonNull WorkSource workSource) { - reportLocation = intervalMillis != INTERVAL_DISABLED; - interval = intervalMillis; - mQuality = quality; - mMaxUpdateDelayMillis = maxUpdateDelayMillis; - mLowPower = lowPower; - mLocationSettingsIgnored = locationSettingsIgnored; - if (intervalMillis != INTERVAL_DISABLED) { - locationRequests = Collections.singletonList(new LocationRequest.Builder(intervalMillis) - .setQuality(quality) - .setLowPower(lowPower) - .setLocationSettingsIgnored(locationSettingsIgnored) - .setWorkSource(workSource) - .build()); - } else { - locationRequests = Collections.emptyList(); - } - mWorkSource = Objects.requireNonNull(workSource); - } - - /** - * True if this is an active request with a valid location reporting interval, false if this - * request is inactive and does not require any locations to be reported. - */ - public boolean isActive() { - return interval != INTERVAL_DISABLED; - } - - /** - * The interval at which a provider should report location. Will return - * {@link #INTERVAL_DISABLED} for an inactive request. - */ - public @IntRange(from = 0) long getIntervalMillis() { - return interval; - } - - /** - * The quality hint for this location request. The quality hint informs the provider how it - * should attempt to manage any accuracy vs power tradeoffs while attempting to satisfy this - * provider request. - */ - public @Quality int getQuality() { - return mQuality; - } - - /** - * The maximum time any location update may be delayed, and thus grouped with following updates - * to enable location batching. If the maximum update delay is equal to or greater than - * twice the interval, then the provider may provide batched results if possible. The maximum - * batch size a provider is allowed to return is the maximum update delay divided by the - * interval. - */ - public @IntRange(from = 0) long getMaxUpdateDelayMillis() { - return mMaxUpdateDelayMillis; - } - - /** - * Whether any applicable hardware low power modes should be used to satisfy this request. - */ - public boolean isLowPower() { - return mLowPower; - } - - /** - * Whether the provider should ignore all location settings, user consents, power restrictions - * or any other restricting factors and always satisfy this request to the best of their - * ability. This should only be used in case of a user initiated emergency. - */ - public boolean isLocationSettingsIgnored() { - return mLocationSettingsIgnored; - } - - /** - * The power blame for this provider request. - */ - public @NonNull WorkSource getWorkSource() { - return mWorkSource; - } - - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public ProviderRequest createFromParcel(Parcel in) { - long intervalMillis = in.readLong(); - if (intervalMillis == INTERVAL_DISABLED) { - return EMPTY_REQUEST; - } else { - return new ProviderRequest( - intervalMillis, - /* quality= */ in.readInt(), - /* maxUpdateDelayMillis= */ in.readLong(), - /* lowPower= */ in.readBoolean(), - /* locationSettingsIgnored= */ in.readBoolean(), - /* workSource= */ in.readTypedObject(WorkSource.CREATOR)); - } - } - - @Override - public ProviderRequest[] newArray(int size) { - return new ProviderRequest[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel parcel, int flags) { - parcel.writeLong(interval); - if (interval != INTERVAL_DISABLED) { - parcel.writeInt(mQuality); - parcel.writeLong(mMaxUpdateDelayMillis); - parcel.writeBoolean(mLowPower); - parcel.writeBoolean(mLocationSettingsIgnored); - parcel.writeTypedObject(mWorkSource, flags); - } - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - ProviderRequest that = (ProviderRequest) o; - if (interval == INTERVAL_DISABLED) { - return that.interval == INTERVAL_DISABLED; - } else { - return interval == that.interval - && mQuality == that.mQuality - && mMaxUpdateDelayMillis == that.mMaxUpdateDelayMillis - && mLowPower == that.mLowPower - && mLocationSettingsIgnored == that.mLocationSettingsIgnored - && mWorkSource.equals(that.mWorkSource); - } - } - - @Override - public int hashCode() { - return Objects.hash(interval, mQuality, mWorkSource); - } - - @Override - public String toString() { - StringBuilder s = new StringBuilder(); - s.append("ProviderRequest["); - if (interval != INTERVAL_DISABLED) { - s.append("@"); - TimeUtils.formatDuration(interval, s); - if (mQuality != QUALITY_BALANCED_POWER_ACCURACY) { - if (mQuality == QUALITY_HIGH_ACCURACY) { - s.append(", HIGH_ACCURACY"); - } else if (mQuality == QUALITY_LOW_POWER) { - s.append(", LOW_POWER"); - } - } - if (mMaxUpdateDelayMillis / 2 > interval) { - s.append(", maxUpdateDelay="); - TimeUtils.formatDuration(mMaxUpdateDelayMillis, s); - } - if (mLowPower) { - s.append(", lowPower"); - } - if (mLocationSettingsIgnored) { - s.append(", locationSettingsIgnored"); - } - if (!mWorkSource.isEmpty()) { - s.append(", ").append(mWorkSource); - } - } else { - s.append("OFF"); - } - s.append(']'); - return s.toString(); - } - - /** - * A Builder for {@link ProviderRequest}s. - */ - public static class Builder { - private long mIntervalMillis = INTERVAL_DISABLED; - private int mQuality = QUALITY_BALANCED_POWER_ACCURACY; - private long mMaxUpdateDelayMillis = 0; - private boolean mLowPower; - private boolean mLocationSettingsIgnored; - private WorkSource mWorkSource = new WorkSource(); - - /** - * Sets the request interval. Use {@link #INTERVAL_DISABLED} for an inactive request. - * Defaults to {@link #INTERVAL_DISABLED}. - */ - public @NonNull Builder setIntervalMillis(@IntRange(from = 0) long intervalMillis) { - mIntervalMillis = Preconditions.checkArgumentInRange(intervalMillis, 0, Long.MAX_VALUE, - "intervalMillis"); - return this; - } - - /** - * Sets the request quality. The quality is a hint to providers on how they should weigh - * power vs accuracy tradeoffs. High accuracy locations may cost more power to produce, and - * lower accuracy locations may cost less power to produce. Defaults to - * {@link LocationRequest#QUALITY_BALANCED_POWER_ACCURACY}. - */ - public @NonNull Builder setQuality(@Quality int quality) { - Preconditions.checkArgument( - quality == QUALITY_LOW_POWER || quality == QUALITY_BALANCED_POWER_ACCURACY - || quality == QUALITY_HIGH_ACCURACY); - mQuality = quality; - return this; - } - - /** - * Sets the maximum time any location update may be delayed, and thus grouped with following - * updates to enable location batching. If the maximum update delay is equal to or greater - * than twice the interval, then location providers may provide batched results. Defaults to - * 0. - */ - public @NonNull Builder setMaxUpdateDelayMillis( - @IntRange(from = 0) long maxUpdateDelayMillis) { - mMaxUpdateDelayMillis = Preconditions.checkArgumentInRange(maxUpdateDelayMillis, 0, - Long.MAX_VALUE, "maxUpdateDelayMillis"); - return this; - } - - /** - * Sets whether hardware low power mode should be used. False by default. - */ - public @NonNull Builder setLowPower(boolean lowPower) { - mLowPower = lowPower; - return this; - } - - /** - * Sets whether location settings should be ignored. False by default. - */ - public @NonNull Builder setLocationSettingsIgnored(boolean locationSettingsIgnored) { - this.mLocationSettingsIgnored = locationSettingsIgnored; - return this; - } - - /** - * Sets the work source for power blame. Empty by default. - */ - public @NonNull Builder setWorkSource(@NonNull WorkSource workSource) { - mWorkSource = Objects.requireNonNull(workSource); - return this; - } - - /** - * Builds a ProviderRequest. - */ - public @NonNull ProviderRequest build() { - if (mIntervalMillis == INTERVAL_DISABLED) { - return EMPTY_REQUEST; - } else { - return new ProviderRequest( - mIntervalMillis, - mQuality, - mMaxUpdateDelayMillis, - mLowPower, - mLocationSettingsIgnored, - mWorkSource); - } - } - } -} -- cgit v1.2.3-59-g8ed1b