GattService.java revision 00975169ba4eb5251397a66532ee9a3288c0f137
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 2a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Copyright (C) 2013 The Android Open Source Project 3d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt * 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Licensed under the Apache License, Version 2.0 (the "License"); 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * you may not use this file except in compliance with the License. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * You may obtain a copy of the License at 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * http://www.apache.org/licenses/LICENSE-2.0 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Unless required by applicable law or agreed to in writing, software 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * distributed under the License is distributed on an "AS IS" BASIS, 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See the License for the specific language governing permissions and 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * limitations under the License. 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtpackage com.android.bluetooth.gatt; 1861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport android.app.Service; 2061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport android.bluetooth.BluetoothAdapter; 2161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport android.bluetooth.BluetoothDevice; 22a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtimport android.bluetooth.BluetoothGatt; 23a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtimport android.bluetooth.BluetoothProfile; 24a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtimport android.bluetooth.IBluetoothGatt; 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport android.bluetooth.IBluetoothGattCallback; 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport android.bluetooth.IBluetoothGattServerCallback; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport android.bluetooth.le.AdvertiseCallback; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport android.bluetooth.le.AdvertiseData; 29fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtimport android.bluetooth.le.AdvertiseSettings; 30fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtimport android.bluetooth.le.ScanFilter; 31807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidtimport android.bluetooth.le.ScanRecord; 324ae50e65ef0eefe6d5c356acbc1839f8eac68af5Dmitry Shmidtimport android.bluetooth.le.ScanResult; 334ae50e65ef0eefe6d5c356acbc1839f8eac68af5Dmitry Shmidtimport android.bluetooth.le.ScanSettings; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport android.content.Intent; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtimport android.os.IBinder; 361d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidtimport android.os.ParcelUuid; 371d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidtimport android.os.RemoteException; 381d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidtimport android.os.SystemClock; 391d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidtimport android.util.Log; 401d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt 411d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidtimport com.android.bluetooth.Utils; 421d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidtimport com.android.bluetooth.btservice.ProfileService; 431d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt 441d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidtimport java.util.ArrayList; 451d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidtimport java.util.Arrays; 461d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidtimport java.util.Collections; 471d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidtimport java.util.HashMap; 481d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidtimport java.util.HashSet; 491d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidtimport java.util.List; 501d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidtimport java.util.Map; 511d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidtimport java.util.Set; 527f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidtimport java.util.UUID; 537f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidtimport java.util.concurrent.TimeUnit; 5457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 551d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt/** 561d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt * Provides Bluetooth Gatt profile, as a service in 571d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt * the Bluetooth application. 581d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt * @hide 591d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt */ 601d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidtpublic class GattService extends ProfileService { 611d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt private static final boolean DBG = GattServiceConfig.DBG; 621d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt private static final boolean VDBG = GattServiceConfig.VDBG; 631d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt private static final String TAG = GattServiceConfig.TAG_PREFIX + "GattService"; 641d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt 651d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt static final int SCAN_FILTER_ENABLED = 1; 661d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt static final int SCAN_FILTER_MODIFIED = 2; 671d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt 681d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt /** 691d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt * Scan params corresponding to scan setting 701d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt */ 711d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt private static final int SCAN_MODE_LOW_POWER_WINDOW_MS = 500; 727f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt private static final int SCAN_MODE_LOW_POWER_INTERVAL_MS = 5000; 737f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt private static final int SCAN_MODE_BALANCED_WINDOW_MS = 2000; 747f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt private static final int SCAN_MODE_BALANCED_INTERVAL_MS = 5000; 751d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt private static final int SCAN_MODE_LOW_LATENCY_WINDOW_MS = 5000; 761d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt private static final int SCAN_MODE_LOW_LATENCY_INTERVAL_MS = 5000; 771d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt 781d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt private static final int MAC_ADDRESS_LENGTH = 6; 791d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt // Batch scan related constants. 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private static final int TRUNCATED_RESULT_SIZE = 11; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private static final int TIME_STAMP_LENGTH = 2; 827f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 837f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt // onFoundLost related constants 847f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt private static final int ADVT_STATE_ONFOUND = 0; 857f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt private static final int ADVT_STATE_ONLOST = 1; 867f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Search queue to serialize remote onbject inspection. 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SearchQueue mSearchQueue = new SearchQueue(); 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * List of our registered clients. 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt class ClientMap extends ContextMap<IBluetoothGattCallback> {} 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ClientMap mClientMap = new ClientMap(); 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * List of our registered server apps. 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt class ServerMap extends ContextMap<IBluetoothGattServerCallback> {} 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ServerMap mServerMap = new ServerMap(); 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 1067f2c753f60025528366b5f19b8b490a47bf5080bDmitry Shmidt * Server handle map. 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HandleMap mHandleMap = new HandleMap(); 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private List<UUID> mAdvertisingServiceUuids = new ArrayList<UUID>(); 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private int mMaxScanFilters; 112092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 113092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart /** 114092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart * Pending service declaration queue 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt private List<ServiceDeclaration> mServiceDeclarations = new ArrayList<ServiceDeclaration>(); 11761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private ServiceDeclaration addDeclaration() { 11955840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt synchronized (mServiceDeclarations) { 12055840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt mServiceDeclarations.add(new ServiceDeclaration()); 12155840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt } 12255840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt return getActiveDeclaration(); 12355840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt } 12455840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt 12555840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt private ServiceDeclaration getActiveDeclaration() { 12655840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt synchronized (mServiceDeclarations) { 12755840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt if (mServiceDeclarations.size() > 0) 12855840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt return mServiceDeclarations.get(mServiceDeclarations.size() - 1); 12955840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt } 13055840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt return null; 13155840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt } 13255840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt 13355840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt private ServiceDeclaration getPendingDeclaration() { 13455840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt synchronized (mServiceDeclarations) { 13555840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt if (mServiceDeclarations.size() > 0) 13655840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt return mServiceDeclarations.get(0); 13755840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt } 13855840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt return null; 13955840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt } 14055840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt 14155840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt private void removePendingDeclaration() { 14255840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt synchronized (mServiceDeclarations) { 14355840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt if (mServiceDeclarations.size() > 0) 14455840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt mServiceDeclarations.remove(0); 14555840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt } 14655840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt } 14755840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt 14855840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt private AdvertiseManager mAdvertiseManager; 14955840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt private ScanManager mScanManager; 15055840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt 15155840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt /** 15255840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt * Reliable write queue 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private Set<String> mReliableQueue = new HashSet<String>(); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 156d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt static { 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt classInitNative(); 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt protected String getName() { 161d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return TAG; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 164d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt protected IProfileServiceBinder initBinder() { 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return new BluetoothGattBinder(this); 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt protected boolean start() { 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (DBG) Log.d(TAG, "start()"); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt initializeNative(); 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mAdvertiseManager = new AdvertiseManager(this); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mAdvertiseManager.start(); 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mScanManager = new ScanManager(this); 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mScanManager.start(); 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return true; 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1799ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt protected boolean stop() { 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (DBG) Log.d(TAG, "stop()"); 182d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt mClientMap.clear(); 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mServerMap.clear(); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mSearchQueue.clear(); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mHandleMap.clear(); 186d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt mServiceDeclarations.clear(); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mReliableQueue.clear(); 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mAdvertiseManager.cleanup(); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mScanManager.cleanup(); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return true; 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1931d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt protected boolean cleanup() { 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (DBG) Log.d(TAG, "cleanup()"); 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cleanupNative(); 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mAdvertiseManager.cleanup(); 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mScanManager.cleanup(); 1981d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt return true; 1991d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt } 2001d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt 2011d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt @Override 2021d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt public int onStartCommand(Intent intent, int flags, int startId) { 2031d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt if (GattDebugUtils.handleDebugAction(this, intent)) { 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return Service.START_NOT_STICKY; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return super.onStartCommand(intent, flags, startId); 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /** 2101d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt * DeathReceipient handlers used to unregister applications that 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * disconnect ungracefully (ie. crash or forced close). 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt class ClientDeathRecipient implements IBinder.DeathRecipient { 2151d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt int mAppIf; 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public ClientDeathRecipient(int appIf) { 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mAppIf = appIf; 2191d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt } 22057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public void binderDied() { 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (DBG) Log.d(TAG, "Binder is dead - unregistering client (" + mAppIf + ")!"); 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (isScanClient(mAppIf)) { 224d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt stopScan(mAppIf, false); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt stopMultiAdvertising(mAppIf); 227d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // TODO: Move unregisterClient after stop scan/advertise callback to avoid race 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // condition. 23061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt unregisterClient(mAppIf); 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 232d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private boolean isScanClient(int clientIf) { 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (ScanClient client : mScanManager.getRegularScanQueue()) { 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (client.clientIf == clientIf) { 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return true; 23761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (ScanClient client : mScanManager.getBatchScanQueue()) { 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (client.clientIf == clientIf) { 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return true; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return false; 24561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt class ServerDeathRecipient implements IBinder.DeathRecipient { 249d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int mAppIf; 250092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 251092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart public ServerDeathRecipient(int appIf) { 252092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart mAppIf = appIf; 253092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart } 254092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart 255092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart public void binderDied() { 256092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart if (DBG) Log.d(TAG, "Binder is dead - unregistering server (" + mAppIf + ")!"); 257092955c7394ee96d6c8c9724ff46a3c038b36143Paul Stewart unregisterServer(mAppIf); 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 259d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 260d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 261d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt /** 262d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt * Handlers for incoming service calls 263d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt */ 264d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt private static class BluetoothGattBinder extends IBluetoothGatt.Stub implements IProfileServiceBinder { 265d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt private GattService mService; 266d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 267d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt public BluetoothGattBinder(GattService svc) { 26861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt mService = svc; 26961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 27061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 27161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt public boolean cleanup() { 27261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt mService = null; 2739ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt return true; 27461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 27561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 2769ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt private GattService getService() { 27761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (mService != null && mService.isAvailable()) return mService; 27861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt Log.e(TAG, "getService() - Service requested, but not available!"); 27961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return null; 28061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 28161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 28261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 28361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt GattService service = getService(); 28461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (service == null) return new ArrayList<BluetoothDevice>(); 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return service.getDevicesMatchingConnectionStates(states); 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 28761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 28861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt public void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback) { 28961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt GattService service = getService(); 2901d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt if (service == null) return; 2911d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt service.registerClient(uuid.getUuid(), callback); 2921d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt } 29361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 29461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt public void unregisterClient(int clientIf) { 29561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt GattService service = getService(); 29661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (service == null) return; 2971d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt service.unregisterClient(clientIf); 29861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt @Override 30161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt public void startScan(int appIf, boolean isServer, ScanSettings settings, 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt List<ScanFilter> filters) { 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GattService service = getService(); 30461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (service == null) return; 30561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt service.startScan(appIf, isServer, settings, filters); 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public void stopScan(int appIf, boolean isServer) { 309d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt GattService service = getService(); 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (service == null) return; 31161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt service.stopScan(appIf, isServer); 31261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 31361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 31461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt @Override 31561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt public void flushPendingBatchResults(int appIf, boolean isServer) { 316d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt GattService service = getService(); 31761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (service == null) return; 318d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt service.flushPendingBatchResults(appIf, isServer); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public void clientConnect(int clientIf, String address, boolean isDirect, int transport) { 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GattService service = getService(); 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (service == null) return; 32461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt service.clientConnect(clientIf, address, isDirect, transport); 32561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 32661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 32761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt public void clientDisconnect(int clientIf, String address) { 32861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt GattService service = getService(); 32961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (service == null) return; 33061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt service.clientDisconnect(clientIf, address); 33161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 33261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 33361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt public void refreshDevice(int clientIf, String address) { 33461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt GattService service = getService(); 3351d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt if (service == null) return; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt service.refreshDevice(clientIf, address); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public void discoverServices(int clientIf, String address) { 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GattService service = getService(); 34161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (service == null) return; 34261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt service.discoverServices(clientIf, address); 34361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 3441d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt 3451d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt public void readCharacteristic(int clientIf, String address, int srvcType, 3461d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt int srvcInstanceId, ParcelUuid srvcId, 34761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int charInstanceId, ParcelUuid charId, 34861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int authReq) { 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GattService service = getService(); 35061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (service == null) return; 3511d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt service.readCharacteristic(clientIf, address, srvcType, srvcInstanceId, 35261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt srvcId.getUuid(), charInstanceId, 35361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt charId.getUuid(), authReq); 35461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 3551d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public void writeCharacteristic(int clientIf, String address, int srvcType, 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int srvcInstanceId, ParcelUuid srvcId, 35861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int charInstanceId, ParcelUuid charId, 35961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int writeType, int authReq, byte[] value) { 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GattService service = getService(); 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (service == null) return; 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt service.writeCharacteristic(clientIf, address, srvcType, srvcInstanceId, 363d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt srvcId.getUuid(), charInstanceId, 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt charId.getUuid(), writeType, authReq, 36561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt value); 36661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 36761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 36861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt public void readDescriptor(int clientIf, String address, int srvcType, 36961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int srvcInstanceId, ParcelUuid srvcId, 370d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int charInstanceId, ParcelUuid charId, 37161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int descrInstanceId, ParcelUuid descrId, 372d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int authReq) { 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GattService service = getService(); 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (service == null) return; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt service.readDescriptor(clientIf, address, srvcType, 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srvcInstanceId, srvcId.getUuid(), 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt charInstanceId, charId.getUuid(), 37861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt descrInstanceId, descrId.getUuid(), 37961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt authReq); 38061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 38161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 38261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt public void writeDescriptor(int clientIf, String address, int srvcType, 38361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int srvcInstanceId, ParcelUuid srvcId, 38461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int charInstanceId, ParcelUuid charId, 38561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int descrInstanceId, ParcelUuid descrId, 38661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int writeType, int authReq, byte[] value) { 38761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt GattService service = getService(); 38861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (service == null) return; 3891d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt service.writeDescriptor(clientIf, address, srvcType, 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srvcInstanceId, srvcId.getUuid(), 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt charInstanceId, charId.getUuid(), 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt descrInstanceId, descrId.getUuid(), 393d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt writeType, authReq, value); 394d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 395d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 396216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt public void beginReliableWrite(int clientIf, String address) { 397216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt GattService service = getService(); 398216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (service == null) return; 399216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt service.beginReliableWrite(clientIf, address); 400216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 401ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt 402ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt public void endReliableWrite(int clientIf, String address, boolean execute) { 403216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt GattService service = getService(); 404216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (service == null) return; 405216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt service.endReliableWrite(clientIf, address, execute); 406216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 407216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 408216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt public void registerForNotification(int clientIf, String address, int srvcType, 409216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt int srvcInstanceId, ParcelUuid srvcId, 410216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt int charInstanceId, ParcelUuid charId, 411216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt boolean enable) { 412216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt GattService service = getService(); 413216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (service == null) return; 414216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt service.registerForNotification(clientIf, address, srvcType, srvcInstanceId, 415216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt srvcId.getUuid(), charInstanceId, 416216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt charId.getUuid(), enable); 417ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt } 418ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt 419216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt public void readRemoteRssi(int clientIf, String address) { 420216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt GattService service = getService(); 421216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (service == null) return; 422216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt service.readRemoteRssi(clientIf, address); 423216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 424216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 425216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt public void configureMTU(int clientIf, String address, int mtu) { 426d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt GattService service = getService(); 427d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (service == null) return; 428d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt service.configureMTU(clientIf, address, mtu); 429216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 430912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt 431912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt public void connectionParameterUpdate(int clientIf, String address, 4321d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt int connectionPriority) { 433912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt GattService service = getService(); 434912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt if (service == null) return; 4351d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt service.connectionParameterUpdate(clientIf, address, connectionPriority); 436912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt } 437d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 438d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt public void registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback) { 439d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt GattService service = getService(); 4401d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt if (service == null) return; 4411d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt service.registerServer(uuid.getUuid(), callback); 442912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt } 443912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt 444912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt public void unregisterServer(int serverIf) { 4451d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt GattService service = getService(); 4461d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt if (service == null) return; 4471d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt service.unregisterServer(serverIf); 4481d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt } 4491d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt 4501d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt public void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 45157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt GattService service = getService(); 452912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt if (service == null) return; 4531d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt service.serverConnect(serverIf, address, isDirect, transport); 454912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt } 455912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt 456912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt public void serverDisconnect(int serverIf, String address) { 457912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt GattService service = getService(); 458912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt if (service == null) return; 4591d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt service.serverDisconnect(serverIf, address); 460912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt } 461912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt 4621d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt public void beginServiceDeclaration(int serverIf, int srvcType, 463912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt int srvcInstanceId, int minHandles, 464d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt ParcelUuid srvcId, boolean advertisePreferred) { 465d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt GattService service = getService(); 466d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (service == null) return; 4671d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt service.beginServiceDeclaration(serverIf, srvcType, srvcInstanceId, 4681d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt minHandles, srvcId.getUuid(), advertisePreferred); 469912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt } 470912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt 471912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt public void addIncludedService(int serverIf, int srvcType, 4721d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt int srvcInstanceId, ParcelUuid srvcId) { 4731d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt GattService service = getService(); 4741d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt if (service == null) return; 4751d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt service.addIncludedService(serverIf, srvcType, srvcInstanceId, 4761d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt srvcId.getUuid()); 4771d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt } 47857c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 4791d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt public void addCharacteristic(int serverIf, ParcelUuid charId, 4801d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt int properties, int permissions) { 481912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt GattService service = getService(); 482912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt if (service == null) return; 483912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt service.addCharacteristic(serverIf, charId.getUuid(), properties, 484912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt permissions); 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public void addDescriptor(int serverIf, ParcelUuid descId, 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int permissions) { 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GattService service = getService(); 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (service == null) return; 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt service.addDescriptor(serverIf, descId.getUuid(), permissions); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public void endServiceDeclaration(int serverIf) { 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GattService service = getService(); 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (service == null) return; 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt service.endServiceDeclaration(serverIf); 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public void removeService(int serverIf, int srvcType, 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int srvcInstanceId, ParcelUuid srvcId) { 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GattService service = getService(); 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (service == null) return; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt service.removeService(serverIf, srvcType, srvcInstanceId, 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srvcId.getUuid()); 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public void clearServices(int serverIf) { 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GattService service = getService(); 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (service == null) return; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt service.clearServices(serverIf); 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5147f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt public void sendResponse(int serverIf, String address, int requestId, 5157f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt int status, int offset, byte[] value) { 5167f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt GattService service = getService(); 5177f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt if (service == null) return; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt service.sendResponse(serverIf, address, requestId, status, offset, value); 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public void sendNotification(int serverIf, String address, int srvcType, 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int srvcInstanceId, ParcelUuid srvcId, 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int charInstanceId, ParcelUuid charId, 5241d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt boolean confirm, byte[] value) { 5251d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt GattService service = getService(); 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (service == null) return; 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt service.sendNotification(serverIf, address, srvcType, srvcInstanceId, 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srvcId.getUuid(), charInstanceId, charId.getUuid(), confirm, value); 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt @Override 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public void startMultiAdvertising(int clientIf, AdvertiseData advertiseData, 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt AdvertiseData scanResponse, AdvertiseSettings settings) { 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GattService service = getService(); 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (service == null) return; 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt service.startMultiAdvertising(clientIf, advertiseData, scanResponse, settings); 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt @Override 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt public void stopMultiAdvertising(int clientIf) { 541d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt GattService service = getService(); 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (service == null) return; 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt service.stopMultiAdvertising(clientIf); 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 547d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt /************************************************************************** 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Callback functions - CLIENT 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *************************************************************************/ 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void onScanResult(String address, int rssi, byte[] adv_data) { 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (VDBG) Log.d(TAG, "onScanResult() - address=" + address 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt + ", rssi=" + rssi); 5549ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt ScanRecord record = ScanRecord.parseFromBytes(adv_data); 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt List<UUID> remoteUuids = parseUuids(adv_data); 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (ScanClient client : mScanManager.getRegularScanQueue()) { 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (client.uuids.length > 0) { 5589ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt int matches = 0; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (UUID search : client.uuids) { 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (UUID remote: remoteUuids) { 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (remote.equals(search)) { 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ++matches; 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; // Only count 1st match in case of duplicates 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (matches < client.uuids.length) continue; 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!client.isServer) { 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ClientMap.App app = mClientMap.getById(client.clientIf); 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (app != null) { 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BluetoothDevice device = BluetoothAdapter.getDefaultAdapter() 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .getRemoteDevice(address); 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt long scanTimeNanos = 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TimeUnit.NANOSECONDS.toMicros(SystemClock.elapsedRealtimeNanos()); 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ScanResult result = new ScanResult(device, ScanRecord.parseFromBytes(adv_data), 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rssi, scanTimeNanos); 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (matchesFilters(client, result)) { 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt try { 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt app.callback.onScanResult(result); 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } catch (RemoteException e) { 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Log.e(TAG, "Exception: " + e); 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mClientMap.remove(client.clientIf); 5861d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt mScanManager.stopScan(client); 5871d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt } 5881d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt } 5891d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt } 5901d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt } else { 5911d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt ServerMap.App app = mServerMap.getById(client.clientIf); 59257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (app != null) { 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt try { 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt app.callback.onScanResult(address, rssi, adv_data); 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } catch (RemoteException e) { 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt Log.e(TAG, "Exception: " + e); 5971d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt mServerMap.remove(client.clientIf); 5981d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt mScanManager.stopScan(client); 5991d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt } 6001d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt } 6011d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt } 60257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt } 6031d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt } 60457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // Check if a scan record matches a specific filters. 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt private boolean matchesFilters(ScanClient client, ScanResult scanResult) { 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (client.filters == null || client.filters.isEmpty()) { 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return true; 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (DBG) Log.d(TAG, "result: " + scanResult.toString()); 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (ScanFilter filter : client.filters) { 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (DBG) Log.d(TAG, "filter: " + filter.toString()); 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (filter.matches(scanResult)) { 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return true; 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6171d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt return false; 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb) 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt throws RemoteException { 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt UUID uuid = new UUID(uuidMsb, uuidLsb); 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (DBG) Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf); 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ClientMap.App app = mClientMap.getByUuid(uuid); 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (app != null) { 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt app.id = clientIf; 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt app.linkToDeath(new ClientDeathRecipient(clientIf)); 6281d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt app.callback.onClientRegistered(status, clientIf); 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void onConnected(int clientIf, int connId, int status, String address) 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt throws RemoteException { 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (DBG) Log.d(TAG, "onConnected() - clientIf=" + clientIf 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt + ", connId=" + connId + ", address=" + address); 63657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt 63757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (status == 0) mClientMap.addConnection(clientIf, connId, address); 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ClientMap.App app = mClientMap.getById(clientIf); 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (app != null) { 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt app.callback.onClientConnectionState(status, clientIf, true, address); 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6449839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt void onDisconnected(int clientIf, int connId, int status, String address) 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt throws RemoteException { 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (DBG) Log.d(TAG, "onDisconnected() - clientIf=" + clientIf 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt + ", connId=" + connId + ", address=" + address); 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mClientMap.removeConnection(clientIf, connId); 650849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt mSearchQueue.removeConnId(connId); 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ClientMap.App app = mClientMap.getById(clientIf); 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (app != null) { 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt app.callback.onClientConnectionState(status, clientIf, false, address); 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void onSearchCompleted(int connId, int status) throws RemoteException { 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (DBG) Log.d(TAG, "onSearchCompleted() - connId=" + connId+ ", status=" + status); 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // We got all services, now let's explore characteristics... 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continueSearch(connId, status); 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void onSearchResult(int connId, int srvcType, 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int srvcInstId, long srvcUuidLsb, long srvcUuidMsb) 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt throws RemoteException { 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb); 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt String address = mClientMap.addressByConnId(connId); 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (VDBG) Log.d(TAG, "onSearchResult() - address=" + address + ", uuid=" + uuid); 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mSearchQueue.add(connId, srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb); 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ClientMap.App app = mClientMap.getByConnId(connId); 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (app != null) { 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt app.callback.onGetService(address, srvcType, srvcInstId, 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new ParcelUuid(uuid)); 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void onGetCharacteristic(int connId, int status, int srvcType, 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int charInstId, long charUuidLsb, long charUuidMsb, 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int charProp) throws RemoteException { 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 685ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 686ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt String address = mClientMap.addressByConnId(connId); 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 689849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt if (VDBG) Log.d(TAG, "onGetCharacteristic() - address=" + address 690849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt + ", status=" + status + ", charUuid=" + charUuid + ", prop=" + charProp); 691849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt 692849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt if (status == 0) { 6934ae50e65ef0eefe6d5c356acbc1839f8eac68af5Dmitry Shmidt mSearchQueue.add(connId, srvcType, 6944ae50e65ef0eefe6d5c356acbc1839f8eac68af5Dmitry Shmidt srvcInstId, srvcUuidLsb, srvcUuidMsb, 695849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt charInstId, charUuidLsb, charUuidMsb); 696849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt 697849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt ClientMap.App app = mClientMap.getByConnId(connId); 698849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt if (app != null) { 699849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt app.callback.onGetCharacteristic(address, srvcType, 700849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt srvcInstId, new ParcelUuid(srvcUuid), 701849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt charInstId, new ParcelUuid(charUuid), charProp); 702849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt } 703849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt 704849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt // Get next characteristic in the current service 705849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt gattClientGetCharacteristicNative(connId, srvcType, 706849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt srvcInstId, srvcUuidLsb, srvcUuidMsb, 707849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt charInstId, charUuidLsb, charUuidMsb); 708849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt } else { 709849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt // Check for included services next 710849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt gattClientGetIncludedServiceNative(connId, 711849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb, 712849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt 0,0,0,0); 713849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt } 714849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt } 715849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt 716849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt void onGetDescriptor(int connId, int status, int srvcType, 717849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 718849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt int charInstId, long charUuidLsb, long charUuidMsb, 719849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt int descrInstId, long descrUuidLsb, long descrUuidMsb) throws RemoteException { 720849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt 721849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 722849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 723849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt UUID descUuid = new UUID(descrUuidMsb, descrUuidLsb); 724849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt String address = mClientMap.addressByConnId(connId); 725849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt 726849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt if (VDBG) Log.d(TAG, "onGetDescriptor() - address=" + address 727849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt + ", status=" + status + ", descUuid=" + descUuid); 728849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt 729849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt if (status == 0) { 730849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt ClientMap.App app = mClientMap.getByConnId(connId); 731849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt if (app != null) { 732849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt app.callback.onGetDescriptor(address, srvcType, 733849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt srvcInstId, new ParcelUuid(srvcUuid), 734849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt charInstId, new ParcelUuid(charUuid), 735849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt descrInstId, new ParcelUuid(descUuid)); 736849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt } 737849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt 738849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt // Get next descriptor for the current characteristic 739849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt gattClientGetDescriptorNative(connId, srvcType, 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srvcInstId, srvcUuidLsb, srvcUuidMsb, 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt charInstId, charUuidLsb, charUuidMsb, 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt descrInstId, descrUuidLsb, descrUuidMsb); 74304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else { 74404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt // Explore the next service 7459839ecd75c832023d4d13fd2917a8c28261ff668Dmitry Shmidt continueSearch(connId, 0); 74604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 74704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 74804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 74904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt void onGetIncludedService(int connId, int status, int srvcType, 75004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int inclSrvcType, 75104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int inclSrvcInstId, long inclSrvcUuidLsb, long inclSrvcUuidMsb) 75204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt throws RemoteException { 75304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 75404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt UUID inclSrvcUuid = new UUID(inclSrvcUuidMsb, inclSrvcUuidLsb); 75504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt String address = mClientMap.addressByConnId(connId); 75604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 75704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (VDBG) Log.d(TAG, "onGetIncludedService() - address=" + address 75804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt + ", status=" + status + ", uuid=" + srvcUuid 75904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt + ", inclUuid=" + inclSrvcUuid); 76004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 76104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (status == 0) { 76204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ClientMap.App app = mClientMap.getByConnId(connId); 76304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (app != null) { 76404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt app.callback.onGetIncludedService(address, 76504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt srvcType, srvcInstId, new ParcelUuid(srvcUuid), 76604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt inclSrvcType, inclSrvcInstId, new ParcelUuid(inclSrvcUuid)); 76704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 76804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 76904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt // Find additional included services 77004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt gattClientGetIncludedServiceNative(connId, 77104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb, 77204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt inclSrvcType, inclSrvcInstId, inclSrvcUuidLsb, inclSrvcUuidMsb); 77304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else { 77404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt // Discover descriptors now 77504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continueSearch(connId, 0); 776849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt } 777849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt } 778849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt 779849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt void onRegisterForNotifications(int connId, int status, int registered, int srvcType, 780849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 781849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt int charInstId, long charUuidLsb, long charUuidMsb) { 782849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 783849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 784849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt String address = mClientMap.addressByConnId(connId); 785849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt 786849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt if (DBG) Log.d(TAG, "onRegisterForNotifications() - address=" + address 787849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt + ", status=" + status + ", registered=" + registered 788849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt + ", charUuid=" + charUuid); 789849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt } 790849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt 791849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt void onNotify(int connId, String address, int srvcType, 792849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 793849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt int charInstId, long charUuidLsb, long charUuidMsb, 79458d12adcdf693a076f719cef9b9f2ccf81892045Dmitry Shmidt boolean isNotify, byte[] data) throws RemoteException { 795849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 796849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 797849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt 798849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt if (VDBG) Log.d(TAG, "onNotify() - address=" + address 799849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt + ", charUuid=" + charUuid + ", length=" + data.length); 800849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt 801849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt ClientMap.App app = mClientMap.getByConnId(connId); 802849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt if (app != null) { 803849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt app.callback.onNotify(address, srvcType, 804849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt srvcInstId, new ParcelUuid(srvcUuid), 805849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt charInstId, new ParcelUuid(charUuid), 806849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt data); 807849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt } 808849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt } 809849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt 810849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt void onReadCharacteristic(int connId, int status, int srvcType, 811849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 81204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int charInstId, long charUuidLsb, long charUuidMsb, 81304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int charType, byte[] data) throws RemoteException { 81404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt String address = mClientMap.addressByConnId(connId); 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (VDBG) Log.d(TAG, "onReadCharacteristic() - address=" + address 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt + ", status=" + status + ", length=" + data.length); 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ClientMap.App app = mClientMap.getByConnId(connId); 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (app != null) { 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt app.callback.onCharacteristicRead(address, status, srvcType, 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srvcInstId, new ParcelUuid(srvcUuid), 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt charInstId, new ParcelUuid(charUuid), data); 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void onWriteCharacteristic(int connId, int status, int srvcType, 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int charInstId, long charUuidLsb, long charUuidMsb) 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt throws RemoteException { 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt String address = mClientMap.addressByConnId(connId); 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (VDBG) Log.d(TAG, "onWriteCharacteristic() - address=" + address 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt + ", status=" + status); 8417f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ClientMap.App app = mClientMap.getByConnId(connId); 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (app != null) { 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt app.callback.onCharacteristicWrite(address, status, srvcType, 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt srvcInstId, new ParcelUuid(srvcUuid), 8467f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt charInstId, new ParcelUuid(charUuid)); 847ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void onExecuteCompleted(int connId, int status) throws RemoteException { 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt String address = mClientMap.addressByConnId(connId); 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (VDBG) Log.d(TAG, "onExecuteCompleted() - address=" + address 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt + ", status=" + status); 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ClientMap.App app = mClientMap.getByConnId(connId); 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (app != null) { 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt app.callback.onExecuteWrite(address, status); 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 86004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 86104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt void onReadDescriptor(int connId, int status, int srvcType, 86204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 86355840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt int charInstId, long charUuidLsb, long charUuidMsb, 86404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int descrInstId, long descrUuidLsb, long descrUuidMsb, 86504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int charType, byte[] data) throws RemoteException { 86604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 86704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 86804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 86904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt UUID descrUuid = new UUID(descrUuidMsb, descrUuidLsb); 87004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt String address = mClientMap.addressByConnId(connId); 87104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 87204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (VDBG) Log.d(TAG, "onReadDescriptor() - address=" + address 87304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt + ", status=" + status + ", length=" + data.length); 87404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 87504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ClientMap.App app = mClientMap.getByConnId(connId); 87604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (app != null) { 87704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt app.callback.onDescriptorRead(address, status, srvcType, 87804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt srvcInstId, new ParcelUuid(srvcUuid), 87904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt charInstId, new ParcelUuid(charUuid), 88004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt descrInstId, new ParcelUuid(descrUuid), data); 88104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 88204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 88304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 88404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt void onWriteDescriptor(int connId, int status, int srvcType, 88504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 88604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int charInstId, long charUuidLsb, long charUuidMsb, 88704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int descrInstId, long descrUuidLsb, long descrUuidMsb) throws RemoteException { 88804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 88904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 89004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 89104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt UUID descrUuid = new UUID(descrUuidMsb, descrUuidLsb); 89204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt String address = mClientMap.addressByConnId(connId); 89304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 89404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (VDBG) Log.d(TAG, "onWriteDescriptor() - address=" + address 89504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt + ", status=" + status); 89604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 89704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ClientMap.App app = mClientMap.getByConnId(connId); 89855840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt if (app != null) { 89955840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt app.callback.onDescriptorWrite(address, status, srvcType, 90055840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt srvcInstId, new ParcelUuid(srvcUuid), 90155840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt charInstId, new ParcelUuid(charUuid), 90255840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt descrInstId, new ParcelUuid(descrUuid)); 90355840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt } 90455840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt } 90555840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt 90655840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt void onReadRemoteRssi(int clientIf, String address, 90755840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt int rssi, int status) throws RemoteException{ 90855840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt if (DBG) Log.d(TAG, "onReadRemoteRssi() - clientIf=" + clientIf + " address=" + 90904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt address + ", rssi=" + rssi + ", status=" + status); 91004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 91104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ClientMap.App app = mClientMap.getById(clientIf); 91204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (app != null) { 91304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt app.callback.onReadRemoteRssi(address, rssi, status); 91404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 91504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 91604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 91704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt void onScanFilterEnableDisabled(int action, int status, int clientIf) { 91855840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt if (DBG) { 91904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt Log.d(TAG, "onScanFilterEnableDisabled() - clientIf=" + clientIf + ", status=" + status 92004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt + ", action=" + action); 92104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 92204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt mScanManager.callbackDone(clientIf, status); 92304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 92404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 92504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt void onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace) { 92604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (DBG) { 92704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt Log.d(TAG, "onScanFilterParamsConfigured() - clientIf=" + clientIf 92804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt + ", status=" + status + ", action=" + action 92904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt + ", availableSpace=" + availableSpace); 93004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 93155840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt mScanManager.callbackDone(clientIf, status); 932ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 93304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 93404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt void onScanFilterConfig(int action, int status, int clientIf, int filterType, 93504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int availableSpace) { 93604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (DBG) { 93755840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt Log.d(TAG, "onScanFilterConfig() - clientIf=" + clientIf + ", action = " + action 93855840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt + " status = " + status + ", filterType=" + filterType 939ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt + ", availableSpace=" + availableSpace); 94004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 94104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 94204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt mScanManager.callbackDone(clientIf, status); 94304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 94404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 94504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt void onBatchScanStorageConfigured(int status, int clientIf) { 94604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (DBG) { 94704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt Log.d(TAG, "onBatchScanStorageConfigured() - clientIf="+ clientIf + ", status=" + status); 94861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 94961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt mScanManager.callbackDone(clientIf, status); 950216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 951216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 952216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt // TODO: split into two different callbacks : onBatchScanStarted and onBatchScanStopped. 953216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt void onBatchScanStartStopped(int startStopAction, int status, int clientIf) { 95461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (DBG) { 95555840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt Log.d(TAG, "onBatchScanStartStopped() - clientIf=" + clientIf 95655840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt + ", status=" + status + ", startStopAction=" + startStopAction); 95755840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt } 95855840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt mScanManager.callbackDone(clientIf, status); 95955840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt } 96055840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt 96155840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt void onBatchScanReports(int status, int clientIf, int reportType, int numRecords, 96255840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt byte[] recordData) throws RemoteException { 96355840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt if (DBG) { 96455840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt Log.d(TAG, "onBatchScanReports() - clientIf=" + clientIf + ", status=" + status 96555840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt + ", reportType=" + reportType + ", numRecords=" + numRecords); 96655840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt } 96755840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt mScanManager.callbackDone(clientIf, status); 96855840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData); 96955840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { 97055840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt // We only support single client for truncated mode. 97155840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt ClientMap.App app = mClientMap.getById(clientIf); 97255840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt if (app == null) return; 97355840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt app.callback.onBatchScanResults(new ArrayList<ScanResult>(results)); 97455840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt } else { 97555840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt for (ScanClient client : mScanManager.getBatchScanQueue()) { 97655840adb6cd32ca52064f327b72a40e769f70661Dmitry Shmidt // Deliver results for each client. 97761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt deliverBatchScan(client, results); 97861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 97961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 980216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 981216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 982216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt // Check and deliver scan results for different scan clients. 983216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults) throws 984216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt RemoteException { 985216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt ClientMap.App app = mClientMap.getById(client.clientIf); 986216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (app == null) return; 987216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (client.filters == null || client.filters.isEmpty()) { 988216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt app.callback.onBatchScanResults(new ArrayList<ScanResult>(allResults)); 989216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 990216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt // Reconstruct the scan results. 991216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt List<ScanResult> results = new ArrayList<ScanResult>(); 992216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt for (ScanResult scanResult : allResults) { 993216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (matchesFilters(client, scanResult)) { 994216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt results.add(scanResult); 995216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 996216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 997216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt app.callback.onBatchScanResults(results); 998216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 999216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 1000216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt private Set<ScanResult> parseBatchScanResults(int numRecords, int reportType, 1001216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt byte[] batchRecord) { 1002216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (numRecords == 0) { 1003216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt return Collections.emptySet(); 1004216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 1005216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (DBG) Log.d(TAG, "current time is " + SystemClock.elapsedRealtimeNanos()); 1006216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { 1007216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt return parseTruncatedResults(numRecords, batchRecord); 1008216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } else { 1009216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt return parseFullResults(numRecords, batchRecord); 1010216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 1011216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 1012216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt 1013216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) { 1014216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (DBG) Log.d(TAG, "batch record " + Arrays.toString(batchRecord)); 1015216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt Set<ScanResult> results = new HashSet<ScanResult>(numRecords); 1016216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt for (int i = 0; i < numRecords; ++i) { 101761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt byte[] record = extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE, 101861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt TRUNCATED_RESULT_SIZE); 101961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt byte[] address = extractBytes(record, 0, 6); 102061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt // TODO: remove temp hack. 102161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt reverse(address); 102261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt BluetoothDevice device = mAdapter.getRemoteDevice(address); 102361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int rssi = record[8]; 102461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt // Timestamp is in every 50 ms. 102561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt long timestampNanos = parseTimestampNanos(extractBytes(record, 9, 2)); 102661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt results.add(new ScanResult(device, ScanRecord.parseFromBytes(new byte[0]), 102761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt rssi, timestampNanos)); 102861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 1029216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt return results; 1030216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt } 103161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 103261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt private long parseTimestampNanos(byte[] data) { 103361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt long timestampUnit = data[1] & 0xFF << 8 + data[0]; 103461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt long timestampNanos = SystemClock.elapsedRealtimeNanos() - 103561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50); 103661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return timestampNanos; 103761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 103861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 103961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) { 104061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt Log.d(TAG, "Batch record : " + Arrays.toString(batchRecord)); 104161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt Set<ScanResult> results = new HashSet<ScanResult>(numRecords); 104261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int position = 0; 1043807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt while (position < batchRecord.length) { 1044807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt byte[] address = extractBytes(batchRecord, position, 6); 1045807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt // TODO: remove temp hack. 1046807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt reverse(address); 1047807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt BluetoothDevice device = mAdapter.getRemoteDevice(address); 1048216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt position += 6; 1049ebd93af924f6e54fb4982b3312ff875a4896b62bDmitry Shmidt // Skip address type. 1050807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt position++; 1051807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt // Skip tx power level. 1052807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt position++; 1053807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt int rssi = batchRecord[position++]; 1054807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt long timestampNanos = parseTimestampNanos(extractBytes(batchRecord, position, 2)); 1055807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt position += 2; 1056807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 1057807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt // Combine advertise packet and scan response packet. 1058807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt int advertisePacketLen = batchRecord[position++]; 1059807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt byte[] advertiseBytes = extractBytes(batchRecord, position, advertisePacketLen); 1060807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt position += advertisePacketLen; 1061807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt int scanResponsePacketLen = batchRecord[position++]; 1062d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt byte[] scanResponseBytes = extractBytes(batchRecord, position, scanResponsePacketLen); 1063d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt position += scanResponsePacketLen; 1064d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt byte[] scanRecord = new byte[advertisePacketLen + scanResponsePacketLen]; 1065d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt System.arraycopy(advertiseBytes, 0, scanRecord, 0, advertisePacketLen); 1066d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt System.arraycopy(scanResponseBytes, 0, scanRecord, 1067d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt advertisePacketLen, scanResponsePacketLen); 1068d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt Log.d(TAG, "ScanRecord : " + Arrays.toString(scanRecord)); 1069d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt results.add(new ScanResult(device, ScanRecord.parseFromBytes(scanRecord), 1070d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt rssi, timestampNanos)); 1071d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1072d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt return results; 1073d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1074d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1075d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt // Reverse byte array. 1076d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt private void reverse(byte[] address) { 1077d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int len = address.length; 1078d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt for (int i = 0; i < len / 2; ++i) { 1079d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt byte b = address[i]; 1080d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt address[i] = address[len - 1 - i]; 108161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt address[len - 1 - i] = b; 108261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 108361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 108461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 108561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt // Helper method to extract bytes from byte array. 108661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt private static byte[] extractBytes(byte[] scanRecord, int start, int length) { 108761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt byte[] bytes = new byte[length]; 108861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt System.arraycopy(scanRecord, start, bytes, 0, length); 108961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return bytes; 1090807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } 1091807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 109261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt void onBatchScanThresholdCrossed(int clientIf) { 109361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (DBG) { 109461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt Log.d(TAG, "onBatchScanThresholdCrossed() - clientIf=" + clientIf); 109561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 109661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt boolean isServer = false; 1097d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt flushPendingBatchResults(clientIf, isServer); 1098d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1099d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 110061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt void onTrackAdvFoundLost(int filterIndex, int addrType, String address, int advState, 110161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int clientIf) throws RemoteException { 110261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (DBG) Log.d(TAG, "onClientAdvertiserFoundLost() - clientIf=" 110361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt + clientIf + "address = " + address + "adv_state = " 1104807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt + advState + "client_if = " + clientIf); 1105807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt ClientMap.App app = mClientMap.getById(clientIf); 1106807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (app == null || app.callback == null) { 1107807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt Log.e(TAG, "app or callback is null"); 1108807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return; 1109807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } 1110807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (advState == ADVT_STATE_ONFOUND || advState == ADVT_STATE_ONLOST) { 111161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int rssi = 0; 1112807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt byte [] advData = new byte[0]; 111361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt boolean found; 111461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (advState == ADVT_STATE_ONFOUND) { 111561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt found = true; 111661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else { 111761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt found = false; 111861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 111961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt //ToDo: Address reporting format and content and then enable 112061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt app.callback.onFoundOrLost(found, address, rssi, advData); 112161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 112261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 112361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 112461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt // callback from AdvertiseManager for advertise status dispatch. 112561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt void onMultipleAdvertiseCallback(int clientIf, int status, boolean isStart, 112661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt AdvertiseSettings settings) throws RemoteException { 1127807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt ClientMap.App app = mClientMap.getById(clientIf); 1128807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (app == null || app.callback == null) { 1129807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt Log.e(TAG, "Advertise app or callback is null"); 1130807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return; 1131807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } 1132807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt app.callback.onMultiAdvertiseCallback(status, isStart, settings); 1133807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } 113461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 113561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt void onConfigureMTU(int connId, int status, int mtu) throws RemoteException { 113661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt String address = mClientMap.addressByConnId(connId); 113761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1138807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (DBG) Log.d(TAG, "onConfigureMTU() address=" + address + ", status=" 1139807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt + status + ", mtu=" + mtu); 1140807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 1141807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt ClientMap.App app = mClientMap.getByConnId(connId); 1142807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (app != null) { 1143807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt app.callback.onConfigureMTU(address, mtu, status); 114461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 1145a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1146a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1147a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt // Callback for standard advertising instance. 1148a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void onAdvertiseCallback(int status, int clientIf) { 1149e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (DBG) Log.d(TAG, "onAdvertiseCallback,- clientIf=" + clientIf + ", status=" + status); 1150e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt } 1151a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1152a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt // Followings are callbacks for Bluetooth LE Advertise operations. 1153a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt // Start advertising flow is 1154a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt // enable advertising instance -> onAdvertiseInstaceEnabled 1155a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt // -> set advertise data -> onAdvertiseDataSet 1156a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt // -> set scan response -> onAdvertiseDataSet 1157e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 1158e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt // Callback when advertise instance is enabled. 1159e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt void onAdvertiseInstanceEnabled(int status, int clientIf) { 1160e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (DBG) Log.d(TAG, "onAdvertiseInstanceEnabled() - " 1161e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt + "clientIf=" + clientIf + ", status=" + status); 1162e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt mAdvertiseManager.callbackDone(clientIf, status); 1163a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1164a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1165a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt // Not really used. 1166a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void onAdvertiseDataUpdated(int status, int client_if) { 1167a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "onAdvertiseDataUpdated() - client_if=" + client_if 1168a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt + ", status=" + status); 1169a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1170a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1171a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt // Callback when advertise data or scan response is set. 1172a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void onAdvertiseDataSet(int status, int clientIf) { 1173a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "onAdvertiseDataSet() - clientIf=" + clientIf 1174a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt + ", status=" + status); 1175a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt mAdvertiseManager.callbackDone(clientIf, status); 1176a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1177a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1178a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt // Callback when advertise instance is disabled 1179a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void onAdvertiseInstanceDisabled(int status, int clientIf) throws RemoteException { 1180a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "onAdvertiseInstanceEnabled() - clientIf=" + clientIf 1181e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt + ", status=" + status); 1182e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt ClientMap.App app = mClientMap.getById(clientIf); 1183e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (app != null) { 1184a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt Log.d(TAG, "Client app is not null!"); 1185a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt boolean isStart = false; 1186a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (status == 0) { 1187a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt app.callback.onMultiAdvertiseCallback(AdvertiseCallback.ADVERTISE_SUCCESS, 1188a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt isStart, null); 1189a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } else { 1190a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt app.callback.onMultiAdvertiseCallback( 1191a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR, isStart, null); 1192a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1193a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1194a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1195a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1196a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void onClientCongestion(int connId, boolean congested) throws RemoteException { 1197a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "onClientCongestion() - connId=" + connId + ", congested=" + congested); 1198a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1199a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt ClientMap.App app = mClientMap.getByConnId(connId); 1200a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (app != null) { 1201a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt app.callback.onConnectionCongested(mClientMap.addressByConnId(connId), congested); 1202a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1203a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1204a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1205a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt /************************************************************************** 1206a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * GATT Service functions - Shared CLIENT/SERVER 1207a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *************************************************************************/ 1208a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1209a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 1210a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1211a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1212a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt final int DEVICE_TYPE_BREDR = 0x1; 1213a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1214a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt Map<BluetoothDevice, Integer> deviceStates = new HashMap<BluetoothDevice, 1215a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt Integer>(); 1216a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1217a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt // Add paired LE devices 1218a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1219a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices(); 1220a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt for (BluetoothDevice device : bondedDevices) { 1221a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (getDeviceType(device) != DEVICE_TYPE_BREDR) { 1222a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt deviceStates.put(device, BluetoothProfile.STATE_DISCONNECTED); 1223a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1224a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1225a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1226a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt // Add connected deviceStates 1227a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1228a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt Set<String> connectedDevices = new HashSet<String>(); 1229a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt connectedDevices.addAll(mClientMap.getConnectedDevices()); 1230a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt connectedDevices.addAll(mServerMap.getConnectedDevices()); 1231a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1232a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt for (String address : connectedDevices ) { 1233a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt BluetoothDevice device = mAdapter.getRemoteDevice(address); 1234a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (device != null) { 1235a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt deviceStates.put(device, BluetoothProfile.STATE_CONNECTED); 1236a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1237e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt } 1238e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 1239e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt // Create matching device sub-set 1240a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1241a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>(); 1242a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1243a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt for (Map.Entry<BluetoothDevice, Integer> entry : deviceStates.entrySet()) { 1244a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt for(int state : states) { 1245a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (entry.getValue() == state) { 1246a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt deviceList.add(entry.getKey()); 1247a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1248a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1249a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1250a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1251a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return deviceList; 1252a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1253a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1254a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void startScan(int appIf, boolean isServer, ScanSettings settings, 1255a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt List<ScanFilter> filters) { 1256a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "start scan with filters"); 1257a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enforceAdminPermission(); 1258e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt mScanManager.startScan(new ScanClient(appIf, isServer, settings, filters)); 1259e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt } 1260a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1261a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void flushPendingBatchResults(int clientIf, boolean isServer) { 1262a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "flushPendingBatchResults - clientIf=" + clientIf + 1263a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt ", isServer=" + isServer); 1264a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt mScanManager.flushBatchScanResults(new ScanClient(clientIf, isServer)); 1265a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1266a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1267a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void stopScan(int appIf, boolean isServer) { 1268a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enforceAdminPermission(); 1269a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int scanQueueSize = mScanManager.getBatchScanQueue().size() + 1270a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt mScanManager.getRegularScanQueue().size(); 1271a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "stopScan() - queue size =" + scanQueueSize); 1272a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt mScanManager.stopScan(new ScanClient(appIf, isServer)); 1273a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1274a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1275e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt /************************************************************************** 1276e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * GATT Service functions - CLIENT 1277a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *************************************************************************/ 1278a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1279a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void registerClient(UUID uuid, IBluetoothGattCallback callback) { 1280a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1281a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1282a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid); 1283a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt mClientMap.add(uuid, callback); 1284a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt gattClientRegisterAppNative(uuid.getLeastSignificantBits(), 1285a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt uuid.getMostSignificantBits()); 1286a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1287a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1288a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void unregisterClient(int clientIf) { 1289a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1290e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 1291e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (DBG) Log.d(TAG, "unregisterClient() - clientIf=" + clientIf); 1292e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt mClientMap.remove(clientIf); 1293a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt gattClientUnregisterAppNative(clientIf); 1294a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1295a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1296a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void clientConnect(int clientIf, String address, boolean isDirect, int transport) { 1297a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1298a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1299a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect); 1300a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt gattClientConnectNative(clientIf, address, isDirect, transport); 1301a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1302a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1303a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void clientDisconnect(int clientIf, String address) { 1304a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1305a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1306a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt Integer connId = mClientMap.connIdByAddress(clientIf, address); 1307a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId); 1308a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1309a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0); 1310a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1311a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1312a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void startMultiAdvertising(int clientIf, AdvertiseData advertiseData, 1313e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt AdvertiseData scanResponse, AdvertiseSettings settings) { 1314e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt enforceAdminPermission(); 1315e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt mAdvertiseManager.startAdvertising(new AdvertiseClient(clientIf, settings, advertiseData, 1316a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt scanResponse)); 1317a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1318a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1319a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void stopMultiAdvertising(int clientIf) { 1320a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enforceAdminPermission(); 1321a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt mAdvertiseManager.stopAdvertising(new AdvertiseClient(clientIf)); 1322a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1323a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1324a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1325a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt synchronized List<ParcelUuid> getRegisteredServiceUuids() { 1326a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt Utils.enforceAdminPermission(this); 1327a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); 1328a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt for (HandleMap.Entry entry : mHandleMap.mEntries) { 1329a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt serviceUuids.add(new ParcelUuid(entry.uuid)); 1330a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1331a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return serviceUuids; 1332a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1333a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1334a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt List<String> getConnectedDevices() { 1335a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1336a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1337a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt Set<String> connectedDevAddress = new HashSet<String>(); 1338a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt connectedDevAddress.addAll(mClientMap.getConnectedDevices()); 1339a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt connectedDevAddress.addAll(mServerMap.getConnectedDevices()); 1340a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress); 1341a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return connectedDeviceList; 1342a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1343a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1344a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void refreshDevice(int clientIf, String address) { 1345a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1346a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1347a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "refreshDevice() - address=" + address); 1348a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt gattClientRefreshNative(clientIf, address); 1349a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1350a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1351a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void discoverServices(int clientIf, String address) { 13524171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 13534171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 13544171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt Integer connId = mClientMap.connIdByAddress(clientIf, address); 13554171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt if (DBG) Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId); 13564171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 13574171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt if (connId != null) 13584171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt gattClientSearchServiceNative(connId, true, 0, 0); 1359e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt else 1360e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt Log.e(TAG, "discoverServices() - No connection for " + address + "..."); 1361e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt } 13624171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 13634171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt void readCharacteristic(int clientIf, String address, int srvcType, 13644171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt int srvcInstanceId, UUID srvcUuid, 13654171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt int charInstanceId, UUID charUuid, int authReq) { 13664171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 13674171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 13684171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt if (VDBG) Log.d(TAG, "readCharacteristic() - address=" + address); 13694171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 13704171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt Integer connId = mClientMap.connIdByAddress(clientIf, address); 13714171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt if (connId != null) 13724171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt gattClientReadCharacteristicNative(connId, srvcType, 13734171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt srvcInstanceId, srvcUuid.getLeastSignificantBits(), 13744171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt srvcUuid.getMostSignificantBits(), charInstanceId, 13754171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 13764171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt authReq); 13774171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt else 13784171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt Log.e(TAG, "readCharacteristic() - No connection for " + address + "..."); 13794171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt } 13804171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 13814171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt void writeCharacteristic(int clientIf, String address, int srvcType, 13824171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt int srvcInstanceId, UUID srvcUuid, 13834171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt int charInstanceId, UUID charUuid, int writeType, 13844171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt int authReq, byte[] value) { 13854171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 13864171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 13874171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt if (VDBG) Log.d(TAG, "writeCharacteristic() - address=" + address); 13884171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 13894171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt if (mReliableQueue.contains(address)) writeType = 3; // Prepared write 13904171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 1391a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt Integer connId = mClientMap.connIdByAddress(clientIf, address); 1392a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (connId != null) 1393a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt gattClientWriteCharacteristicNative(connId, srvcType, 1394a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1395d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt srvcUuid.getMostSignificantBits(), charInstanceId, 1396a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1397a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt writeType, authReq, value); 1398a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt else 13994171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); 14004171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt } 1401a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1402a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void readDescriptor(int clientIf, String address, int srvcType, 1403a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int srvcInstanceId, UUID srvcUuid, 1404a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int charInstanceId, UUID charUuid, 1405a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int descrInstanceId, UUID descrUuid, 1406a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int authReq) { 1407a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1408a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1409a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (VDBG) Log.d(TAG, "readDescriptor() - address=" + address); 1410a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1411a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt Integer connId = mClientMap.connIdByAddress(clientIf, address); 1412a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (connId != null) 1413a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt gattClientReadDescriptorNative(connId, srvcType, 1414a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt srvcInstanceId, 1415a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(), 1416a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt charInstanceId, 1417a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1418a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt descrInstanceId, 1419a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 1420a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt authReq); 1421a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt else 1422a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt Log.e(TAG, "readDescriptor() - No connection for " + address + "..."); 1423a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt }; 1424a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 14254171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt void writeDescriptor(int clientIf, String address, int srvcType, 14264171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt int srvcInstanceId, UUID srvcUuid, 14274171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt int charInstanceId, UUID charUuid, 14284171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt int descrInstanceId, UUID descrUuid, 14294171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt int writeType, int authReq, byte[] value) { 14304171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 14314171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 14324171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt if (VDBG) Log.d(TAG, "writeDescriptor() - address=" + address); 14334171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 14344171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt Integer connId = mClientMap.connIdByAddress(clientIf, address); 14354171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt if (connId != null) 14364171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt gattClientWriteDescriptorNative(connId, srvcType, 14374171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt srvcInstanceId, 14384171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(), 14394171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt charInstanceId, 14404171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 14414171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt descrInstanceId, 14424171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 14434171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt writeType, authReq, value); 14444171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt else 1445a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); 1446a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1447a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1448a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void beginReliableWrite(int clientIf, String address) { 1449a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1450a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1451a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "beginReliableWrite() - address=" + address); 1452a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt mReliableQueue.add(address); 1453d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1454a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1455a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void endReliableWrite(int clientIf, String address, boolean execute) { 1456a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1457a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 14584171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt if (DBG) Log.d(TAG, "endReliableWrite() - address=" + address 14594171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt + " execute: " + execute); 1460a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt mReliableQueue.remove(address); 14614171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 14624171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt Integer connId = mClientMap.connIdByAddress(clientIf, address); 1463a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (connId != null) gattClientExecuteWriteNative(connId, execute); 1464a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1465a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1466a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void registerForNotification(int clientIf, String address, int srvcType, 1467a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int srvcInstanceId, UUID srvcUuid, 1468a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int charInstanceId, UUID charUuid, 1469a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt boolean enable) { 1470a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1471a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1472a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable); 1473a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1474a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt Integer connId = mClientMap.connIdByAddress(clientIf, address); 1475a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (connId != null) { 14764171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt gattClientRegisterForNotificationsNative(clientIf, address, 14774171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt srvcType, srvcInstanceId, srvcUuid.getLeastSignificantBits(), 14787f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt srvcUuid.getMostSignificantBits(), charInstanceId, 1479661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1480a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enable); 1481a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } else { 1482a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt Log.e(TAG, "registerForNotification() - No connection for " + address + "..."); 1483a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1484a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1485a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1486a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void readRemoteRssi(int clientIf, String address) { 1487a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1488e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 1489e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (DBG) Log.d(TAG, "readRemoteRssi() - address=" + address); 1490a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt gattClientReadRemoteRssiNative(clientIf, address); 1491a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1492a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1493a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void configureMTU(int clientIf, String address, int mtu) { 1494a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1495a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1496a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu); 1497a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt Integer connId = mClientMap.connIdByAddress(clientIf, address); 1498a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (connId != null) { 1499a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt gattClientConfigureMTUNative(connId, mtu); 1500a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } else { 1501a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt Log.e(TAG, "configureMTU() - No connection for " + address + "..."); 1502a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1503a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1504a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1505a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void connectionParameterUpdate(int clientIf, String address, int connectionPriority) { 1506a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1507a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1508a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt // Default spec recommended interval is 30->50 ms 1509a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int minInterval = 24; // 24 * 1.25ms = 30ms 1510a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int maxInterval = 40; // 40 * 1.25ms = 50ms 1511a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1512a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt // Slave latency 1513a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int latency = 0; 1514a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1515a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt // Link supervision timeout is measured in N * 10ms 1516a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int timeout = 2000; // 20s 1517a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1518a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt switch (connectionPriority) 1519a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt { 1520a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt case BluetoothGatt.GATT_CONNECTION_HIGH_PRIORITY: 1521a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt minInterval = 6; // 7.5ms 1522a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt maxInterval = 8; // 10ms 1523a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt break; 1524a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1525a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt case BluetoothGatt.GATT_CONNECTION_LOW_POWER: 1526a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt minInterval = 80; // 100ms 1527a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt maxInterval = 100; // 125ms 1528a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt latency = 2; 1529a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt break; 1530a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1531a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1532a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "connectionParameterUpdate() - address=" + address 1533a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt + "params=" + connectionPriority + " interval=" + minInterval + "/" + maxInterval); 1534a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval, 1535a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt latency, timeout); 1536e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt } 1537e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 1538e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt /************************************************************************** 1539a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Callback functions - SERVER 1540a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *************************************************************************/ 1541a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1542a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) 1543a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt throws RemoteException { 1544a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1545a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt UUID uuid = new UUID(uuidMsb, uuidLsb); 1546a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf); 1547a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt ServerMap.App app = mServerMap.getByUuid(uuid); 1548a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (app != null) { 1549a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt app.id = serverIf; 1550a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt app.linkToDeath(new ServerDeathRecipient(serverIf)); 1551a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt app.callback.onServerRegistered(status, serverIf); 1552a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1553a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1554a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1555a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void onServiceAdded(int status, int serverIf, int srvcType, int srvcInstId, 15567f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt long srvcUuidLsb, long srvcUuidMsb, int srvcHandle) 15577f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt throws RemoteException { 1558a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb); 1559a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "onServiceAdded() UUID=" + uuid + ", status=" + status 1560a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt + ", handle=" + srvcHandle); 1561a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (status == 0) { 1562a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt mHandleMap.addService(serverIf, srvcHandle, uuid, srvcType, srvcInstId, 1563a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt mAdvertisingServiceUuids.remove(uuid)); 1564a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1565a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1566a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt continueServiceDeclaration(serverIf, status, srvcHandle); 1567a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1568a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1569e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt void onIncludedServiceAdded(int status, int serverIf, int srvcHandle, 1570e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt int includedSrvcHandle) throws RemoteException { 1571e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (DBG) Log.d(TAG, "onIncludedServiceAdded() status=" + status 1572a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt + ", service=" + srvcHandle + ", included=" + includedSrvcHandle); 1573a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt continueServiceDeclaration(serverIf, status, srvcHandle); 1574a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1575a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 15767f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt void onCharacteristicAdded(int status, int serverIf, 15777f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt long charUuidLsb, long charUuidMsb, 15787f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt int srvcHandle, int charHandle) 1579a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt throws RemoteException { 1580a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt UUID uuid = new UUID(charUuidMsb, charUuidLsb); 1581a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "onCharacteristicAdded() UUID=" + uuid + ", status=" + status 1582a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt + ", srvcHandle=" + srvcHandle + ", charHandle=" + charHandle); 1583a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (status == 0) 15847f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt mHandleMap.addCharacteristic(serverIf, charHandle, uuid, srvcHandle); 1585a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt continueServiceDeclaration(serverIf, status, srvcHandle); 1586a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1587a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 15887f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt void onDescriptorAdded(int status, int serverIf, 15897f0b69e88015ca077ef7a417fde0a76c10df23a5Dmitry Shmidt long descrUuidLsb, long descrUuidMsb, 1590a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int srvcHandle, int descrHandle) 1591a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt throws RemoteException { 1592a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt UUID uuid = new UUID(descrUuidMsb, descrUuidLsb); 1593a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "onDescriptorAdded() UUID=" + uuid + ", status=" + status 1594a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt + ", srvcHandle=" + srvcHandle + ", descrHandle=" + descrHandle); 1595a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (status == 0) 1596a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt mHandleMap.addDescriptor(serverIf, descrHandle, uuid, srvcHandle); 1597a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt continueServiceDeclaration(serverIf, status, srvcHandle); 1598a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1599e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 1600e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt void onServiceStarted(int status, int serverIf, int srvcHandle) 1601a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt throws RemoteException { 1602a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "onServiceStarted() srvcHandle=" + srvcHandle 1603a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt + ", status=" + status); 1604a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (status == 0) 1605a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt mHandleMap.setStarted(serverIf, srvcHandle, true); 1606a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1607a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1608a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void onServiceStopped(int status, int serverIf, int srvcHandle) 1609a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt throws RemoteException { 1610e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (DBG) Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle 1611e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt + ", status=" + status); 1612a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (status == 0) 1613a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt mHandleMap.setStarted(serverIf, srvcHandle, false); 1614a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt stopNextService(serverIf, status); 1615a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1616a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1617a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void onServiceDeleted(int status, int serverIf, int srvcHandle) { 1618a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle 1619a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt + ", status=" + status); 1620e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt mHandleMap.deleteService(serverIf, srvcHandle); 1621e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt } 1622a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1623a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt void onClientConnected(String address, boolean connected, int connId, int serverIf) 1624a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt throws RemoteException { 1625a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1626a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (DBG) Log.d(TAG, "onConnected() connId=" + connId 1627a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt + ", address=" + address + ", connected=" + connected); 1628a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1629a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt ServerMap.App app = mServerMap.getById(serverIf); 1630e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (app == null) return; 1631e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 1632a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (connected) { 1633a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt mServerMap.addConnection(serverIf, connId, address); 1634a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } else { 1635a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt mServerMap.removeConnection(serverIf, connId); 1636a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1637a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1638a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt app.callback.onServerConnectionState((byte)0, serverIf, connected, address); 1639a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1640a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 16414171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt void onAttributeRead(String address, int connId, int transId, 16424171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt int attrHandle, int offset, boolean isLong) 16434171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt throws RemoteException { 16444171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt if (VDBG) Log.d(TAG, "onAttributeRead() connId=" + connId 16454171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt + ", address=" + address + ", handle=" + attrHandle 16464171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt + ", requestId=" + transId + ", offset=" + offset); 1647e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt 1648e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1649e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt if (entry == null) return; 16504171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 16514171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt if (DBG) Log.d(TAG, "onAttributeRead() UUID=" + entry.uuid 16524171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt + ", serverIf=" + entry.serverIf + ", type=" + entry.type); 16534171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 16544171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt mHandleMap.addRequest(transId, attrHandle); 16554171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 16564171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt ServerMap.App app = mServerMap.getById(entry.serverIf); 16574171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt if (app == null) return; 16584171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 16594171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt switch(entry.type) { 16604171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt case HandleMap.TYPE_CHARACTERISTIC: 16614171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt { 16624171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 16634171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, 16644171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt serviceEntry.serviceType, serviceEntry.instance, 16654171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt new ParcelUuid(serviceEntry.uuid), entry.instance, 16664171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt new ParcelUuid(entry.uuid)); 16674171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt break; 16684171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt } 16694171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 16704171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt case HandleMap.TYPE_DESCRIPTOR: 1671a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt { 1672a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1673a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1674a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt app.callback.onDescriptorReadRequest(address, transId, offset, isLong, 1675a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt serviceEntry.serviceType, serviceEntry.instance, 1676a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1677a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt new ParcelUuid(charEntry.uuid), 1678a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt new ParcelUuid(entry.uuid)); 1679a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt break; 1680a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 16814171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 16824171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt default: 16834171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt Log.e(TAG, "onAttributeRead() - Requested unknown attribute type."); 16844171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt break; 16854171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt } 16864171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt } 16874171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt 16884171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt void onAttributeWrite(String address, int connId, int transId, 16894171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt int attrHandle, int offset, int length, 16904171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt boolean needRsp, boolean isPrep, 16914171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt byte[] data) 1692a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt throws RemoteException { 1693a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (VDBG) Log.d(TAG, "onAttributeWrite() connId=" + connId 1694d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt + ", address=" + address + ", handle=" + attrHandle 1695d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt + ", requestId=" + transId + ", isPrep=" + isPrep 1696d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt + ", offset=" + offset); 1697d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1698d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1699d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (entry == null) return; 1700d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1701d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (DBG) Log.d(TAG, "onAttributeWrite() UUID=" + entry.uuid 1702d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt + ", serverIf=" + entry.serverIf + ", type=" + entry.type); 1703d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1704d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt mHandleMap.addRequest(transId, attrHandle); 1705d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1706d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt ServerMap.App app = mServerMap.getById(entry.serverIf); 1707d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (app == null) return; 1708d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1709d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt switch(entry.type) { 1710d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt case HandleMap.TYPE_CHARACTERISTIC: 1711d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt { 1712d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1713d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt app.callback.onCharacteristicWriteRequest(address, transId, 1714d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt offset, length, isPrep, needRsp, 1715d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt serviceEntry.serviceType, serviceEntry.instance, 1716d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt new ParcelUuid(serviceEntry.uuid), entry.instance, 1717d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt new ParcelUuid(entry.uuid), data); 1718d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt break; 1719d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1720d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1721d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt case HandleMap.TYPE_DESCRIPTOR: 1722d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt { 1723d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1724d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1725d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt app.callback.onDescriptorWriteRequest(address, transId, 1726d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt offset, length, isPrep, needRsp, 1727d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt serviceEntry.serviceType, serviceEntry.instance, 1728d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1729d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt new ParcelUuid(charEntry.uuid), 1730d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt new ParcelUuid(entry.uuid), data); 1731d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt break; 1732d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1733d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1734d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt default: 1735d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt Log.e(TAG, "onAttributeWrite() - Requested unknown attribute type."); 1736d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt break; 1737d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1738d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1739d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1740d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt void onExecuteWrite(String address, int connId, int transId, int execWrite) 1741d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt throws RemoteException { 1742d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (DBG) Log.d(TAG, "onExecuteWrite() connId=" + connId 1743d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt + ", address=" + address + ", transId=" + transId); 1744d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1745d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt ServerMap.App app = mServerMap.getByConnId(connId); 1746d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (app == null) return; 1747d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1748d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt app.callback.onExecuteWrite(address, transId, execWrite == 1); 1749d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1750d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1751d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt void onResponseSendCompleted(int status, int attrHandle) { 1752d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (DBG) Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle); 1753d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1754d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1755d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt void onNotificationSent(int connId, int status) throws RemoteException { 1756d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (DBG) Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status); 1757d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1758d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt String address = mServerMap.addressByConnId(connId); 1759d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (address == null) return; 1760d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1761d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt ServerMap.App app = mServerMap.getByConnId(connId); 1762d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (app == null) return; 1763d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1764d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt app.callback.onNotificationSent(address, status); 1765d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1766d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1767d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt void onServerCongestion(int connId, boolean congested) throws RemoteException { 1768d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (DBG) Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested); 1769d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1770d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt ServerMap.App app = mServerMap.getByConnId(connId); 1771d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (app != null) { 1772d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt app.callback.onConnectionCongested(mServerMap.addressByConnId(connId), congested); 1773d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1774d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1775d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1776d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt /************************************************************************** 1777d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt * GATT Service functions - SERVER 1778d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt *************************************************************************/ 1779d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1780d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt void registerServer(UUID uuid, IBluetoothGattServerCallback callback) { 1781d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1782d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1783d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid); 1784d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt mServerMap.add(uuid, callback); 1785d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt gattServerRegisterAppNative(uuid.getLeastSignificantBits(), 1786d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt uuid.getMostSignificantBits()); 1787d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1788d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1789d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt void unregisterServer(int serverIf) { 1790d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1791d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1792d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (DBG) Log.d(TAG, "unregisterServer() - serverIf=" + serverIf); 1793d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1794d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt deleteServices(serverIf); 1795d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1796d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt mServerMap.remove(serverIf); 1797d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt gattServerUnregisterAppNative(serverIf); 1798d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1799d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1800d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 1801d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1802d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1803d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (DBG) Log.d(TAG, "serverConnect() - address=" + address); 1804d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt gattServerConnectNative(serverIf, address, isDirect,transport); 1805d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1806d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1807d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt void serverDisconnect(int serverIf, String address) { 1808d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1809d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1810d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt Integer connId = mServerMap.connIdByAddress(serverIf, address); 1811d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (DBG) Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId); 1812d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1813d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0); 1814d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1815d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1816d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt void beginServiceDeclaration(int serverIf, int srvcType, int srvcInstanceId, 1817d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int minHandles, UUID srvcUuid, boolean advertisePreferred) { 1818d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1819d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1820d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (DBG) Log.d(TAG, "beginServiceDeclaration() - uuid=" + srvcUuid); 1821d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt ServiceDeclaration serviceDeclaration = addDeclaration(); 1822d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt serviceDeclaration.addService(srvcUuid, srvcType, srvcInstanceId, minHandles, 1823d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt advertisePreferred); 1824d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1825d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1826d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt void addIncludedService(int serverIf, int srvcType, int srvcInstanceId, 1827d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt UUID srvcUuid) { 1828d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1829d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1830d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (DBG) Log.d(TAG, "addIncludedService() - uuid=" + srvcUuid); 1831d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt getActiveDeclaration().addIncludedService(srvcUuid, srvcType, srvcInstanceId); 1832d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1833d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1834d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt void addCharacteristic(int serverIf, UUID charUuid, int properties, 1835d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int permissions) { 1836d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1837d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1838d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (DBG) Log.d(TAG, "addCharacteristic() - uuid=" + charUuid); 1839d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt getActiveDeclaration().addCharacteristic(charUuid, properties, permissions); 1840d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1841d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1842d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt void addDescriptor(int serverIf, UUID descUuid, int permissions) { 1843d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1844d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1845d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (DBG) Log.d(TAG, "addDescriptor() - uuid=" + descUuid); 1846d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt getActiveDeclaration().addDescriptor(descUuid, permissions); 1847d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1848d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1849d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt void endServiceDeclaration(int serverIf) { 1850d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1851d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1852d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (DBG) Log.d(TAG, "endServiceDeclaration()"); 1853d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1854d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (getActiveDeclaration() == getPendingDeclaration()) { 1855d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt try { 1856d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt continueServiceDeclaration(serverIf, (byte)0, 0); 1857d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } catch (RemoteException e) { 1858d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt Log.e(TAG,""+e); 1859d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1860d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1861d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1862d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1863d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt void removeService(int serverIf, int srvcType, 1864d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int srvcInstanceId, UUID srvcUuid) { 1865d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1866d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1867d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (DBG) Log.d(TAG, "removeService() - uuid=" + srvcUuid); 1868d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1869d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 1870d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (srvcHandle == 0) return; 1871d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt gattServerDeleteServiceNative(serverIf, srvcHandle); 1872d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1873d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1874d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt void clearServices(int serverIf) { 1875d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1876d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1877d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (DBG) Log.d(TAG, "clearServices()"); 1878d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt deleteServices(serverIf); 1879d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1880d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1881d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt void sendResponse(int serverIf, String address, int requestId, 1882d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int status, int offset, byte[] value) { 1883d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1884d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1885d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (VDBG) Log.d(TAG, "sendResponse() - address=" + address); 1886d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1887d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int handle = 0; 1888d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt HandleMap.Entry entry = mHandleMap.getByRequestId(requestId); 1889d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (entry != null) handle = entry.handle; 1890d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1891d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int connId = mServerMap.connIdByAddress(serverIf, address); 1892d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt gattServerSendResponseNative(serverIf, connId, requestId, (byte)status, 1893d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt handle, offset, value, (byte)0); 1894d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt mHandleMap.deleteRequest(requestId); 1895d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1896d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1897d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt void sendNotification(int serverIf, String address, int srvcType, 1898d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int srvcInstanceId, UUID srvcUuid, 1899d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int charInstanceId, UUID charUuid, 1900d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt boolean confirm, byte[] value) { 1901d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1902d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1903d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (VDBG) Log.d(TAG, "sendNotification() - address=" + address); 1904d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1905d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 1906d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (srvcHandle == 0) return; 1907d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1908d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int charHandle = mHandleMap.getCharacteristicHandle(srvcHandle, charUuid, charInstanceId); 1909d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (charHandle == 0) return; 1910d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1911d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int connId = mServerMap.connIdByAddress(serverIf, address); 1912d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (connId == 0) return; 1913d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1914d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (confirm) { 1915d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt gattServerSendIndicationNative(serverIf, charHandle, connId, value); 1916d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } else { 1917d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt gattServerSendNotificationNative(serverIf, charHandle, connId, value); 1918d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1919d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1920d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1921d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1922d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt /************************************************************************** 1923d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt * Private functions 1924d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt *************************************************************************/ 1925d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 1926d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt private int getDeviceType(BluetoothDevice device) { 1927d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int type = gattClientGetDeviceTypeNative(device.getAddress()); 1928d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (DBG) Log.d(TAG, "getDeviceType() - device=" + device 1929a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt + ", type=" + type); 1930 return type; 1931 } 1932 1933 private void enforceAdminPermission() { 1934 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 1935 } 1936 1937 // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be 1938 // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission. 1939 private void enforcePrivilegedPermission() { 1940 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 1941 "Need BLUETOOTH_PRIVILEGED permission"); 1942 } 1943 1944 private void continueSearch(int connId, int status) throws RemoteException { 1945 if (status == 0 && !mSearchQueue.isEmpty()) { 1946 SearchQueue.Entry svc = mSearchQueue.pop(); 1947 1948 if (svc.charUuidLsb == 0) { 1949 // Characteristic is up next 1950 gattClientGetCharacteristicNative(svc.connId, svc.srvcType, 1951 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 0, 0, 0); 1952 } else { 1953 // Descriptor is up next 1954 gattClientGetDescriptorNative(svc.connId, svc.srvcType, 1955 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 1956 svc.charInstId, svc.charUuidLsb, svc.charUuidMsb, 0, 0, 0); 1957 } 1958 } else { 1959 ClientMap.App app = mClientMap.getByConnId(connId); 1960 if (app != null) { 1961 app.callback.onSearchComplete(mClientMap.addressByConnId(connId), status); 1962 } 1963 } 1964 } 1965 1966 private void continueServiceDeclaration(int serverIf, int status, int srvcHandle) throws RemoteException { 1967 if (mServiceDeclarations.size() == 0) return; 1968 if (DBG) Log.d(TAG, "continueServiceDeclaration() - srvcHandle=" + srvcHandle); 1969 1970 boolean finished = false; 1971 1972 ServiceDeclaration.Entry entry = null; 1973 if (status == 0) 1974 entry = getPendingDeclaration().getNext(); 1975 1976 if (entry != null) { 1977 if (DBG) Log.d(TAG, "continueServiceDeclaration() - next entry type=" 1978 + entry.type); 1979 switch(entry.type) { 1980 case ServiceDeclaration.TYPE_SERVICE: 1981 if (entry.advertisePreferred) { 1982 mAdvertisingServiceUuids.add(entry.uuid); 1983 } 1984 gattServerAddServiceNative(serverIf, entry.serviceType, 1985 entry.instance, 1986 entry.uuid.getLeastSignificantBits(), 1987 entry.uuid.getMostSignificantBits(), 1988 getPendingDeclaration().getNumHandles()); 1989 break; 1990 1991 case ServiceDeclaration.TYPE_CHARACTERISTIC: 1992 gattServerAddCharacteristicNative(serverIf, srvcHandle, 1993 entry.uuid.getLeastSignificantBits(), 1994 entry.uuid.getMostSignificantBits(), 1995 entry.properties, entry.permissions); 1996 break; 1997 1998 case ServiceDeclaration.TYPE_DESCRIPTOR: 1999 gattServerAddDescriptorNative(serverIf, srvcHandle, 2000 entry.uuid.getLeastSignificantBits(), 2001 entry.uuid.getMostSignificantBits(), 2002 entry.permissions); 2003 break; 2004 2005 case ServiceDeclaration.TYPE_INCLUDED_SERVICE: 2006 { 2007 int inclSrvc = mHandleMap.getServiceHandle(entry.uuid, 2008 entry.serviceType, entry.instance); 2009 if (inclSrvc != 0) { 2010 gattServerAddIncludedServiceNative(serverIf, srvcHandle, 2011 inclSrvc); 2012 } else { 2013 finished = true; 2014 } 2015 break; 2016 } 2017 } 2018 } else { 2019 gattServerStartServiceNative(serverIf, srvcHandle, 2020 (byte)BluetoothDevice.TRANSPORT_BREDR | BluetoothDevice.TRANSPORT_LE); 2021 finished = true; 2022 } 2023 2024 if (finished) { 2025 if (DBG) Log.d(TAG, "continueServiceDeclaration() - completed."); 2026 ServerMap.App app = mServerMap.getById(serverIf); 2027 if (app != null) { 2028 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(srvcHandle); 2029 2030 if (serviceEntry != null) { 2031 app.callback.onServiceAdded(status, serviceEntry.serviceType, 2032 serviceEntry.instance, new ParcelUuid(serviceEntry.uuid)); 2033 } else { 2034 app.callback.onServiceAdded(status, 0, 0, null); 2035 } 2036 } 2037 removePendingDeclaration(); 2038 2039 if (getPendingDeclaration() != null) { 2040 continueServiceDeclaration(serverIf, (byte)0, 0); 2041 } 2042 } 2043 } 2044 2045 private void stopNextService(int serverIf, int status) throws RemoteException { 2046 if (DBG) Log.d(TAG, "stopNextService() - serverIf=" + serverIf 2047 + ", status=" + status); 2048 2049 if (status == 0) { 2050 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2051 for(HandleMap.Entry entry : entries) { 2052 if (entry.type != HandleMap.TYPE_SERVICE || 2053 entry.serverIf != serverIf || 2054 entry.started == false) 2055 continue; 2056 2057 gattServerStopServiceNative(serverIf, entry.handle); 2058 return; 2059 } 2060 } 2061 } 2062 2063 private void deleteServices(int serverIf) { 2064 if (DBG) Log.d(TAG, "deleteServices() - serverIf=" + serverIf); 2065 2066 /* 2067 * Figure out which handles to delete. 2068 * The handles are copied into a new list to avoid race conditions. 2069 */ 2070 List<Integer> handleList = new ArrayList<Integer>(); 2071 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2072 for(HandleMap.Entry entry : entries) { 2073 if (entry.type != HandleMap.TYPE_SERVICE || 2074 entry.serverIf != serverIf) 2075 continue; 2076 handleList.add(entry.handle); 2077 } 2078 2079 /* Now actually delete the services.... */ 2080 for(Integer handle : handleList) { 2081 gattServerDeleteServiceNative(serverIf, handle); 2082 } 2083 } 2084 2085 private List<UUID> parseUuids(byte[] adv_data) { 2086 List<UUID> uuids = new ArrayList<UUID>(); 2087 2088 int offset = 0; 2089 while(offset < (adv_data.length-2)) { 2090 int len = adv_data[offset++]; 2091 if (len == 0) break; 2092 2093 int type = adv_data[offset++]; 2094 switch (type) { 2095 case 0x02: // Partial list of 16-bit UUIDs 2096 case 0x03: // Complete list of 16-bit UUIDs 2097 while (len > 1) { 2098 int uuid16 = adv_data[offset++]; 2099 uuid16 += (adv_data[offset++] << 8); 2100 len -= 2; 2101 uuids.add(UUID.fromString(String.format( 2102 "%08x-0000-1000-8000-00805f9b34fb", uuid16))); 2103 } 2104 break; 2105 2106 default: 2107 offset += (len - 1); 2108 break; 2109 } 2110 } 2111 2112 return uuids; 2113 } 2114 2115 /************************************************************************** 2116 * GATT Test functions 2117 *************************************************************************/ 2118 2119 void gattTestCommand(int command, UUID uuid1, String bda1, 2120 int p1, int p2, int p3, int p4, int p5) { 2121 if (bda1 == null) bda1 = "00:00:00:00:00:00"; 2122 if (uuid1 != null) 2123 gattTestNative(command, uuid1.getLeastSignificantBits(), 2124 uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5); 2125 else 2126 gattTestNative(command, 0,0, bda1, p1, p2, p3, p4, p5); 2127 } 2128 2129 private native void gattTestNative(int command, 2130 long uuid1_lsb, long uuid1_msb, String bda1, 2131 int p1, int p2, int p3, int p4, int p5); 2132 2133 /************************************************************************** 2134 * Native functions prototypes 2135 *************************************************************************/ 2136 2137 private native static void classInitNative(); 2138 private native void initializeNative(); 2139 private native void cleanupNative(); 2140 2141 private native int gattClientGetDeviceTypeNative(String address); 2142 2143 private native void gattClientRegisterAppNative(long app_uuid_lsb, 2144 long app_uuid_msb); 2145 2146 private native void gattClientUnregisterAppNative(int clientIf); 2147 2148 private native void gattClientConnectNative(int clientIf, String address, 2149 boolean isDirect, int transport); 2150 2151 private native void gattClientDisconnectNative(int clientIf, String address, 2152 int conn_id); 2153 2154 private native void gattClientRefreshNative(int clientIf, String address); 2155 2156 private native void gattClientSearchServiceNative(int conn_id, 2157 boolean search_all, long service_uuid_lsb, long service_uuid_msb); 2158 2159 private native void gattClientGetCharacteristicNative(int conn_id, 2160 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2161 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2162 long char_id_uuid_msb); 2163 2164 private native void gattClientGetDescriptorNative(int conn_id, int service_type, 2165 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2166 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2167 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb); 2168 2169 private native void gattClientGetIncludedServiceNative(int conn_id, 2170 int service_type, int service_id_inst_id, 2171 long service_id_uuid_lsb, long service_id_uuid_msb, 2172 int incl_service_id_inst_id, int incl_service_type, 2173 long incl_service_id_uuid_lsb, long incl_service_id_uuid_msb); 2174 2175 private native void gattClientReadCharacteristicNative(int conn_id, 2176 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2177 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2178 long char_id_uuid_msb, int authReq); 2179 2180 private native void gattClientReadDescriptorNative(int conn_id, int service_type, 2181 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2182 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2183 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, 2184 int authReq); 2185 2186 private native void gattClientWriteCharacteristicNative(int conn_id, 2187 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2188 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2189 long char_id_uuid_msb, int write_type, int auth_req, byte[] value); 2190 2191 private native void gattClientWriteDescriptorNative(int conn_id, int service_type, 2192 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2193 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2194 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, 2195 int write_type, int auth_req, byte[] value); 2196 2197 private native void gattClientExecuteWriteNative(int conn_id, boolean execute); 2198 2199 private native void gattClientRegisterForNotificationsNative(int clientIf, 2200 String address, int service_type, int service_id_inst_id, 2201 long service_id_uuid_lsb, long service_id_uuid_msb, 2202 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2203 boolean enable); 2204 2205 private native void gattClientReadRemoteRssiNative(int clientIf, 2206 String address); 2207 2208 private native void gattAdvertiseNative(int client_if, boolean start); 2209 2210 private native void gattClientConfigureMTUNative(int conn_id, int mtu); 2211 2212 private native void gattConnectionParameterUpdateNative(int client_if, String address, 2213 int minInterval, int maxInterval, int latency, int timeout); 2214 2215 private native void gattSetAdvDataNative(int serverIf, boolean setScanRsp, boolean inclName, 2216 boolean inclTxPower, int minInterval, int maxInterval, 2217 int appearance, byte[] manufacturerData, byte[] serviceData, byte[] serviceUuid); 2218 2219 private native void gattServerRegisterAppNative(long app_uuid_lsb, 2220 long app_uuid_msb); 2221 2222 private native void gattServerUnregisterAppNative(int serverIf); 2223 2224 private native void gattServerConnectNative(int server_if, String address, 2225 boolean is_direct, int transport); 2226 2227 private native void gattServerDisconnectNative(int serverIf, String address, 2228 int conn_id); 2229 2230 private native void gattServerAddServiceNative (int server_if, 2231 int service_type, int service_id_inst_id, 2232 long service_id_uuid_lsb, long service_id_uuid_msb, 2233 int num_handles); 2234 2235 private native void gattServerAddIncludedServiceNative (int server_if, 2236 int svc_handle, int included_svc_handle); 2237 2238 private native void gattServerAddCharacteristicNative (int server_if, 2239 int svc_handle, long char_uuid_lsb, long char_uuid_msb, 2240 int properties, int permissions); 2241 2242 private native void gattServerAddDescriptorNative (int server_if, 2243 int svc_handle, long desc_uuid_lsb, long desc_uuid_msb, 2244 int permissions); 2245 2246 private native void gattServerStartServiceNative (int server_if, 2247 int svc_handle, int transport ); 2248 2249 private native void gattServerStopServiceNative (int server_if, 2250 int svc_handle); 2251 2252 private native void gattServerDeleteServiceNative (int server_if, 2253 int svc_handle); 2254 2255 private native void gattServerSendIndicationNative (int server_if, 2256 int attr_handle, int conn_id, byte[] val); 2257 2258 private native void gattServerSendNotificationNative (int server_if, 2259 int attr_handle, int conn_id, byte[] val); 2260 2261 private native void gattServerSendResponseNative (int server_if, 2262 int conn_id, int trans_id, int status, int handle, int offset, 2263 byte[] val, int auth_req); 2264} 2265