Loading android/app/jni/com_android_bluetooth_gatt.cpp +31 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,7 @@ namespace android { */ static jmethodID method_onClientRegistered; static jmethodID method_onScannerRegistered; static jmethodID method_onScanResult; static jmethodID method_onConnected; static jmethodID method_onDisconnected; Loading Loading @@ -205,6 +206,14 @@ void btgattc_register_app_cb(int status, int clientIf, bt_uuid_t *app_uuid) clientIf, UUID_PARAMS(app_uuid)); } void btgattc_register_scanner_cb(int status, int scannerId, bt_uuid_t *app_uuid) { CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid()) return; sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onScannerRegistered, status, scannerId, UUID_PARAMS(app_uuid)); } void btgattc_scan_result_cb(bt_bdaddr_t* bda, int rssi, vector<uint8_t> adv_data) { CallbackEnv sCallbackEnv(__func__); Loading Loading @@ -555,6 +564,7 @@ void btgattc_get_gatt_db_cb(int conn_id, btgatt_db_element_t *db, int count) static const btgatt_client_callbacks_t sGattClientCallbacks = { btgattc_register_app_cb, btgattc_register_scanner_cb, btgattc_scan_result_cb, btgattc_open_cb, btgattc_close_cb, Loading Loading @@ -811,6 +821,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) { // Client callbacks method_onClientRegistered = env->GetMethodID(clazz, "onClientRegistered", "(IIJJ)V"); method_onScannerRegistered = env->GetMethodID(clazz, "onScannerRegistered", "(IIJJ)V"); method_onScanResult = env->GetMethodID(clazz, "onScanResult", "(Ljava/lang/String;I[B)V"); method_onConnected = env->GetMethodID(clazz, "onConnected", "(IIILjava/lang/String;)V"); method_onDisconnected = env->GetMethodID(clazz, "onDisconnected", "(IIILjava/lang/String;)V"); Loading Loading @@ -946,6 +957,24 @@ static void gattClientUnregisterAppNative(JNIEnv* env, jobject object, jint clie sGattIf->client->unregister_client(clientIf); } static void registerScannerNative(JNIEnv* env, jobject object, jlong app_uuid_lsb, jlong app_uuid_msb) { bt_uuid_t uuid; if (!sGattIf) return; set_uuid(uuid.uu, app_uuid_msb, app_uuid_lsb); sGattIf->client->register_scanner(&uuid); } static void unregisterScannerNative(JNIEnv* env, jobject object, jint scanner_id) { if (!sGattIf) return; sGattIf->client->unregister_scanner(scanner_id); } static void gattClientScanNative(JNIEnv* env, jobject object, jboolean start) { if (!sGattIf) return; Loading Loading @@ -1630,6 +1659,8 @@ static JNINativeMethod sAdvertiseMethods[] = { // JNI functions defined in ScanManager class. static JNINativeMethod sScanMethods[] = { {"registerScannerNative", "(JJ)V", (void *) registerScannerNative}, {"unregisterScannerNative", "(I)V", (void *) unregisterScannerNative}, {"gattClientScanNative", "(Z)V", (void *) gattClientScanNative}, // Batch scan JNI functions. {"gattClientConfigBatchScanStorageNative", "(IIII)V",(void *) gattClientConfigBatchScanStorageNative}, Loading android/app/src/com/android/bluetooth/gatt/GattService.java +108 −76 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.bluetooth.le.AdvertiseCallback; import android.bluetooth.le.AdvertiseData; import android.bluetooth.le.AdvertiseSettings; import android.bluetooth.le.IAdvertiserCallback; import android.bluetooth.le.IScannerCallback; import android.bluetooth.le.ResultStorageDescriptor; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanRecord; Loading Loading @@ -106,6 +107,12 @@ public class GattService extends ProfileService { class AdvertiserMap extends ContextMap<IAdvertiserCallback> {} AdvertiserMap mAdvertiserMap = new AdvertiserMap(); /** * List of our registered advertisers. */ class ScannerMap extends ContextMap<IScannerCallback> {} ScannerMap mScannerMap = new ScannerMap(); /** * List of our registered clients. */ Loading Loading @@ -172,6 +179,8 @@ public class GattService extends ProfileService { protected boolean stop() { if (DBG) Log.d(TAG, "stop()"); mAdvertiserMap.clear(); mScannerMap.clear(); mClientMap.clear(); mServerMap.clear(); mHandleMap.clear(); Loading Loading @@ -233,19 +242,19 @@ public class GattService extends ProfileService { * disconnect ungracefully (ie. crash or forced close). */ class ClientDeathRecipient implements IBinder.DeathRecipient { int mAppIf; class ScannerDeathRecipient implements IBinder.DeathRecipient { int mScannerId; public ClientDeathRecipient(int appIf) { mAppIf = appIf; public ScannerDeathRecipient(int scannerId) { mScannerId = scannerId; } @Override public void binderDied() { if (DBG) Log.d(TAG, "Binder is dead - unregistering client (" + mAppIf + ")!"); if (DBG) Log.d(TAG, "Binder is dead - unregistering scanner (" + mScannerId + ")!"); if (isScanClient(mAppIf)) { ScanClient client = new ScanClient(mAppIf, false); if (isScanClient(mScannerId)) { ScanClient client = new ScanClient(mScannerId); client.appDied = true; stopScan(client); } Loading @@ -253,12 +262,12 @@ public class GattService extends ProfileService { private boolean isScanClient(int clientIf) { for (ScanClient client : mScanManager.getRegularScanQueue()) { if (client.clientIf == clientIf) { if (client.scannerId == clientIf) { return true; } } for (ScanClient client : mScanManager.getBatchScanQueue()) { if (client.clientIf == clientIf) { if (client.scannerId == clientIf) { return true; } } Loading Loading @@ -335,27 +344,39 @@ public class GattService extends ProfileService { service.unregisterClient(clientIf); } public void registerScanner(IScannerCallback callback) { GattService service = getService(); if (service == null) return; service.registerScanner(callback); } public void unregisterScanner(int scannerId) { GattService service = getService(); if (service == null) return; service.unregisterScanner(scannerId); } @Override public void startScan(int appIf, boolean isServer, ScanSettings settings, public void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, WorkSource workSource, List storages, String callingPackage) { GattService service = getService(); if (service == null) return; service.startScan(appIf, isServer, settings, filters, workSource, storages, service.startScan(scannerId, settings, filters, workSource, storages, callingPackage); } public void stopScan(int appIf, boolean isServer) { public void stopScan(int scannerId) { GattService service = getService(); if (service == null) return; service.stopScan(new ScanClient(appIf, isServer)); service.stopScan(new ScanClient(scannerId)); } @Override public void flushPendingBatchResults(int appIf, boolean isServer) { public void flushPendingBatchResults(int scannerId) { GattService service = getService(); if (service == null) return; service.flushPendingBatchResults(appIf, isServer); service.flushPendingBatchResults(scannerId); } public void clientConnect(int clientIf, String address, boolean isDirect, int transport) { Loading Loading @@ -576,8 +597,7 @@ public class GattService extends ProfileService { if (matches < client.uuids.length) continue; } if (!client.isServer) { ClientMap.App app = mClientMap.getById(client.clientIf); ScannerMap.App app = mScannerMap.getById(client.scannerId); if (app != null) { BluetoothDevice device = BluetoothAdapter.getDefaultAdapter() .getRemoteDevice(address); Loading @@ -595,23 +615,29 @@ public class GattService extends ProfileService { } } catch (RemoteException e) { Log.e(TAG, "Exception: " + e); mClientMap.remove(client.clientIf); mScannerMap.remove(client.scannerId); mScanManager.stopScan(client); } } } } else { ServerMap.App app = mServerMap.getById(client.clientIf); if (app != null) { try { app.callback.onScanResult(address, rssi, adv_data); } catch (RemoteException e) { Log.e(TAG, "Exception: " + e); mServerMap.remove(client.clientIf); mScanManager.stopScan(client); } } void onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb) throws RemoteException { UUID uuid = new UUID(uuidMsb, uuidLsb); if (DBG) Log.d(TAG, "onScannerRegistered() - UUID=" + uuid + ", scannerId=" + scannerId + ", status=" + status); ScannerMap.App app = mScannerMap.getByUuid(uuid); if (app != null) { if (status == 0) { app.id = scannerId; app.linkToDeath(new ScannerDeathRecipient(scannerId)); } else { mScannerMap.remove(scannerId); } app.callback.onScannerRegistered(status, scannerId); } } Loading Loading @@ -649,7 +675,6 @@ public class GattService extends ProfileService { if (app != null) { if (status == 0) { app.id = clientIf; app.linkToDeath(new ClientDeathRecipient(clientIf)); } else { mClientMap.remove(uuid); } Loading Loading @@ -904,17 +929,17 @@ public class GattService extends ProfileService { mScanManager.callbackDone(clientIf, status); } void onBatchScanReports(int status, int clientIf, int reportType, int numRecords, void onBatchScanReports(int status, int scannerId, int reportType, int numRecords, byte[] recordData) throws RemoteException { if (DBG) { Log.d(TAG, "onBatchScanReports() - clientIf=" + clientIf + ", status=" + status Log.d(TAG, "onBatchScanReports() - scannerId=" + scannerId + ", status=" + status + ", reportType=" + reportType + ", numRecords=" + numRecords); } mScanManager.callbackDone(clientIf, status); mScanManager.callbackDone(scannerId, status); Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData); if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { // We only support single client for truncated mode. ClientMap.App app = mClientMap.getById(clientIf); ScannerMap.App app = mScannerMap.getById(scannerId); if (app == null) return; app.callback.onBatchScanResults(new ArrayList<ScanResult>(results)); } else { Loading @@ -928,7 +953,7 @@ public class GattService extends ProfileService { // Check and deliver scan results for different scan clients. private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults) throws RemoteException { ClientMap.App app = mClientMap.getById(client.clientIf); ScannerMap.App app = mScannerMap.getById(client.scannerId); if (app == null) return; if (client.filters == null || client.filters.isEmpty()) { app.callback.onBatchScanResults(new ArrayList<ScanResult>(allResults)); Loading Loading @@ -1039,8 +1064,7 @@ public class GattService extends ProfileService { if (DBG) { Log.d(TAG, "onBatchScanThresholdCrossed() - clientIf=" + clientIf); } boolean isServer = false; flushPendingBatchResults(clientIf, isServer); flushPendingBatchResults(clientIf); } AdvtFilterOnFoundOnLostInfo CreateonTrackAdvFoundLostObject(int client_if, int adv_pkt_len, Loading @@ -1055,11 +1079,11 @@ public class GattService extends ProfileService { } void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) throws RemoteException { if (DBG) Log.d(TAG, "onTrackAdvFoundLost() - clientIf= " + trackingInfo.getClientIf() if (DBG) Log.d(TAG, "onTrackAdvFoundLost() - scannerId= " + trackingInfo.getClientIf() + " address = " + trackingInfo.getAddress() + " adv_state = " + trackingInfo.getAdvState()); ClientMap.App app = mClientMap.getById(trackingInfo.getClientIf()); ScannerMap.App app = mScannerMap.getById(trackingInfo.getClientIf()); if (app == null || app.callback == null) { Log.e(TAG, "app or callback is null"); return; Loading @@ -1073,7 +1097,7 @@ public class GattService extends ProfileService { trackingInfo.getRSSIValue(), SystemClock.elapsedRealtimeNanos()); for (ScanClient client : mScanManager.getRegularScanQueue()) { if (client.clientIf == trackingInfo.getClientIf()) { if (client.scannerId == trackingInfo.getClientIf()) { ScanSettings settings = client.settings; if ((advertiserState == ADVT_STATE_ONFOUND) && ((settings.getCallbackType() Loading @@ -1085,15 +1109,15 @@ public class GattService extends ProfileService { app.callback.onFoundOrLost(false, result); } else { Log.d(TAG, "Not reporting onlost/onfound : " + advertiserState + " clientIf = " + client.clientIf + " scannerId = " + client.scannerId + " callbackType " + settings.getCallbackType()); } } } } void onScanParamSetupCompleted(int status, int clientIf) throws RemoteException { ClientMap.App app = mClientMap.getById(clientIf); void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException { ScannerMap.App app = mScannerMap.getById(scannerId); if (app == null || app.callback == null) { Log.e(TAG, "Advertise app or callback is null"); return; Loading @@ -1115,8 +1139,8 @@ public class GattService extends ProfileService { } // callback from ScanManager for dispatch of errors apps. void onScanManagerErrorCallback(int clientIf, int errorCode) throws RemoteException { ClientMap.App app = mClientMap.getById(clientIf); void onScanManagerErrorCallback(int scannerId, int errorCode) throws RemoteException { ScannerMap.App app = mScannerMap.getById(scannerId); if (app == null || app.callback == null) { Log.e(TAG, "App or callback is null"); return; Loading Loading @@ -1267,7 +1291,24 @@ public class GattService extends ProfileService { return deviceList; } void startScan(int appIf, boolean isServer, ScanSettings settings, void registerScanner(IScannerCallback callback) { enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); UUID uuid = UUID.randomUUID(); if (DBG) Log.d(TAG, "registerScanner() - UUID=" + uuid); mScannerMap.add(uuid, callback, this); mScanManager.registerScanner(uuid); } void unregisterScanner(int scannerId) { enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); if (DBG) Log.d(TAG, "unregisterScanner() - scannerId=" + scannerId); mScannerMap.remove(scannerId); mScanManager.unregisterScanner(scannerId); } void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, WorkSource workSource, List<List<ResultStorageDescriptor>> storages, String callingPackage) { if (DBG) Log.d(TAG, "start scan with filters"); Loading @@ -1281,7 +1322,7 @@ public class GattService extends ProfileService { // Blame the caller if the work source is unspecified. workSource = new WorkSource(Binder.getCallingUid(), callingPackage); } final ScanClient scanClient = new ScanClient(appIf, isServer, settings, filters, workSource, final ScanClient scanClient = new ScanClient(scannerId, settings, filters, workSource, storages); scanClient.hasLocationPermission = Utils.checkCallerHasLocationPermission(this, mAppOps, callingPackage); Loading @@ -1290,11 +1331,7 @@ public class GattService extends ProfileService { scanClient.legacyForegroundApp = Utils.isLegacyForegroundApp(this, callingPackage); AppScanStats app = null; if (isServer) { app = mServerMap.getAppScanStatsById(appIf); } else { app = mClientMap.getAppScanStatsById(appIf); } app = mClientMap.getAppScanStatsById(scannerId); if (app != null) { if (app.isScanningTooFrequently() && Loading @@ -1309,10 +1346,9 @@ public class GattService extends ProfileService { mScanManager.startScan(scanClient); } void flushPendingBatchResults(int clientIf, boolean isServer) { if (DBG) Log.d(TAG, "flushPendingBatchResults - clientIf=" + clientIf + ", isServer=" + isServer); mScanManager.flushBatchScanResults(new ScanClient(clientIf, isServer)); void flushPendingBatchResults(int scannerId) { if (DBG) Log.d(TAG, "flushPendingBatchResults - scannerId=" + scannerId); mScanManager.flushBatchScanResults(new ScanClient(scannerId)); } void stopScan(ScanClient client) { Loading @@ -1322,11 +1358,7 @@ public class GattService extends ProfileService { if (DBG) Log.d(TAG, "stopScan() - queue size =" + scanQueueSize); AppScanStats app = null; if (client.isServer) { app = mServerMap.getAppScanStatsById(client.clientIf); } else { app = mClientMap.getAppScanStatsById(client.clientIf); } app = mScannerMap.getAppScanStatsById(client.scannerId); if (app != null) app.recordScanStop(); mScanManager.stopScan(client); Loading android/app/src/com/android/bluetooth/gatt/ScanClient.java +15 −17 Original line number Diff line number Diff line Loading @@ -31,8 +31,7 @@ import java.util.UUID; * @hide */ /* package */class ScanClient { int clientIf; boolean isServer; int scannerId; UUID[] uuids; ScanSettings settings; List<ScanFilter> filters; Loading @@ -52,35 +51,34 @@ import java.util.UUID; private static final ScanSettings DEFAULT_SCAN_SETTINGS = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); ScanClient(int appIf, boolean isServer) { this(appIf, isServer, new UUID[0], DEFAULT_SCAN_SETTINGS, null, null, null); ScanClient(int scannerId) { this(scannerId, new UUID[0], DEFAULT_SCAN_SETTINGS, null, null, null); } ScanClient(int appIf, boolean isServer, UUID[] uuids) { this(appIf, isServer, uuids, DEFAULT_SCAN_SETTINGS, null, null, null); ScanClient(int scannerId, UUID[] uuids) { this(scannerId, uuids, DEFAULT_SCAN_SETTINGS, null, null, null); } ScanClient(int appIf, boolean isServer, ScanSettings settings, ScanClient(int scannerId, ScanSettings settings, List<ScanFilter> filters) { this(appIf, isServer, new UUID[0], settings, filters, null, null); this(scannerId, new UUID[0], settings, filters, null, null); } ScanClient(int appIf, boolean isServer, ScanSettings settings, ScanClient(int scannerId, ScanSettings settings, List<ScanFilter> filters, List<List<ResultStorageDescriptor>> storages) { this(appIf, isServer, new UUID[0], settings, filters, null, storages); this(scannerId, new UUID[0], settings, filters, null, storages); } ScanClient(int appIf, boolean isServer, ScanSettings settings, ScanClient(int scannerId, ScanSettings settings, List<ScanFilter> filters, WorkSource workSource, List<List<ResultStorageDescriptor>> storages) { this(appIf, isServer, new UUID[0], settings, filters, workSource, storages); this(scannerId, new UUID[0], settings, filters, workSource, storages); } private ScanClient(int appIf, boolean isServer, UUID[] uuids, ScanSettings settings, private ScanClient(int scannerId, UUID[] uuids, ScanSettings settings, List<ScanFilter> filters, WorkSource workSource, List<List<ResultStorageDescriptor>> storages) { this.clientIf = appIf; this.isServer = isServer; this.scannerId = scannerId; this.uuids = uuids; this.settings = settings; this.filters = filters; Loading @@ -97,11 +95,11 @@ import java.util.UUID; return false; } ScanClient other = (ScanClient) obj; return clientIf == other.clientIf; return scannerId == other.scannerId; } @Override public int hashCode() { return Objects.hash(clientIf); return Objects.hash(scannerId); } } Loading
android/app/jni/com_android_bluetooth_gatt.cpp +31 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,7 @@ namespace android { */ static jmethodID method_onClientRegistered; static jmethodID method_onScannerRegistered; static jmethodID method_onScanResult; static jmethodID method_onConnected; static jmethodID method_onDisconnected; Loading Loading @@ -205,6 +206,14 @@ void btgattc_register_app_cb(int status, int clientIf, bt_uuid_t *app_uuid) clientIf, UUID_PARAMS(app_uuid)); } void btgattc_register_scanner_cb(int status, int scannerId, bt_uuid_t *app_uuid) { CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid()) return; sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onScannerRegistered, status, scannerId, UUID_PARAMS(app_uuid)); } void btgattc_scan_result_cb(bt_bdaddr_t* bda, int rssi, vector<uint8_t> adv_data) { CallbackEnv sCallbackEnv(__func__); Loading Loading @@ -555,6 +564,7 @@ void btgattc_get_gatt_db_cb(int conn_id, btgatt_db_element_t *db, int count) static const btgatt_client_callbacks_t sGattClientCallbacks = { btgattc_register_app_cb, btgattc_register_scanner_cb, btgattc_scan_result_cb, btgattc_open_cb, btgattc_close_cb, Loading Loading @@ -811,6 +821,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) { // Client callbacks method_onClientRegistered = env->GetMethodID(clazz, "onClientRegistered", "(IIJJ)V"); method_onScannerRegistered = env->GetMethodID(clazz, "onScannerRegistered", "(IIJJ)V"); method_onScanResult = env->GetMethodID(clazz, "onScanResult", "(Ljava/lang/String;I[B)V"); method_onConnected = env->GetMethodID(clazz, "onConnected", "(IIILjava/lang/String;)V"); method_onDisconnected = env->GetMethodID(clazz, "onDisconnected", "(IIILjava/lang/String;)V"); Loading Loading @@ -946,6 +957,24 @@ static void gattClientUnregisterAppNative(JNIEnv* env, jobject object, jint clie sGattIf->client->unregister_client(clientIf); } static void registerScannerNative(JNIEnv* env, jobject object, jlong app_uuid_lsb, jlong app_uuid_msb) { bt_uuid_t uuid; if (!sGattIf) return; set_uuid(uuid.uu, app_uuid_msb, app_uuid_lsb); sGattIf->client->register_scanner(&uuid); } static void unregisterScannerNative(JNIEnv* env, jobject object, jint scanner_id) { if (!sGattIf) return; sGattIf->client->unregister_scanner(scanner_id); } static void gattClientScanNative(JNIEnv* env, jobject object, jboolean start) { if (!sGattIf) return; Loading Loading @@ -1630,6 +1659,8 @@ static JNINativeMethod sAdvertiseMethods[] = { // JNI functions defined in ScanManager class. static JNINativeMethod sScanMethods[] = { {"registerScannerNative", "(JJ)V", (void *) registerScannerNative}, {"unregisterScannerNative", "(I)V", (void *) unregisterScannerNative}, {"gattClientScanNative", "(Z)V", (void *) gattClientScanNative}, // Batch scan JNI functions. {"gattClientConfigBatchScanStorageNative", "(IIII)V",(void *) gattClientConfigBatchScanStorageNative}, Loading
android/app/src/com/android/bluetooth/gatt/GattService.java +108 −76 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.bluetooth.le.AdvertiseCallback; import android.bluetooth.le.AdvertiseData; import android.bluetooth.le.AdvertiseSettings; import android.bluetooth.le.IAdvertiserCallback; import android.bluetooth.le.IScannerCallback; import android.bluetooth.le.ResultStorageDescriptor; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanRecord; Loading Loading @@ -106,6 +107,12 @@ public class GattService extends ProfileService { class AdvertiserMap extends ContextMap<IAdvertiserCallback> {} AdvertiserMap mAdvertiserMap = new AdvertiserMap(); /** * List of our registered advertisers. */ class ScannerMap extends ContextMap<IScannerCallback> {} ScannerMap mScannerMap = new ScannerMap(); /** * List of our registered clients. */ Loading Loading @@ -172,6 +179,8 @@ public class GattService extends ProfileService { protected boolean stop() { if (DBG) Log.d(TAG, "stop()"); mAdvertiserMap.clear(); mScannerMap.clear(); mClientMap.clear(); mServerMap.clear(); mHandleMap.clear(); Loading Loading @@ -233,19 +242,19 @@ public class GattService extends ProfileService { * disconnect ungracefully (ie. crash or forced close). */ class ClientDeathRecipient implements IBinder.DeathRecipient { int mAppIf; class ScannerDeathRecipient implements IBinder.DeathRecipient { int mScannerId; public ClientDeathRecipient(int appIf) { mAppIf = appIf; public ScannerDeathRecipient(int scannerId) { mScannerId = scannerId; } @Override public void binderDied() { if (DBG) Log.d(TAG, "Binder is dead - unregistering client (" + mAppIf + ")!"); if (DBG) Log.d(TAG, "Binder is dead - unregistering scanner (" + mScannerId + ")!"); if (isScanClient(mAppIf)) { ScanClient client = new ScanClient(mAppIf, false); if (isScanClient(mScannerId)) { ScanClient client = new ScanClient(mScannerId); client.appDied = true; stopScan(client); } Loading @@ -253,12 +262,12 @@ public class GattService extends ProfileService { private boolean isScanClient(int clientIf) { for (ScanClient client : mScanManager.getRegularScanQueue()) { if (client.clientIf == clientIf) { if (client.scannerId == clientIf) { return true; } } for (ScanClient client : mScanManager.getBatchScanQueue()) { if (client.clientIf == clientIf) { if (client.scannerId == clientIf) { return true; } } Loading Loading @@ -335,27 +344,39 @@ public class GattService extends ProfileService { service.unregisterClient(clientIf); } public void registerScanner(IScannerCallback callback) { GattService service = getService(); if (service == null) return; service.registerScanner(callback); } public void unregisterScanner(int scannerId) { GattService service = getService(); if (service == null) return; service.unregisterScanner(scannerId); } @Override public void startScan(int appIf, boolean isServer, ScanSettings settings, public void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, WorkSource workSource, List storages, String callingPackage) { GattService service = getService(); if (service == null) return; service.startScan(appIf, isServer, settings, filters, workSource, storages, service.startScan(scannerId, settings, filters, workSource, storages, callingPackage); } public void stopScan(int appIf, boolean isServer) { public void stopScan(int scannerId) { GattService service = getService(); if (service == null) return; service.stopScan(new ScanClient(appIf, isServer)); service.stopScan(new ScanClient(scannerId)); } @Override public void flushPendingBatchResults(int appIf, boolean isServer) { public void flushPendingBatchResults(int scannerId) { GattService service = getService(); if (service == null) return; service.flushPendingBatchResults(appIf, isServer); service.flushPendingBatchResults(scannerId); } public void clientConnect(int clientIf, String address, boolean isDirect, int transport) { Loading Loading @@ -576,8 +597,7 @@ public class GattService extends ProfileService { if (matches < client.uuids.length) continue; } if (!client.isServer) { ClientMap.App app = mClientMap.getById(client.clientIf); ScannerMap.App app = mScannerMap.getById(client.scannerId); if (app != null) { BluetoothDevice device = BluetoothAdapter.getDefaultAdapter() .getRemoteDevice(address); Loading @@ -595,23 +615,29 @@ public class GattService extends ProfileService { } } catch (RemoteException e) { Log.e(TAG, "Exception: " + e); mClientMap.remove(client.clientIf); mScannerMap.remove(client.scannerId); mScanManager.stopScan(client); } } } } else { ServerMap.App app = mServerMap.getById(client.clientIf); if (app != null) { try { app.callback.onScanResult(address, rssi, adv_data); } catch (RemoteException e) { Log.e(TAG, "Exception: " + e); mServerMap.remove(client.clientIf); mScanManager.stopScan(client); } } void onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb) throws RemoteException { UUID uuid = new UUID(uuidMsb, uuidLsb); if (DBG) Log.d(TAG, "onScannerRegistered() - UUID=" + uuid + ", scannerId=" + scannerId + ", status=" + status); ScannerMap.App app = mScannerMap.getByUuid(uuid); if (app != null) { if (status == 0) { app.id = scannerId; app.linkToDeath(new ScannerDeathRecipient(scannerId)); } else { mScannerMap.remove(scannerId); } app.callback.onScannerRegistered(status, scannerId); } } Loading Loading @@ -649,7 +675,6 @@ public class GattService extends ProfileService { if (app != null) { if (status == 0) { app.id = clientIf; app.linkToDeath(new ClientDeathRecipient(clientIf)); } else { mClientMap.remove(uuid); } Loading Loading @@ -904,17 +929,17 @@ public class GattService extends ProfileService { mScanManager.callbackDone(clientIf, status); } void onBatchScanReports(int status, int clientIf, int reportType, int numRecords, void onBatchScanReports(int status, int scannerId, int reportType, int numRecords, byte[] recordData) throws RemoteException { if (DBG) { Log.d(TAG, "onBatchScanReports() - clientIf=" + clientIf + ", status=" + status Log.d(TAG, "onBatchScanReports() - scannerId=" + scannerId + ", status=" + status + ", reportType=" + reportType + ", numRecords=" + numRecords); } mScanManager.callbackDone(clientIf, status); mScanManager.callbackDone(scannerId, status); Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData); if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { // We only support single client for truncated mode. ClientMap.App app = mClientMap.getById(clientIf); ScannerMap.App app = mScannerMap.getById(scannerId); if (app == null) return; app.callback.onBatchScanResults(new ArrayList<ScanResult>(results)); } else { Loading @@ -928,7 +953,7 @@ public class GattService extends ProfileService { // Check and deliver scan results for different scan clients. private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults) throws RemoteException { ClientMap.App app = mClientMap.getById(client.clientIf); ScannerMap.App app = mScannerMap.getById(client.scannerId); if (app == null) return; if (client.filters == null || client.filters.isEmpty()) { app.callback.onBatchScanResults(new ArrayList<ScanResult>(allResults)); Loading Loading @@ -1039,8 +1064,7 @@ public class GattService extends ProfileService { if (DBG) { Log.d(TAG, "onBatchScanThresholdCrossed() - clientIf=" + clientIf); } boolean isServer = false; flushPendingBatchResults(clientIf, isServer); flushPendingBatchResults(clientIf); } AdvtFilterOnFoundOnLostInfo CreateonTrackAdvFoundLostObject(int client_if, int adv_pkt_len, Loading @@ -1055,11 +1079,11 @@ public class GattService extends ProfileService { } void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) throws RemoteException { if (DBG) Log.d(TAG, "onTrackAdvFoundLost() - clientIf= " + trackingInfo.getClientIf() if (DBG) Log.d(TAG, "onTrackAdvFoundLost() - scannerId= " + trackingInfo.getClientIf() + " address = " + trackingInfo.getAddress() + " adv_state = " + trackingInfo.getAdvState()); ClientMap.App app = mClientMap.getById(trackingInfo.getClientIf()); ScannerMap.App app = mScannerMap.getById(trackingInfo.getClientIf()); if (app == null || app.callback == null) { Log.e(TAG, "app or callback is null"); return; Loading @@ -1073,7 +1097,7 @@ public class GattService extends ProfileService { trackingInfo.getRSSIValue(), SystemClock.elapsedRealtimeNanos()); for (ScanClient client : mScanManager.getRegularScanQueue()) { if (client.clientIf == trackingInfo.getClientIf()) { if (client.scannerId == trackingInfo.getClientIf()) { ScanSettings settings = client.settings; if ((advertiserState == ADVT_STATE_ONFOUND) && ((settings.getCallbackType() Loading @@ -1085,15 +1109,15 @@ public class GattService extends ProfileService { app.callback.onFoundOrLost(false, result); } else { Log.d(TAG, "Not reporting onlost/onfound : " + advertiserState + " clientIf = " + client.clientIf + " scannerId = " + client.scannerId + " callbackType " + settings.getCallbackType()); } } } } void onScanParamSetupCompleted(int status, int clientIf) throws RemoteException { ClientMap.App app = mClientMap.getById(clientIf); void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException { ScannerMap.App app = mScannerMap.getById(scannerId); if (app == null || app.callback == null) { Log.e(TAG, "Advertise app or callback is null"); return; Loading @@ -1115,8 +1139,8 @@ public class GattService extends ProfileService { } // callback from ScanManager for dispatch of errors apps. void onScanManagerErrorCallback(int clientIf, int errorCode) throws RemoteException { ClientMap.App app = mClientMap.getById(clientIf); void onScanManagerErrorCallback(int scannerId, int errorCode) throws RemoteException { ScannerMap.App app = mScannerMap.getById(scannerId); if (app == null || app.callback == null) { Log.e(TAG, "App or callback is null"); return; Loading Loading @@ -1267,7 +1291,24 @@ public class GattService extends ProfileService { return deviceList; } void startScan(int appIf, boolean isServer, ScanSettings settings, void registerScanner(IScannerCallback callback) { enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); UUID uuid = UUID.randomUUID(); if (DBG) Log.d(TAG, "registerScanner() - UUID=" + uuid); mScannerMap.add(uuid, callback, this); mScanManager.registerScanner(uuid); } void unregisterScanner(int scannerId) { enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); if (DBG) Log.d(TAG, "unregisterScanner() - scannerId=" + scannerId); mScannerMap.remove(scannerId); mScanManager.unregisterScanner(scannerId); } void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, WorkSource workSource, List<List<ResultStorageDescriptor>> storages, String callingPackage) { if (DBG) Log.d(TAG, "start scan with filters"); Loading @@ -1281,7 +1322,7 @@ public class GattService extends ProfileService { // Blame the caller if the work source is unspecified. workSource = new WorkSource(Binder.getCallingUid(), callingPackage); } final ScanClient scanClient = new ScanClient(appIf, isServer, settings, filters, workSource, final ScanClient scanClient = new ScanClient(scannerId, settings, filters, workSource, storages); scanClient.hasLocationPermission = Utils.checkCallerHasLocationPermission(this, mAppOps, callingPackage); Loading @@ -1290,11 +1331,7 @@ public class GattService extends ProfileService { scanClient.legacyForegroundApp = Utils.isLegacyForegroundApp(this, callingPackage); AppScanStats app = null; if (isServer) { app = mServerMap.getAppScanStatsById(appIf); } else { app = mClientMap.getAppScanStatsById(appIf); } app = mClientMap.getAppScanStatsById(scannerId); if (app != null) { if (app.isScanningTooFrequently() && Loading @@ -1309,10 +1346,9 @@ public class GattService extends ProfileService { mScanManager.startScan(scanClient); } void flushPendingBatchResults(int clientIf, boolean isServer) { if (DBG) Log.d(TAG, "flushPendingBatchResults - clientIf=" + clientIf + ", isServer=" + isServer); mScanManager.flushBatchScanResults(new ScanClient(clientIf, isServer)); void flushPendingBatchResults(int scannerId) { if (DBG) Log.d(TAG, "flushPendingBatchResults - scannerId=" + scannerId); mScanManager.flushBatchScanResults(new ScanClient(scannerId)); } void stopScan(ScanClient client) { Loading @@ -1322,11 +1358,7 @@ public class GattService extends ProfileService { if (DBG) Log.d(TAG, "stopScan() - queue size =" + scanQueueSize); AppScanStats app = null; if (client.isServer) { app = mServerMap.getAppScanStatsById(client.clientIf); } else { app = mClientMap.getAppScanStatsById(client.clientIf); } app = mScannerMap.getAppScanStatsById(client.scannerId); if (app != null) app.recordScanStop(); mScanManager.stopScan(client); Loading
android/app/src/com/android/bluetooth/gatt/ScanClient.java +15 −17 Original line number Diff line number Diff line Loading @@ -31,8 +31,7 @@ import java.util.UUID; * @hide */ /* package */class ScanClient { int clientIf; boolean isServer; int scannerId; UUID[] uuids; ScanSettings settings; List<ScanFilter> filters; Loading @@ -52,35 +51,34 @@ import java.util.UUID; private static final ScanSettings DEFAULT_SCAN_SETTINGS = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); ScanClient(int appIf, boolean isServer) { this(appIf, isServer, new UUID[0], DEFAULT_SCAN_SETTINGS, null, null, null); ScanClient(int scannerId) { this(scannerId, new UUID[0], DEFAULT_SCAN_SETTINGS, null, null, null); } ScanClient(int appIf, boolean isServer, UUID[] uuids) { this(appIf, isServer, uuids, DEFAULT_SCAN_SETTINGS, null, null, null); ScanClient(int scannerId, UUID[] uuids) { this(scannerId, uuids, DEFAULT_SCAN_SETTINGS, null, null, null); } ScanClient(int appIf, boolean isServer, ScanSettings settings, ScanClient(int scannerId, ScanSettings settings, List<ScanFilter> filters) { this(appIf, isServer, new UUID[0], settings, filters, null, null); this(scannerId, new UUID[0], settings, filters, null, null); } ScanClient(int appIf, boolean isServer, ScanSettings settings, ScanClient(int scannerId, ScanSettings settings, List<ScanFilter> filters, List<List<ResultStorageDescriptor>> storages) { this(appIf, isServer, new UUID[0], settings, filters, null, storages); this(scannerId, new UUID[0], settings, filters, null, storages); } ScanClient(int appIf, boolean isServer, ScanSettings settings, ScanClient(int scannerId, ScanSettings settings, List<ScanFilter> filters, WorkSource workSource, List<List<ResultStorageDescriptor>> storages) { this(appIf, isServer, new UUID[0], settings, filters, workSource, storages); this(scannerId, new UUID[0], settings, filters, workSource, storages); } private ScanClient(int appIf, boolean isServer, UUID[] uuids, ScanSettings settings, private ScanClient(int scannerId, UUID[] uuids, ScanSettings settings, List<ScanFilter> filters, WorkSource workSource, List<List<ResultStorageDescriptor>> storages) { this.clientIf = appIf; this.isServer = isServer; this.scannerId = scannerId; this.uuids = uuids; this.settings = settings; this.filters = filters; Loading @@ -97,11 +95,11 @@ import java.util.UUID; return false; } ScanClient other = (ScanClient) obj; return clientIf == other.clientIf; return scannerId == other.scannerId; } @Override public int hashCode() { return Objects.hash(clientIf); return Objects.hash(scannerId); } }