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