| /* |
| * 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, |
| false, |
| new WorkSource()); |
| |
| private final long mIntervalMillis; |
| private final @Quality int mQuality; |
| private final long mMaxUpdateDelayMillis; |
| private final boolean mLowPower; |
| private final boolean mAdasGnssBypass; |
| private final boolean mLocationSettingsIgnored; |
| private final WorkSource mWorkSource; |
| |
| /** |
| * Listener to be invoked when a new request is set to the provider. |
| */ |
| public interface ChangedListener { |
| |
| /** |
| * Invoked when a new request is set. |
| * |
| * @param provider the location provider associated with the request |
| * @param request the new {@link ProviderRequest} |
| */ |
| void onProviderRequestChanged(@NonNull String provider, @NonNull ProviderRequest request); |
| } |
| |
| private ProviderRequest( |
| long intervalMillis, |
| @Quality int quality, |
| long maxUpdateDelayMillis, |
| boolean lowPower, |
| boolean adasGnssBypass, |
| boolean locationSettingsIgnored, |
| @NonNull WorkSource workSource) { |
| mIntervalMillis = intervalMillis; |
| mQuality = quality; |
| mMaxUpdateDelayMillis = maxUpdateDelayMillis; |
| mLowPower = lowPower; |
| mAdasGnssBypass = adasGnssBypass; |
| 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; |
| } |
| |
| /** |
| * Returns true if this request may access GNSS even if location settings would normally deny |
| * this, in order to enable automotive safety features. This field is only respected on |
| * automotive devices, and only if the client is recognized as a legitimate ADAS (Advanced |
| * Driving Assistance Systems) application. |
| * |
| * @hide |
| */ |
| public boolean isAdasGnssBypass() { |
| return mAdasGnssBypass; |
| } |
| |
| /** |
| * 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; |
| } |
| |
| /** |
| * Returns true if any bypass flag is set on this request. |
| * |
| * @hide |
| */ |
| public boolean isBypass() { |
| return mAdasGnssBypass || mLocationSettingsIgnored; |
| } |
| |
| /** |
| * The power blame for this provider request. |
| */ |
| public @NonNull WorkSource getWorkSource() { |
| return mWorkSource; |
| } |
| |
| public static final @NonNull Creator<ProviderRequest> CREATOR = new Creator<ProviderRequest>() { |
| @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(), |
| /* adasGnssBypass= */ 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(mAdasGnssBypass); |
| 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 |
| && mAdasGnssBypass == that.mAdasGnssBypass |
| && 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 (mAdasGnssBypass) { |
| s.append(", adasGnssBypass"); |
| } |
| if (mLocationSettingsIgnored) { |
| s.append(", settingsBypass"); |
| } |
| 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 mAdasGnssBypass; |
| 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 this ADAS request should bypass GNSS settings. False by default. |
| * |
| * @hide |
| */ |
| public @NonNull Builder setAdasGnssBypass(boolean adasGnssBypass) { |
| this.mAdasGnssBypass = adasGnssBypass; |
| 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, |
| mAdasGnssBypass, |
| mLocationSettingsIgnored, |
| mWorkSource); |
| } |
| } |
| } |
| } |