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