Loading android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +6 −4 Original line number Diff line number Diff line Loading @@ -367,7 +367,8 @@ static void acl_state_changed_callback(bt_status_t status, RawAddress* bd_addr, bt_acl_state_t state, int transport_link_type, bt_hci_error_code_t hci_reason, bt_conn_direction_t direction) { bt_conn_direction_t direction, uint16_t acl_handle) { if (!bd_addr) { ALOGE("Address is null in %s", __func__); return; Loading @@ -387,7 +388,8 @@ static void acl_state_changed_callback(bt_status_t status, RawAddress* bd_addr, sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_aclStateChangeCallback, (jint)status, addr.get(), (jint)state, (jint)transport_link_type, (jint)hci_reason); (jint)transport_link_type, (jint)hci_reason, (jint)acl_handle); } static void discovery_state_changed_callback(bt_discovery_state_t state) { Loading Loading @@ -953,8 +955,8 @@ static void classInitNative(JNIEnv* env, jclass clazz) { method_leAddressAssociateCallback = env->GetMethodID( jniCallbackClass, "leAddressAssociateCallback", "([B[B)V"); method_aclStateChangeCallback = env->GetMethodID(jniCallbackClass, "aclStateChangeCallback", "(I[BIII)V"); method_aclStateChangeCallback = env->GetMethodID( jniCallbackClass, "aclStateChangeCallback", "(I[BIIII)V"); method_linkQualityReportCallback = env->GetMethodID( jniCallbackClass, "linkQualityReportCallback", "(JIIIIII)V"); Loading android/app/src/com/android/bluetooth/btservice/AdapterService.java +36 −0 Original line number Diff line number Diff line Loading @@ -2466,6 +2466,34 @@ public class AdapterService extends Service { return service.getConnectionState(device); } @Override public void getConnectionHandle(BluetoothDevice device, int transport, AttributionSource source, SynchronousResultReceiver receiver) { try { receiver.send(getConnectionHandle(device, transport, source)); } catch (RuntimeException e) { receiver.propagateException(e); } } @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) private int getConnectionHandle( BluetoothDevice device, int transport, AttributionSource attributionSource) { AdapterService service = getService(); if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveDevice") || !Utils.checkConnectPermissionForDataDelivery( service, attributionSource, TAG)) { return BluetoothDevice.ERROR; } enforceBluetoothPrivilegedPermission(service); return service.getConnectionHandle(device, transport); } @Override public void canBondWithoutDialog(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver) { Loading Loading @@ -4453,6 +4481,14 @@ public class AdapterService extends Service { return getConnectionStateNative(getBytesFromAddress(device.getAddress())); } int getConnectionHandle(BluetoothDevice device, int transport) { DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); if (deviceProp == null) { return BluetoothDevice.ERROR; } return deviceProp.getConnectionHandle(transport); } /** * Checks whether the device was recently associated with the comapnion app that called * {@link BluetoothDevice#createBond}. This allows these devices to skip the pairing dialog if Loading android/app/src/com/android/bluetooth/btservice/JniCallbacks.java +2 −2 Original line number Diff line number Diff line Loading @@ -76,9 +76,9 @@ final class JniCallbacks { } void aclStateChangeCallback(int status, byte[] address, int newState, int transportLinkType, int hciReason) { int transportLinkType, int hciReason, int handle) { mRemoteDevices.aclStateChangeCallback(status, address, newState, transportLinkType, hciReason); transportLinkType, hciReason, handle); } void stateChangeCallback(int status) { Loading android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +40 −1 Original line number Diff line number Diff line Loading @@ -307,6 +307,8 @@ final class RemoteDevices { private String mIdentityAddress; private boolean mIsConsolidated = false; private int mBluetoothClass = BluetoothClass.Device.Major.UNCATEGORIZED; private int mBredrConnectionHandle = BluetoothDevice.ERROR; private int mLeConnectionHandle = BluetoothDevice.ERROR; private short mRssi; private String mAlias; private BluetoothDevice mDevice; Loading Loading @@ -394,6 +396,38 @@ final class RemoteDevices { } } /** * @param transport the transport on which the connection exists * @return the mConnectionHandle */ int getConnectionHandle(int transport) { synchronized (mObject) { if (transport == BluetoothDevice.TRANSPORT_BREDR) { return mBredrConnectionHandle; } else if (transport == BluetoothDevice.TRANSPORT_LE) { return mLeConnectionHandle; } else { return BluetoothDevice.ERROR; } } } /** * @param connectionHandle the connectionHandle to set * @param transport the transport on which to set the handle */ void setConnectionHandle(int connectionHandle, int transport) { synchronized (mObject) { if (transport == BluetoothDevice.TRANSPORT_BREDR) { mBredrConnectionHandle = connectionHandle; } else if (transport == BluetoothDevice.TRANSPORT_LE) { mLeConnectionHandle = connectionHandle; } else { errorLog("setConnectionHandle() unexpected transport value " + transport); } } } /** * @return the mUuids */ Loading Loading @@ -945,7 +979,7 @@ final class RemoteDevices { android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) void aclStateChangeCallback(int status, byte[] address, int newState, int transportLinkType, int hciReason) { int transportLinkType, int hciReason, int handle) { if (status != AbstractionLayer.BT_STATUS_SUCCESS) { debugLog("aclStateChangeCallback status is " + status + ", skipping"); return; Loading @@ -958,10 +992,14 @@ final class RemoteDevices { + Utils.getAddressStringFromByte(address) + ", newState=" + newState); return; } DeviceProperties deviceProperties = getDeviceProperties(device); int state = mAdapterService.getState(); Intent intent = null; if (newState == AbstractionLayer.BT_ACL_STATE_CONNECTED) { deviceProperties.setConnectionHandle(handle, transportLinkType); if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_TURNING_ON) { intent = new Intent(BluetoothDevice.ACTION_ACL_CONNECTED); intent.putExtra(BluetoothDevice.EXTRA_TRANSPORT, transportLinkType); Loading @@ -979,6 +1017,7 @@ final class RemoteDevices { "aclStateChangeCallback: Adapter State: " + BluetoothAdapter.nameForState(state) + " Connected: " + device); } else { deviceProperties.setConnectionHandle(BluetoothDevice.ERROR, transportLinkType); if (device.getBondState() == BluetoothDevice.BOND_BONDING) { // Send PAIRING_CANCEL intent to dismiss any dialog requesting bonding. intent = new Intent(BluetoothDevice.ACTION_PAIRING_CANCEL); Loading android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java +2 −1 Original line number Diff line number Diff line Loading @@ -296,7 +296,8 @@ public class RemoteDevicesTest { // BluetoothDevice.BATTERY_LEVEL_UNKNOWN when(mAdapterService.getState()).thenReturn(BluetoothAdapter.STATE_ON); mRemoteDevices.aclStateChangeCallback(0, Utils.getByteAddress(mDevice1), AbstractionLayer.BT_ACL_STATE_DISCONNECTED, 2, 19); // HCI code 19 remote terminated AbstractionLayer.BT_ACL_STATE_DISCONNECTED, 2, 19, BluetoothDevice.ERROR); // HCI code 19 remote terminated // Verify ACTION_ACL_DISCONNECTED and BATTERY_LEVEL_CHANGED intent are sent verify(mAdapterService, times(3)).sendBroadcast(mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); Loading Loading
android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +6 −4 Original line number Diff line number Diff line Loading @@ -367,7 +367,8 @@ static void acl_state_changed_callback(bt_status_t status, RawAddress* bd_addr, bt_acl_state_t state, int transport_link_type, bt_hci_error_code_t hci_reason, bt_conn_direction_t direction) { bt_conn_direction_t direction, uint16_t acl_handle) { if (!bd_addr) { ALOGE("Address is null in %s", __func__); return; Loading @@ -387,7 +388,8 @@ static void acl_state_changed_callback(bt_status_t status, RawAddress* bd_addr, sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_aclStateChangeCallback, (jint)status, addr.get(), (jint)state, (jint)transport_link_type, (jint)hci_reason); (jint)transport_link_type, (jint)hci_reason, (jint)acl_handle); } static void discovery_state_changed_callback(bt_discovery_state_t state) { Loading Loading @@ -953,8 +955,8 @@ static void classInitNative(JNIEnv* env, jclass clazz) { method_leAddressAssociateCallback = env->GetMethodID( jniCallbackClass, "leAddressAssociateCallback", "([B[B)V"); method_aclStateChangeCallback = env->GetMethodID(jniCallbackClass, "aclStateChangeCallback", "(I[BIII)V"); method_aclStateChangeCallback = env->GetMethodID( jniCallbackClass, "aclStateChangeCallback", "(I[BIIII)V"); method_linkQualityReportCallback = env->GetMethodID( jniCallbackClass, "linkQualityReportCallback", "(JIIIIII)V"); Loading
android/app/src/com/android/bluetooth/btservice/AdapterService.java +36 −0 Original line number Diff line number Diff line Loading @@ -2466,6 +2466,34 @@ public class AdapterService extends Service { return service.getConnectionState(device); } @Override public void getConnectionHandle(BluetoothDevice device, int transport, AttributionSource source, SynchronousResultReceiver receiver) { try { receiver.send(getConnectionHandle(device, transport, source)); } catch (RuntimeException e) { receiver.propagateException(e); } } @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) private int getConnectionHandle( BluetoothDevice device, int transport, AttributionSource attributionSource) { AdapterService service = getService(); if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveDevice") || !Utils.checkConnectPermissionForDataDelivery( service, attributionSource, TAG)) { return BluetoothDevice.ERROR; } enforceBluetoothPrivilegedPermission(service); return service.getConnectionHandle(device, transport); } @Override public void canBondWithoutDialog(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver) { Loading Loading @@ -4453,6 +4481,14 @@ public class AdapterService extends Service { return getConnectionStateNative(getBytesFromAddress(device.getAddress())); } int getConnectionHandle(BluetoothDevice device, int transport) { DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); if (deviceProp == null) { return BluetoothDevice.ERROR; } return deviceProp.getConnectionHandle(transport); } /** * Checks whether the device was recently associated with the comapnion app that called * {@link BluetoothDevice#createBond}. This allows these devices to skip the pairing dialog if Loading
android/app/src/com/android/bluetooth/btservice/JniCallbacks.java +2 −2 Original line number Diff line number Diff line Loading @@ -76,9 +76,9 @@ final class JniCallbacks { } void aclStateChangeCallback(int status, byte[] address, int newState, int transportLinkType, int hciReason) { int transportLinkType, int hciReason, int handle) { mRemoteDevices.aclStateChangeCallback(status, address, newState, transportLinkType, hciReason); transportLinkType, hciReason, handle); } void stateChangeCallback(int status) { Loading
android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +40 −1 Original line number Diff line number Diff line Loading @@ -307,6 +307,8 @@ final class RemoteDevices { private String mIdentityAddress; private boolean mIsConsolidated = false; private int mBluetoothClass = BluetoothClass.Device.Major.UNCATEGORIZED; private int mBredrConnectionHandle = BluetoothDevice.ERROR; private int mLeConnectionHandle = BluetoothDevice.ERROR; private short mRssi; private String mAlias; private BluetoothDevice mDevice; Loading Loading @@ -394,6 +396,38 @@ final class RemoteDevices { } } /** * @param transport the transport on which the connection exists * @return the mConnectionHandle */ int getConnectionHandle(int transport) { synchronized (mObject) { if (transport == BluetoothDevice.TRANSPORT_BREDR) { return mBredrConnectionHandle; } else if (transport == BluetoothDevice.TRANSPORT_LE) { return mLeConnectionHandle; } else { return BluetoothDevice.ERROR; } } } /** * @param connectionHandle the connectionHandle to set * @param transport the transport on which to set the handle */ void setConnectionHandle(int connectionHandle, int transport) { synchronized (mObject) { if (transport == BluetoothDevice.TRANSPORT_BREDR) { mBredrConnectionHandle = connectionHandle; } else if (transport == BluetoothDevice.TRANSPORT_LE) { mLeConnectionHandle = connectionHandle; } else { errorLog("setConnectionHandle() unexpected transport value " + transport); } } } /** * @return the mUuids */ Loading Loading @@ -945,7 +979,7 @@ final class RemoteDevices { android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) void aclStateChangeCallback(int status, byte[] address, int newState, int transportLinkType, int hciReason) { int transportLinkType, int hciReason, int handle) { if (status != AbstractionLayer.BT_STATUS_SUCCESS) { debugLog("aclStateChangeCallback status is " + status + ", skipping"); return; Loading @@ -958,10 +992,14 @@ final class RemoteDevices { + Utils.getAddressStringFromByte(address) + ", newState=" + newState); return; } DeviceProperties deviceProperties = getDeviceProperties(device); int state = mAdapterService.getState(); Intent intent = null; if (newState == AbstractionLayer.BT_ACL_STATE_CONNECTED) { deviceProperties.setConnectionHandle(handle, transportLinkType); if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_TURNING_ON) { intent = new Intent(BluetoothDevice.ACTION_ACL_CONNECTED); intent.putExtra(BluetoothDevice.EXTRA_TRANSPORT, transportLinkType); Loading @@ -979,6 +1017,7 @@ final class RemoteDevices { "aclStateChangeCallback: Adapter State: " + BluetoothAdapter.nameForState(state) + " Connected: " + device); } else { deviceProperties.setConnectionHandle(BluetoothDevice.ERROR, transportLinkType); if (device.getBondState() == BluetoothDevice.BOND_BONDING) { // Send PAIRING_CANCEL intent to dismiss any dialog requesting bonding. intent = new Intent(BluetoothDevice.ACTION_PAIRING_CANCEL); Loading
android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java +2 −1 Original line number Diff line number Diff line Loading @@ -296,7 +296,8 @@ public class RemoteDevicesTest { // BluetoothDevice.BATTERY_LEVEL_UNKNOWN when(mAdapterService.getState()).thenReturn(BluetoothAdapter.STATE_ON); mRemoteDevices.aclStateChangeCallback(0, Utils.getByteAddress(mDevice1), AbstractionLayer.BT_ACL_STATE_DISCONNECTED, 2, 19); // HCI code 19 remote terminated AbstractionLayer.BT_ACL_STATE_DISCONNECTED, 2, 19, BluetoothDevice.ERROR); // HCI code 19 remote terminated // Verify ACTION_ACL_DISCONNECTED and BATTERY_LEVEL_CHANGED intent are sent verify(mAdapterService, times(3)).sendBroadcast(mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); Loading