• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.nearby;
18 
19 import android.Manifest;
20 import android.annotation.IntDef;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.RequiresPermission;
24 import android.annotation.SystemApi;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 import android.os.WorkSource;
28 
29 import com.android.internal.util.Preconditions;
30 
31 import java.lang.annotation.Retention;
32 import java.lang.annotation.RetentionPolicy;
33 import java.util.ArrayList;
34 import java.util.List;
35 import java.util.Objects;
36 
37 /**
38  * An encapsulation of various parameters for requesting nearby scans.
39  *
40  * @hide
41  */
42 @SystemApi
43 public final class ScanRequest implements Parcelable {
44 
45     /** Scan type for scanning devices using fast pair protocol. */
46     public static final int SCAN_TYPE_FAST_PAIR = 1;
47     /** Scan type for scanning devices using nearby presence protocol. */
48     public static final int SCAN_TYPE_NEARBY_PRESENCE = 2;
49 
50     /** Scan mode uses highest duty cycle. */
51     public static final int SCAN_MODE_LOW_LATENCY = 2;
52     /** Scan in balanced power mode.
53      *  Scan results are returned at a rate that provides a good trade-off between scan
54      *  frequency and power consumption.
55      */
56     public static final int SCAN_MODE_BALANCED = 1;
57     /** Perform scan in low power mode. This is the default scan mode. */
58     public static final int SCAN_MODE_LOW_POWER = 0;
59     /**
60      * A special scan mode. Applications using this scan mode will passively listen for other scan
61      * results without starting BLE scans themselves.
62      */
63     public static final int SCAN_MODE_NO_POWER = -1;
64     /**
65      * Used to read a ScanRequest from a Parcel.
66      */
67     @NonNull
68     public static final Creator<ScanRequest> CREATOR = new Creator<ScanRequest>() {
69         @Override
70         public ScanRequest createFromParcel(Parcel in) {
71             ScanRequest.Builder builder = new ScanRequest.Builder()
72                     .setScanType(in.readInt())
73                     .setScanMode(in.readInt())
74                     .setBleEnabled(in.readBoolean())
75                     .setWorkSource(in.readTypedObject(WorkSource.CREATOR));
76             final int size = in.readInt();
77             for (int i = 0; i < size; i++) {
78                 builder.addScanFilter(ScanFilter.createFromParcel(in));
79             }
80             return builder.build();
81         }
82 
83         @Override
84         public ScanRequest[] newArray(int size) {
85             return new ScanRequest[size];
86         }
87     };
88 
89     private final @ScanType int mScanType;
90     private final @ScanMode int mScanMode;
91     private final boolean mBleEnabled;
92     private final @NonNull WorkSource mWorkSource;
93     private final List<ScanFilter> mScanFilters;
94 
ScanRequest(@canType int scanType, @ScanMode int scanMode, boolean bleEnabled, @NonNull WorkSource workSource, List<ScanFilter> scanFilters)95     private ScanRequest(@ScanType int scanType, @ScanMode int scanMode, boolean bleEnabled,
96             @NonNull WorkSource workSource, List<ScanFilter> scanFilters) {
97         mScanType = scanType;
98         mScanMode = scanMode;
99         mBleEnabled = bleEnabled;
100         mWorkSource = workSource;
101         mScanFilters = scanFilters;
102     }
103 
104     /**
105      * Convert scan mode to readable string.
106      *
107      * @param scanMode Integer that may represent a{@link ScanMode}.
108      */
109     @NonNull
scanModeToString(@canMode int scanMode)110     public static String scanModeToString(@ScanMode int scanMode) {
111         switch (scanMode) {
112             case SCAN_MODE_LOW_LATENCY:
113                 return "SCAN_MODE_LOW_LATENCY";
114             case SCAN_MODE_BALANCED:
115                 return "SCAN_MODE_BALANCED";
116             case SCAN_MODE_LOW_POWER:
117                 return "SCAN_MODE_LOW_POWER";
118             case SCAN_MODE_NO_POWER:
119                 return "SCAN_MODE_NO_POWER";
120             default:
121                 return "SCAN_MODE_INVALID";
122         }
123     }
124 
125     /**
126      * Returns true if an integer is a defined scan type.
127      */
isValidScanType(@canType int scanType)128     public static boolean isValidScanType(@ScanType int scanType) {
129         return scanType == SCAN_TYPE_FAST_PAIR
130                 || scanType == SCAN_TYPE_NEARBY_PRESENCE;
131     }
132 
133     /**
134      * Returns true if an integer is a defined scan mode.
135      */
isValidScanMode(@canMode int scanMode)136     public static boolean isValidScanMode(@ScanMode int scanMode) {
137         return scanMode == SCAN_MODE_LOW_LATENCY
138                 || scanMode == SCAN_MODE_BALANCED
139                 || scanMode == SCAN_MODE_LOW_POWER
140                 || scanMode == SCAN_MODE_NO_POWER;
141     }
142 
143     /**
144      * Returns the scan type for this request.
145      */
getScanType()146     public @ScanType int getScanType() {
147         return mScanType;
148     }
149 
150     /**
151      * Returns the scan mode for this request.
152      */
getScanMode()153     public @ScanMode int getScanMode() {
154         return mScanMode;
155     }
156 
157     /**
158      * Returns if Bluetooth Low Energy enabled for scanning.
159      */
isBleEnabled()160     public boolean isBleEnabled() {
161         return mBleEnabled;
162     }
163 
164     /**
165      * Returns Scan Filters for this request.
166      */
167     @NonNull
getScanFilters()168     public List<ScanFilter> getScanFilters() {
169         return mScanFilters;
170     }
171 
172     /**
173      * Returns the work source used for power attribution of this request.
174      *
175      * @hide
176      */
177     @SystemApi
178     @NonNull
getWorkSource()179     public WorkSource getWorkSource() {
180         return mWorkSource;
181     }
182 
183     /**
184      * No special parcel contents.
185      */
186     @Override
describeContents()187     public int describeContents() {
188         return 0;
189     }
190 
191     /**
192      * Returns a string representation of this ScanRequest.
193      */
194     @Override
toString()195     public String toString() {
196         StringBuilder stringBuilder = new StringBuilder();
197         stringBuilder.append("Request[")
198                 .append("scanType=").append(mScanType);
199         stringBuilder.append(", scanMode=").append(scanModeToString(mScanMode));
200         stringBuilder.append(", enableBle=").append(mBleEnabled);
201         stringBuilder.append(", workSource=").append(mWorkSource);
202         stringBuilder.append(", scanFilters=").append(mScanFilters);
203         stringBuilder.append("]");
204         return stringBuilder.toString();
205     }
206 
207     @Override
writeToParcel(@onNull Parcel dest, int flags)208     public void writeToParcel(@NonNull Parcel dest, int flags) {
209         dest.writeInt(mScanType);
210         dest.writeInt(mScanMode);
211         dest.writeBoolean(mBleEnabled);
212         dest.writeTypedObject(mWorkSource, /* parcelableFlags= */0);
213         final int size = mScanFilters.size();
214         dest.writeInt(size);
215         for (int i = 0; i < size; i++) {
216             mScanFilters.get(i).writeToParcel(dest, flags);
217         }
218     }
219 
220     @Override
equals(Object other)221     public boolean equals(Object other) {
222         if (other instanceof ScanRequest) {
223             ScanRequest otherRequest = (ScanRequest) other;
224             return mScanType == otherRequest.mScanType
225                     && (mScanMode == otherRequest.mScanMode)
226                     && (mBleEnabled == otherRequest.mBleEnabled)
227                     && (Objects.equals(mWorkSource, otherRequest.mWorkSource));
228         }
229         return false;
230     }
231 
232     @Override
hashCode()233     public int hashCode() {
234         return Objects.hash(mScanType, mScanMode, mBleEnabled, mWorkSource);
235     }
236 
237     /** @hide **/
238     @Retention(RetentionPolicy.SOURCE)
239     @IntDef({SCAN_TYPE_FAST_PAIR, SCAN_TYPE_NEARBY_PRESENCE})
240     public @interface ScanType {
241     }
242 
243     /** @hide **/
244     @Retention(RetentionPolicy.SOURCE)
245     @IntDef({SCAN_MODE_LOW_LATENCY, SCAN_MODE_BALANCED,
246             SCAN_MODE_LOW_POWER,
247             SCAN_MODE_NO_POWER})
248     public @interface ScanMode {}
249 
250     /** A builder class for {@link ScanRequest}. */
251     public static final class Builder {
252         private static final int INVALID_SCAN_TYPE = -1;
253         private @ScanType int mScanType;
254         private @ScanMode int mScanMode;
255 
256         private boolean mBleEnabled;
257         private WorkSource mWorkSource;
258         private List<ScanFilter> mScanFilters;
259 
260         /** Creates a new Builder with the given scan type. */
Builder()261         public Builder() {
262             mScanType = INVALID_SCAN_TYPE;
263             mBleEnabled = true;
264             mWorkSource = new WorkSource();
265             mScanFilters = new ArrayList<>();
266         }
267 
268         /**
269          * Sets the scan type for the request. The scan type must be one of the SCAN_TYPE_ constants
270          * in {@link ScanRequest}.
271          *
272          * @param scanType The scan type for the request
273          */
274         @NonNull
setScanType(@canType int scanType)275         public Builder setScanType(@ScanType int scanType) {
276             mScanType = scanType;
277             return this;
278         }
279 
280         /**
281          * Sets the scan mode for the request. The scan type must be one of the SCAN_MODE_ constants
282          * in {@link ScanRequest}.
283          *
284          * @param scanMode The scan mode for the request
285          */
286         @NonNull
setScanMode(@canMode int scanMode)287         public Builder setScanMode(@ScanMode int scanMode) {
288             mScanMode = scanMode;
289             return this;
290         }
291 
292         /**
293          * Sets if the ble is enabled for scanning.
294          *
295          * @param bleEnabled If the BluetoothLe is enabled in the device.
296          */
297         @NonNull
setBleEnabled(boolean bleEnabled)298         public Builder setBleEnabled(boolean bleEnabled) {
299             mBleEnabled = bleEnabled;
300             return this;
301         }
302 
303         /**
304          * Sets the work source to use for power attribution for this scan request. Defaults to
305          * empty work source, which implies the caller that sends the scan request will be used
306          * for power attribution.
307          *
308          * <p>Permission enforcement occurs when the resulting scan request is used, not when
309          * this method is invoked.
310          *
311          * @param workSource identifying the application(s) for which to blame for the scan.
312          * @hide
313          */
314         @RequiresPermission(Manifest.permission.UPDATE_DEVICE_STATS)
315         @NonNull
316         @SystemApi
setWorkSource(@ullable WorkSource workSource)317         public Builder setWorkSource(@Nullable WorkSource workSource) {
318             if (workSource == null) {
319                 mWorkSource = new WorkSource();
320             } else {
321                 mWorkSource = workSource;
322             }
323             return this;
324         }
325 
326         /**
327          * Adds a scan filter to the request. Client can call this method multiple times to add
328          * more than one scan filter. Scan results that match any of these scan filters will
329          * be returned.
330          *
331          * <p>On devices with hardware support, scan filters can significantly improve the battery
332          * usage of Nearby scans.
333          *
334          * @param scanFilter Filter for scanning the request.
335          */
336         @NonNull
addScanFilter(@onNull ScanFilter scanFilter)337         public Builder addScanFilter(@NonNull ScanFilter scanFilter) {
338             Objects.requireNonNull(scanFilter);
339             mScanFilters.add(scanFilter);
340             return this;
341         }
342 
343         /**
344          * Builds a scan request from this builder.
345          *
346          * @return a new nearby scan request.
347          * @throws IllegalStateException if the scanType is not one of the SCAN_TYPE_ constants in
348          *                               {@link ScanRequest}.
349          */
350         @NonNull
build()351         public ScanRequest build() {
352             Preconditions.checkState(isValidScanType(mScanType),
353                     "invalid scan type : " + mScanType
354                             + ", scan type must be one of ScanRequest#SCAN_TYPE_");
355             Preconditions.checkState(isValidScanMode(mScanMode),
356                     "invalid scan mode : " + mScanMode
357                             + ", scan mode must be one of ScanMode#SCAN_MODE_");
358             return new ScanRequest(mScanType, mScanMode, mBleEnabled, mWorkSource, mScanFilters);
359         }
360     }
361 }
362