Loading android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java +1 −16 Original line number Diff line number Diff line Loading @@ -1749,15 +1749,7 @@ public class BassClientStateMachine extends StateMachine { log("Enter Connected(" + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); removeDeferredMessages(CONNECT); if (mLastConnectionState == BluetoothProfile.STATE_CONNECTED) { log("CONNECTED->CONNECTED: Ignore"); // Broadcast for testing purpose only if (Utils.isInstrumentationTestMode()) { Intent intent = new Intent("android.bluetooth.bass_client.NOTIFY_TEST"); mService.sendBroadcast( intent, BLUETOOTH_CONNECT, Utils.getTempBroadcastOptions().toBundle()); } } else { if (mLastConnectionState != BluetoothProfile.STATE_CONNECTED) { broadcastConnectionState(mDevice, mLastConnectionState, BluetoothProfile.STATE_CONNECTED); } Loading Loading @@ -2169,13 +2161,6 @@ public class BassClientStateMachine extends StateMachine { public void enter() { log("Enter ConnectedProcessing(" + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); // Broadcast for testing purpose only if (Utils.isInstrumentationTestMode()) { Intent intent = new Intent("android.bluetooth.bass_client.NOTIFY_TEST"); mService.sendBroadcast( intent, BLUETOOTH_CONNECT, Utils.getTempBroadcastOptions().toBundle()); } } @Override public void exit() { Loading android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +10 −8 Original line number Diff line number Diff line Loading @@ -1247,6 +1247,7 @@ public class RemoteDevices { String address = device.getAddress(); if (Flags.temporaryPairingDeviceProperties() && oldState != BluetoothDevice.BOND_BONDED) { DeviceProperties deviceProperties = mDevices.get(address); if (deviceProperties != null) { int leConnectionHandle = deviceProperties.getConnectionHandle(BluetoothDevice.TRANSPORT_LE); int bredrConnectionHandle = Loading @@ -1257,6 +1258,7 @@ public class RemoteDevices { return; } } } if (Flags.removeAddressMapOnUnbond() && newState == BluetoothDevice.BOND_NONE) { removeAddressMapping(address); Loading android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java +76 −7 Original line number Diff line number Diff line Loading @@ -18,6 +18,11 @@ package com.android.bluetooth.bass_client; import static android.bluetooth.BluetoothGatt.GATT_FAILURE; import static android.bluetooth.BluetoothGatt.GATT_SUCCESS; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra; import static androidx.test.espresso.intent.matcher.IntentMatchers.hasFlag; import static com.android.bluetooth.bass_client.BassClientStateMachine.ADD_BCAST_SOURCE; import static com.android.bluetooth.bass_client.BassClientStateMachine.CONNECT; Loading Loading @@ -68,6 +73,7 @@ import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothLeAudioCodecConfigMetadata; import android.bluetooth.BluetoothLeAudioContentMetadata; import android.bluetooth.BluetoothLeBroadcastAssistant; import android.bluetooth.BluetoothLeBroadcastChannel; import android.bluetooth.BluetoothLeBroadcastMetadata; import android.bluetooth.BluetoothLeBroadcastReceiveState; Loading Loading @@ -97,7 +103,9 @@ import com.android.bluetooth.flags.Flags; import com.google.common.primitives.Bytes; import org.hamcrest.core.AllOf; import org.hamcrest.core.IsInstanceOf; import org.hamcrest.Matcher; import org.junit.After; import org.junit.Assert; import org.junit.Before; Loading @@ -106,6 +114,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.ArgumentCaptor; import org.mockito.hamcrest.MockitoHamcrest; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnit; Loading @@ -127,6 +136,7 @@ public class BassClientStateMachineTest { private static final int CONNECTION_TIMEOUT_MS = 1_000; private static final int TIMEOUT_MS = 2_000; private static final int NO_TIMEOUT_MS = 0; private static final int WAIT_MS = 1_200; private static final String TEST_BROADCAST_NAME = "Test"; private static final String EMPTY_BLUETOOTH_DEVICE_ADDRESS = "00:00:00:00:00:00"; Loading Loading @@ -179,6 +189,20 @@ public class BassClientStateMachineTest { mBassClientStateMachine.start(); } private int classTypeToConnectionState(Class type) { if (type == BassClientStateMachine.Disconnected.class) { return BluetoothProfile.STATE_DISCONNECTED; } else if (type == BassClientStateMachine.Connecting.class) { return BluetoothProfile.STATE_CONNECTING; } else if (type == BassClientStateMachine.Connected.class || type == BassClientStateMachine.ConnectedProcessing.class) { return BluetoothProfile.STATE_CONNECTED; } else { Assert.fail("Invalid class type given: " + type); return 0; } } @After public void tearDown() throws Exception { if (mBassClientStateMachine == null) { Loading Loading @@ -316,6 +340,9 @@ public class BassClientStateMachineTest { allowConnection(true); allowConnectGatt(true); BassClientStateMachine.BluetoothGattTestableWrapper btGatt = Mockito.mock(BassClientStateMachine.BluetoothGattTestableWrapper.class); mBassClientStateMachine.mBluetoothGatt = btGatt; // need this to ensure expected mock behavior for getActiveSyncedSource when(mBassClientService.getActiveSyncedSources(any())).thenReturn(null); Loading @@ -327,19 +354,25 @@ public class BassClientStateMachineTest { mBassClientStateMachine.obtainMessage(CONNECT), BassClientStateMachine.Connecting.class); sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.CONNECT_TIMEOUT), mBassClientStateMachine.obtainMessage( BassClientStateMachine.CONNECT_TIMEOUT, mTestDevice), BassClientStateMachine.Disconnected.class); // disconnected -> connecting ---DISCONNECT---> disconnected // disconnected -> connecting ---DISCONNECT---> CONNECTION_STATE_CHANGED(connected) // --> connected -> disconnected mBassClientStateMachine.mBluetoothGatt = btGatt; sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(CONNECT), BassClientStateMachine.Connecting.class); sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.DISCONNECT), BassClientStateMachine.Disconnected.class); BassClientStateMachine.Connecting.class); mBassClientStateMachine.sendMessage( CONNECTION_STATE_CHANGED, Integer.valueOf(BluetoothProfile.STATE_CONNECTED)); // disconnected -> connecting ---CONNECTION_STATE_CHANGED(connected)---> connected --> // disconnected mBassClientStateMachine.mBluetoothGatt = btGatt; sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(CONNECT), BassClientStateMachine.Connecting.class); Loading Loading @@ -2248,13 +2281,49 @@ public class BassClientStateMachineTest { Mockito.clearInvocations(mBassClientService); } private boolean isConnectionIntentExpected(Class currentType, Class nextType) { if (currentType == nextType) { return false; // Same state, no intent expected } if ((currentType == BassClientStateMachine.ConnectedProcessing.class) || (nextType == BassClientStateMachine.ConnectedProcessing.class)) { return false; // ConnectedProcessing is an internal state that doesn't generate a // broadcast } else { return true; // All other state are generating broadcast } } @SafeVarargs private void verifyIntentSent(int timeout_ms, Matcher<Intent>... matchers) { verify(mBassClientService, timeout(timeout_ms).times(1)) .sendBroadcast( MockitoHamcrest.argThat(AllOf.allOf(matchers)), eq(BLUETOOTH_CONNECT), any()); } private <T> void sendMessageAndVerifyTransition(Message msg, Class<T> type) { Mockito.clearInvocations(mBassClientService); mBassClientStateMachine.sendMessage(msg); // Verify that one connection state broadcast is executed verify(mBassClientService, timeout(TIMEOUT_MS) .times(1)) .sendBroadcast(any(Intent.class), anyString(), any()); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); Class currentStateClass = mBassClientStateMachine.getCurrentState().getClass(); if (isConnectionIntentExpected(currentStateClass, type)) { verifyIntentSent( NO_TIMEOUT_MS, hasAction(BluetoothLeBroadcastAssistant.ACTION_CONNECTION_STATE_CHANGED), hasExtra( BluetoothProfile.EXTRA_STATE, classTypeToConnectionState(currentStateClass)), hasExtra( BluetoothProfile.EXTRA_PREVIOUS_STATE, classTypeToConnectionState(type)), hasFlag( Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND)); } Assert.assertThat(mBassClientStateMachine.getCurrentState(), IsInstanceOf.instanceOf(type)); } Loading system/bta/hh/bta_hh_headtracker.cc +3 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,9 @@ uint16_t bta_hh_get_uuid16(tBTA_HH_DEV_CB* p_dev_cb, Uuid uuid) { uuid == ANDROID_HEADTRACKER_CONTROL_CHARAC_UUID || uuid == ANDROID_HEADTRACKER_REPORT_CHARAC_UUID)) { return GATT_UUID_HID_REPORT; } else if (!uuid.Is16Bit()) { log::warn("UUID is not 16 bit"); return 0; } else { return uuid.As16Bit(); } Loading system/bta/hh/bta_hh_le.cc +25 −2 Original line number Diff line number Diff line Loading @@ -658,7 +658,7 @@ static bool bta_hh_le_write_ccc(tBTA_HH_DEV_CB* p_cb, uint16_t char_handle, static bool bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB* p_cb); static void write_rpt_ctl_cfg_cb(uint16_t conn_id, tGATT_STATUS status, static void write_rpt_clt_cfg_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, const uint8_t* value, void* data) { uint8_t srvc_inst_id; Loading @@ -666,6 +666,16 @@ static void write_rpt_ctl_cfg_cb(uint16_t conn_id, tGATT_STATUS status, tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data; const gatt::Characteristic* characteristic = BTA_GATTC_GetOwningCharacteristic(conn_id, handle); if (characteristic == nullptr) { log::error("Characteristic with handle {} not found clt cfg", handle); return; } if (!characteristic->uuid.Is16Bit()) { log::error("Unexpected len characteristic ID clt cfg: {}", characteristic->uuid.ToString()); return; } uint16_t char_uuid = bta_hh_get_uuid16(p_dev_cb, characteristic->uuid); srvc_inst_id = BTA_GATTC_GetOwningService(conn_id, handle)->handle; Loading Loading @@ -706,7 +716,7 @@ static bool bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB* p_cb) { if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT) { if (bta_hh_le_write_ccc(p_cb, p_rpt->char_inst_id, GATT_CLT_CONFIG_NOTIFICATION, write_rpt_ctl_cfg_cb, p_cb)) { write_rpt_clt_cfg_cb, p_cb)) { p_cb->clt_cfg_idx = i; return true; } Loading Loading @@ -1646,6 +1656,11 @@ static void bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY* p_data) { const gatt::Service* p_svc = BTA_GATTC_GetOwningService(p_dev_cb->conn_id, p_char->value_handle); if (!p_char->uuid.Is16Bit()) { log::error("Unexpected characteristic len: {}", p_char->uuid.ToString()); return; } p_rpt = bta_hh_le_find_report_entry(p_dev_cb, p_svc->handle, bta_hh_get_uuid16(p_dev_cb, p_char->uuid), p_char->value_handle); Loading Loading @@ -1838,6 +1853,10 @@ static void read_report_cb(uint16_t conn_id, tGATT_STATUS status, log::error("Unknown handle"); return; } if (!p_char->uuid.Is16Bit()) { log::error("Unexpected characteristic len: {}", p_char->uuid.ToString()); return; } uint16_t char_uuid = bta_hh_get_uuid16(p_dev_cb, p_char->uuid); Loading Loading @@ -1924,6 +1943,10 @@ static void write_report_cb(uint16_t conn_id, tGATT_STATUS status, BTA_GATTC_GetCharacteristic(conn_id, handle); if (p_char == nullptr) return; if (!p_char->uuid.Is16Bit()) { log::error("Unexpected characteristic len: {}", p_char->uuid.ToString()); return; } uint16_t uuid16 = bta_hh_get_uuid16(p_dev_cb, p_char->uuid); if (uuid16 != GATT_UUID_HID_REPORT && uuid16 != GATT_UUID_HID_BT_KB_INPUT && Loading Loading
android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java +1 −16 Original line number Diff line number Diff line Loading @@ -1749,15 +1749,7 @@ public class BassClientStateMachine extends StateMachine { log("Enter Connected(" + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); removeDeferredMessages(CONNECT); if (mLastConnectionState == BluetoothProfile.STATE_CONNECTED) { log("CONNECTED->CONNECTED: Ignore"); // Broadcast for testing purpose only if (Utils.isInstrumentationTestMode()) { Intent intent = new Intent("android.bluetooth.bass_client.NOTIFY_TEST"); mService.sendBroadcast( intent, BLUETOOTH_CONNECT, Utils.getTempBroadcastOptions().toBundle()); } } else { if (mLastConnectionState != BluetoothProfile.STATE_CONNECTED) { broadcastConnectionState(mDevice, mLastConnectionState, BluetoothProfile.STATE_CONNECTED); } Loading Loading @@ -2169,13 +2161,6 @@ public class BassClientStateMachine extends StateMachine { public void enter() { log("Enter ConnectedProcessing(" + mDevice + "): " + messageWhatToString(getCurrentMessage().what)); // Broadcast for testing purpose only if (Utils.isInstrumentationTestMode()) { Intent intent = new Intent("android.bluetooth.bass_client.NOTIFY_TEST"); mService.sendBroadcast( intent, BLUETOOTH_CONNECT, Utils.getTempBroadcastOptions().toBundle()); } } @Override public void exit() { Loading
android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +10 −8 Original line number Diff line number Diff line Loading @@ -1247,6 +1247,7 @@ public class RemoteDevices { String address = device.getAddress(); if (Flags.temporaryPairingDeviceProperties() && oldState != BluetoothDevice.BOND_BONDED) { DeviceProperties deviceProperties = mDevices.get(address); if (deviceProperties != null) { int leConnectionHandle = deviceProperties.getConnectionHandle(BluetoothDevice.TRANSPORT_LE); int bredrConnectionHandle = Loading @@ -1257,6 +1258,7 @@ public class RemoteDevices { return; } } } if (Flags.removeAddressMapOnUnbond() && newState == BluetoothDevice.BOND_NONE) { removeAddressMapping(address); Loading
android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java +76 −7 Original line number Diff line number Diff line Loading @@ -18,6 +18,11 @@ package com.android.bluetooth.bass_client; import static android.bluetooth.BluetoothGatt.GATT_FAILURE; import static android.bluetooth.BluetoothGatt.GATT_SUCCESS; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra; import static androidx.test.espresso.intent.matcher.IntentMatchers.hasFlag; import static com.android.bluetooth.bass_client.BassClientStateMachine.ADD_BCAST_SOURCE; import static com.android.bluetooth.bass_client.BassClientStateMachine.CONNECT; Loading Loading @@ -68,6 +73,7 @@ import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothLeAudioCodecConfigMetadata; import android.bluetooth.BluetoothLeAudioContentMetadata; import android.bluetooth.BluetoothLeBroadcastAssistant; import android.bluetooth.BluetoothLeBroadcastChannel; import android.bluetooth.BluetoothLeBroadcastMetadata; import android.bluetooth.BluetoothLeBroadcastReceiveState; Loading Loading @@ -97,7 +103,9 @@ import com.android.bluetooth.flags.Flags; import com.google.common.primitives.Bytes; import org.hamcrest.core.AllOf; import org.hamcrest.core.IsInstanceOf; import org.hamcrest.Matcher; import org.junit.After; import org.junit.Assert; import org.junit.Before; Loading @@ -106,6 +114,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.ArgumentCaptor; import org.mockito.hamcrest.MockitoHamcrest; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnit; Loading @@ -127,6 +136,7 @@ public class BassClientStateMachineTest { private static final int CONNECTION_TIMEOUT_MS = 1_000; private static final int TIMEOUT_MS = 2_000; private static final int NO_TIMEOUT_MS = 0; private static final int WAIT_MS = 1_200; private static final String TEST_BROADCAST_NAME = "Test"; private static final String EMPTY_BLUETOOTH_DEVICE_ADDRESS = "00:00:00:00:00:00"; Loading Loading @@ -179,6 +189,20 @@ public class BassClientStateMachineTest { mBassClientStateMachine.start(); } private int classTypeToConnectionState(Class type) { if (type == BassClientStateMachine.Disconnected.class) { return BluetoothProfile.STATE_DISCONNECTED; } else if (type == BassClientStateMachine.Connecting.class) { return BluetoothProfile.STATE_CONNECTING; } else if (type == BassClientStateMachine.Connected.class || type == BassClientStateMachine.ConnectedProcessing.class) { return BluetoothProfile.STATE_CONNECTED; } else { Assert.fail("Invalid class type given: " + type); return 0; } } @After public void tearDown() throws Exception { if (mBassClientStateMachine == null) { Loading Loading @@ -316,6 +340,9 @@ public class BassClientStateMachineTest { allowConnection(true); allowConnectGatt(true); BassClientStateMachine.BluetoothGattTestableWrapper btGatt = Mockito.mock(BassClientStateMachine.BluetoothGattTestableWrapper.class); mBassClientStateMachine.mBluetoothGatt = btGatt; // need this to ensure expected mock behavior for getActiveSyncedSource when(mBassClientService.getActiveSyncedSources(any())).thenReturn(null); Loading @@ -327,19 +354,25 @@ public class BassClientStateMachineTest { mBassClientStateMachine.obtainMessage(CONNECT), BassClientStateMachine.Connecting.class); sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.CONNECT_TIMEOUT), mBassClientStateMachine.obtainMessage( BassClientStateMachine.CONNECT_TIMEOUT, mTestDevice), BassClientStateMachine.Disconnected.class); // disconnected -> connecting ---DISCONNECT---> disconnected // disconnected -> connecting ---DISCONNECT---> CONNECTION_STATE_CHANGED(connected) // --> connected -> disconnected mBassClientStateMachine.mBluetoothGatt = btGatt; sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(CONNECT), BassClientStateMachine.Connecting.class); sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(BassClientStateMachine.DISCONNECT), BassClientStateMachine.Disconnected.class); BassClientStateMachine.Connecting.class); mBassClientStateMachine.sendMessage( CONNECTION_STATE_CHANGED, Integer.valueOf(BluetoothProfile.STATE_CONNECTED)); // disconnected -> connecting ---CONNECTION_STATE_CHANGED(connected)---> connected --> // disconnected mBassClientStateMachine.mBluetoothGatt = btGatt; sendMessageAndVerifyTransition( mBassClientStateMachine.obtainMessage(CONNECT), BassClientStateMachine.Connecting.class); Loading Loading @@ -2248,13 +2281,49 @@ public class BassClientStateMachineTest { Mockito.clearInvocations(mBassClientService); } private boolean isConnectionIntentExpected(Class currentType, Class nextType) { if (currentType == nextType) { return false; // Same state, no intent expected } if ((currentType == BassClientStateMachine.ConnectedProcessing.class) || (nextType == BassClientStateMachine.ConnectedProcessing.class)) { return false; // ConnectedProcessing is an internal state that doesn't generate a // broadcast } else { return true; // All other state are generating broadcast } } @SafeVarargs private void verifyIntentSent(int timeout_ms, Matcher<Intent>... matchers) { verify(mBassClientService, timeout(timeout_ms).times(1)) .sendBroadcast( MockitoHamcrest.argThat(AllOf.allOf(matchers)), eq(BLUETOOTH_CONNECT), any()); } private <T> void sendMessageAndVerifyTransition(Message msg, Class<T> type) { Mockito.clearInvocations(mBassClientService); mBassClientStateMachine.sendMessage(msg); // Verify that one connection state broadcast is executed verify(mBassClientService, timeout(TIMEOUT_MS) .times(1)) .sendBroadcast(any(Intent.class), anyString(), any()); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); Class currentStateClass = mBassClientStateMachine.getCurrentState().getClass(); if (isConnectionIntentExpected(currentStateClass, type)) { verifyIntentSent( NO_TIMEOUT_MS, hasAction(BluetoothLeBroadcastAssistant.ACTION_CONNECTION_STATE_CHANGED), hasExtra( BluetoothProfile.EXTRA_STATE, classTypeToConnectionState(currentStateClass)), hasExtra( BluetoothProfile.EXTRA_PREVIOUS_STATE, classTypeToConnectionState(type)), hasFlag( Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND)); } Assert.assertThat(mBassClientStateMachine.getCurrentState(), IsInstanceOf.instanceOf(type)); } Loading
system/bta/hh/bta_hh_headtracker.cc +3 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,9 @@ uint16_t bta_hh_get_uuid16(tBTA_HH_DEV_CB* p_dev_cb, Uuid uuid) { uuid == ANDROID_HEADTRACKER_CONTROL_CHARAC_UUID || uuid == ANDROID_HEADTRACKER_REPORT_CHARAC_UUID)) { return GATT_UUID_HID_REPORT; } else if (!uuid.Is16Bit()) { log::warn("UUID is not 16 bit"); return 0; } else { return uuid.As16Bit(); } Loading
system/bta/hh/bta_hh_le.cc +25 −2 Original line number Diff line number Diff line Loading @@ -658,7 +658,7 @@ static bool bta_hh_le_write_ccc(tBTA_HH_DEV_CB* p_cb, uint16_t char_handle, static bool bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB* p_cb); static void write_rpt_ctl_cfg_cb(uint16_t conn_id, tGATT_STATUS status, static void write_rpt_clt_cfg_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, const uint8_t* value, void* data) { uint8_t srvc_inst_id; Loading @@ -666,6 +666,16 @@ static void write_rpt_ctl_cfg_cb(uint16_t conn_id, tGATT_STATUS status, tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data; const gatt::Characteristic* characteristic = BTA_GATTC_GetOwningCharacteristic(conn_id, handle); if (characteristic == nullptr) { log::error("Characteristic with handle {} not found clt cfg", handle); return; } if (!characteristic->uuid.Is16Bit()) { log::error("Unexpected len characteristic ID clt cfg: {}", characteristic->uuid.ToString()); return; } uint16_t char_uuid = bta_hh_get_uuid16(p_dev_cb, characteristic->uuid); srvc_inst_id = BTA_GATTC_GetOwningService(conn_id, handle)->handle; Loading Loading @@ -706,7 +716,7 @@ static bool bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB* p_cb) { if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT) { if (bta_hh_le_write_ccc(p_cb, p_rpt->char_inst_id, GATT_CLT_CONFIG_NOTIFICATION, write_rpt_ctl_cfg_cb, p_cb)) { write_rpt_clt_cfg_cb, p_cb)) { p_cb->clt_cfg_idx = i; return true; } Loading Loading @@ -1646,6 +1656,11 @@ static void bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY* p_data) { const gatt::Service* p_svc = BTA_GATTC_GetOwningService(p_dev_cb->conn_id, p_char->value_handle); if (!p_char->uuid.Is16Bit()) { log::error("Unexpected characteristic len: {}", p_char->uuid.ToString()); return; } p_rpt = bta_hh_le_find_report_entry(p_dev_cb, p_svc->handle, bta_hh_get_uuid16(p_dev_cb, p_char->uuid), p_char->value_handle); Loading Loading @@ -1838,6 +1853,10 @@ static void read_report_cb(uint16_t conn_id, tGATT_STATUS status, log::error("Unknown handle"); return; } if (!p_char->uuid.Is16Bit()) { log::error("Unexpected characteristic len: {}", p_char->uuid.ToString()); return; } uint16_t char_uuid = bta_hh_get_uuid16(p_dev_cb, p_char->uuid); Loading Loading @@ -1924,6 +1943,10 @@ static void write_report_cb(uint16_t conn_id, tGATT_STATUS status, BTA_GATTC_GetCharacteristic(conn_id, handle); if (p_char == nullptr) return; if (!p_char->uuid.Is16Bit()) { log::error("Unexpected characteristic len: {}", p_char->uuid.ToString()); return; } uint16_t uuid16 = bta_hh_get_uuid16(p_dev_cb, p_char->uuid); if (uuid16 != GATT_UUID_HID_REPORT && uuid16 != GATT_UUID_HID_BT_KB_INPUT && Loading