1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.location;
18 
19 import android.Manifest;
20 import android.annotation.FlaggedApi;
21 import android.annotation.IntRange;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.RequiresPermission;
25 import android.annotation.SystemApi;
26 import android.location.flags.Flags;
27 import android.os.Parcel;
28 import android.os.Parcelable;
29 import android.os.WorkSource;
30 import android.util.TimeUtils;
31 
32 import com.android.internal.util.Preconditions;
33 
34 import java.util.Objects;
35 
36 /**
37  * This class contains extra parameters to pass in a GNSS measurement request.
38  */
39 public final class GnssMeasurementRequest implements Parcelable {
40     /**
41      * Represents a passive only request. Such a request will not trigger any active GNSS
42      * measurements or power usage itself, but may receive GNSS measurements generated in response
43      * to other requests.
44      *
45      * <p class="note">Note that on Android T, such a request will trigger one GNSS measurement.
46      * Another GNSS measurement will be triggered after {@link #PASSIVE_INTERVAL} and so on.
47      *
48      * @see GnssMeasurementRequest#getIntervalMillis()
49      */
50     public static final int PASSIVE_INTERVAL = Integer.MAX_VALUE;
51 
52     private final boolean mCorrelationVectorOutputsEnabled;
53     private final boolean mFullTracking;
54     private final int mIntervalMillis;
55     private WorkSource mWorkSource;
56     /**
57      * Creates a {@link GnssMeasurementRequest} with a full list of parameters.
58      */
GnssMeasurementRequest(boolean fullTracking, boolean correlationVectorOutputsEnabled, int intervalMillis, WorkSource workSource)59     private GnssMeasurementRequest(boolean fullTracking, boolean correlationVectorOutputsEnabled,
60             int intervalMillis, WorkSource workSource) {
61         mFullTracking = fullTracking;
62         mCorrelationVectorOutputsEnabled = correlationVectorOutputsEnabled;
63         mIntervalMillis = intervalMillis;
64         mWorkSource = Objects.requireNonNull(workSource);
65     }
66 
67     /**
68      * Represents whether to enable correlation vector outputs.
69      *
70      * <p>If true, enable correlation vectors as part of the raw GNSS measurements outputs.
71      * If false, disable correlation vectors.
72      *
73      * @hide
74      */
75     @SystemApi
isCorrelationVectorOutputsEnabled()76     public boolean isCorrelationVectorOutputsEnabled() {
77         return mCorrelationVectorOutputsEnabled;
78     }
79 
80     /**
81      * Represents whether to enable full GNSS tracking.
82      *
83      * <p>If true, GNSS chipset switches off duty cycling. In such a mode, no clock
84      * discontinuities are expected, and when supported, carrier phase should be continuous in
85      * good signal conditions. All non-blocklisted, healthy constellations, satellites and
86      * frequency bands that are meaningful to positioning accuracy must be tracked and reported in
87      * this mode. The GNSS chipset will consume more power in full tracking mode than in duty
88      * cycling mode. If false, GNSS chipset optimizes power via duty cycling, constellations and
89      * frequency limits, etc.
90      *
91      * <p>Full GNSS tracking mode affects GnssMeasurement and other GNSS functionalities
92      * including GNSS location.
93      */
isFullTracking()94     public boolean isFullTracking() {
95         return mFullTracking;
96     }
97 
98     /**
99      * Returns the requested time interval between the reported measurements in milliseconds, or
100      * {@link #PASSIVE_INTERVAL} if this is a passive, no power request. A passive request will not
101      * actively generate GNSS measurement updates, but may receive GNSS measurement updates
102      * generated as a result of other GNSS measurement requests.
103      *
104      * <p>If the time interval is not set, the default value is 0, which means the fastest rate the
105      * GNSS chipset can report.
106      *
107      * <p>The GNSS chipset may report measurements with a rate faster than requested.
108      *
109      * <p class="note">Note that on Android T, a request interval of {@link #PASSIVE_INTERVAL}
110      * will first trigger one GNSS measurement. Another GNSS measurement will be triggered after
111      * {@link #PASSIVE_INTERVAL} milliseconds ans so on.
112      */
getIntervalMillis()113     public @IntRange(from = 0) int getIntervalMillis() {
114         return mIntervalMillis;
115     }
116 
117     /**
118      * Returns the work source used for power blame for this request. If empty (i.e.,
119      * {@link WorkSource#isEmpty()} is {@code true}, the system is free to assign power blame as it
120      * deems most appropriate.
121      *
122      * @return the work source used for power blame for this request
123      *
124      * @hide
125      */
126     @FlaggedApi(Flags.FLAG_GNSS_API_MEASUREMENT_REQUEST_WORK_SOURCE)
127     @SystemApi
getWorkSource()128     public @NonNull WorkSource getWorkSource() {
129         return mWorkSource;
130     }
131 
132     @NonNull
133     public static final Creator<GnssMeasurementRequest> CREATOR =
134             new Creator<GnssMeasurementRequest>() {
135                 @Override
136                 @NonNull
137                 public GnssMeasurementRequest createFromParcel(@NonNull Parcel parcel) {
138                     return new GnssMeasurementRequest(
139                             /* fullTracking= */ parcel.readBoolean(),
140                             /* correlationVectorOutputsEnabled= */ parcel.readBoolean(),
141                             /* intervalMillis= */ parcel.readInt(),
142                             /* workSource= */ parcel.readTypedObject(WorkSource.CREATOR));
143                 }
144 
145                 @Override
146                 public GnssMeasurementRequest[] newArray(int i) {
147                     return new GnssMeasurementRequest[i];
148                 }
149             };
150 
151     @Override
writeToParcel(@onNull Parcel parcel, int flags)152     public void writeToParcel(@NonNull Parcel parcel, int flags) {
153         parcel.writeBoolean(mFullTracking);
154         parcel.writeBoolean(mCorrelationVectorOutputsEnabled);
155         parcel.writeInt(mIntervalMillis);
156         parcel.writeTypedObject(mWorkSource, 0);
157     }
158 
159     @NonNull
160     @Override
toString()161     public String toString() {
162         StringBuilder s = new StringBuilder();
163         s.append("GnssMeasurementRequest[");
164         if (mIntervalMillis == PASSIVE_INTERVAL) {
165             s.append("passive");
166         } else {
167             s.append("@");
168             TimeUtils.formatDuration(mIntervalMillis, s);
169         }
170         if (mFullTracking) {
171             s.append(", FullTracking");
172         }
173         if (mCorrelationVectorOutputsEnabled) {
174             s.append(", CorrelationVectorOutputs");
175         }
176         if (mWorkSource != null && !mWorkSource.isEmpty()) {
177             s.append(", ").append(mWorkSource);
178         }
179         s.append(']');
180         return s.toString();
181     }
182 
183     @Override
equals(Object obj)184     public boolean equals(Object obj) {
185         if (this == obj) return true;
186         if (obj == null) return false;
187         if (!(obj instanceof GnssMeasurementRequest)) return false;
188 
189         GnssMeasurementRequest other = (GnssMeasurementRequest) obj;
190         if (mFullTracking != other.mFullTracking) return false;
191         if (mCorrelationVectorOutputsEnabled != other.mCorrelationVectorOutputsEnabled) {
192             return false;
193         }
194         if (mIntervalMillis != other.mIntervalMillis) {
195             return false;
196         }
197         if (!Objects.equals(mWorkSource, other.mWorkSource)) {
198             return false;
199         }
200         return true;
201     }
202 
203     @Override
hashCode()204     public int hashCode() {
205         return Objects.hash(mFullTracking, mCorrelationVectorOutputsEnabled, mIntervalMillis,
206                 mWorkSource);
207     }
208 
209     @Override
describeContents()210     public int describeContents() {
211         return 0;
212     }
213 
214     /** Builder for {@link GnssMeasurementRequest} */
215     public static final class Builder {
216         private boolean mCorrelationVectorOutputsEnabled;
217         private boolean mFullTracking;
218         private int mIntervalMillis;
219         private WorkSource mWorkSource;
220 
221         /**
222          * Constructs a {@link Builder} instance.
223          */
Builder()224         public Builder() {
225         }
226 
227         /**
228          * Constructs a {@link Builder} instance by copying a {@link GnssMeasurementRequest}.
229          */
Builder(@onNull GnssMeasurementRequest request)230         public Builder(@NonNull GnssMeasurementRequest request) {
231             mCorrelationVectorOutputsEnabled = request.isCorrelationVectorOutputsEnabled();
232             mFullTracking = request.isFullTracking();
233             mIntervalMillis = request.getIntervalMillis();
234             mWorkSource = request.getWorkSource();
235         }
236 
237         /**
238          * Set the value of whether to enable correlation vector outputs, which is false by default.
239          *
240          * <p>If true, enable correlation vectors as part of the raw GNSS measurements outputs.
241          * If false, disable correlation vectors.
242          *
243          * @hide
244          */
245         @SystemApi
setCorrelationVectorOutputsEnabled(boolean value)246         @NonNull public Builder setCorrelationVectorOutputsEnabled(boolean value) {
247             mCorrelationVectorOutputsEnabled = value;
248             return this;
249         }
250 
251         /**
252          * Set the value of whether to enable full GNSS tracking, which is false by default.
253          *
254          * <p>If true, GNSS chipset switches off duty cycling. In such a mode, no clock
255          * discontinuities are expected, and when supported, carrier phase should be continuous in
256          * good signal conditions. All non-blocklisted, healthy constellations, satellites and
257          * frequency bands that the chipset supports must be reported in this mode. The GNSS chipset
258          * will consume more power in full tracking mode than in duty cycling mode. If false,
259          * GNSS chipset optimizes power via duty cycling, constellations and frequency limits, etc.
260          *
261          * <p>Full GNSS tracking mode affects GnssMeasurement and other GNSS functionalities
262          * including GNSS location.
263          *
264          * <p>Full tracking requests always override non-full tracking requests. If any full
265          * tracking request occurs, all listeners on the device will receive full tracking GNSS
266          * measurements.
267          */
setFullTracking(boolean value)268         @NonNull public Builder setFullTracking(boolean value) {
269             mFullTracking = value;
270             return this;
271         }
272 
273         /**
274          * Set the time interval between the reported measurements in milliseconds, which is 0 by
275          * default. The request interval may be set to {@link #PASSIVE_INTERVAL} which indicates
276          * this request will not actively generate GNSS measurement updates, but may receive
277          * GNSS measurement updates generated as a result of other GNSS measurement requests.
278          *
279          * <p>An interval of 0 milliseconds means the fastest rate the chipset can report.
280          *
281          * <p>The GNSS chipset may report measurements with a rate faster than requested.
282          *
283          * <p class="note">Note that on Android T, a request interval of {@link #PASSIVE_INTERVAL}
284          * will first trigger one GNSS measurement. Another GNSS measurement will be triggered after
285          * {@link #PASSIVE_INTERVAL} milliseconds and so on.
286          */
setIntervalMillis(@ntRangefrom = 0) int value)287         @NonNull public Builder setIntervalMillis(@IntRange(from = 0) int value) {
288             mIntervalMillis = Preconditions.checkArgumentInRange(value, 0, Integer.MAX_VALUE,
289                     "intervalMillis");
290             return this;
291         }
292 
293         /**
294          * Sets the work source to use for power blame for this request. Passing in null or leaving
295          * it unset will be an empty WorkSource, which implies the system is free to assign power
296          * blame as it determines best for this request (which usually means blaming the owner of
297          * the GnssMeasurement listener).
298          *
299          * <p>Permissions enforcement occurs when resulting request is actually used, not when this
300          * method is invoked.
301          *
302          * @hide
303          */
304         @FlaggedApi(Flags.FLAG_GNSS_API_MEASUREMENT_REQUEST_WORK_SOURCE)
305         @SystemApi
306         @RequiresPermission(Manifest.permission.UPDATE_DEVICE_STATS)
setWorkSource(@ullable WorkSource workSource)307         public @NonNull Builder setWorkSource(@Nullable WorkSource workSource) {
308             mWorkSource = workSource;
309             return this;
310         }
311 
312         /** Builds a {@link GnssMeasurementRequest} instance as specified by this builder. */
313         @NonNull
build()314         public GnssMeasurementRequest build() {
315             return new GnssMeasurementRequest(mFullTracking, mCorrelationVectorOutputsEnabled,
316                     mIntervalMillis, new WorkSource(mWorkSource));
317         }
318     }
319 }
320