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