1/* 2 * Copyright (C) 2013 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 17package com.android.bluetooth.gatt; 18 19import android.app.Service; 20import android.bluetooth.BluetoothAdapter; 21import android.bluetooth.BluetoothDevice; 22import android.bluetooth.BluetoothProfile; 23import android.bluetooth.IBluetoothGatt; 24import android.bluetooth.IBluetoothGattCallback; 25import android.bluetooth.IBluetoothGattServerCallback; 26import android.content.Intent; 27import android.os.IBinder; 28import android.os.IBinder.DeathRecipient; 29import android.os.ParcelUuid; 30import android.os.RemoteException; 31import android.util.Log; 32 33import java.util.ArrayList; 34import java.util.HashMap; 35import java.util.HashSet; 36import java.util.Iterator; 37import java.util.List; 38import java.util.Map; 39import java.util.Set; 40import java.util.UUID; 41 42import com.android.bluetooth.btservice.ProfileService; 43import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder; 44 45/** 46 * Provides Bluetooth Gatt profile, as a service in 47 * the Bluetooth application. 48 * @hide 49 */ 50public class GattService extends ProfileService { 51 private static final boolean DBG = GattServiceConfig.DBG; 52 private static final String TAG = GattServiceConfig.TAG_PREFIX + "GattService"; 53 BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); 54 55 /** 56 * Search queue to serialize remote onbject inspection. 57 */ 58 SearchQueue mSearchQueue = new SearchQueue(); 59 60 /** 61 * List of our registered clients. 62 */ 63 64 class ClientMap extends ContextMap<IBluetoothGattCallback> {} 65 ClientMap mClientMap = new ClientMap(); 66 67 /** 68 * List of our registered server apps. 69 */ 70 class ServerMap extends ContextMap<IBluetoothGattServerCallback> {} 71 ServerMap mServerMap = new ServerMap(); 72 73 /** 74 * Server handle map. 75 */ 76 HandleMap mHandleMap = new HandleMap(); 77 78 /** 79 * Pending service declaration queue 80 */ 81 private List<ServiceDeclaration> mServiceDeclarations = new ArrayList<ServiceDeclaration>(); 82 83 private ServiceDeclaration addDeclaration() { 84 synchronized (mServiceDeclarations) { 85 mServiceDeclarations.add(new ServiceDeclaration()); 86 } 87 return getActiveDeclaration(); 88 } 89 90 private ServiceDeclaration getActiveDeclaration() { 91 synchronized (mServiceDeclarations) { 92 if (mServiceDeclarations.size() > 0) 93 return mServiceDeclarations.get(mServiceDeclarations.size() - 1); 94 } 95 return null; 96 } 97 98 private ServiceDeclaration getPendingDeclaration() { 99 synchronized (mServiceDeclarations) { 100 if (mServiceDeclarations.size() > 0) 101 return mServiceDeclarations.get(0); 102 } 103 return null; 104 } 105 106 private void removePendingDeclaration() { 107 synchronized (mServiceDeclarations) { 108 if (mServiceDeclarations.size() > 0) 109 mServiceDeclarations.remove(0); 110 } 111 } 112 113 /** 114 * List of clients intereste in scan results. 115 */ 116 private List<ScanClient> mScanQueue = new ArrayList<ScanClient>(); 117 118 private ScanClient getScanClient(int appIf, boolean isServer) { 119 for(ScanClient client : mScanQueue) { 120 if (client.appIf == appIf && client.isServer == isServer) { 121 return client; 122 } 123 } 124 return null; 125 } 126 127 private void removeScanClient(int appIf, boolean isServer) { 128 for(ScanClient client : mScanQueue) { 129 if (client.appIf == appIf && client.isServer == isServer) { 130 mScanQueue.remove(client); 131 break; 132 } 133 } 134 } 135 136 /** 137 * Reliable write queue 138 */ 139 private Set<String> mReliableQueue = new HashSet<String>(); 140 141 static { 142 classInitNative(); 143 } 144 145 protected String getName() { 146 return TAG; 147 } 148 149 protected IProfileServiceBinder initBinder() { 150 return new BluetoothGattBinder(this); 151 } 152 153 protected boolean start() { 154 if (DBG) Log.d(TAG, "start()"); 155 initializeNative(); 156 return true; 157 } 158 159 protected boolean stop() { 160 if (DBG) Log.d(TAG, "stop()"); 161 mClientMap.clear(); 162 mServerMap.clear(); 163 mSearchQueue.clear(); 164 mScanQueue.clear(); 165 mHandleMap.clear(); 166 mServiceDeclarations.clear(); 167 mReliableQueue.clear(); 168 return true; 169 } 170 171 protected boolean cleanup() { 172 if (DBG) Log.d(TAG, "cleanup()"); 173 cleanupNative(); 174 return true; 175 } 176 177 @Override 178 public int onStartCommand(Intent intent, int flags, int startId) { 179 if (GattDebugUtils.handleDebugAction(this, intent)) { 180 return Service.START_NOT_STICKY; 181 } 182 return super.onStartCommand(intent, flags, startId); 183 } 184 185 /** 186 * DeathReceipient handlers used to unregister applications that 187 * disconnect ungracefully (ie. crash or forced close). 188 */ 189 190 class ClientDeathRecipient implements IBinder.DeathRecipient { 191 int mAppIf; 192 193 public ClientDeathRecipient(int appIf) { 194 mAppIf = appIf; 195 } 196 197 public void binderDied() { 198 if (DBG) Log.d(TAG, "Binder is dead - unregistering client (" + mAppIf + ")!"); 199 stopScan(mAppIf, false); 200 unregisterClient(mAppIf); 201 } 202 } 203 204 class ServerDeathRecipient implements IBinder.DeathRecipient { 205 int mAppIf; 206 207 public ServerDeathRecipient(int appIf) { 208 mAppIf = appIf; 209 } 210 211 public void binderDied() { 212 if (DBG) Log.d(TAG, "Binder is dead - unregistering server (" + mAppIf + ")!"); 213 unregisterServer(mAppIf); 214 } 215 } 216 217 /** 218 * Handlers for incoming service calls 219 */ 220 private static class BluetoothGattBinder extends IBluetoothGatt.Stub implements IProfileServiceBinder { 221 private GattService mService; 222 223 public BluetoothGattBinder(GattService svc) { 224 mService = svc; 225 } 226 227 public boolean cleanup() { 228 mService = null; 229 return true; 230 } 231 232 private GattService getService() { 233 if (mService != null && mService.isAvailable()) return mService; 234 Log.e(TAG, "getService() - Service requested, but not available!"); 235 return null; 236 } 237 238 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 239 GattService service = getService(); 240 if (service == null) return new ArrayList<BluetoothDevice>(); 241 return service.getDevicesMatchingConnectionStates(states); 242 } 243 244 public void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback) { 245 GattService service = getService(); 246 if (service == null) return; 247 service.registerClient(uuid.getUuid(), callback); 248 } 249 250 public void unregisterClient(int clientIf) { 251 GattService service = getService(); 252 if (service == null) return; 253 service.unregisterClient(clientIf); 254 } 255 256 public void startScan(int appIf, boolean isServer) { 257 GattService service = getService(); 258 if (service == null) return; 259 service.startScan(appIf, isServer); 260 } 261 262 public void startScanWithUuids(int appIf, boolean isServer, ParcelUuid[] ids) { 263 GattService service = getService(); 264 if (service == null) return; 265 UUID[] uuids = new UUID[ids.length]; 266 for(int i = 0; i != ids.length; ++i) { 267 uuids[i] = ids[i].getUuid(); 268 } 269 service.startScanWithUuids(appIf, isServer, uuids); 270 } 271 272 public void stopScan(int appIf, boolean isServer) { 273 GattService service = getService(); 274 if (service == null) return; 275 service.stopScan(appIf, isServer); 276 } 277 278 public void clientConnect(int clientIf, String address, boolean isDirect) { 279 GattService service = getService(); 280 if (service == null) return; 281 service.clientConnect(clientIf, address, isDirect); 282 } 283 284 public void clientDisconnect(int clientIf, String address) { 285 GattService service = getService(); 286 if (service == null) return; 287 service.clientDisconnect(clientIf, address); 288 } 289 290 public void clientListen(int clientIf, boolean start) { 291 GattService service = getService(); 292 if (service == null) return; 293 service.clientListen(clientIf, start); 294 } 295 296 public void refreshDevice(int clientIf, String address) { 297 GattService service = getService(); 298 if (service == null) return; 299 service.refreshDevice(clientIf, address); 300 } 301 302 public void discoverServices(int clientIf, String address) { 303 GattService service = getService(); 304 if (service == null) return; 305 service.discoverServices(clientIf, address); 306 } 307 308 public void readCharacteristic(int clientIf, String address, int srvcType, 309 int srvcInstanceId, ParcelUuid srvcId, 310 int charInstanceId, ParcelUuid charId, 311 int authReq) { 312 GattService service = getService(); 313 if (service == null) return; 314 service.readCharacteristic(clientIf, address, srvcType, srvcInstanceId, 315 srvcId.getUuid(), charInstanceId, 316 charId.getUuid(), authReq); 317 } 318 319 public void writeCharacteristic(int clientIf, String address, int srvcType, 320 int srvcInstanceId, ParcelUuid srvcId, 321 int charInstanceId, ParcelUuid charId, 322 int writeType, int authReq, byte[] value) { 323 GattService service = getService(); 324 if (service == null) return; 325 service.writeCharacteristic(clientIf, address, srvcType, srvcInstanceId, 326 srvcId.getUuid(), charInstanceId, 327 charId.getUuid(), writeType, authReq, 328 value); 329 } 330 331 public void readDescriptor(int clientIf, String address, int srvcType, 332 int srvcInstanceId, ParcelUuid srvcId, 333 int charInstanceId, ParcelUuid charId, 334 int descrInstanceId, ParcelUuid descrId, 335 int authReq) { 336 GattService service = getService(); 337 if (service == null) return; 338 service.readDescriptor(clientIf, address, srvcType, 339 srvcInstanceId, srvcId.getUuid(), 340 charInstanceId, charId.getUuid(), 341 descrInstanceId, descrId.getUuid(), 342 authReq); 343 } 344 345 public void writeDescriptor(int clientIf, String address, int srvcType, 346 int srvcInstanceId, ParcelUuid srvcId, 347 int charInstanceId, ParcelUuid charId, 348 int descrInstanceId, ParcelUuid descrId, 349 int writeType, int authReq, byte[] value) { 350 GattService service = getService(); 351 if (service == null) return; 352 service.writeDescriptor(clientIf, address, srvcType, 353 srvcInstanceId, srvcId.getUuid(), 354 charInstanceId, charId.getUuid(), 355 descrInstanceId, descrId.getUuid(), 356 writeType, authReq, value); 357 } 358 359 public void beginReliableWrite(int clientIf, String address) { 360 GattService service = getService(); 361 if (service == null) return; 362 service.beginReliableWrite(clientIf, address); 363 } 364 365 public void endReliableWrite(int clientIf, String address, boolean execute) { 366 GattService service = getService(); 367 if (service == null) return; 368 service.endReliableWrite(clientIf, address, execute); 369 } 370 371 public void registerForNotification(int clientIf, String address, int srvcType, 372 int srvcInstanceId, ParcelUuid srvcId, 373 int charInstanceId, ParcelUuid charId, 374 boolean enable) { 375 GattService service = getService(); 376 if (service == null) return; 377 service.registerForNotification(clientIf, address, srvcType, srvcInstanceId, 378 srvcId.getUuid(), charInstanceId, 379 charId.getUuid(), enable); 380 } 381 382 public void readRemoteRssi(int clientIf, String address) { 383 GattService service = getService(); 384 if (service == null) return; 385 service.readRemoteRssi(clientIf, address); 386 } 387 388 public void registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback) { 389 GattService service = getService(); 390 if (service == null) return; 391 service.registerServer(uuid.getUuid(), callback); 392 } 393 394 public void unregisterServer(int serverIf) { 395 GattService service = getService(); 396 if (service == null) return; 397 service.unregisterServer(serverIf); 398 } 399 400 public void serverConnect(int serverIf, String address, boolean isDirect) { 401 GattService service = getService(); 402 if (service == null) return; 403 service.serverConnect(serverIf, address, isDirect); 404 } 405 406 public void serverDisconnect(int serverIf, String address) { 407 GattService service = getService(); 408 if (service == null) return; 409 service.serverDisconnect(serverIf, address); 410 } 411 412 public void beginServiceDeclaration(int serverIf, int srvcType, 413 int srvcInstanceId, int minHandles, 414 ParcelUuid srvcId) { 415 GattService service = getService(); 416 if (service == null) return; 417 service.beginServiceDeclaration(serverIf, srvcType, srvcInstanceId, 418 minHandles, srvcId.getUuid()); 419 } 420 421 public void addIncludedService(int serverIf, int srvcType, 422 int srvcInstanceId, ParcelUuid srvcId) { 423 GattService service = getService(); 424 if (service == null) return; 425 service.addIncludedService(serverIf, srvcType, srvcInstanceId, 426 srvcId.getUuid()); 427 } 428 429 public void addCharacteristic(int serverIf, ParcelUuid charId, 430 int properties, int permissions) { 431 GattService service = getService(); 432 if (service == null) return; 433 service.addCharacteristic(serverIf, charId.getUuid(), properties, 434 permissions); 435 } 436 437 public void addDescriptor(int serverIf, ParcelUuid descId, 438 int permissions) { 439 GattService service = getService(); 440 if (service == null) return; 441 service.addDescriptor(serverIf, descId.getUuid(), permissions); 442 } 443 444 public void endServiceDeclaration(int serverIf) { 445 GattService service = getService(); 446 if (service == null) return; 447 service.endServiceDeclaration(serverIf); 448 } 449 450 public void removeService(int serverIf, int srvcType, 451 int srvcInstanceId, ParcelUuid srvcId) { 452 GattService service = getService(); 453 if (service == null) return; 454 service.removeService(serverIf, srvcType, srvcInstanceId, 455 srvcId.getUuid()); 456 } 457 458 public void clearServices(int serverIf) { 459 GattService service = getService(); 460 if (service == null) return; 461 service.clearServices(serverIf); 462 } 463 464 public void sendResponse(int serverIf, String address, int requestId, 465 int status, int offset, byte[] value) { 466 GattService service = getService(); 467 if (service == null) return; 468 service.sendResponse(serverIf, address, requestId, status, offset, value); 469 } 470 471 public void sendNotification(int serverIf, String address, int srvcType, 472 int srvcInstanceId, ParcelUuid srvcId, 473 int charInstanceId, ParcelUuid charId, 474 boolean confirm, byte[] value) { 475 GattService service = getService(); 476 if (service == null) return; 477 service.sendNotification(serverIf, address, srvcType, srvcInstanceId, 478 srvcId.getUuid(), charInstanceId, charId.getUuid(), confirm, value); 479 } 480 481 public void setAdvData(int serverIf, boolean setScanRsp, boolean inclName, 482 boolean inclTxPower, int minInterval, int maxInterval, 483 int appearance, byte[] manufacturerData) { 484 GattService service = getService(); 485 if (service == null) return; 486 service.setAdvData(serverIf, setScanRsp, inclName, inclTxPower, 487 minInterval, maxInterval, appearance, manufacturerData); 488 } 489 }; 490 491 /************************************************************************** 492 * Callback functions - CLIENT 493 *************************************************************************/ 494 495 void onScanResult(String address, int rssi, byte[] adv_data) { 496 if (DBG) Log.d(TAG, "onScanResult() - address=" + address 497 + ", rssi=" + rssi); 498 499 List<UUID> remoteUuids = parseUuids(adv_data); 500 for (ScanClient client : mScanQueue) { 501 if (client.uuids.length > 0) { 502 int matches = 0; 503 for (UUID search : client.uuids) { 504 for (UUID remote: remoteUuids) { 505 if (remote.equals(search)) { 506 ++matches; 507 break; // Only count 1st match in case of duplicates 508 } 509 } 510 } 511 512 if (matches < client.uuids.length) continue; 513 } 514 515 if (!client.isServer) { 516 ClientMap.App app = mClientMap.getById(client.appIf); 517 if (app != null) { 518 try { 519 app.callback.onScanResult(address, rssi, adv_data); 520 } catch (RemoteException e) { 521 Log.e(TAG, "Exception: " + e); 522 mClientMap.remove(client.appIf); 523 mScanQueue.remove(client); 524 } 525 } 526 } else { 527 ServerMap.App app = mServerMap.getById(client.appIf); 528 if (app != null) { 529 try { 530 app.callback.onScanResult(address, rssi, adv_data); 531 } catch (RemoteException e) { 532 Log.e(TAG, "Exception: " + e); 533 mServerMap.remove(client.appIf); 534 mScanQueue.remove(client); 535 } 536 } 537 } 538 } 539 } 540 541 void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb) 542 throws RemoteException { 543 UUID uuid = new UUID(uuidMsb, uuidLsb); 544 if (DBG) Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf); 545 ClientMap.App app = mClientMap.getByUuid(uuid); 546 if (app != null) { 547 app.id = clientIf; 548 app.linkToDeath(new ClientDeathRecipient(clientIf)); 549 app.callback.onClientRegistered(status, clientIf); 550 } 551 } 552 553 void onConnected(int clientIf, int connId, int status, String address) 554 throws RemoteException { 555 if (DBG) Log.d(TAG, "onConnected() - clientIf=" + clientIf 556 + ", connId=" + connId + ", address=" + address); 557 558 if (status == 0) mClientMap.addConnection(clientIf, connId, address); 559 ClientMap.App app = mClientMap.getById(clientIf); 560 if (app != null) { 561 app.callback.onClientConnectionState(status, clientIf, true, address); 562 } 563 } 564 565 void onDisconnected(int clientIf, int connId, int status, String address) 566 throws RemoteException { 567 if (DBG) Log.d(TAG, "onDisconnected() - clientIf=" + clientIf 568 + ", connId=" + connId + ", address=" + address); 569 570 mClientMap.removeConnection(clientIf, connId); 571 mSearchQueue.removeConnId(connId); 572 ClientMap.App app = mClientMap.getById(clientIf); 573 if (app != null) { 574 app.callback.onClientConnectionState(status, clientIf, false, address); 575 } 576 } 577 578 void onSearchCompleted(int connId, int status) throws RemoteException { 579 if (DBG) Log.d(TAG, "onSearchCompleted() - connId=" + connId+ ", status=" + status); 580 // We got all services, now let's explore characteristics... 581 continueSearch(connId, status); 582 } 583 584 void onSearchResult(int connId, int srvcType, 585 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb) 586 throws RemoteException { 587 UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb); 588 String address = mClientMap.addressByConnId(connId); 589 590 if (DBG) Log.d(TAG, "onSearchResult() - address=" + address + ", uuid=" + uuid); 591 592 mSearchQueue.add(connId, srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb); 593 594 ClientMap.App app = mClientMap.getByConnId(connId); 595 if (app != null) { 596 app.callback.onGetService(address, srvcType, srvcInstId, 597 new ParcelUuid(uuid)); 598 } 599 } 600 601 void onGetCharacteristic(int connId, int status, int srvcType, 602 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 603 int charInstId, long charUuidLsb, long charUuidMsb, 604 int charProp) throws RemoteException { 605 606 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 607 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 608 String address = mClientMap.addressByConnId(connId); 609 610 if (DBG) Log.d(TAG, "onGetCharacteristic() - address=" + address 611 + ", status=" + status + ", charUuid=" + charUuid + ", prop=" + charProp); 612 613 if (status == 0) { 614 mSearchQueue.add(connId, srvcType, 615 srvcInstId, srvcUuidLsb, srvcUuidMsb, 616 charInstId, charUuidLsb, charUuidMsb); 617 618 ClientMap.App app = mClientMap.getByConnId(connId); 619 if (app != null) { 620 app.callback.onGetCharacteristic(address, srvcType, 621 srvcInstId, new ParcelUuid(srvcUuid), 622 charInstId, new ParcelUuid(charUuid), charProp); 623 } 624 625 // Get next characteristic in the current service 626 gattClientGetCharacteristicNative(connId, srvcType, 627 srvcInstId, srvcUuidLsb, srvcUuidMsb, 628 charInstId, charUuidLsb, charUuidMsb); 629 } else { 630 // Check for included services next 631 gattClientGetIncludedServiceNative(connId, 632 srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb, 633 0,0,0,0); 634 } 635 } 636 637 void onGetDescriptor(int connId, int status, int srvcType, 638 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 639 int charInstId, long charUuidLsb, long charUuidMsb, 640 int descrInstId, long descrUuidLsb, long descrUuidMsb) throws RemoteException { 641 642 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 643 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 644 UUID descUuid = new UUID(descrUuidMsb, descrUuidLsb); 645 String address = mClientMap.addressByConnId(connId); 646 647 if (DBG) Log.d(TAG, "onGetDescriptor() - address=" + address 648 + ", status=" + status + ", descUuid=" + descUuid); 649 650 if (status == 0) { 651 ClientMap.App app = mClientMap.getByConnId(connId); 652 if (app != null) { 653 app.callback.onGetDescriptor(address, srvcType, 654 srvcInstId, new ParcelUuid(srvcUuid), 655 charInstId, new ParcelUuid(charUuid), 656 descrInstId, new ParcelUuid(descUuid)); 657 } 658 659 // Get next descriptor for the current characteristic 660 gattClientGetDescriptorNative(connId, srvcType, 661 srvcInstId, srvcUuidLsb, srvcUuidMsb, 662 charInstId, charUuidLsb, charUuidMsb, 663 descrInstId, descrUuidLsb, descrUuidMsb); 664 } else { 665 // Explore the next service 666 continueSearch(connId, 0); 667 } 668 } 669 670 void onGetIncludedService(int connId, int status, int srvcType, 671 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int inclSrvcType, 672 int inclSrvcInstId, long inclSrvcUuidLsb, long inclSrvcUuidMsb) 673 throws RemoteException { 674 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 675 UUID inclSrvcUuid = new UUID(inclSrvcUuidMsb, inclSrvcUuidLsb); 676 String address = mClientMap.addressByConnId(connId); 677 678 if (DBG) Log.d(TAG, "onGetIncludedService() - address=" + address 679 + ", status=" + status + ", uuid=" + srvcUuid 680 + ", inclUuid=" + inclSrvcUuid); 681 682 if (status == 0) { 683 ClientMap.App app = mClientMap.getByConnId(connId); 684 if (app != null) { 685 app.callback.onGetIncludedService(address, 686 srvcType, srvcInstId, new ParcelUuid(srvcUuid), 687 inclSrvcType, inclSrvcInstId, new ParcelUuid(inclSrvcUuid)); 688 } 689 690 // Find additional included services 691 gattClientGetIncludedServiceNative(connId, 692 srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb, 693 inclSrvcType, inclSrvcInstId, inclSrvcUuidLsb, inclSrvcUuidMsb); 694 } else { 695 // Discover descriptors now 696 continueSearch(connId, 0); 697 } 698 } 699 700 void onRegisterForNotifications(int connId, int status, int registered, int srvcType, 701 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 702 int charInstId, long charUuidLsb, long charUuidMsb) { 703 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 704 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 705 String address = mClientMap.addressByConnId(connId); 706 707 if (DBG) Log.d(TAG, "onRegisterForNotifications() - address=" + address 708 + ", status=" + status + ", registered=" + registered 709 + ", charUuid=" + charUuid); 710 } 711 712 void onNotify(int connId, String address, int srvcType, 713 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 714 int charInstId, long charUuidLsb, long charUuidMsb, 715 boolean isNotify, byte[] data) throws RemoteException { 716 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 717 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 718 719 if (DBG) Log.d(TAG, "onNotify() - address=" + address 720 + ", charUuid=" + charUuid + ", length=" + data.length); 721 722 ClientMap.App app = mClientMap.getByConnId(connId); 723 if (app != null) { 724 app.callback.onNotify(address, srvcType, 725 srvcInstId, new ParcelUuid(srvcUuid), 726 charInstId, new ParcelUuid(charUuid), 727 data); 728 } 729 } 730 731 void onReadCharacteristic(int connId, int status, int srvcType, 732 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 733 int charInstId, long charUuidLsb, long charUuidMsb, 734 int charType, byte[] data) throws RemoteException { 735 736 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 737 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 738 String address = mClientMap.addressByConnId(connId); 739 740 if (DBG) Log.d(TAG, "onReadCharacteristic() - address=" + address 741 + ", status=" + status + ", length=" + data.length); 742 743 ClientMap.App app = mClientMap.getByConnId(connId); 744 if (app != null) { 745 app.callback.onCharacteristicRead(address, status, srvcType, 746 srvcInstId, new ParcelUuid(srvcUuid), 747 charInstId, new ParcelUuid(charUuid), data); 748 } 749 } 750 751 void onWriteCharacteristic(int connId, int status, int srvcType, 752 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 753 int charInstId, long charUuidLsb, long charUuidMsb) 754 throws RemoteException { 755 756 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 757 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 758 String address = mClientMap.addressByConnId(connId); 759 760 if (DBG) Log.d(TAG, "onWriteCharacteristic() - address=" + address 761 + ", status=" + status); 762 763 ClientMap.App app = mClientMap.getByConnId(connId); 764 if (app != null) { 765 app.callback.onCharacteristicWrite(address, status, srvcType, 766 srvcInstId, new ParcelUuid(srvcUuid), 767 charInstId, new ParcelUuid(charUuid)); 768 } 769 } 770 771 void onExecuteCompleted(int connId, int status) throws RemoteException { 772 String address = mClientMap.addressByConnId(connId); 773 if (DBG) Log.d(TAG, "onExecuteCompleted() - address=" + address 774 + ", status=" + status); 775 776 ClientMap.App app = mClientMap.getByConnId(connId); 777 if (app != null) { 778 app.callback.onExecuteWrite(address, status); 779 } 780 } 781 782 void onReadDescriptor(int connId, int status, int srvcType, 783 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 784 int charInstId, long charUuidLsb, long charUuidMsb, 785 int descrInstId, long descrUuidLsb, long descrUuidMsb, 786 int charType, byte[] data) throws RemoteException { 787 788 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 789 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 790 UUID descrUuid = new UUID(descrUuidMsb, descrUuidLsb); 791 String address = mClientMap.addressByConnId(connId); 792 793 if (DBG) Log.d(TAG, "onReadDescriptor() - address=" + address 794 + ", status=" + status + ", length=" + data.length); 795 796 ClientMap.App app = mClientMap.getByConnId(connId); 797 if (app != null) { 798 app.callback.onDescriptorRead(address, status, srvcType, 799 srvcInstId, new ParcelUuid(srvcUuid), 800 charInstId, new ParcelUuid(charUuid), 801 descrInstId, new ParcelUuid(descrUuid), data); 802 } 803 } 804 805 void onWriteDescriptor(int connId, int status, int srvcType, 806 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 807 int charInstId, long charUuidLsb, long charUuidMsb, 808 int descrInstId, long descrUuidLsb, long descrUuidMsb) throws RemoteException { 809 810 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 811 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 812 UUID descrUuid = new UUID(descrUuidMsb, descrUuidLsb); 813 String address = mClientMap.addressByConnId(connId); 814 815 if (DBG) Log.d(TAG, "onWriteDescriptor() - address=" + address 816 + ", status=" + status); 817 818 ClientMap.App app = mClientMap.getByConnId(connId); 819 if (app != null) { 820 app.callback.onDescriptorWrite(address, status, srvcType, 821 srvcInstId, new ParcelUuid(srvcUuid), 822 charInstId, new ParcelUuid(charUuid), 823 descrInstId, new ParcelUuid(descrUuid)); 824 } 825 } 826 827 void onReadRemoteRssi(int clientIf, String address, 828 int rssi, int status) throws RemoteException{ 829 if (DBG) Log.d(TAG, "onReadRemoteRssi() - clientIf=" + clientIf + " address=" + 830 address + ", rssi=" + rssi + ", status=" + status); 831 832 ClientMap.App app = mClientMap.getById(clientIf); 833 if (app != null) { 834 app.callback.onReadRemoteRssi(address, rssi, status); 835 } 836 } 837 838 void onClientListen(int status, int clientIf) 839 throws RemoteException { 840 if (DBG) Log.d(TAG, "onClientListen() status=" + status); 841 842 ClientMap.App app = mClientMap.getById(clientIf); 843 if (app == null) return; 844 845 app.callback.onListen(status); 846 } 847 848 /************************************************************************** 849 * GATT Service functions - Shared CLIENT/SERVER 850 *************************************************************************/ 851 852 List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 853 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 854 855 final int DEVICE_TYPE_BREDR = 0x1; 856 857 Map<BluetoothDevice, Integer> deviceStates = new HashMap<BluetoothDevice, 858 Integer>(); 859 860 // Add paired LE devices 861 862 Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices(); 863 for (BluetoothDevice device : bondedDevices) { 864 if (getDeviceType(device) != DEVICE_TYPE_BREDR) { 865 deviceStates.put(device, BluetoothProfile.STATE_DISCONNECTED); 866 } 867 } 868 869 // Add connected deviceStates 870 871 Set<String> connectedDevices = new HashSet<String>(); 872 connectedDevices.addAll(mClientMap.getConnectedDevices()); 873 connectedDevices.addAll(mServerMap.getConnectedDevices()); 874 875 for (String address : connectedDevices ) { 876 BluetoothDevice device = mAdapter.getRemoteDevice(address); 877 if (device != null) { 878 deviceStates.put(device, BluetoothProfile.STATE_CONNECTED); 879 } 880 } 881 882 // Create matching device sub-set 883 884 List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>(); 885 886 for (Map.Entry<BluetoothDevice, Integer> entry : deviceStates.entrySet()) { 887 for(int state : states) { 888 if (entry.getValue() == state) { 889 deviceList.add(entry.getKey()); 890 } 891 } 892 } 893 894 return deviceList; 895 } 896 897 void startScan(int appIf, boolean isServer) { 898 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 899 900 if (DBG) Log.d(TAG, "startScan() - queue=" + mScanQueue.size()); 901 902 if (getScanClient(appIf, isServer) == null) { 903 if (DBG) Log.d(TAG, "startScan() - adding client=" + appIf); 904 mScanQueue.add(new ScanClient(appIf, isServer)); 905 } 906 907 gattClientScanNative(appIf, true); 908 } 909 910 void startScanWithUuids(int appIf, boolean isServer, UUID[] uuids) { 911 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 912 913 if (DBG) Log.d(TAG, "startScanWithUuids() - queue=" + mScanQueue.size()); 914 915 if (getScanClient(appIf, isServer) == null) { 916 if (DBG) Log.d(TAG, "startScanWithUuids() - adding client=" + appIf); 917 mScanQueue.add(new ScanClient(appIf, isServer, uuids)); 918 } 919 920 gattClientScanNative(appIf, true); 921 } 922 923 void stopScan(int appIf, boolean isServer) { 924 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH_ADMIN permission"); 925 926 if (DBG) Log.d(TAG, "stopScan() - queue=" + mScanQueue.size()); 927 removeScanClient(appIf, isServer); 928 929 if (mScanQueue.isEmpty()) { 930 if (DBG) Log.d(TAG, "stopScan() - queue empty; stopping scan"); 931 gattClientScanNative(appIf, false); 932 } 933 } 934 935 /************************************************************************** 936 * GATT Service functions - CLIENT 937 *************************************************************************/ 938 939 void registerClient(UUID uuid, IBluetoothGattCallback callback) { 940 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 941 942 if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid); 943 mClientMap.add(uuid, callback); 944 gattClientRegisterAppNative(uuid.getLeastSignificantBits(), 945 uuid.getMostSignificantBits()); 946 } 947 948 void unregisterClient(int clientIf) { 949 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 950 951 if (DBG) Log.d(TAG, "unregisterClient() - clientIf=" + clientIf); 952 mClientMap.remove(clientIf); 953 gattClientUnregisterAppNative(clientIf); 954 } 955 956 void clientConnect(int clientIf, String address, boolean isDirect) { 957 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 958 959 if (DBG) Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect); 960 gattClientConnectNative(clientIf, address, isDirect); 961 } 962 963 void clientDisconnect(int clientIf, String address) { 964 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 965 966 Integer connId = mClientMap.connIdByAddress(clientIf, address); 967 if (DBG) Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId); 968 969 gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0); 970 } 971 972 void clientListen(int clientIf, boolean start) { 973 if (DBG) Log.d(TAG, "clientListen() - start=" + start); 974 gattClientListenNative(clientIf, start); 975 } 976 977 List<String> getConnectedDevices() { 978 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 979 980 Set<String> connectedDevAddress = new HashSet<String>(); 981 connectedDevAddress.addAll(mClientMap.getConnectedDevices()); 982 connectedDevAddress.addAll(mServerMap.getConnectedDevices()); 983 List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress); 984 return connectedDeviceList; 985 } 986 987 void refreshDevice(int clientIf, String address) { 988 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 989 990 if (DBG) Log.d(TAG, "refreshDevice() - address=" + address); 991 gattClientRefreshNative(clientIf, address); 992 } 993 994 void discoverServices(int clientIf, String address) { 995 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 996 997 Integer connId = mClientMap.connIdByAddress(clientIf, address); 998 if (DBG) Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId); 999 1000 if (connId != null) 1001 gattClientSearchServiceNative(connId, true, 0, 0); 1002 else 1003 Log.e(TAG, "discoverServices() - No connection for " + address + "..."); 1004 } 1005 1006 void readCharacteristic(int clientIf, String address, int srvcType, 1007 int srvcInstanceId, UUID srvcUuid, 1008 int charInstanceId, UUID charUuid, int authReq) { 1009 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1010 1011 if (DBG) Log.d(TAG, "readCharacteristic() - address=" + address); 1012 1013 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1014 if (connId != null) 1015 gattClientReadCharacteristicNative(connId, srvcType, 1016 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1017 srvcUuid.getMostSignificantBits(), charInstanceId, 1018 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1019 authReq); 1020 else 1021 Log.e(TAG, "readCharacteristic() - No connection for " + address + "..."); 1022 } 1023 1024 void writeCharacteristic(int clientIf, String address, int srvcType, 1025 int srvcInstanceId, UUID srvcUuid, 1026 int charInstanceId, UUID charUuid, int writeType, 1027 int authReq, byte[] value) { 1028 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1029 1030 if (DBG) Log.d(TAG, "writeCharacteristic() - address=" + address); 1031 1032 if (mReliableQueue.contains(address)) writeType = 3; // Prepared write 1033 1034 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1035 if (connId != null) 1036 gattClientWriteCharacteristicNative(connId, srvcType, 1037 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1038 srvcUuid.getMostSignificantBits(), charInstanceId, 1039 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1040 writeType, authReq, value); 1041 else 1042 Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); 1043 } 1044 1045 void readDescriptor(int clientIf, String address, int srvcType, 1046 int srvcInstanceId, UUID srvcUuid, 1047 int charInstanceId, UUID charUuid, 1048 int descrInstanceId, UUID descrUuid, 1049 int authReq) { 1050 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1051 1052 if (DBG) Log.d(TAG, "readDescriptor() - address=" + address); 1053 1054 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1055 if (connId != null) 1056 gattClientReadDescriptorNative(connId, srvcType, 1057 srvcInstanceId, 1058 srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(), 1059 charInstanceId, 1060 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1061 descrInstanceId, 1062 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 1063 authReq); 1064 else 1065 Log.e(TAG, "readDescriptor() - No connection for " + address + "..."); 1066 }; 1067 1068 void writeDescriptor(int clientIf, String address, int srvcType, 1069 int srvcInstanceId, UUID srvcUuid, 1070 int charInstanceId, UUID charUuid, 1071 int descrInstanceId, UUID descrUuid, 1072 int writeType, int authReq, byte[] value) { 1073 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1074 1075 if (DBG) Log.d(TAG, "writeDescriptor() - address=" + address); 1076 1077 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1078 if (connId != null) 1079 gattClientWriteDescriptorNative(connId, srvcType, 1080 srvcInstanceId, 1081 srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(), 1082 charInstanceId, 1083 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1084 descrInstanceId, 1085 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 1086 writeType, authReq, value); 1087 else 1088 Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); 1089 } 1090 1091 void beginReliableWrite(int clientIf, String address) { 1092 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1093 1094 if (DBG) Log.d(TAG, "beginReliableWrite() - address=" + address); 1095 mReliableQueue.add(address); 1096 } 1097 1098 void endReliableWrite(int clientIf, String address, boolean execute) { 1099 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1100 1101 if (DBG) Log.d(TAG, "endReliableWrite() - address=" + address 1102 + " execute: " + execute); 1103 mReliableQueue.remove(address); 1104 1105 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1106 if (connId != null) gattClientExecuteWriteNative(connId, execute); 1107 } 1108 1109 void registerForNotification(int clientIf, String address, int srvcType, 1110 int srvcInstanceId, UUID srvcUuid, 1111 int charInstanceId, UUID charUuid, 1112 boolean enable) { 1113 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1114 1115 if (DBG) Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable); 1116 1117 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1118 if (connId != null) { 1119 gattClientRegisterForNotificationsNative(clientIf, address, 1120 srvcType, srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1121 srvcUuid.getMostSignificantBits(), charInstanceId, 1122 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1123 enable); 1124 } else { 1125 Log.e(TAG, "registerForNotification() - No connection for " + address + "..."); 1126 } 1127 } 1128 1129 void readRemoteRssi(int clientIf, String address) { 1130 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1131 1132 if (DBG) Log.d(TAG, "readRemoteRssi() - address=" + address); 1133 gattClientReadRemoteRssiNative(clientIf, address); 1134 } 1135 1136 void setAdvData(int serverIf, boolean setScanRsp, boolean inclName, 1137 boolean inclTxPower, int minInterval, int maxInterval, 1138 int appearance, byte[] manufacturerData) { 1139 if (DBG) Log.d(TAG, "setAdvData() - setScanRsp=" + setScanRsp); 1140 if (minInterval == 0) maxInterval = 0; 1141 gattSetAdvDataNative(serverIf, setScanRsp, inclName, inclTxPower, 1142 minInterval, maxInterval, appearance, manufacturerData); 1143 } 1144 1145 /************************************************************************** 1146 * Callback functions - SERVER 1147 *************************************************************************/ 1148 1149 void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) 1150 throws RemoteException { 1151 1152 UUID uuid = new UUID(uuidMsb, uuidLsb); 1153 if (DBG) Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf); 1154 ServerMap.App app = mServerMap.getByUuid(uuid); 1155 if (app != null) { 1156 app.id = serverIf; 1157 app.linkToDeath(new ServerDeathRecipient(serverIf)); 1158 app.callback.onServerRegistered(status, serverIf); 1159 } 1160 } 1161 1162 void onServiceAdded(int status, int serverIf, int srvcType, int srvcInstId, 1163 long srvcUuidLsb, long srvcUuidMsb, int srvcHandle) 1164 throws RemoteException { 1165 UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb); 1166 if (DBG) Log.d(TAG, "onServiceAdded() UUID=" + uuid + ", status=" + status 1167 + ", handle=" + srvcHandle); 1168 if (status == 0) 1169 mHandleMap.addService(serverIf, srvcHandle, uuid, srvcType, srvcInstId); 1170 continueServiceDeclaration(serverIf, status, srvcHandle); 1171 } 1172 1173 void onIncludedServiceAdded(int status, int serverIf, int srvcHandle, 1174 int includedSrvcHandle) throws RemoteException { 1175 if (DBG) Log.d(TAG, "onIncludedServiceAdded() status=" + status 1176 + ", service=" + srvcHandle + ", included=" + includedSrvcHandle); 1177 continueServiceDeclaration(serverIf, status, srvcHandle); 1178 } 1179 1180 void onCharacteristicAdded(int status, int serverIf, 1181 long charUuidLsb, long charUuidMsb, 1182 int srvcHandle, int charHandle) 1183 throws RemoteException { 1184 UUID uuid = new UUID(charUuidMsb, charUuidLsb); 1185 if (DBG) Log.d(TAG, "onCharacteristicAdded() UUID=" + uuid + ", status=" + status 1186 + ", srvcHandle=" + srvcHandle + ", charHandle=" + charHandle); 1187 if (status == 0) 1188 mHandleMap.addCharacteristic(serverIf, charHandle, uuid, srvcHandle); 1189 continueServiceDeclaration(serverIf, status, srvcHandle); 1190 } 1191 1192 void onDescriptorAdded(int status, int serverIf, 1193 long descrUuidLsb, long descrUuidMsb, 1194 int srvcHandle, int descrHandle) 1195 throws RemoteException { 1196 UUID uuid = new UUID(descrUuidMsb, descrUuidLsb); 1197 if (DBG) Log.d(TAG, "onDescriptorAdded() UUID=" + uuid + ", status=" + status 1198 + ", srvcHandle=" + srvcHandle + ", descrHandle=" + descrHandle); 1199 if (status == 0) 1200 mHandleMap.addDescriptor(serverIf, descrHandle, uuid, srvcHandle); 1201 continueServiceDeclaration(serverIf, status, srvcHandle); 1202 } 1203 1204 void onServiceStarted(int status, int serverIf, int srvcHandle) 1205 throws RemoteException { 1206 if (DBG) Log.d(TAG, "onServiceStarted() srvcHandle=" + srvcHandle 1207 + ", status=" + status); 1208 if (status == 0) 1209 mHandleMap.setStarted(serverIf, srvcHandle, true); 1210 } 1211 1212 void onServiceStopped(int status, int serverIf, int srvcHandle) 1213 throws RemoteException { 1214 if (DBG) Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle 1215 + ", status=" + status); 1216 if (status == 0) 1217 mHandleMap.setStarted(serverIf, srvcHandle, false); 1218 stopNextService(serverIf, status); 1219 } 1220 1221 void onServiceDeleted(int status, int serverIf, int srvcHandle) { 1222 if (DBG) Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle 1223 + ", status=" + status); 1224 mHandleMap.deleteService(serverIf, srvcHandle); 1225 } 1226 1227 void onClientConnected(String address, boolean connected, int connId, int serverIf) 1228 throws RemoteException { 1229 1230 if (DBG) Log.d(TAG, "onConnected() connId=" + connId 1231 + ", address=" + address + ", connected=" + connected); 1232 1233 ServerMap.App app = mServerMap.getById(serverIf); 1234 if (app == null) return; 1235 1236 if (connected) { 1237 mServerMap.addConnection(serverIf, connId, address); 1238 } else { 1239 mServerMap.removeConnection(serverIf, connId); 1240 } 1241 1242 app.callback.onServerConnectionState((byte)0, serverIf, connected, address); 1243 } 1244 1245 void onAttributeRead(String address, int connId, int transId, 1246 int attrHandle, int offset, boolean isLong) 1247 throws RemoteException { 1248 if (DBG) Log.d(TAG, "onAttributeRead() connId=" + connId 1249 + ", address=" + address + ", handle=" + attrHandle 1250 + ", requestId=" + transId + ", offset=" + offset); 1251 1252 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1253 if (entry == null) return; 1254 1255 if (DBG) Log.d(TAG, "onAttributeRead() UUID=" + entry.uuid 1256 + ", serverIf=" + entry.serverIf + ", type=" + entry.type); 1257 1258 mHandleMap.addRequest(transId, attrHandle); 1259 1260 ServerMap.App app = mServerMap.getById(entry.serverIf); 1261 if (app == null) return; 1262 1263 switch(entry.type) { 1264 case HandleMap.TYPE_CHARACTERISTIC: 1265 { 1266 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1267 app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, 1268 serviceEntry.serviceType, serviceEntry.instance, 1269 new ParcelUuid(serviceEntry.uuid), entry.instance, 1270 new ParcelUuid(entry.uuid)); 1271 break; 1272 } 1273 1274 case HandleMap.TYPE_DESCRIPTOR: 1275 { 1276 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1277 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1278 app.callback.onDescriptorReadRequest(address, transId, offset, isLong, 1279 serviceEntry.serviceType, serviceEntry.instance, 1280 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1281 new ParcelUuid(charEntry.uuid), 1282 new ParcelUuid(entry.uuid)); 1283 break; 1284 } 1285 1286 default: 1287 Log.e(TAG, "onAttributeRead() - Requested unknown attribute type."); 1288 break; 1289 } 1290 } 1291 1292 void onAttributeWrite(String address, int connId, int transId, 1293 int attrHandle, int offset, int length, 1294 boolean needRsp, boolean isPrep, 1295 byte[] data) 1296 throws RemoteException { 1297 if (DBG) Log.d(TAG, "onAttributeWrite() connId=" + connId 1298 + ", address=" + address + ", handle=" + attrHandle 1299 + ", requestId=" + transId + ", isPrep=" + isPrep 1300 + ", offset=" + offset); 1301 1302 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1303 if (entry == null) return; 1304 1305 if (DBG) Log.d(TAG, "onAttributeWrite() UUID=" + entry.uuid 1306 + ", serverIf=" + entry.serverIf + ", type=" + entry.type); 1307 1308 mHandleMap.addRequest(transId, attrHandle); 1309 1310 ServerMap.App app = mServerMap.getById(entry.serverIf); 1311 if (app == null) return; 1312 1313 switch(entry.type) { 1314 case HandleMap.TYPE_CHARACTERISTIC: 1315 { 1316 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1317 app.callback.onCharacteristicWriteRequest(address, transId, 1318 offset, length, isPrep, needRsp, 1319 serviceEntry.serviceType, serviceEntry.instance, 1320 new ParcelUuid(serviceEntry.uuid), entry.instance, 1321 new ParcelUuid(entry.uuid), data); 1322 break; 1323 } 1324 1325 case HandleMap.TYPE_DESCRIPTOR: 1326 { 1327 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1328 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1329 app.callback.onDescriptorWriteRequest(address, transId, 1330 offset, length, isPrep, needRsp, 1331 serviceEntry.serviceType, serviceEntry.instance, 1332 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1333 new ParcelUuid(charEntry.uuid), 1334 new ParcelUuid(entry.uuid), data); 1335 break; 1336 } 1337 1338 default: 1339 Log.e(TAG, "onAttributeWrite() - Requested unknown attribute type."); 1340 break; 1341 } 1342 } 1343 1344 void onExecuteWrite(String address, int connId, int transId, int execWrite) 1345 throws RemoteException { 1346 if (DBG) Log.d(TAG, "onExecuteWrite() connId=" + connId 1347 + ", address=" + address + ", transId=" + transId); 1348 1349 ServerMap.App app = mServerMap.getByConnId(connId); 1350 if (app == null) return; 1351 1352 app.callback.onExecuteWrite(address, transId, execWrite == 1); 1353 } 1354 1355 void onResponseSendCompleted(int status, int attrHandle) { 1356 if (DBG) Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle); 1357 } 1358 1359 /************************************************************************** 1360 * GATT Service functions - SERVER 1361 *************************************************************************/ 1362 1363 void registerServer(UUID uuid, IBluetoothGattServerCallback callback) { 1364 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1365 1366 if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid); 1367 mServerMap.add(uuid, callback); 1368 gattServerRegisterAppNative(uuid.getLeastSignificantBits(), 1369 uuid.getMostSignificantBits()); 1370 } 1371 1372 void unregisterServer(int serverIf) { 1373 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1374 1375 if (DBG) Log.d(TAG, "unregisterServer() - serverIf=" + serverIf); 1376 1377 deleteServices(serverIf); 1378 1379 mServerMap.remove(serverIf); 1380 gattServerUnregisterAppNative(serverIf); 1381 } 1382 1383 void serverConnect(int serverIf, String address, boolean isDirect) { 1384 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1385 1386 if (DBG) Log.d(TAG, "serverConnect() - address=" + address); 1387 gattServerConnectNative(serverIf, address, isDirect); 1388 } 1389 1390 void serverDisconnect(int serverIf, String address) { 1391 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1392 1393 Integer connId = mServerMap.connIdByAddress(serverIf, address); 1394 if (DBG) Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId); 1395 1396 gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0); 1397 } 1398 1399 void beginServiceDeclaration(int serverIf, int srvcType, int srvcInstanceId, 1400 int minHandles, UUID srvcUuid) { 1401 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1402 1403 if (DBG) Log.d(TAG, "beginServiceDeclaration() - uuid=" + srvcUuid); 1404 ServiceDeclaration serviceDeclaration = addDeclaration(); 1405 serviceDeclaration.addService(srvcUuid, srvcType, srvcInstanceId, minHandles); 1406 } 1407 1408 void addIncludedService(int serverIf, int srvcType, int srvcInstanceId, 1409 UUID srvcUuid) { 1410 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1411 1412 if (DBG) Log.d(TAG, "addIncludedService() - uuid=" + srvcUuid); 1413 getActiveDeclaration().addIncludedService(srvcUuid, srvcType, srvcInstanceId); 1414 } 1415 1416 void addCharacteristic(int serverIf, UUID charUuid, int properties, 1417 int permissions) { 1418 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1419 1420 if (DBG) Log.d(TAG, "addCharacteristic() - uuid=" + charUuid); 1421 getActiveDeclaration().addCharacteristic(charUuid, properties, permissions); 1422 } 1423 1424 void addDescriptor(int serverIf, UUID descUuid, int permissions) { 1425 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1426 1427 if (DBG) Log.d(TAG, "addDescriptor() - uuid=" + descUuid); 1428 getActiveDeclaration().addDescriptor(descUuid, permissions); 1429 } 1430 1431 void endServiceDeclaration(int serverIf) { 1432 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1433 1434 if (DBG) Log.d(TAG, "endServiceDeclaration()"); 1435 1436 if (getActiveDeclaration() == getPendingDeclaration()) { 1437 try { 1438 continueServiceDeclaration(serverIf, (byte)0, 0); 1439 } catch (RemoteException e) { 1440 Log.e(TAG,""+e); 1441 } 1442 } 1443 } 1444 1445 void removeService(int serverIf, int srvcType, 1446 int srvcInstanceId, UUID srvcUuid) { 1447 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1448 1449 if (DBG) Log.d(TAG, "removeService() - uuid=" + srvcUuid); 1450 1451 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 1452 if (srvcHandle == 0) return; 1453 gattServerDeleteServiceNative(serverIf, srvcHandle); 1454 } 1455 1456 void clearServices(int serverIf) { 1457 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1458 1459 if (DBG) Log.d(TAG, "clearServices()"); 1460 deleteServices(serverIf); 1461 } 1462 1463 void sendResponse(int serverIf, String address, int requestId, 1464 int status, int offset, byte[] value) { 1465 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1466 1467 if (DBG) Log.d(TAG, "sendResponse() - address=" + address); 1468 1469 int handle = 0; 1470 HandleMap.Entry entry = mHandleMap.getByRequestId(requestId); 1471 if (entry != null) handle = entry.handle; 1472 1473 int connId = mServerMap.connIdByAddress(serverIf, address); 1474 gattServerSendResponseNative(serverIf, connId, requestId, (byte)status, 1475 handle, offset, value, (byte)0); 1476 mHandleMap.deleteRequest(requestId); 1477 } 1478 1479 void sendNotification(int serverIf, String address, int srvcType, 1480 int srvcInstanceId, UUID srvcUuid, 1481 int charInstanceId, UUID charUuid, 1482 boolean confirm, byte[] value) { 1483 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1484 1485 if (DBG) Log.d(TAG, "sendNotification() - address=" + address); 1486 1487 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 1488 if (srvcHandle == 0) return; 1489 1490 int charHandle = mHandleMap.getCharacteristicHandle(srvcHandle, charUuid, charInstanceId); 1491 if (charHandle == 0) return; 1492 1493 int connId = mServerMap.connIdByAddress(serverIf, address); 1494 if (connId == 0) return; 1495 1496 if (confirm) { 1497 gattServerSendIndicationNative(serverIf, charHandle, connId, value); 1498 } else { 1499 gattServerSendNotificationNative(serverIf, charHandle, connId, value); 1500 } 1501 } 1502 1503 /************************************************************************** 1504 * Private functions 1505 *************************************************************************/ 1506 1507 private int getDeviceType(BluetoothDevice device) { 1508 int type = gattClientGetDeviceTypeNative(device.getAddress()); 1509 if (DBG) Log.d(TAG, "getDeviceType() - device=" + device 1510 + ", type=" + type); 1511 return type; 1512 } 1513 1514 private void continueSearch(int connId, int status) throws RemoteException { 1515 if (status == 0 && !mSearchQueue.isEmpty()) { 1516 SearchQueue.Entry svc = mSearchQueue.pop(); 1517 1518 if (svc.charUuidLsb == 0) { 1519 // Characteristic is up next 1520 gattClientGetCharacteristicNative(svc.connId, svc.srvcType, 1521 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 0, 0, 0); 1522 } else { 1523 // Descriptor is up next 1524 gattClientGetDescriptorNative(svc.connId, svc.srvcType, 1525 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 1526 svc.charInstId, svc.charUuidLsb, svc.charUuidMsb, 0, 0, 0); 1527 } 1528 } else { 1529 ClientMap.App app = mClientMap.getByConnId(connId); 1530 if (app != null) { 1531 app.callback.onSearchComplete(mClientMap.addressByConnId(connId), status); 1532 } 1533 } 1534 } 1535 1536 private void continueServiceDeclaration(int serverIf, int status, int srvcHandle) throws RemoteException { 1537 if (mServiceDeclarations.size() == 0) return; 1538 if (DBG) Log.d(TAG, "continueServiceDeclaration() - srvcHandle=" + srvcHandle); 1539 1540 boolean finished = false; 1541 1542 ServiceDeclaration.Entry entry = null; 1543 if (status == 0) 1544 entry = getPendingDeclaration().getNext(); 1545 1546 if (entry != null) { 1547 if (DBG) Log.d(TAG, "continueServiceDeclaration() - next entry type=" 1548 + entry.type); 1549 switch(entry.type) { 1550 case ServiceDeclaration.TYPE_SERVICE: 1551 gattServerAddServiceNative(serverIf, entry.serviceType, 1552 entry.instance, 1553 entry.uuid.getLeastSignificantBits(), 1554 entry.uuid.getMostSignificantBits(), 1555 getPendingDeclaration().getNumHandles()); 1556 break; 1557 1558 case ServiceDeclaration.TYPE_CHARACTERISTIC: 1559 gattServerAddCharacteristicNative(serverIf, srvcHandle, 1560 entry.uuid.getLeastSignificantBits(), 1561 entry.uuid.getMostSignificantBits(), 1562 entry.properties, entry.permissions); 1563 break; 1564 1565 case ServiceDeclaration.TYPE_DESCRIPTOR: 1566 gattServerAddDescriptorNative(serverIf, srvcHandle, 1567 entry.uuid.getLeastSignificantBits(), 1568 entry.uuid.getMostSignificantBits(), 1569 entry.permissions); 1570 break; 1571 1572 case ServiceDeclaration.TYPE_INCLUDED_SERVICE: 1573 { 1574 int inclSrvc = mHandleMap.getServiceHandle(entry.uuid, 1575 entry.serviceType, entry.instance); 1576 if (inclSrvc != 0) { 1577 gattServerAddIncludedServiceNative(serverIf, srvcHandle, 1578 inclSrvc); 1579 } else { 1580 finished = true; 1581 } 1582 break; 1583 } 1584 } 1585 } else { 1586 gattServerStartServiceNative(serverIf, srvcHandle, (byte)2 /*BREDR/LE*/); 1587 finished = true; 1588 } 1589 1590 if (finished) { 1591 if (DBG) Log.d(TAG, "continueServiceDeclaration() - completed."); 1592 ServerMap.App app = mServerMap.getById(serverIf); 1593 if (app != null) { 1594 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(srvcHandle); 1595 if (serviceEntry != null) { 1596 app.callback.onServiceAdded(status, serviceEntry.serviceType, 1597 serviceEntry.instance, new ParcelUuid(serviceEntry.uuid)); 1598 } else { 1599 app.callback.onServiceAdded(status, 0, 0, null); 1600 } 1601 } 1602 removePendingDeclaration(); 1603 1604 if (getPendingDeclaration() != null) { 1605 continueServiceDeclaration(serverIf, (byte)0, 0); 1606 } 1607 } 1608 } 1609 1610 private void stopNextService(int serverIf, int status) throws RemoteException { 1611 if (DBG) Log.d(TAG, "stopNextService() - serverIf=" + serverIf 1612 + ", status=" + status); 1613 1614 if (status == 0) { 1615 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 1616 for(HandleMap.Entry entry : entries) { 1617 if (entry.type != HandleMap.TYPE_SERVICE || 1618 entry.serverIf != serverIf || 1619 entry.started == false) 1620 continue; 1621 1622 gattServerStopServiceNative(serverIf, entry.handle); 1623 return; 1624 } 1625 } 1626 } 1627 1628 private void deleteServices(int serverIf) { 1629 if (DBG) Log.d(TAG, "deleteServices() - serverIf=" + serverIf); 1630 1631 /* 1632 * Figure out which handles to delete. 1633 * The handles are copied into a new list to avoid race conditions. 1634 */ 1635 List<Integer> handleList = new ArrayList<Integer>(); 1636 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 1637 for(HandleMap.Entry entry : entries) { 1638 if (entry.type != HandleMap.TYPE_SERVICE || 1639 entry.serverIf != serverIf) 1640 continue; 1641 handleList.add(entry.handle); 1642 } 1643 1644 /* Now actually delete the services.... */ 1645 for(Integer handle : handleList) { 1646 gattServerDeleteServiceNative(serverIf, handle); 1647 } 1648 } 1649 1650 private List<UUID> parseUuids(byte[] adv_data) { 1651 List<UUID> uuids = new ArrayList<UUID>(); 1652 1653 int offset = 0; 1654 while(offset < (adv_data.length-2)) { 1655 int len = adv_data[offset++]; 1656 if (len == 0) break; 1657 1658 int type = adv_data[offset++]; 1659 switch (type) { 1660 case 0x02: // Partial list of 16-bit UUIDs 1661 case 0x03: // Complete list of 16-bit UUIDs 1662 while (len > 1) { 1663 int uuid16 = adv_data[offset++]; 1664 uuid16 += (adv_data[offset++] << 8); 1665 len -= 2; 1666 uuids.add(UUID.fromString(String.format( 1667 "%08x-0000-1000-8000-00805f9b34fb", uuid16))); 1668 } 1669 break; 1670 1671 default: 1672 offset += (len - 1); 1673 break; 1674 } 1675 } 1676 1677 return uuids; 1678 } 1679 1680 /************************************************************************** 1681 * GATT Test functions 1682 *************************************************************************/ 1683 1684 void gattTestCommand(int command, UUID uuid1, String bda1, 1685 int p1, int p2, int p3, int p4, int p5) { 1686 if (bda1 == null) bda1 = "00:00:00:00:00:00"; 1687 if (uuid1 != null) 1688 gattTestNative(command, uuid1.getLeastSignificantBits(), 1689 uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5); 1690 else 1691 gattTestNative(command, 0,0, bda1, p1, p2, p3, p4, p5); 1692 } 1693 1694 private native void gattTestNative(int command, 1695 long uuid1_lsb, long uuid1_msb, String bda1, 1696 int p1, int p2, int p3, int p4, int p5); 1697 1698 /************************************************************************** 1699 * Native functions prototypes 1700 *************************************************************************/ 1701 1702 private native static void classInitNative(); 1703 private native void initializeNative(); 1704 private native void cleanupNative(); 1705 1706 private native int gattClientGetDeviceTypeNative(String address); 1707 1708 private native void gattClientRegisterAppNative(long app_uuid_lsb, 1709 long app_uuid_msb); 1710 1711 private native void gattClientUnregisterAppNative(int clientIf); 1712 1713 private native void gattClientScanNative(int clientIf, boolean start); 1714 1715 private native void gattClientConnectNative(int clientIf, String address, 1716 boolean isDirect); 1717 1718 private native void gattClientDisconnectNative(int clientIf, String address, 1719 int conn_id); 1720 1721 private native void gattClientRefreshNative(int clientIf, String address); 1722 1723 private native void gattClientSearchServiceNative(int conn_id, 1724 boolean search_all, long service_uuid_lsb, long service_uuid_msb); 1725 1726 private native void gattClientGetCharacteristicNative(int conn_id, 1727 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 1728 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 1729 long char_id_uuid_msb); 1730 1731 private native void gattClientGetDescriptorNative(int conn_id, int service_type, 1732 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 1733 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 1734 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb); 1735 1736 private native void gattClientGetIncludedServiceNative(int conn_id, 1737 int service_type, int service_id_inst_id, 1738 long service_id_uuid_lsb, long service_id_uuid_msb, 1739 int incl_service_id_inst_id, int incl_service_type, 1740 long incl_service_id_uuid_lsb, long incl_service_id_uuid_msb); 1741 1742 private native void gattClientReadCharacteristicNative(int conn_id, 1743 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 1744 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 1745 long char_id_uuid_msb, int authReq); 1746 1747 private native void gattClientReadDescriptorNative(int conn_id, int service_type, 1748 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 1749 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 1750 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, 1751 int authReq); 1752 1753 private native void gattClientWriteCharacteristicNative(int conn_id, 1754 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 1755 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 1756 long char_id_uuid_msb, int write_type, int auth_req, byte[] value); 1757 1758 private native void gattClientWriteDescriptorNative(int conn_id, int service_type, 1759 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 1760 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 1761 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, 1762 int write_type, int auth_req, byte[] value); 1763 1764 private native void gattClientExecuteWriteNative(int conn_id, boolean execute); 1765 1766 private native void gattClientRegisterForNotificationsNative(int clientIf, 1767 String address, int service_type, int service_id_inst_id, 1768 long service_id_uuid_lsb, long service_id_uuid_msb, 1769 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 1770 boolean enable); 1771 1772 private native void gattClientReadRemoteRssiNative(int clientIf, 1773 String address); 1774 1775 private native void gattClientListenNative(int client_if, boolean start); 1776 1777 private native void gattSetAdvDataNative(int serverIf, boolean setScanRsp, boolean inclName, 1778 boolean inclTxPower, int minInterval, int maxInterval, 1779 int appearance, byte[] manufacturerData); 1780 1781 private native void gattServerRegisterAppNative(long app_uuid_lsb, 1782 long app_uuid_msb); 1783 1784 private native void gattServerUnregisterAppNative(int serverIf); 1785 1786 private native void gattServerConnectNative(int server_if, String address, 1787 boolean is_direct); 1788 1789 private native void gattServerDisconnectNative(int serverIf, String address, 1790 int conn_id); 1791 1792 private native void gattServerAddServiceNative (int server_if, 1793 int service_type, int service_id_inst_id, 1794 long service_id_uuid_lsb, long service_id_uuid_msb, 1795 int num_handles); 1796 1797 private native void gattServerAddIncludedServiceNative (int server_if, 1798 int svc_handle, int included_svc_handle); 1799 1800 private native void gattServerAddCharacteristicNative (int server_if, 1801 int svc_handle, long char_uuid_lsb, long char_uuid_msb, 1802 int properties, int permissions); 1803 1804 private native void gattServerAddDescriptorNative (int server_if, 1805 int svc_handle, long desc_uuid_lsb, long desc_uuid_msb, 1806 int permissions); 1807 1808 private native void gattServerStartServiceNative (int server_if, 1809 int svc_handle, int transport ); 1810 1811 private native void gattServerStopServiceNative (int server_if, 1812 int svc_handle); 1813 1814 private native void gattServerDeleteServiceNative (int server_if, 1815 int svc_handle); 1816 1817 private native void gattServerSendIndicationNative (int server_if, 1818 int attr_handle, int conn_id, byte[] val); 1819 1820 private native void gattServerSendNotificationNative (int server_if, 1821 int attr_handle, int conn_id, byte[] val); 1822 1823 private native void gattServerSendResponseNative (int server_if, 1824 int conn_id, int trans_id, int status, int handle, int offset, 1825 byte[] val, int auth_req); 1826} 1827