• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.bluetooth.le;
18 
19 import static android.bluetooth.le.BluetoothLeUtils.getSyncTimeout;
20 
21 import android.annotation.RequiresNoPermission;
22 import android.annotation.RequiresPermission;
23 import android.annotation.SystemApi;
24 import android.bluetooth.BluetoothAdapter;
25 import android.bluetooth.IBluetoothGatt;
26 import android.bluetooth.IBluetoothManager;
27 import android.bluetooth.annotations.RequiresBluetoothAdvertisePermission;
28 import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
29 import android.content.AttributionSource;
30 import android.os.RemoteException;
31 import android.util.Log;
32 
33 import com.android.modules.utils.SynchronousResultReceiver;
34 
35 import java.util.concurrent.TimeoutException;
36 
37 /**
38  * This class provides a way to control single Bluetooth LE advertising instance.
39  * <p>
40  * To get an instance of {@link AdvertisingSet}, call the
41  * {@link BluetoothLeAdvertiser#startAdvertisingSet} method.
42  *
43  * @see AdvertiseData
44  */
45 public final class AdvertisingSet {
46     private static final String TAG = "AdvertisingSet";
47 
48     private final IBluetoothGatt mGatt;
49     private int mAdvertiserId;
50     private AttributionSource mAttributionSource;
51 
AdvertisingSet(int advertiserId, IBluetoothManager bluetoothManager, AttributionSource attributionSource)52     /* package */ AdvertisingSet(int advertiserId, IBluetoothManager bluetoothManager,
53             AttributionSource attributionSource) {
54         mAdvertiserId = advertiserId;
55         mAttributionSource = attributionSource;
56         try {
57             mGatt = bluetoothManager.getBluetoothGatt();
58         } catch (RemoteException e) {
59             Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
60             throw new IllegalStateException("Failed to get Bluetooth");
61         }
62     }
63 
setAdvertiserId(int advertiserId)64     /* package */ void setAdvertiserId(int advertiserId) {
65         mAdvertiserId = advertiserId;
66     }
67 
68     /**
69      * Enables Advertising. This method returns immediately, the operation status is
70      * delivered through {@code callback.onAdvertisingEnabled()}.
71      *
72      * @param enable whether the advertising should be enabled (true), or disabled (false)
73      * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to 65535
74      * (655,350 ms)
75      * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the
76      * controller shall attempt to send prior to terminating the extended advertising, even if the
77      * duration has not expired. Valid range is from 1 to 255.
78      */
79     @RequiresLegacyBluetoothAdminPermission
80     @RequiresBluetoothAdvertisePermission
81     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
enableAdvertising(boolean enable, int duration, int maxExtendedAdvertisingEvents)82     public void enableAdvertising(boolean enable, int duration,
83             int maxExtendedAdvertisingEvents) {
84         try {
85             final SynchronousResultReceiver recv = SynchronousResultReceiver.get();
86             mGatt.enableAdvertisingSet(mAdvertiserId, enable, duration,
87                     maxExtendedAdvertisingEvents, mAttributionSource, recv);
88             recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
89         } catch (TimeoutException | RemoteException e) {
90             Log.e(TAG, "remote exception - ", e);
91         }
92     }
93 
94     /**
95      * Set/update data being Advertised. Make sure that data doesn't exceed the size limit for
96      * specified AdvertisingSetParameters. This method returns immediately, the operation status is
97      * delivered through {@code callback.onAdvertisingDataSet()}.
98      * <p>
99      * Advertising data must be empty if non-legacy scannable advertising is used.
100      *
101      * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link
102      * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable,
103      * three bytes will be added for flags. If the update takes place when the advertising set is
104      * enabled, the data can be maximum 251 bytes long.
105      */
106     @RequiresLegacyBluetoothAdminPermission
107     @RequiresBluetoothAdvertisePermission
108     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
setAdvertisingData(AdvertiseData advertiseData)109     public void setAdvertisingData(AdvertiseData advertiseData) {
110         try {
111             final SynchronousResultReceiver recv = SynchronousResultReceiver.get();
112             mGatt.setAdvertisingData(mAdvertiserId, advertiseData, mAttributionSource, recv);
113             recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
114         } catch (TimeoutException | RemoteException e) {
115             Log.e(TAG, "remote exception - ", e);
116         }
117     }
118 
119     /**
120      * Set/update scan response data. Make sure that data doesn't exceed the size limit for
121      * specified AdvertisingSetParameters. This method returns immediately, the operation status
122      * is delivered through {@code callback.onScanResponseDataSet()}.
123      *
124      * @param scanResponse Scan response associated with the advertisement data. Size must not
125      * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the update takes place
126      * when the advertising set is enabled, the data can be maximum 251 bytes long.
127      */
128     @RequiresLegacyBluetoothAdminPermission
129     @RequiresBluetoothAdvertisePermission
130     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
setScanResponseData(AdvertiseData scanResponse)131     public void setScanResponseData(AdvertiseData scanResponse) {
132         try {
133             final SynchronousResultReceiver recv = SynchronousResultReceiver.get();
134             mGatt.setScanResponseData(mAdvertiserId, scanResponse, mAttributionSource, recv);
135             recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
136         } catch (TimeoutException | RemoteException e) {
137             Log.e(TAG, "remote exception - ", e);
138         }
139     }
140 
141     /**
142      * Update advertising parameters associated with this AdvertisingSet. Must be called when
143      * advertising is not active. This method returns immediately, the operation status is delivered
144      * through {@code callback.onAdvertisingParametersUpdated}.
145      *
146      * @param parameters advertising set parameters.
147      */
148     @RequiresLegacyBluetoothAdminPermission
149     @RequiresBluetoothAdvertisePermission
150     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
setAdvertisingParameters(AdvertisingSetParameters parameters)151     public void setAdvertisingParameters(AdvertisingSetParameters parameters) {
152         try {
153             final SynchronousResultReceiver recv = SynchronousResultReceiver.get();
154             mGatt.setAdvertisingParameters(mAdvertiserId, parameters, mAttributionSource, recv);
155             recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
156         } catch (TimeoutException | RemoteException e) {
157             Log.e(TAG, "remote exception - ", e);
158         }
159     }
160 
161     /**
162      * Update periodic advertising parameters associated with this set. Must be called when
163      * periodic advertising is not enabled. This method returns immediately, the operation
164      * status is delivered through {@code callback.onPeriodicAdvertisingParametersUpdated()}.
165      */
166     @RequiresLegacyBluetoothAdminPermission
167     @RequiresBluetoothAdvertisePermission
168     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
setPeriodicAdvertisingParameters(PeriodicAdvertisingParameters parameters)169     public void setPeriodicAdvertisingParameters(PeriodicAdvertisingParameters parameters) {
170         try {
171             final SynchronousResultReceiver recv = SynchronousResultReceiver.get();
172             mGatt.setPeriodicAdvertisingParameters(mAdvertiserId, parameters, mAttributionSource,
173                     recv);
174             recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
175         } catch (TimeoutException | RemoteException e) {
176             Log.e(TAG, "remote exception - ", e);
177         }
178     }
179 
180     /**
181      * Used to set periodic advertising data, must be called after setPeriodicAdvertisingParameters,
182      * or after advertising was started with periodic advertising data set. This method returns
183      * immediately, the operation status is delivered through
184      * {@code callback.onPeriodicAdvertisingDataSet()}.
185      *
186      * @param periodicData Periodic advertising data. Size must not exceed {@link
187      * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the update takes place when the
188      * periodic advertising is enabled for this set, the data can be maximum 251 bytes long.
189      */
190     @RequiresLegacyBluetoothAdminPermission
191     @RequiresBluetoothAdvertisePermission
192     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
setPeriodicAdvertisingData(AdvertiseData periodicData)193     public void setPeriodicAdvertisingData(AdvertiseData periodicData) {
194         try {
195             final SynchronousResultReceiver recv = SynchronousResultReceiver.get();
196             mGatt.setPeriodicAdvertisingData(mAdvertiserId, periodicData, mAttributionSource, recv);
197             recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
198         } catch (TimeoutException | RemoteException e) {
199             Log.e(TAG, "remote exception - ", e);
200         }
201     }
202 
203     /**
204      * Used to enable/disable periodic advertising. This method returns immediately, the operation
205      * status is delivered through {@code callback.onPeriodicAdvertisingEnable()}.
206      *
207      * @param enable whether the periodic advertising should be enabled (true), or disabled
208      * (false).
209      */
210     @RequiresLegacyBluetoothAdminPermission
211     @RequiresBluetoothAdvertisePermission
212     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
setPeriodicAdvertisingEnabled(boolean enable)213     public void setPeriodicAdvertisingEnabled(boolean enable) {
214         try {
215             final SynchronousResultReceiver recv = SynchronousResultReceiver.get();
216             mGatt.setPeriodicAdvertisingEnable(mAdvertiserId, enable, mAttributionSource, recv);
217             recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
218         } catch (TimeoutException | RemoteException e) {
219             Log.e(TAG, "remote exception - ", e);
220         }
221     }
222 
223     /**
224      * Returns address associated with this advertising set.
225      * This method is exposed only for Bluetooth PTS tests, no app or system service
226      * should ever use it.
227      *
228      * @hide
229      */
230     @RequiresBluetoothAdvertisePermission
231     @RequiresPermission(allOf = {
232             android.Manifest.permission.BLUETOOTH_ADVERTISE,
233             android.Manifest.permission.BLUETOOTH_PRIVILEGED,
234     })
getOwnAddress()235     public void getOwnAddress() {
236         try {
237             final SynchronousResultReceiver recv = SynchronousResultReceiver.get();
238             mGatt.getOwnAddress(mAdvertiserId, mAttributionSource, recv);
239             recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
240         } catch (TimeoutException | RemoteException e) {
241             Log.e(TAG, "remote exception - ", e);
242         }
243     }
244 
245     /**
246      * Returns the advertiser ID associated with this advertising set.
247      *
248      * <p>This corresponds to the advertising set ID used at the HCI layer, in either LE Extended
249      * Advertising or Android-specific Multi-Advertising.
250      *
251      * @hide
252      */
253     @RequiresNoPermission
254     @SystemApi
getAdvertiserId()255     public int getAdvertiserId() {
256         return mAdvertiserId;
257     }
258 }
259