LocationRequest.java revision 6fa9ad4afcd762aea519ff61811386c23d18ddb2
1/*
2 * Copyright (C) 2012 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
17package android.location;
18
19import android.os.Parcel;
20import android.os.Parcelable;
21import android.os.SystemClock;
22import android.util.TimeUtils;
23
24public final class LocationRequest implements Parcelable {
25    // QOS control
26    public static final int ACCURACY_FINE = 100;  // ~1 meter
27    public static final int ACCURACY_BLOCK = 102; // ~100 meters
28    public static final int ACCURACY_CITY = 104;  // ~10 km
29    public static final int POWER_NONE = 200;
30    public static final int POWER_LOW = 201;
31    public static final int POWER_HIGH = 203;
32
33    private int mQuality = POWER_LOW;
34    private long mFastestInterval = 6 * 1000;  // 6 seconds
35    private long mInterval = 60 * 1000;        // 1 minute
36    private long mExpireAt = Long.MAX_VALUE;  // no expiry
37    private int mNumUpdates = Integer.MAX_VALUE;  // no expiry
38    private float mSmallestDisplacement = 0.0f;    // meters
39
40    private String mProvider = null;  // for deprecated API's that explicitly request a provider
41
42    public static LocationRequest create() {
43        LocationRequest request = new LocationRequest();
44        return request;
45    }
46
47    /** @hide */
48    public static LocationRequest createFromDeprecatedProvider(String provider, long minTime,
49            float minDistance, boolean singleShot) {
50        if (minTime < 0) minTime = 0;
51        if (minDistance < 0) minDistance = 0;
52
53        int quality;
54        if (LocationManager.PASSIVE_PROVIDER.equals(provider)) {
55            quality = POWER_NONE;
56        } else if (LocationManager.GPS_PROVIDER.equals(provider)) {
57            quality = ACCURACY_FINE;
58        } else {
59            quality = POWER_LOW;
60        }
61
62        LocationRequest request = new LocationRequest()
63            .setProvider(provider)
64            .setQuality(quality)
65            .setInterval(minTime)
66            .setFastestInterval(minTime)
67            .setSmallestDisplacement(minDistance);
68        if (singleShot) request.setNumUpdates(1);
69        return request;
70    }
71
72    /** @hide */
73    public static LocationRequest createFromDeprecatedCriteria(Criteria criteria, long minTime,
74            float minDistance, boolean singleShot) {
75        if (minTime < 0) minTime = 0;
76        if (minDistance < 0) minDistance = 0;
77
78        int quality;
79        switch (criteria.getAccuracy()) {
80            case Criteria.ACCURACY_COARSE:
81                quality = ACCURACY_BLOCK;
82                break;
83            case Criteria.ACCURACY_FINE:
84                quality = ACCURACY_FINE;
85                break;
86            default: {
87                switch (criteria.getPowerRequirement()) {
88                    case Criteria.POWER_HIGH:
89                        quality = POWER_HIGH;
90                    default:
91                        quality = POWER_LOW;
92                }
93            }
94        }
95
96        LocationRequest request = new LocationRequest()
97            .setQuality(quality)
98            .setInterval(minTime)
99            .setFastestInterval(minTime)
100            .setSmallestDisplacement(minDistance);
101        if (singleShot) request.setNumUpdates(1);
102        return request;
103    }
104
105    /** @hide */
106    public LocationRequest() { }
107
108    public LocationRequest setQuality(int quality) {
109        checkQuality(quality);
110        mQuality = quality;
111        return this;
112    }
113
114    public int getQuality() {
115        return mQuality;
116    }
117
118    public LocationRequest setInterval(long millis) {
119        checkInterval(millis);
120        mInterval = millis;
121        return this;
122    }
123
124    public long getInterval() {
125        return mInterval;
126    }
127
128    public LocationRequest setFastestInterval(long millis) {
129        checkInterval(millis);
130        mFastestInterval = millis;
131        return this;
132    }
133
134    public long getFastestInterval() {
135        return mFastestInterval;
136    }
137
138    public LocationRequest setExpireIn(long millis) {
139        mExpireAt = millis + SystemClock.elapsedRealtime();
140        if (mExpireAt < 0) mExpireAt = 0;
141        return this;
142    }
143
144    public LocationRequest setExpireAt(long millis) {
145        mExpireAt = millis;
146        if (mExpireAt < 0) mExpireAt = 0;
147        return this;
148    }
149
150    public long getExpireAt() {
151        return mExpireAt;
152    }
153
154    public int getNumUpdates() {
155        return mNumUpdates;
156    }
157
158    /** @hide */
159    public void decrementNumUpdates() {
160        if (mNumUpdates != Integer.MAX_VALUE) {
161            mNumUpdates--;
162        }
163        if (mNumUpdates < 0) {
164            mNumUpdates = 0;
165        }
166    }
167
168    public LocationRequest setNumUpdates(int numUpdates) {
169        if (numUpdates < 0) throw new IllegalArgumentException("invalid numUpdates: " + numUpdates);
170        mNumUpdates = numUpdates;
171        return this;
172    }
173
174    /** @hide */
175    public LocationRequest setProvider(String provider) {
176        checkProvider(provider);
177        mProvider = provider;
178        return this;
179    }
180
181    /** @hide */
182    public String getProvider() {
183        return mProvider;
184    }
185
186    /** @hide */
187    public LocationRequest setSmallestDisplacement(float meters) {
188        checkDisplacement(meters);
189        mSmallestDisplacement = meters;
190        return this;
191    }
192
193    /** @hide */
194    public float getSmallestDisplacement() {
195        return mSmallestDisplacement;
196    }
197
198    /** @hide */
199    public LocationRequest applyCoarsePermissionRestrictions() {
200        switch (mQuality) {
201            case ACCURACY_FINE:
202                mQuality = ACCURACY_BLOCK;
203                break;
204        }
205        // cap fastest interval to 6 seconds
206        if (mFastestInterval < 6 * 1000) mFastestInterval = 6 * 1000;
207        // cap requested interval to 1 minute
208        if (mInterval < 60 * 1000) mInterval = 60 * 1000;
209        return this;
210    }
211
212    private static void checkInterval(long millis) {
213        if (millis < 0) {
214            throw new IllegalArgumentException("invalid interval: " + millis);
215        }
216    }
217
218    private static void checkQuality(int quality) {
219        switch (quality) {
220            case ACCURACY_FINE:
221            case ACCURACY_BLOCK:
222            case ACCURACY_CITY:
223            case POWER_NONE:
224            case POWER_LOW:
225            case POWER_HIGH:
226                break;
227            default:
228                throw new IllegalArgumentException("invalid quality: " + quality);
229        }
230    }
231
232    private static void checkDisplacement(float meters) {
233        if (meters < 0.0f) {
234            throw new IllegalArgumentException("invalid displacement: " + meters);
235        }
236    }
237
238    private static void checkProvider(String name) {
239        if (name == null) {
240            throw new IllegalArgumentException("invalid provider: " + name);
241        }
242    }
243
244    public static final Parcelable.Creator<LocationRequest> CREATOR =
245            new Parcelable.Creator<LocationRequest>() {
246        @Override
247        public LocationRequest createFromParcel(Parcel in) {
248            LocationRequest request = new LocationRequest();
249            request.setQuality(in.readInt());
250            request.setFastestInterval(in.readLong());
251            request.setInterval(in.readLong());
252            request.setExpireAt(in.readLong());
253            request.setNumUpdates(in.readInt());
254            request.setSmallestDisplacement(in.readFloat());
255            String provider = in.readString();
256            if (provider != null) request.setProvider(provider);
257            return request;
258        }
259        @Override
260        public LocationRequest[] newArray(int size) {
261            return new LocationRequest[size];
262        }
263    };
264    @Override
265    public int describeContents() {
266        return 0;
267    }
268    @Override
269    public void writeToParcel(Parcel parcel, int flags) {
270        parcel.writeInt(mQuality);
271        parcel.writeLong(mFastestInterval);
272        parcel.writeLong(mInterval);
273        parcel.writeLong(mExpireAt);
274        parcel.writeInt(mNumUpdates);
275        parcel.writeFloat(mSmallestDisplacement);
276        parcel.writeString(mProvider);
277    }
278
279    /** @hide */
280    public static String qualityToString(int quality) {
281        switch (quality) {
282            case ACCURACY_FINE:
283                return "ACCURACY_FINE";
284            case ACCURACY_BLOCK:
285                return "ACCURACY_BLOCK";
286            case ACCURACY_CITY:
287                return "ACCURACY_CITY";
288            case POWER_NONE:
289                return "POWER_NONE";
290            case POWER_LOW:
291                return "POWER_LOW";
292            case POWER_HIGH:
293                return "POWER_HIGH";
294            default:
295                return "???";
296        }
297    }
298
299    @Override
300    public String toString() {
301        StringBuilder s = new StringBuilder();
302        s.append("Request[").append(qualityToString(mQuality));
303        if (mProvider != null) s.append(' ').append(mProvider);
304        if (mQuality != POWER_NONE) {
305            s.append(" requested=");
306            TimeUtils.formatDuration(mInterval, s);
307        }
308        s.append(" fastest=");
309        TimeUtils.formatDuration(mFastestInterval, s);
310        if (mExpireAt != Long.MAX_VALUE) {
311            long expireIn = mExpireAt - SystemClock.elapsedRealtime();
312            s.append(" expireIn=");
313            TimeUtils.formatDuration(expireIn, s);
314        }
315        if (mNumUpdates != Integer.MAX_VALUE){
316            s.append(" num=").append(mNumUpdates);
317        }
318        s.append(']');
319        return s.toString();
320    }
321}
322