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 com.android.bluetooth.gatt; 18 19 import static android.bluetooth.BluetoothProtoEnums.LE_ADV_ERROR_ON_START_COUNT; 20 21 import android.bluetooth.le.AdvertiseCallback; 22 import android.bluetooth.le.AdvertiseData; 23 import android.bluetooth.le.AdvertisingSetParameters; 24 import android.bluetooth.le.IAdvertisingSetCallback; 25 import android.bluetooth.le.PeriodicAdvertisingParameters; 26 import android.os.Handler; 27 import android.os.HandlerThread; 28 import android.os.IBinder; 29 import android.os.IInterface; 30 import android.os.Looper; 31 import android.os.RemoteException; 32 import android.util.Log; 33 34 import com.android.bluetooth.btservice.AdapterService; 35 import com.android.bluetooth.gatt.GattService.AdvertiserMap; 36 import com.android.internal.annotations.VisibleForTesting; 37 38 import java.util.Collections; 39 import java.util.HashMap; 40 import java.util.Map; 41 42 /** 43 * Manages Bluetooth LE advertising operations and interacts with bluedroid stack. TODO: add tests. 44 * 45 * @hide 46 */ 47 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) 48 public class AdvertiseManager { 49 private static final boolean DBG = GattServiceConfig.DBG; 50 private static final String TAG = GattServiceConfig.TAG_PREFIX + "AdvertiseManager"; 51 52 private final GattService mService; 53 private final AdapterService mAdapterService; 54 private final AdvertiserMap mAdvertiserMap; 55 private Handler mHandler; 56 Map<IBinder, AdvertiserInfo> mAdvertisers = Collections.synchronizedMap(new HashMap<>()); 57 static int sTempRegistrationId = -1; 58 59 /** 60 * Constructor of {@link AdvertiseManager}. 61 */ AdvertiseManager(GattService service, AdapterService adapterService, AdvertiserMap advertiserMap)62 AdvertiseManager(GattService service, AdapterService adapterService, 63 AdvertiserMap advertiserMap) { 64 if (DBG) { 65 Log.d(TAG, "advertise manager created"); 66 } 67 mService = service; 68 mAdapterService = adapterService; 69 mAdvertiserMap = advertiserMap; 70 } 71 72 /** 73 * Start a {@link HandlerThread} that handles advertising operations. 74 */ start()75 void start() { 76 initializeNative(); 77 HandlerThread thread = new HandlerThread("BluetoothAdvertiseManager"); 78 thread.start(); 79 mHandler = new Handler(thread.getLooper()); 80 } 81 cleanup()82 void cleanup() { 83 if (DBG) { 84 Log.d(TAG, "cleanup()"); 85 } 86 cleanupNative(); 87 mAdvertisers.clear(); 88 sTempRegistrationId = -1; 89 90 if (mHandler != null) { 91 // Shut down the thread 92 mHandler.removeCallbacksAndMessages(null); 93 Looper looper = mHandler.getLooper(); 94 if (looper != null) { 95 looper.quit(); 96 } 97 mHandler = null; 98 } 99 } 100 101 class AdvertiserInfo { 102 /* When id is negative, the registration is ongoing. When the registration finishes, id 103 * becomes equal to advertiser_id */ 104 public Integer id; 105 public AdvertisingSetDeathRecipient deathRecipient; 106 public IAdvertisingSetCallback callback; 107 AdvertiserInfo(Integer id, AdvertisingSetDeathRecipient deathRecipient, IAdvertisingSetCallback callback)108 AdvertiserInfo(Integer id, AdvertisingSetDeathRecipient deathRecipient, 109 IAdvertisingSetCallback callback) { 110 this.id = id; 111 this.deathRecipient = deathRecipient; 112 this.callback = callback; 113 } 114 } 115 toBinder(IAdvertisingSetCallback e)116 IBinder toBinder(IAdvertisingSetCallback e) { 117 return ((IInterface) e).asBinder(); 118 } 119 120 class AdvertisingSetDeathRecipient implements IBinder.DeathRecipient { 121 public IAdvertisingSetCallback callback; 122 AdvertisingSetDeathRecipient(IAdvertisingSetCallback callback)123 AdvertisingSetDeathRecipient(IAdvertisingSetCallback callback) { 124 this.callback = callback; 125 } 126 127 @Override binderDied()128 public void binderDied() { 129 if (DBG) { 130 Log.d(TAG, "Binder is dead - unregistering advertising set"); 131 } 132 stopAdvertisingSet(callback); 133 } 134 } 135 findAdvertiser(int advertiserId)136 Map.Entry<IBinder, AdvertiserInfo> findAdvertiser(int advertiserId) { 137 Map.Entry<IBinder, AdvertiserInfo> entry = null; 138 for (Map.Entry<IBinder, AdvertiserInfo> e : mAdvertisers.entrySet()) { 139 if (e.getValue().id == advertiserId) { 140 entry = e; 141 break; 142 } 143 } 144 return entry; 145 } 146 onAdvertisingSetStarted(int regId, int advertiserId, int txPower, int status)147 void onAdvertisingSetStarted(int regId, int advertiserId, int txPower, int status) 148 throws Exception { 149 if (DBG) { 150 Log.d(TAG, 151 "onAdvertisingSetStarted() - regId=" + regId + ", advertiserId=" + advertiserId 152 + ", status=" + status); 153 } 154 155 Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(regId); 156 157 if (entry == null) { 158 Log.i(TAG, "onAdvertisingSetStarted() - no callback found for regId " + regId); 159 // Advertising set was stopped before it was properly registered. 160 stopAdvertisingSetNative(advertiserId); 161 return; 162 } 163 164 IAdvertisingSetCallback callback = entry.getValue().callback; 165 if (status == 0) { 166 entry.setValue( 167 new AdvertiserInfo(advertiserId, entry.getValue().deathRecipient, callback)); 168 169 mAdvertiserMap.setAdvertiserIdByRegId(regId, advertiserId); 170 } else { 171 IBinder binder = entry.getKey(); 172 binder.unlinkToDeath(entry.getValue().deathRecipient, 0); 173 mAdvertisers.remove(binder); 174 175 AppAdvertiseStats stats = mAdvertiserMap.getAppAdvertiseStatsById(regId); 176 if (stats != null) { 177 stats.recordAdvertiseStop(); 178 } 179 mAdvertiserMap.removeAppAdvertiseStats(regId); 180 AppAdvertiseStats.recordAdvertiseErrorCount(LE_ADV_ERROR_ON_START_COUNT); 181 } 182 183 callback.onAdvertisingSetStarted(advertiserId, txPower, status); 184 } 185 onAdvertisingEnabled(int advertiserId, boolean enable, int status)186 void onAdvertisingEnabled(int advertiserId, boolean enable, int status) throws Exception { 187 if (DBG) { 188 Log.d(TAG, "onAdvertisingSetEnabled() - advertiserId=" + advertiserId + ", enable=" 189 + enable + ", status=" + status); 190 } 191 192 Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiserId); 193 if (entry == null) { 194 Log.i(TAG, "onAdvertisingSetEnable() - no callback found for advertiserId " 195 + advertiserId); 196 return; 197 } 198 199 IAdvertisingSetCallback callback = entry.getValue().callback; 200 callback.onAdvertisingEnabled(advertiserId, enable, status); 201 202 if (!enable && status != 0) { 203 AppAdvertiseStats stats = mAdvertiserMap.getAppAdvertiseStatsById(advertiserId); 204 if (stats != null) { 205 stats.recordAdvertiseStop(); 206 } 207 } 208 } 209 startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, int duration, int maxExtAdvEvents, int serverIf, IAdvertisingSetCallback callback)210 void startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, 211 AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, 212 AdvertiseData periodicData, int duration, int maxExtAdvEvents, int serverIf, 213 IAdvertisingSetCallback callback) { 214 // If we are using an isolated server, force usage of an NRPA 215 if (serverIf != 0 216 && parameters.getOwnAddressType() 217 != AdvertisingSetParameters.ADDRESS_TYPE_RANDOM_NON_RESOLVABLE) { 218 Log.w(TAG, "Cannot advertise an isolated GATT server using a resolvable address"); 219 try { 220 callback.onAdvertisingSetStarted( 221 0x00, 0x00, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); 222 } catch (RemoteException exception) { 223 Log.e(TAG, "Failed to callback:" + Log.getStackTraceString(exception)); 224 } 225 return; 226 } 227 228 AdvertisingSetDeathRecipient deathRecipient = new AdvertisingSetDeathRecipient(callback); 229 IBinder binder = toBinder(callback); 230 try { 231 binder.linkToDeath(deathRecipient, 0); 232 } catch (RemoteException e) { 233 throw new IllegalArgumentException("Can't link to advertiser's death"); 234 } 235 236 String deviceName = AdapterService.getAdapterService().getName(); 237 try { 238 byte[] advDataBytes = AdvertiseHelper.advertiseDataToBytes(advertiseData, deviceName); 239 byte[] scanResponseBytes = 240 AdvertiseHelper.advertiseDataToBytes(scanResponse, deviceName); 241 byte[] periodicDataBytes = 242 AdvertiseHelper.advertiseDataToBytes(periodicData, deviceName); 243 244 int cbId = --sTempRegistrationId; 245 mAdvertisers.put(binder, new AdvertiserInfo(cbId, deathRecipient, callback)); 246 247 if (DBG) { 248 Log.d(TAG, "startAdvertisingSet() - reg_id=" + cbId + ", callback: " + binder); 249 } 250 251 mAdvertiserMap.add(cbId, callback, mService); 252 mAdvertiserMap.recordAdvertiseStart(cbId, parameters, advertiseData, 253 scanResponse, periodicParameters, periodicData, duration, maxExtAdvEvents); 254 255 startAdvertisingSetNative(parameters, advDataBytes, scanResponseBytes, 256 periodicParameters, periodicDataBytes, duration, maxExtAdvEvents, cbId, 257 serverIf); 258 259 } catch (IllegalArgumentException e) { 260 try { 261 binder.unlinkToDeath(deathRecipient, 0); 262 callback.onAdvertisingSetStarted(0x00, 0x00, 263 AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE); 264 } catch (RemoteException exception) { 265 Log.e(TAG, "Failed to callback:" + Log.getStackTraceString(exception)); 266 } 267 } 268 } 269 onOwnAddressRead(int advertiserId, int addressType, String address)270 void onOwnAddressRead(int advertiserId, int addressType, String address) 271 throws RemoteException { 272 if (DBG) { 273 Log.d(TAG, "onOwnAddressRead() advertiserId=" + advertiserId); 274 } 275 276 Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiserId); 277 if (entry == null) { 278 Log.w(TAG, "onOwnAddressRead() - bad advertiserId " + advertiserId); 279 return; 280 } 281 282 IAdvertisingSetCallback callback = entry.getValue().callback; 283 callback.onOwnAddressRead(advertiserId, addressType, address); 284 } 285 getOwnAddress(int advertiserId)286 void getOwnAddress(int advertiserId) { 287 Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiserId); 288 if (entry == null) { 289 Log.w(TAG, "getOwnAddress() - bad advertiserId " + advertiserId); 290 return; 291 } 292 getOwnAddressNative(advertiserId); 293 } 294 stopAdvertisingSet(IAdvertisingSetCallback callback)295 void stopAdvertisingSet(IAdvertisingSetCallback callback) { 296 IBinder binder = toBinder(callback); 297 if (DBG) { 298 Log.d(TAG, "stopAdvertisingSet() " + binder); 299 } 300 301 AdvertiserInfo adv = mAdvertisers.remove(binder); 302 if (adv == null) { 303 Log.e(TAG, "stopAdvertisingSet() - no client found for callback"); 304 return; 305 } 306 307 Integer advertiserId = adv.id; 308 binder.unlinkToDeath(adv.deathRecipient, 0); 309 310 if (advertiserId < 0) { 311 Log.i(TAG, "stopAdvertisingSet() - advertiser not finished registration yet"); 312 // Advertiser will be freed once initiated in onAdvertisingSetStarted() 313 return; 314 } 315 316 stopAdvertisingSetNative(advertiserId); 317 318 try { 319 callback.onAdvertisingSetStopped(advertiserId); 320 } catch (RemoteException e) { 321 Log.i(TAG, "error sending onAdvertisingSetStopped callback", e); 322 } 323 324 mAdvertiserMap.recordAdvertiseStop(advertiserId); 325 } 326 enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents)327 void enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents) { 328 Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiserId); 329 if (entry == null) { 330 Log.w(TAG, "enableAdvertisingSet() - bad advertiserId " + advertiserId); 331 return; 332 } 333 enableAdvertisingSetNative(advertiserId, enable, duration, maxExtAdvEvents); 334 335 mAdvertiserMap.enableAdvertisingSet(advertiserId, 336 enable, duration, maxExtAdvEvents); 337 } 338 setAdvertisingData(int advertiserId, AdvertiseData data)339 void setAdvertisingData(int advertiserId, AdvertiseData data) { 340 Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiserId); 341 if (entry == null) { 342 Log.w(TAG, "setAdvertisingData() - bad advertiserId " + advertiserId); 343 return; 344 } 345 String deviceName = AdapterService.getAdapterService().getName(); 346 try { 347 setAdvertisingDataNative(advertiserId, 348 AdvertiseHelper.advertiseDataToBytes(data, deviceName)); 349 350 mAdvertiserMap.setAdvertisingData(advertiserId, data); 351 } catch (IllegalArgumentException e) { 352 try { 353 onAdvertisingDataSet(advertiserId, 354 AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE); 355 } catch (Exception exception) { 356 Log.e(TAG, "Failed to callback:" + Log.getStackTraceString(exception)); 357 } 358 } 359 } 360 setScanResponseData(int advertiserId, AdvertiseData data)361 void setScanResponseData(int advertiserId, AdvertiseData data) { 362 Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiserId); 363 if (entry == null) { 364 Log.w(TAG, "setScanResponseData() - bad advertiserId " + advertiserId); 365 return; 366 } 367 String deviceName = AdapterService.getAdapterService().getName(); 368 try { 369 setScanResponseDataNative(advertiserId, 370 AdvertiseHelper.advertiseDataToBytes(data, deviceName)); 371 372 mAdvertiserMap.setScanResponseData(advertiserId, data); 373 } catch (IllegalArgumentException e) { 374 try { 375 onScanResponseDataSet(advertiserId, 376 AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE); 377 } catch (Exception exception) { 378 Log.e(TAG, "Failed to callback:" + Log.getStackTraceString(exception)); 379 } 380 } 381 } 382 setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters)383 void setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters) { 384 Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiserId); 385 if (entry == null) { 386 Log.w(TAG, "setAdvertisingParameters() - bad advertiserId " + advertiserId); 387 return; 388 } 389 setAdvertisingParametersNative(advertiserId, parameters); 390 391 mAdvertiserMap.setAdvertisingParameters(advertiserId, parameters); 392 } 393 setPeriodicAdvertisingParameters(int advertiserId, PeriodicAdvertisingParameters parameters)394 void setPeriodicAdvertisingParameters(int advertiserId, 395 PeriodicAdvertisingParameters parameters) { 396 Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiserId); 397 if (entry == null) { 398 Log.w(TAG, "setPeriodicAdvertisingParameters() - bad advertiserId " + advertiserId); 399 return; 400 } 401 setPeriodicAdvertisingParametersNative(advertiserId, parameters); 402 403 mAdvertiserMap.setPeriodicAdvertisingParameters(advertiserId, parameters); 404 } 405 setPeriodicAdvertisingData(int advertiserId, AdvertiseData data)406 void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data) { 407 Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiserId); 408 if (entry == null) { 409 Log.w(TAG, "setPeriodicAdvertisingData() - bad advertiserId " + advertiserId); 410 return; 411 } 412 String deviceName = AdapterService.getAdapterService().getName(); 413 try { 414 setPeriodicAdvertisingDataNative(advertiserId, 415 AdvertiseHelper.advertiseDataToBytes(data, deviceName)); 416 417 mAdvertiserMap.setPeriodicAdvertisingData(advertiserId, data); 418 } catch (IllegalArgumentException e) { 419 try { 420 onPeriodicAdvertisingDataSet(advertiserId, 421 AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE); 422 } catch (Exception exception) { 423 Log.e(TAG, "Failed to callback:" + Log.getStackTraceString(exception)); 424 } 425 } 426 } 427 setPeriodicAdvertisingEnable(int advertiserId, boolean enable)428 void setPeriodicAdvertisingEnable(int advertiserId, boolean enable) { 429 Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiserId); 430 if (entry == null) { 431 Log.w(TAG, "setPeriodicAdvertisingEnable() - bad advertiserId " + advertiserId); 432 return; 433 } 434 setPeriodicAdvertisingEnableNative(advertiserId, enable); 435 } 436 onAdvertisingDataSet(int advertiserId, int status)437 void onAdvertisingDataSet(int advertiserId, int status) throws Exception { 438 if (DBG) { 439 Log.d(TAG, 440 "onAdvertisingDataSet() advertiserId=" + advertiserId + ", status=" + status); 441 } 442 443 Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiserId); 444 if (entry == null) { 445 Log.i(TAG, "onAdvertisingDataSet() - bad advertiserId " + advertiserId); 446 return; 447 } 448 449 IAdvertisingSetCallback callback = entry.getValue().callback; 450 callback.onAdvertisingDataSet(advertiserId, status); 451 } 452 onScanResponseDataSet(int advertiserId, int status)453 void onScanResponseDataSet(int advertiserId, int status) throws Exception { 454 if (DBG) { 455 Log.d(TAG, 456 "onScanResponseDataSet() advertiserId=" + advertiserId + ", status=" + status); 457 } 458 459 Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiserId); 460 if (entry == null) { 461 Log.i(TAG, "onScanResponseDataSet() - bad advertiserId " + advertiserId); 462 return; 463 } 464 465 IAdvertisingSetCallback callback = entry.getValue().callback; 466 callback.onScanResponseDataSet(advertiserId, status); 467 } 468 onAdvertisingParametersUpdated(int advertiserId, int txPower, int status)469 void onAdvertisingParametersUpdated(int advertiserId, int txPower, int status) 470 throws Exception { 471 if (DBG) { 472 Log.d(TAG, 473 "onAdvertisingParametersUpdated() advertiserId=" + advertiserId + ", txPower=" 474 + txPower + ", status=" + status); 475 } 476 477 Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiserId); 478 if (entry == null) { 479 Log.i(TAG, "onAdvertisingParametersUpdated() - bad advertiserId " + advertiserId); 480 return; 481 } 482 483 IAdvertisingSetCallback callback = entry.getValue().callback; 484 callback.onAdvertisingParametersUpdated(advertiserId, txPower, status); 485 } 486 onPeriodicAdvertisingParametersUpdated(int advertiserId, int status)487 void onPeriodicAdvertisingParametersUpdated(int advertiserId, int status) throws Exception { 488 if (DBG) { 489 Log.d(TAG, "onPeriodicAdvertisingParametersUpdated() advertiserId=" + advertiserId 490 + ", status=" + status); 491 } 492 493 Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiserId); 494 if (entry == null) { 495 Log.i(TAG, 496 "onPeriodicAdvertisingParametersUpdated() - bad advertiserId " + advertiserId); 497 return; 498 } 499 500 IAdvertisingSetCallback callback = entry.getValue().callback; 501 callback.onPeriodicAdvertisingParametersUpdated(advertiserId, status); 502 } 503 onPeriodicAdvertisingDataSet(int advertiserId, int status)504 void onPeriodicAdvertisingDataSet(int advertiserId, int status) throws Exception { 505 if (DBG) { 506 Log.d(TAG, "onPeriodicAdvertisingDataSet() advertiserId=" + advertiserId + ", status=" 507 + status); 508 } 509 510 Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiserId); 511 if (entry == null) { 512 Log.i(TAG, "onPeriodicAdvertisingDataSet() - bad advertiserId " + advertiserId); 513 return; 514 } 515 516 IAdvertisingSetCallback callback = entry.getValue().callback; 517 callback.onPeriodicAdvertisingDataSet(advertiserId, status); 518 } 519 onPeriodicAdvertisingEnabled(int advertiserId, boolean enable, int status)520 void onPeriodicAdvertisingEnabled(int advertiserId, boolean enable, int status) 521 throws Exception { 522 if (DBG) { 523 Log.d(TAG, "onPeriodicAdvertisingEnabled() advertiserId=" + advertiserId + ", status=" 524 + status); 525 } 526 527 Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(advertiserId); 528 if (entry == null) { 529 Log.i(TAG, "onAdvertisingSetEnable() - bad advertiserId " + advertiserId); 530 return; 531 } 532 533 IAdvertisingSetCallback callback = entry.getValue().callback; 534 callback.onPeriodicAdvertisingEnabled(advertiserId, enable, status); 535 536 AppAdvertiseStats stats = mAdvertiserMap.getAppAdvertiseStatsById(advertiserId); 537 if (stats != null) { 538 stats.onPeriodicAdvertiseEnabled(enable); 539 } 540 } 541 542 static { classInitNative()543 classInitNative(); 544 } 545 classInitNative()546 private static native void classInitNative(); 547 initializeNative()548 private native void initializeNative(); 549 cleanupNative()550 private native void cleanupNative(); 551 startAdvertisingSetNative(AdvertisingSetParameters parameters, byte[] advertiseData, byte[] scanResponse, PeriodicAdvertisingParameters periodicParameters, byte[] periodicData, int duration, int maxExtAdvEvents, int regId, int serverIf)552 private native void startAdvertisingSetNative(AdvertisingSetParameters parameters, 553 byte[] advertiseData, byte[] scanResponse, 554 PeriodicAdvertisingParameters periodicParameters, byte[] periodicData, int duration, 555 int maxExtAdvEvents, int regId, int serverIf); 556 getOwnAddressNative(int advertiserId)557 private native void getOwnAddressNative(int advertiserId); 558 stopAdvertisingSetNative(int advertiserId)559 private native void stopAdvertisingSetNative(int advertiserId); 560 enableAdvertisingSetNative(int advertiserId, boolean enable, int duration, int maxExtAdvEvents)561 private native void enableAdvertisingSetNative(int advertiserId, boolean enable, int duration, 562 int maxExtAdvEvents); 563 setAdvertisingDataNative(int advertiserId, byte[] data)564 private native void setAdvertisingDataNative(int advertiserId, byte[] data); 565 setScanResponseDataNative(int advertiserId, byte[] data)566 private native void setScanResponseDataNative(int advertiserId, byte[] data); 567 setAdvertisingParametersNative(int advertiserId, AdvertisingSetParameters parameters)568 private native void setAdvertisingParametersNative(int advertiserId, 569 AdvertisingSetParameters parameters); 570 setPeriodicAdvertisingParametersNative(int advertiserId, PeriodicAdvertisingParameters parameters)571 private native void setPeriodicAdvertisingParametersNative(int advertiserId, 572 PeriodicAdvertisingParameters parameters); 573 setPeriodicAdvertisingDataNative(int advertiserId, byte[] data)574 private native void setPeriodicAdvertisingDataNative(int advertiserId, byte[] data); 575 setPeriodicAdvertisingEnableNative(int advertiserId, boolean enable)576 private native void setPeriodicAdvertisingEnableNative(int advertiserId, boolean enable); 577 } 578