Merge "Disable btif_gatt_check_encrypted_link." into tm-qpr-dev
diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpService.java b/android/app/src/com/android/bluetooth/a2dp/A2dpService.java
index 9bc4fad..7ca6166 100644
--- a/android/app/src/com/android/bluetooth/a2dp/A2dpService.java
+++ b/android/app/src/com/android/bluetooth/a2dp/A2dpService.java
@@ -106,7 +106,6 @@
boolean mA2dpOffloadEnabled = false;
private BroadcastReceiver mBondStateChangedReceiver;
- private BroadcastReceiver mConnectionStateChangedReceiver;
public static boolean isEnabled() {
return BluetoothProperties.isProfileA2dpSourceEnabled().orElse(false);
@@ -169,10 +168,6 @@
filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
mBondStateChangedReceiver = new BondStateChangedReceiver();
registerReceiver(mBondStateChangedReceiver, filter);
- filter = new IntentFilter();
- filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
- mConnectionStateChangedReceiver = new ConnectionStateChangedReceiver();
- registerReceiver(mConnectionStateChangedReceiver, filter);
// Step 8: Mark service as started
setA2dpService(this);
@@ -208,8 +203,6 @@
setA2dpService(null);
// Step 7: Unregister broadcast receivers
- unregisterReceiver(mConnectionStateChangedReceiver);
- mConnectionStateChangedReceiver = null;
unregisterReceiver(mBondStateChangedReceiver);
mBondStateChangedReceiver = null;
@@ -1242,7 +1235,7 @@
}
}
- private void connectionStateChanged(BluetoothDevice device, int fromState, int toState) {
+ void connectionStateChanged(BluetoothDevice device, int fromState, int toState) {
if ((device == null) || (fromState == toState)) {
return;
}
@@ -1269,27 +1262,6 @@
}
/**
- * Receiver for processing device connection state changes.
- *
- * <ul>
- * <li> Update codec support per device when device is (re)connected
- * <li> Delete the state machine instance if the device is disconnected and unbond
- * </ul>
- */
- private class ConnectionStateChangedReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (!BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
- return;
- }
- BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- int toState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
- int fromState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1);
- connectionStateChanged(device, fromState, toState);
- }
- }
-
- /**
* Retrieves the most recently connected device in the A2DP connected devices list.
*/
public BluetoothDevice getFallbackDevice() {
diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java b/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java
index 9e7323f..11d33ad 100644
--- a/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java
+++ b/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java
@@ -701,6 +701,7 @@
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+ mA2dpService.connectionStateChanged(mDevice, prevState, newState);
mA2dpService.sendBroadcast(intent, BLUETOOTH_CONNECT,
Utils.getTempAllowlistBroadcastOptions());
}
diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java
index b75da6a..56e63d1 100644
--- a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java
+++ b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java
@@ -2018,8 +2018,7 @@
public void onConnectionStateChangedFromStateMachine(BluetoothDevice device, int fromState,
int toState) {
synchronized (mStateMachines) {
- List<BluetoothDevice> audioConnectableDevices =
- getDevicesMatchingConnectionStates(CONNECTING_CONNECTED_STATES);
+ List<BluetoothDevice> audioConnectableDevices = getConnectedDevices();
if (fromState != BluetoothProfile.STATE_CONNECTED
&& toState == BluetoothProfile.STATE_CONNECTED) {
if (audioConnectableDevices.size() > 1) {
diff --git a/android/app/src/com/android/bluetooth/mapclient/MapClientContent.java b/android/app/src/com/android/bluetooth/mapclient/MapClientContent.java
index 36d4535..aa60b5b 100644
--- a/android/app/src/com/android/bluetooth/mapclient/MapClientContent.java
+++ b/android/app/src/com/android/bluetooth/mapclient/MapClientContent.java
@@ -137,6 +137,10 @@
SubscriptionManager subscriptionManager =
context.getSystemService(SubscriptionManager.class);
List<SubscriptionInfo> subscriptions = subscriptionManager.getActiveSubscriptionInfoList();
+ if (subscriptions == null) {
+ Log.w(TAG, "Active subscription list is missing");
+ return;
+ }
for (SubscriptionInfo info : subscriptions) {
if (info.getSubscriptionType() == SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM) {
clearMessages(context, info.getSubscriptionId());
diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceFactoryResetTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceFactoryResetTest.java
index 85fdf8b..6acc5a0 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceFactoryResetTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceFactoryResetTest.java
@@ -145,7 +145,7 @@
private int mForegroundUserId;
private void configureEnabledProfiles() {
- Log.e("AdapterServiceTest", "configureEnabledProfiles");
+ Log.e(TAG, "configureEnabledProfiles");
Config.setProfileEnabled(PanService.class, true);
Config.setProfileEnabled(BluetoothPbapService.class, true);
Config.setProfileEnabled(GattService.class, true);
@@ -176,7 +176,7 @@
@BeforeClass
public static void setupClass() {
- Log.e("AdapterServiceTest", "setupClass");
+ Log.e(TAG, "setupClass");
// Bring native layer up and down to make sure config files are properly loaded
if (Looper.myLooper() == null) {
Looper.prepare();
@@ -194,7 +194,7 @@
@Before
public void setUp() throws PackageManager.NameNotFoundException {
- Log.e("AdapterServiceTest", "setUp()");
+ Log.e(TAG, "setUp()");
MockitoAnnotations.initMocks(this);
if (Looper.myLooper() == null) {
Looper.prepare();
@@ -327,7 +327,10 @@
@After
public void tearDown() {
- Log.e("AdapterServiceTest", "tearDown()");
+ Log.e(TAG, "tearDown()");
+
+ // Enable the stack to re-create the config. Next tests rely on it.
+ doEnable(0, false);
// Restores the foregroundUserId to the ID prior to the test setup
Utils.setForegroundUserId(mForegroundUserId);
@@ -351,7 +354,7 @@
}
private void doEnable(int invocationNumber, boolean onlyGatt) {
- Log.e("AdapterServiceTest", "doEnable() start");
+ Log.e(TAG, "doEnable() start");
Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON);
int startServiceCalls;
@@ -398,7 +401,7 @@
|| scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
Assert.assertTrue(mAdapterService.getState() == BluetoothAdapter.STATE_ON);
- Log.e("AdapterServiceTest", "doEnable() complete success");
+ Log.e(TAG, "doEnable() complete success");
}
/**
diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceRestartTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceRestartTest.java
index 900ab86..c93837b 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceRestartTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceRestartTest.java
@@ -131,7 +131,7 @@
private int mForegroundUserId;
private void configureEnabledProfiles() {
- Log.e("AdapterServiceTest", "configureEnabledProfiles");
+ Log.e(TAG, "configureEnabledProfiles");
Config.setProfileEnabled(PanService.class, true);
Config.setProfileEnabled(BluetoothPbapService.class, true);
Config.setProfileEnabled(GattService.class, true);
@@ -162,7 +162,7 @@
@BeforeClass
public static void setupClass() {
- Log.e("AdapterServiceTest", "setupClass");
+ Log.e(TAG, "setupClass");
// Bring native layer up and down to make sure config files are properly loaded
if (Looper.myLooper() == null) {
Looper.prepare();
@@ -180,7 +180,7 @@
@Before
public void setUp() throws PackageManager.NameNotFoundException {
- Log.e("AdapterServiceTest", "setUp()");
+ Log.e(TAG, "setUp()");
MockitoAnnotations.initMocks(this);
if (Looper.myLooper() == null) {
Looper.prepare();
@@ -309,7 +309,7 @@
@After
public void tearDown() {
- Log.e("AdapterServiceTest", "tearDown()");
+ Log.e(TAG, "tearDown()");
// Restores the foregroundUserId to the ID prior to the test setup
Utils.setForegroundUserId(mForegroundUserId);
@@ -341,6 +341,11 @@
obfuscatedAddress1);
tearDown();
setUp();
+
+ byte[] metricsSalt2 = AdapterServiceTest.getMetricsSalt(mAdapterConfig);
+ Assert.assertNotNull(metricsSalt2);
+ Assert.assertArrayEquals(metricsSalt, metricsSalt2);
+
Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON);
byte[] obfuscatedAddress2 = mAdapterService.obfuscateAddress(device);
Assert.assertTrue(obfuscatedAddress2.length > 0);
diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
index 1763f83..c320b35 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
@@ -741,7 +741,6 @@
/**
* Test: Check if obfuscated Bluetooth address stays the same after toggling Bluetooth
*/
- @Ignore("b/265588558")
@Test
public void testObfuscateBluetoothAddress_PersistentBetweenToggle() {
Assert.assertFalse(mAdapterService.getState() == BluetoothAdapter.STATE_ON);
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java
index f64cda7..db5fdd5 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java
@@ -1,5 +1,26 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.android.bluetooth.hfpclient;
+import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
+import static android.bluetooth.BluetoothProfile.STATE_CONNECTING;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING;
+
import static com.android.bluetooth.hfpclient.HeadsetClientStateMachine.AT_OK;
import static com.android.bluetooth.hfpclient.HeadsetClientStateMachine.ENTER_PRIVATE_MODE;
import static com.android.bluetooth.hfpclient.HeadsetClientStateMachine.EXPLICIT_CALL_TRANSFER;
@@ -21,6 +42,7 @@
import android.media.AudioManager;
import android.os.Bundle;
import android.os.HandlerThread;
+import android.os.Looper;
import android.os.Message;
import android.util.Pair;
@@ -36,6 +58,7 @@
import com.android.bluetooth.TestUtils;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AdapterService;
+import com.android.bluetooth.hfp.HeadsetStackEvent;
import org.hamcrest.core.AllOf;
import org.hamcrest.core.IsInstanceOf;
@@ -47,18 +70,22 @@
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.hamcrest.MockitoHamcrest;
import java.util.List;
import java.util.Set;
+/**
+ * Test cases for {@link HeadsetClientStateMachine}.
+ */
@LargeTest
@RunWith(AndroidJUnit4.class)
public class HeadsetClientStateMachineTest {
private BluetoothAdapter mAdapter;
private HandlerThread mHandlerThread;
- private HeadsetClientStateMachine mHeadsetClientStateMachine;
+ private TestHeadsetClientStateMachine mHeadsetClientStateMachine;
private BluetoothDevice mTestDevice;
private Context mTargetContext;
@@ -77,6 +104,7 @@
private static final int QUERY_CURRENT_CALLS_WAIT_MILLIS = 2000;
private static final int QUERY_CURRENT_CALLS_TEST_WAIT_MILLIS = QUERY_CURRENT_CALLS_WAIT_MILLIS
* 3 / 2;
+ private static final int TIMEOUT_MS = 1000;
@Before
public void setUp() throws Exception {
@@ -109,9 +137,8 @@
mHandlerThread = new HandlerThread("HeadsetClientStateMachineTestHandlerThread");
mHandlerThread.start();
// Manage looper execution in main test thread explicitly to guarantee timing consistency
- mHeadsetClientStateMachine =
- new HeadsetClientStateMachine(mHeadsetClientService, mHandlerThread.getLooper(),
- mNativeInterface);
+ mHeadsetClientStateMachine = new TestHeadsetClientStateMachine(mHeadsetClientService,
+ mHandlerThread.getLooper(), mNativeInterface);
mHeadsetClientStateMachine.start();
TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
}
@@ -123,6 +150,7 @@
}
TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
TestUtils.clearAdapterService(mAdapterService);
+ mHeadsetClientStateMachine.allowConnect = null;
mHeadsetClientStateMachine.doQuit();
mHandlerThread.quit();
}
@@ -1073,4 +1101,316 @@
mHeadsetClientStateMachine.setAudioPolicy(dummyAudioPolicy);
verify(mNativeInterface).sendAndroidAt(mTestDevice, "+ANDROID=1,1,2,1");
}
+
+ @Test
+ public void testDumpDoesNotCrash() {
+ mHeadsetClientStateMachine.dump(new StringBuilder());
+ }
+
+ @Test
+ public void testProcessDisconnectMessage_onDisconnectedState() {
+ mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT);
+ TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
+ Assert.assertEquals(STATE_DISCONNECTED,
+ mHeadsetClientStateMachine.getConnectionState(mTestDevice));
+ }
+
+ @Test
+ public void testProcessConnectMessage_onDisconnectedState() {
+ doReturn(true).when(mNativeInterface).connect(any(BluetoothDevice.class));
+ sendMessageAndVerifyTransition(
+ mHeadsetClientStateMachine
+ .obtainMessage(HeadsetClientStateMachine.CONNECT, mTestDevice),
+ HeadsetClientStateMachine.Connecting.class);
+ }
+
+ @Test
+ public void testStackEvent_toConnectingState_onDisconnectedState() {
+ allowConnection(true);
+ StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
+ event.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED;
+ event.device = mTestDevice;
+ sendMessageAndVerifyTransition(
+ mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event),
+ HeadsetClientStateMachine.Connecting.class);
+ }
+
+ @Test
+ public void testStackEvent_toConnectingState_disallowConnection_onDisconnectedState() {
+ allowConnection(false);
+ StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
+ event.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED;
+ event.device = mTestDevice;
+ sendMessageAndVerifyTransition(
+ mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event),
+ HeadsetClientStateMachine.Disconnected.class);
+ }
+
+ @Test
+ public void testProcessConnectMessage_onConnectingState() {
+ initToConnectingState();
+ mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT);
+ TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
+ Assert.assertTrue(mHeadsetClientStateMachine.doesSuperHaveDeferredMessages(
+ HeadsetClientStateMachine.CONNECT));
+ }
+
+ @Test
+ public void testProcessStackEvent_ConnectionStateChanged_Disconnected_onConnectingState() {
+ initToConnectingState();
+ StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
+ event.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_DISCONNECTED;
+ event.device = mTestDevice;
+ sendMessageAndVerifyTransition(
+ mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event),
+ HeadsetClientStateMachine.Disconnected.class);
+ }
+
+ @Test
+ public void testProcessStackEvent_ConnectionStateChanged_Connected_onConnectingState() {
+ initToConnectingState();
+ StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
+ event.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED;
+ event.device = mTestDevice;
+ mHeadsetClientStateMachine.sendMessage(
+ mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event));
+ Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
+ IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connecting.class));
+ }
+
+ @Test
+ public void testProcessStackEvent_ConnectionStateChanged_Connecting_onConnectingState() {
+ initToConnectingState();
+ StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
+ event.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTING;
+ event.device = mTestDevice;
+ mHeadsetClientStateMachine.sendMessage(
+ mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event));
+ Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
+ IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connecting.class));
+ }
+
+ @Test
+ public void testProcessStackEvent_Call_onConnectingState() {
+ initToConnectingState();
+ StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CALL);
+ event.valueInt = StackEvent.EVENT_TYPE_CALL;
+ event.device = mTestDevice;
+ mHeadsetClientStateMachine.sendMessage(
+ mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event));
+ TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
+ Assert.assertTrue(mHeadsetClientStateMachine.doesSuperHaveDeferredMessages(
+ StackEvent.STACK_EVENT));
+ }
+
+ @Test
+ public void testProcessStackEvent_CmdResultWithEmptyQueuedActions_onConnectingState() {
+ initToConnectingState();
+ StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CMD_RESULT);
+ event.valueInt = StackEvent.CMD_RESULT_TYPE_OK;
+ event.device = mTestDevice;
+ mHeadsetClientStateMachine.sendMessage(
+ mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event));
+ Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
+ IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connecting.class));
+ }
+
+ @Test
+ public void testProcessStackEvent_Unknown_onConnectingState() {
+ String atCommand = "+ANDROID: 1";
+
+ initToConnectingState();
+ StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_UNKNOWN_EVENT);
+ event.valueString = atCommand;
+ event.device = mTestDevice;
+ mHeadsetClientStateMachine.sendMessage(
+ mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event));
+ TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
+ Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
+ IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connected.class));
+ }
+
+ @Test
+ public void testProcessConnectTimeoutMessage_onConnectingState() {
+ initToConnectingState();
+ Message msg = mHeadsetClientStateMachine
+ .obtainMessage(HeadsetClientStateMachine.CONNECTING_TIMEOUT);
+ sendMessageAndVerifyTransition(msg, HeadsetClientStateMachine.Disconnected.class);
+ }
+
+ @Test
+ public void testProcessConnectMessage_onConnectedState() {
+ initToConnectedState();
+ mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT);
+ TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
+ Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
+ IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connected.class));
+ }
+
+ @Test
+ public void testProcessDisconnectMessage_onConnectedState() {
+ initToConnectedState();
+ mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT, mTestDevice);
+ TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
+ verify(mNativeInterface).disconnect(any(BluetoothDevice.class));
+ }
+
+ @Test
+ public void testProcessConnectAudioMessage_onConnectedState() {
+ initToConnectedState();
+ mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT_AUDIO);
+ TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
+ verify(mNativeInterface).connectAudio(any(BluetoothDevice.class));
+ }
+
+ @Test
+ public void testProcessDisconnectAudioMessage_onConnectedState() {
+ initToConnectedState();
+ mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT_AUDIO);
+ TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
+ verify(mNativeInterface).disconnectAudio(any(BluetoothDevice.class));
+ }
+
+ @Test
+ public void testProcessVoiceRecognitionStartMessage_onConnectedState() {
+ initToConnectedState();
+ mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.VOICE_RECOGNITION_START);
+ TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
+ verify(mNativeInterface).startVoiceRecognition(any(BluetoothDevice.class));
+ }
+
+ @Test
+ public void testProcessDisconnectMessage_onAudioOnState() {
+ initToAudioOnState();
+ mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT, mTestDevice);
+ TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
+ Assert.assertTrue(mHeadsetClientStateMachine.doesSuperHaveDeferredMessages(
+ HeadsetClientStateMachine.DISCONNECT));
+ }
+
+ @Test
+ public void testProcessDisconnectAudioMessage_onAudioOnState() {
+ initToAudioOnState();
+ mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT_AUDIO,
+ mTestDevice);
+ TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
+ verify(mNativeInterface).disconnectAudio(any(BluetoothDevice.class));
+ }
+
+ @Test
+ public void testProcessHoldCall_onAudioOnState() {
+ initToAudioOnState();
+ HfpClientCall call = new HfpClientCall(mTestDevice, 0, HfpClientCall.CALL_STATE_ACTIVE,
+ "1", true, false, false);
+ mHeadsetClientStateMachine.mCalls.put(0, call);
+ int[] states = new int[1];
+ states[0] = HfpClientCall.CALL_STATE_ACTIVE;
+ mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.HOLD_CALL,
+ mTestDevice);
+ TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
+ verify(mNativeInterface).handleCallAction(any(BluetoothDevice.class), anyInt(), eq(0));
+ }
+
+ @Test
+ public void testProcessStackEvent_ConnectionStateChanged_onAudioOnState() {
+ initToAudioOnState();
+ Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
+ IsInstanceOf.instanceOf(HeadsetClientStateMachine.AudioOn.class));
+ StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
+ event.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_DISCONNECTED;
+ event.device = mTestDevice;
+ mHeadsetClientStateMachine.sendMessage(
+ mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event));
+ TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
+ Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
+ IsInstanceOf.instanceOf(HeadsetClientStateMachine.Disconnected.class));
+ }
+
+ @Test
+ public void testProcessStackEvent_AudioStateChanged_onAudioOnState() {
+ initToAudioOnState();
+ Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
+ IsInstanceOf.instanceOf(HeadsetClientStateMachine.AudioOn.class));
+ StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED);
+ event.valueInt = HeadsetClientHalConstants.AUDIO_STATE_DISCONNECTED;
+ event.device = mTestDevice;
+ mHeadsetClientStateMachine.sendMessage(
+ mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event));
+ TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
+ Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
+ IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connected.class));
+ }
+
+ /**
+ * Allow/disallow connection to any device
+ *
+ * @param allow if true, connection is allowed
+ */
+ private void allowConnection(boolean allow) {
+ mHeadsetClientStateMachine.allowConnect = allow;
+ }
+
+ private void initToConnectingState() {
+ doReturn(true).when(mNativeInterface).connect(any(BluetoothDevice.class));
+ sendMessageAndVerifyTransition(
+ mHeadsetClientStateMachine
+ .obtainMessage(HeadsetClientStateMachine.CONNECT, mTestDevice),
+ HeadsetClientStateMachine.Connecting.class);
+ }
+
+ private void initToConnectedState() {
+ String atCommand = "+ANDROID: 1";
+ initToConnectingState();
+ StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_UNKNOWN_EVENT);
+ event.valueString = atCommand;
+ event.device = mTestDevice;
+ mHeadsetClientStateMachine.sendMessage(
+ mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event));
+ TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
+ Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
+ IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connected.class));
+ }
+
+ private void initToAudioOnState() {
+ mHeadsetClientStateMachine.setAudioRouteAllowed(true);
+ initToConnectedState();
+ StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED);
+ event.valueInt = HeadsetClientHalConstants.AUDIO_STATE_CONNECTED;
+ event.device = mTestDevice;
+ mHeadsetClientStateMachine.sendMessage(
+ mHeadsetClientStateMachine.obtainMessage(StackEvent.STACK_EVENT, event));
+ TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
+ Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
+ IsInstanceOf.instanceOf(HeadsetClientStateMachine.AudioOn.class));
+ }
+
+ private <T> void sendMessageAndVerifyTransition(Message msg, Class<T> type) {
+ Mockito.clearInvocations(mHeadsetClientService);
+ mHeadsetClientStateMachine.sendMessage(msg);
+ // Verify that one connection state broadcast is executed
+ verify(mHeadsetClientService, timeout(TIMEOUT_MS)).sendBroadcastMultiplePermissions(
+ any(Intent.class), any(String[].class), any(BroadcastOptions.class)
+ );
+ Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
+ IsInstanceOf.instanceOf(type));
+ }
+
+ public static class TestHeadsetClientStateMachine extends HeadsetClientStateMachine {
+
+ Boolean allowConnect = null;
+
+ TestHeadsetClientStateMachine(HeadsetClientService context, Looper looper,
+ NativeInterface nativeInterface) {
+ super(context, looper, nativeInterface);
+ }
+
+ public boolean doesSuperHaveDeferredMessages(int what) {
+ return super.hasDeferredMessages(what);
+ }
+
+ @Override
+ public boolean okToConnect(BluetoothDevice device) {
+ return allowConnect != null ? allowConnect : super.okToConnect(device);
+ }
+ }
}
diff --git a/system/bta/hf_client/bta_hf_client_at.cc b/system/bta/hf_client/bta_hf_client_at.cc
index 7a710bf..97fcb97 100644
--- a/system/bta/hf_client/bta_hf_client_at.cc
+++ b/system/bta/hf_client/bta_hf_client_at.cc
@@ -2149,7 +2149,7 @@
at_len = snprintf(buf, sizeof(buf), "AT+BIA=");
const int32_t position = osi_property_get_int32(
- "bluetooth.headsetclient.disable_indicator.position", -1);
+ "bluetooth.headset_client.disable_indicator.position", -1);
for (i = 0; i < BTA_HF_CLIENT_AT_INDICATOR_COUNT; i++) {
int sup = client_cb->at_cb.indicator_lookup[i] == -1 ? 0 : 1;
diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc
index 49f80f5..6da4c40 100644
--- a/system/bta/le_audio/state_machine.cc
+++ b/system/bta/le_audio/state_machine.cc
@@ -681,8 +681,6 @@
LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice,
const bluetooth::hci::iso_manager::cis_establish_cmpl_evt* event)
override {
- std::vector<uint8_t> value;
-
auto ases_pair = leAudioDevice->GetAsesByCisConnHdl(event->cis_conn_hdl);
if (event->status) {
@@ -734,11 +732,17 @@
}
if (!leAudioDevice->HaveAllActiveAsesCisEst()) {
- /* More cis established event has to come */
+ /* More cis established events has to come */
return;
}
- std::vector<uint8_t> ids;
+ if (!leAudioDevice->IsReadyToCreateStream()) {
+ /* Device still remains in ready to create stream state. It means that
+ * more enabling status notifications has to come. This may only happen
+ * for reconnection scenario for bi-directional CIS.
+ */
+ return;
+ }
/* All CISes created. Send start ready for source ASE before we can go
* to streaming state.
@@ -749,21 +753,8 @@
"id: %d, cis handle 0x%04x",
leAudioDevice->address_.ToString().c_str(), event->cig_id,
event->cis_conn_hdl);
- do {
- if (ase->direction == le_audio::types::kLeAudioDirectionSource)
- ids.push_back(ase->id);
- } while ((ase = leAudioDevice->GetNextActiveAse(ase)));
- if (ids.size() > 0) {
- le_audio::client_parser::ascs::PrepareAseCtpAudioReceiverStartReady(
- ids, value);
-
- BtaGattQueue::WriteCharacteristic(leAudioDevice->conn_id_,
- leAudioDevice->ctp_hdls_.val_hdl, value,
- GATT_WRITE_NO_RSP, NULL, NULL);
-
- return;
- }
+ PrepareAndSendReceiverStartReady(leAudioDevice, ase);
/* Cis establishment may came after setting group state to streaming, e.g.
* for autonomous scenario when ase is sink */
@@ -2187,6 +2178,28 @@
}
}
+ void PrepareAndSendReceiverStartReady(LeAudioDevice* leAudioDevice,
+ struct ase* ase) {
+ std::vector<uint8_t> ids;
+ std::vector<uint8_t> value;
+
+ do {
+ if (ase->direction == le_audio::types::kLeAudioDirectionSource)
+ ids.push_back(ase->id);
+ } while ((ase = leAudioDevice->GetNextActiveAse(ase)));
+
+ if (ids.size() > 0) {
+ le_audio::client_parser::ascs::PrepareAseCtpAudioReceiverStartReady(
+ ids, value);
+
+ BtaGattQueue::WriteCharacteristic(leAudioDevice->conn_id_,
+ leAudioDevice->ctp_hdls_.val_hdl, value,
+ GATT_WRITE_NO_RSP, NULL, NULL);
+
+ return;
+ }
+ }
+
void AseStateMachineProcessEnabling(
struct le_audio::client_parser::ascs::ase_rsp_hdr& arh, struct ase* ase,
LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice) {
@@ -2200,8 +2213,32 @@
ase->state = AseState::BTA_LE_AUDIO_ASE_STATE_ENABLING;
if (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
- /* We are here because of the reconnection of the single device. */
- CisCreateForDevice(leAudioDevice);
+ if (ase->data_path_state < AudioStreamDataPathState::CIS_PENDING) {
+ /* We are here because of the reconnection of the single device. */
+ CisCreateForDevice(leAudioDevice);
+ }
+
+ if (!leAudioDevice->HaveAllActiveAsesCisEst()) {
+ /* More cis established events has to come */
+ return;
+ }
+
+ if (!leAudioDevice->IsReadyToCreateStream()) {
+ /* Device still remains in ready to create stream state. It means
+ * that more enabling status notifications has to come.
+ */
+ return;
+ }
+
+ /* All CISes created. Send start ready for source ASE before we can go
+ * to streaming state.
+ */
+ struct ase* ase = leAudioDevice->GetFirstActiveAse();
+ ASSERT_LOG(ase != nullptr,
+ "shouldn't be called without an active ASE, device %s",
+ leAudioDevice->address_.ToString().c_str());
+ PrepareAndSendReceiverStartReady(leAudioDevice, ase);
+
return;
}
diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc
index 1cafe06..d704a76 100644
--- a/system/bta/le_audio/state_machine_test.cc
+++ b/system/bta/le_audio/state_machine_test.cc
@@ -3100,6 +3100,118 @@
ASSERT_NE(ase->retrans_nb, 0);
}
+TEST_F(StateMachineTest, testAttachDeviceToTheConversationalStream) {
+ const auto context_type = kContextTypeConversational;
+ const auto leaudio_group_id = 6;
+ const auto num_devices = 2;
+
+ ContentControlIdKeeper::GetInstance()->SetCcid(call_context, call_ccid);
+
+ // Prepare multiple fake connected devices in a group
+ auto* group =
+ PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
+ ASSERT_EQ(group->Size(), num_devices);
+
+ PrepareConfigureCodecHandler(group);
+ PrepareConfigureQosHandler(group);
+ PrepareEnableHandler(group);
+ PrepareReceiverStartReady(group);
+ PrepareDisableHandler(group);
+ PrepareReleaseHandler(group);
+
+ auto* leAudioDevice = group->GetFirstDevice();
+ LeAudioDevice* lastDevice;
+ LeAudioDevice* fistDevice = leAudioDevice;
+
+ auto expected_devices_written = 0;
+ while (leAudioDevice) {
+ /* Three Writes:
+ * 1: Codec Config
+ * 2: Codec QoS
+ * 3: Enabling
+ */
+ lastDevice = leAudioDevice;
+ EXPECT_CALL(gatt_queue,
+ WriteCharacteristic(leAudioDevice->conn_id_,
+ leAudioDevice->ctp_hdls_.val_hdl, _,
+ GATT_WRITE_NO_RSP, _, _))
+ .Times(AtLeast(3));
+ expected_devices_written++;
+ leAudioDevice = group->GetNextDevice(leAudioDevice);
+ }
+ ASSERT_EQ(expected_devices_written, num_devices);
+
+ EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
+ EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
+ EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(4);
+
+ InjectInitialIdleNotification(group);
+
+ // Start the configuration and stream Conversational content
+ LeAudioGroupStateMachine::Get()->StartStream(
+ group, static_cast<LeAudioContextType>(context_type),
+ types::AudioContexts(context_type));
+
+ // Check if group has transitioned to a proper state
+ ASSERT_EQ(group->GetState(),
+ types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
+ testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_);
+
+ // Inject CIS and ACL disconnection of first device
+ InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
+ InjectAclDisconnected(group, lastDevice);
+
+ // Check if group keeps streaming
+ ASSERT_EQ(group->GetState(),
+ types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
+
+ lastDevice->conn_id_ = 3;
+ group->UpdateAudioContextTypeAvailability();
+
+ // Make sure ASE with disconnected CIS are not left in STREAMING
+ ASSERT_EQ(lastDevice->GetFirstAseWithState(
+ ::le_audio::types::kLeAudioDirectionSink,
+ types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
+ nullptr);
+ ASSERT_EQ(lastDevice->GetFirstAseWithState(
+ ::le_audio::types::kLeAudioDirectionSource,
+ types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
+ nullptr);
+
+ EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_,
+ lastDevice->ctp_hdls_.val_hdl, _,
+ GATT_WRITE_NO_RSP, _, _))
+ .Times(AtLeast(3));
+
+ EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
+ EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
+ LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice);
+
+ // Check if group keeps streaming
+ ASSERT_EQ(group->GetState(),
+ types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
+
+ // Verify that the joining device receives the right CCID list
+ auto lastMeta = lastDevice->GetFirstActiveAse()->metadata;
+ bool parsedOk = false;
+ auto ltv = le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(),
+ lastMeta.size(), parsedOk);
+ ASSERT_TRUE(parsedOk);
+
+ auto ccids = ltv.Find(le_audio::types::kLeAudioMetadataTypeCcidList);
+ ASSERT_TRUE(ccids.has_value());
+ ASSERT_NE(std::find(ccids->begin(), ccids->end(), call_ccid), ccids->end());
+
+ /* Verify that ASE of first device are still good*/
+ auto ase = fistDevice->GetFirstActiveAse();
+ ASSERT_NE(ase->max_transport_latency, 0);
+ ASSERT_NE(ase->retrans_nb, 0);
+
+ // Make sure ASEs with reconnected CIS are in STREAMING state
+ ASSERT_TRUE(lastDevice->HaveAllActiveAsesSameState(
+ types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING));
+}
+
TEST_F(StateMachineTest, StartStreamAfterConfigure) {
const auto context_type = kContextTypeMedia;
const auto leaudio_group_id = 6;
diff --git a/system/btif/src/btif_config.cc b/system/btif/src/btif_config.cc
index 4b99365..a777ba8 100644
--- a/system/btif/src/btif_config.cc
+++ b/system/btif/src/btif_config.cc
@@ -112,7 +112,7 @@
metrics_salt.fill(0);
}
if (!AddressObfuscator::IsSaltValid(metrics_salt)) {
- LOG(INFO) << __func__ << ": Metrics salt is not invalid, creating new one";
+ LOG(INFO) << __func__ << ": Metrics salt is invalid, creating new one";
if (RAND_bytes(metrics_salt.data(), metrics_salt.size()) != 1) {
LOG(FATAL) << __func__ << "Failed to generate salt for metrics";
}
diff --git a/system/gd/hal/snoop_logger.cc b/system/gd/hal/snoop_logger.cc
index 8591027..e3b585c 100644
--- a/system/gd/hal/snoop_logger.cc
+++ b/system/gd/hal/snoop_logger.cc
@@ -462,9 +462,8 @@
size_t SnoopLogger::GetMaxPacketsPerBuffer() {
// We want to use at most 256 KB memory for btsnooz log for release builds
// and 512 KB memory for userdebug/eng builds
- auto is_debuggable = os::GetSystemProperty(kIsDebuggableProperty);
- size_t btsnooz_max_memory_usage_bytes =
- ((is_debuggable.has_value() && common::StringTrim(is_debuggable.value()) == "1") ? 1024 : 256) * 1024;
+ auto is_debuggable = os::GetSystemPropertyBool(kIsDebuggableProperty, false);
+ size_t btsnooz_max_memory_usage_bytes = (is_debuggable ? 1024 : 256) * 1024;
// Calculate max number of packets based on max memory usage and max packet size
return btsnooz_max_memory_usage_bytes / kDefaultBtSnoozMaxBytesPerPacket;
}
@@ -474,8 +473,8 @@
// In userdebug/eng build, it can also be overwritten by modifying the global setting
std::string default_mode = kBtSnoopLogModeDisabled;
{
- auto is_debuggable = os::GetSystemProperty(kIsDebuggableProperty);
- if (is_debuggable.has_value() && common::StringTrim(is_debuggable.value()) == "1") {
+ auto is_debuggable = os::GetSystemPropertyBool(kIsDebuggableProperty, false);
+ if (is_debuggable) {
auto default_mode_property = os::GetSystemProperty(kBtSnoopDefaultLogModeProperty);
if (default_mode_property) {
default_mode = std::move(default_mode_property.value());
diff --git a/system/gd/os/Android.bp b/system/gd/os/Android.bp
index 7431f15..292da06 100644
--- a/system/gd/os/Android.bp
+++ b/system/gd/os/Android.bp
@@ -17,6 +17,7 @@
filegroup {
name: "BluetoothOsSources_android",
srcs: [
+ "system_properties_common.cc",
"android/metrics.cc",
"android/parameter_provider.cc",
"android/system_properties.cc",
@@ -35,6 +36,7 @@
filegroup {
name: "BluetoothOsSources_host",
srcs: [
+ "system_properties_common.cc",
"host/metrics.cc",
"host/parameter_provider.cc",
"host/system_properties.cc",
diff --git a/system/gd/os/BUILD.gn b/system/gd/os/BUILD.gn
index 48337e1..7204ccd 100644
--- a/system/gd/os/BUILD.gn
+++ b/system/gd/os/BUILD.gn
@@ -18,6 +18,7 @@
"linux/parameter_provider.cc",
"linux/system_properties.cc",
"linux/wakelock_native.cc",
+ "system_properties_common.cc",
"syslog.cc",
]
diff --git a/system/gd/os/android/metrics.cc b/system/gd/os/android/metrics.cc
index db42fc5..eacaa72 100644
--- a/system/gd/os/android/metrics.cc
+++ b/system/gd/os/android/metrics.cc
@@ -236,7 +236,7 @@
}
void LogMetricSmpPairingEvent(
- const Address& address, uint8_t smp_cmd, android::bluetooth::DirectionEnum direction, uint8_t smp_fail_reason) {
+ const Address& address, uint16_t smp_cmd, android::bluetooth::DirectionEnum direction, uint16_t smp_fail_reason) {
int metric_id = 0;
if (!address.IsEmpty()) {
metric_id = MetricIdManager::GetInstance().AllocateId(address);
diff --git a/system/gd/os/host/metrics.cc b/system/gd/os/host/metrics.cc
index 955d22e..2e85e73 100644
--- a/system/gd/os/host/metrics.cc
+++ b/system/gd/os/host/metrics.cc
@@ -96,7 +96,7 @@
const char* attribute_value) {}
void LogMetricSmpPairingEvent(
- const Address& address, uint8_t smp_cmd, android::bluetooth::DirectionEnum direction, uint8_t smp_fail_reason) {}
+ const Address& address, uint16_t smp_cmd, android::bluetooth::DirectionEnum direction, uint16_t smp_fail_reason) {}
void LogMetricA2dpPlaybackEvent(const Address& address, int playback_state, int audio_coding_mode) {}
diff --git a/system/gd/os/linux/metrics.cc b/system/gd/os/linux/metrics.cc
index 65fb181..3941f77 100644
--- a/system/gd/os/linux/metrics.cc
+++ b/system/gd/os/linux/metrics.cc
@@ -96,7 +96,7 @@
const char* attribute_value) {}
void LogMetricSmpPairingEvent(
- const Address& address, uint8_t smp_cmd, android::bluetooth::DirectionEnum direction, uint8_t smp_fail_reason) {}
+ const Address& address, uint16_t smp_cmd, android::bluetooth::DirectionEnum direction, uint16_t smp_fail_reason) {}
void LogMetricA2dpPlaybackEvent(const Address& address, int playback_state, int audio_coding_mode) {}
diff --git a/system/gd/os/linux_generic/queue_unittest.cc b/system/gd/os/linux_generic/queue_unittest.cc
index 7994aba..706fcd2 100644
--- a/system/gd/os/linux_generic/queue_unittest.cc
+++ b/system/gd/os/linux_generic/queue_unittest.cc
@@ -19,6 +19,7 @@
#include <sys/eventfd.h>
#include <atomic>
+#include <chrono>
#include <future>
#include <unordered_map>
@@ -26,6 +27,8 @@
#include "gtest/gtest.h"
#include "os/reactor.h"
+using namespace std::chrono_literals;
+
namespace bluetooth {
namespace os {
namespace {
@@ -60,6 +63,11 @@
Handler* enqueue_handler_;
Thread* dequeue_thread_;
Handler* dequeue_handler_;
+
+ void sync_enqueue_handler() {
+ ASSERT(enqueue_thread_ != nullptr);
+ ASSERT(enqueue_thread_->GetReactor()->WaitForIdle(2s));
+ }
};
class TestEnqueueEnd {
@@ -338,6 +346,7 @@
test_enqueue_end.RegisterEnqueue(&enqueue_promise_map);
enqueue_future.wait();
EXPECT_EQ(enqueue_future.get(), 0);
+ sync_enqueue_handler();
}
// Enqueue end level : 1
diff --git a/system/gd/os/metrics.h b/system/gd/os/metrics.h
index 339a2cf..cb35d68 100644
--- a/system/gd/os/metrics.h
+++ b/system/gd/os/metrics.h
@@ -166,7 +166,10 @@
* @param smp_fail_reason SMP pairing failure reason code from SMP spec
*/
void LogMetricSmpPairingEvent(
- const hci::Address& address, uint8_t smp_cmd, android::bluetooth::DirectionEnum direction, uint8_t smp_fail_reason);
+ const hci::Address& address,
+ uint16_t smp_cmd,
+ android::bluetooth::DirectionEnum direction,
+ uint16_t smp_fail_reason);
/**
* Logs there is an event related Bluetooth classic pairing
diff --git a/system/gd/os/system_properties.h b/system/gd/os/system_properties.h
index f5a82b8..42ea4e7 100644
--- a/system/gd/os/system_properties.h
+++ b/system/gd/os/system_properties.h
@@ -26,6 +26,21 @@
// or if the platform does not support system property
std::optional<std::string> GetSystemProperty(const std::string& property);
+// Get |property| keyed system property as uint32_t from supported platform, return |default_value| if the property
+// does not exist or if the platform does not support system property
+uint32_t GetSystemPropertyUint32(const std::string& property, uint32_t default_value);
+
+// Get |property| keyed system property as uint32_t from supported platform, return |default_value|
+// if the property does not exist or if the platform does not support system property if property is
+// found it will call stoul with |base|
+uint32_t GetSystemPropertyUint32Base(
+ const std::string& property, uint32_t default_value, int base = 0);
+
+// Get |property| keyed property as bool from supported platform, return
+// |default_value| if the property does not exist or if the platform
+// does not support system property
+bool GetSystemPropertyBool(const std::string& property, bool default_value);
+
// Set |property| keyed system property to |value|, return true if the set was successful and false if the set failed
// Replace existing value if property already exists
bool SetSystemProperty(const std::string& property, const std::string& value);
diff --git a/system/gd/os/system_properties_common.cc b/system/gd/os/system_properties_common.cc
new file mode 100644
index 0000000..f59560c
--- /dev/null
+++ b/system/gd/os/system_properties_common.cc
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+
+#include "common/strings.h"
+#include "os/system_properties.h"
+
+namespace bluetooth {
+namespace os {
+
+uint32_t GetSystemPropertyUint32(const std::string& property, uint32_t default_value) {
+ return GetSystemPropertyUint32Base(property, default_value, 10);
+}
+
+uint32_t GetSystemPropertyUint32Base(
+ const std::string& property, uint32_t default_value, int base) {
+ std::optional<std::string> result = GetSystemProperty(property);
+ if (result.has_value()) {
+ return static_cast<uint32_t>(std::stoul(*result, nullptr, base));
+ }
+ return default_value;
+}
+
+bool GetSystemPropertyBool(const std::string& property, bool default_value) {
+ std::optional<std::string> result = GetSystemProperty(property);
+ if (result.has_value()) {
+ std::string trimmed_val = common::StringTrim(result.value());
+ if (trimmed_val == "true" || trimmed_val == "1") {
+ return true;
+ }
+ if (trimmed_val == "false" || trimmed_val == "0") {
+ return false;
+ }
+ }
+ return default_value;
+}
+
+} // namespace os
+} // namespace bluetooth
diff --git a/system/internal_include/bt_target.h b/system/internal_include/bt_target.h
index a61d1b2..89478dc 100644
--- a/system/internal_include/bt_target.h
+++ b/system/internal_include/bt_target.h
@@ -1026,8 +1026,4 @@
#include "bt_trace.h"
-#ifndef BTM_DISABLE_CONCURRENT_PEER_AUTH
-#define BTM_DISABLE_CONCURRENT_PEER_AUTH FALSE
-#endif
-
#endif /* BT_TARGET_H */
diff --git a/system/main/shim/metrics_api.cc b/system/main/shim/metrics_api.cc
index 99832be..82ad3c1 100644
--- a/system/main/shim/metrics_api.cc
+++ b/system/main/shim/metrics_api.cc
@@ -89,9 +89,9 @@
transmit_power_level);
}
-void LogMetricSmpPairingEvent(const RawAddress& raw_address, uint8_t smp_cmd,
+void LogMetricSmpPairingEvent(const RawAddress& raw_address, uint16_t smp_cmd,
android::bluetooth::DirectionEnum direction,
- uint8_t smp_fail_reason) {
+ uint16_t smp_fail_reason) {
Address address = bluetooth::ToGdAddress(raw_address);
bluetooth::os::LogMetricSmpPairingEvent(address, smp_cmd, direction,
smp_fail_reason);
diff --git a/system/main/shim/metrics_api.h b/system/main/shim/metrics_api.h
index ce13876..f838908 100644
--- a/system/main/shim/metrics_api.h
+++ b/system/main/shim/metrics_api.h
@@ -134,9 +134,9 @@
* @param direction direction of this SMP command
* @param smp_fail_reason SMP pairing failure reason code from SMP spec
*/
-void LogMetricSmpPairingEvent(const RawAddress& address, uint8_t smp_cmd,
+void LogMetricSmpPairingEvent(const RawAddress& address, uint16_t smp_cmd,
android::bluetooth::DirectionEnum direction,
- uint8_t smp_fail_reason);
+ uint16_t smp_fail_reason);
/**
* Logs there is an event related Bluetooth classic pairing
diff --git a/system/stack/Android.bp b/system/stack/Android.bp
index 16ffa63..fcf0874 100644
--- a/system/stack/Android.bp
+++ b/system/stack/Android.bp
@@ -1002,9 +1002,14 @@
"libprotobuf-cpp-lite",
],
sanitize: {
- hwaddress: true,
- integer_overflow: true,
- scs: true,
+ address: true,
+ all_undefined: true,
+ cfi: true,
+ integer_overflow: true,
+ scs: true,
+ diag: {
+ undefined : true
+ },
},
}
diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc
index 10f56e6..df9b6cc 100644
--- a/system/stack/btm/btm_sec.cc
+++ b/system/stack/btm/btm_sec.cc
@@ -154,6 +154,14 @@
}
}
+static bool concurrentPeerAuthIsEnabled() {
+ // Was previously named BTM_DISABLE_CONCURRENT_PEER_AUTH.
+ // Renamed to ENABLED for homogeneity with system properties
+ static const bool sCONCURRENT_PEER_AUTH_IS_ENABLED = osi_property_get_bool(
+ "bluetooth.btm.sec.concurrent_peer_auth.enabled", true);
+ return sCONCURRENT_PEER_AUTH_IS_ENABLED;
+}
+
void NotifyBondingCanceled(tBTM_STATUS btm_status) {
if (btm_cb.api.p_bond_cancel_cmpl_callback) {
btm_cb.api.p_bond_cancel_cmpl_callback(BTM_SUCCESS);
@@ -3407,11 +3415,9 @@
__func__, p_dev_rec, p_dev_rec->p_callback);
p_dev_rec->p_callback = NULL;
l2cu_resubmit_pending_sec_req(&p_dev_rec->bd_addr);
-#ifdef BTM_DISABLE_CONCURRENT_PEER_AUTH
- } else if (BTM_DISABLE_CONCURRENT_PEER_AUTH &&
+ } else if (!concurrentPeerAuthIsEnabled() &&
p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING) {
p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
-#endif
}
return;
}
@@ -4036,10 +4042,9 @@
tBTM_SEC_DEV_REC* p_dev_rec = btm_find_or_alloc_dev(bda);
VLOG(2) << __func__ << " bda: " << bda;
-#if (defined(BTM_DISABLE_CONCURRENT_PEER_AUTH) && \
- (BTM_DISABLE_CONCURRENT_PEER_AUTH == TRUE))
- p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
-#endif
+ if (!concurrentPeerAuthIsEnabled()) {
+ p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
+ }
if ((btm_cb.pairing_state == BTM_PAIR_STATE_WAIT_PIN_REQ) &&
(btm_cb.collision_start_time != 0) &&
diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc
index 3861016..2185f6d 100644
--- a/system/stack/gatt/gatt_api.cc
+++ b/system/stack/gatt/gatt_api.cc
@@ -304,7 +304,7 @@
elem.type = list.asgn_range.is_primary ? GATT_UUID_PRI_SERVICE
: GATT_UUID_SEC_SERVICE;
- if (elem.type == GATT_UUID_PRI_SERVICE) {
+ if (elem.type == GATT_UUID_PRI_SERVICE && gatt_cb.over_br_enabled) {
Uuid* p_uuid = gatts_get_service_uuid(elem.p_db);
if (*p_uuid != Uuid::From16Bit(UUID_SERVCLASS_GMCS_SERVER) &&
*p_uuid != Uuid::From16Bit(UUID_SERVCLASS_GTBS_SERVER)) {
diff --git a/system/stack/gatt/gatt_int.h b/system/stack/gatt/gatt_int.h
index 6cacdfe..fa173f5 100644
--- a/system/stack/gatt/gatt_int.h
+++ b/system/stack/gatt/gatt_int.h
@@ -446,6 +446,7 @@
tGATT_APPL_INFO cb_info;
tGATT_HDL_CFG hdl_cfg;
+ bool over_br_enabled;
} tGATT_CB;
#define GATT_SIZE_OF_SRV_CHG_HNDL_RANGE 4
diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc
index 0ee27d8..b9d1120 100644
--- a/system/stack/gatt/gatt_main.cc
+++ b/system/stack/gatt/gatt_main.cc
@@ -123,10 +123,10 @@
L2CA_RegisterFixedChannel(L2CAP_ATT_CID, &fixed_reg);
- bool gatt_over_br_is_disabled =
- osi_property_get_bool("bluetooth.gatt_over_bredr.disabled", false);
+ gatt_cb.over_br_enabled =
+ osi_property_get_bool("bluetooth.gatt.over_bredr.enabled", true);
/* Now, register with L2CAP for ATT PSM over BR/EDR */
- if (!gatt_over_br_is_disabled &&
+ if (gatt_cb.over_br_enabled &&
!L2CA_Register2(BT_PSM_ATT, dyn_info, false /* enable_snoop */, nullptr,
GATT_MAX_MTU_SIZE, 0, BTM_SEC_NONE)) {
LOG(ERROR) << "ATT Dynamic Registration failed";
diff --git a/system/stack/include/stack_metrics_logging.h b/system/stack/include/stack_metrics_logging.h
index 158c98f..58d869f 100644
--- a/system/stack/include/stack_metrics_logging.h
+++ b/system/stack/include/stack_metrics_logging.h
@@ -34,9 +34,9 @@
uint32_t hci_cmd, uint16_t hci_event, uint16_t hci_ble_event,
uint16_t cmd_status, uint16_t reason_code);
-void log_smp_pairing_event(const RawAddress& address, uint8_t smp_cmd,
+void log_smp_pairing_event(const RawAddress& address, uint16_t smp_cmd,
android::bluetooth::DirectionEnum direction,
- uint8_t smp_fail_reason);
+ uint16_t smp_fail_reason);
void log_sdp_attribute(const RawAddress& address, uint16_t protocol_uuid,
uint16_t attribute_id, size_t attribute_size,
diff --git a/system/stack/l2cap/l2c_api.cc b/system/stack/l2cap/l2c_api.cc
index 9d8eb20..2a7efd8 100644
--- a/system/stack/l2cap/l2c_api.cc
+++ b/system/stack/l2cap/l2c_api.cc
@@ -34,10 +34,10 @@
#include "device/include/controller.h" // TODO Remove
#include "gd/common/init_flags.h"
+#include "gd/os/system_properties.h"
#include "main/shim/shim.h"
#include "osi/include/allocator.h"
#include "osi/include/log.h"
-#include "osi/include/properties.h"
#include "stack/btm/btm_sec.h"
#include "stack/include/bt_hdr.h"
#include "stack/include/btu.h" // do_in_main_thread
@@ -68,14 +68,14 @@
uint16_t L2CA_LeCreditDefault() {
static const uint16_t sL2CAP_LE_CREDIT_DEFAULT =
- (uint16_t)osi_property_get_int32(
+ bluetooth::os::GetSystemPropertyUint32Base(
"bluetooth.l2cap.le.credit_default.value", 0xffff);
return sL2CAP_LE_CREDIT_DEFAULT;
}
uint16_t L2CA_LeCreditThreshold() {
static const uint16_t sL2CAP_LE_CREDIT_THRESHOLD =
- (uint16_t)osi_property_get_int32(
+ bluetooth::os::GetSystemPropertyUint32Base(
"bluetooth.l2cap.le.credit_threshold.value", 0x0040);
return sL2CAP_LE_CREDIT_THRESHOLD;
}
diff --git a/system/stack/metrics/stack_metrics_logging.cc b/system/stack/metrics/stack_metrics_logging.cc
index 4e23bd2..d69d54e 100644
--- a/system/stack/metrics/stack_metrics_logging.cc
+++ b/system/stack/metrics/stack_metrics_logging.cc
@@ -42,9 +42,9 @@
hci_ble_event, cmd_status, reason_code);
}
-void log_smp_pairing_event(const RawAddress& address, uint8_t smp_cmd,
+void log_smp_pairing_event(const RawAddress& address, uint16_t smp_cmd,
android::bluetooth::DirectionEnum direction,
- uint8_t smp_fail_reason) {
+ uint16_t smp_fail_reason) {
bluetooth::shim::LogMetricSmpPairingEvent(address, smp_cmd, direction,
smp_fail_reason);
}
diff --git a/system/stack/smp/smp_int.h b/system/stack/smp/smp_int.h
index c4ddf3e..52b5c2b 100644
--- a/system/stack/smp/smp_int.h
+++ b/system/stack/smp/smp_int.h
@@ -32,6 +32,15 @@
#include "stack/include/bt_octets.h"
#include "types/raw_address.h"
+typedef enum : uint16_t {
+ SMP_METRIC_COMMAND_LE_FLAG = 0x0000,
+ SMP_METRIC_COMMAND_BR_FLAG = 0x0100,
+ SMP_METRIC_COMMAND_LE_PAIRING_CMPL = 0xFF00,
+ SMP_METRIC_COMMAND_BR_PAIRING_CMPL = 0xFF01,
+} tSMP_METRIC_COMMAND;
+
+constexpr uint16_t SMP_METRIC_STATUS_INTERNAL_FLAG = 0x0100;
+
typedef enum : uint8_t {
/* Legacy mode */
SMP_MODEL_ENCRYPTION_ONLY = 0, /* Just Works model */
@@ -414,7 +423,8 @@
/* smp_util.cc */
extern void smp_log_metrics(const RawAddress& bd_addr, bool is_outgoing,
- const uint8_t* p_buf, size_t buf_len);
+ const uint8_t* p_buf, size_t buf_len,
+ bool is_over_br);
extern bool smp_send_cmd(uint8_t cmd_code, tSMP_CB* p_cb);
extern void smp_cb_cleanup(tSMP_CB* p_cb);
extern void smp_reset_control_value(tSMP_CB* p_cb);
diff --git a/system/stack/smp/smp_l2c.cc b/system/stack/smp/smp_l2c.cc
index 6a13e8a..264cdc3 100644
--- a/system/stack/smp/smp_l2c.cc
+++ b/system/stack/smp/smp_l2c.cc
@@ -195,7 +195,8 @@
smp_rsp_timeout, NULL);
smp_log_metrics(p_cb->pairing_bda, false /* incoming */,
- p_buf->data + p_buf->offset, p_buf->len);
+ p_buf->data + p_buf->offset, p_buf->len,
+ false /* is_over_br */);
if (cmd == SMP_OPCODE_CONFIRM) {
SMP_TRACE_DEBUG(
@@ -334,7 +335,8 @@
smp_rsp_timeout, NULL);
smp_log_metrics(p_cb->pairing_bda, false /* incoming */,
- p_buf->data + p_buf->offset, p_buf->len);
+ p_buf->data + p_buf->offset, p_buf->len,
+ true /* is_over_br */);
p_cb->rcvd_cmd_code = cmd;
p_cb->rcvd_cmd_len = (uint8_t)p_buf->len;
diff --git a/system/stack/smp/smp_utils.cc b/system/stack/smp/smp_utils.cc
index 71fa55d..f2aba5e 100644
--- a/system/stack/smp/smp_utils.cc
+++ b/system/stack/smp/smp_utils.cc
@@ -316,22 +316,26 @@
* @param buf_len length available to read for p_buf
*/
void smp_log_metrics(const RawAddress& bd_addr, bool is_outgoing,
- const uint8_t* p_buf, size_t buf_len) {
+ const uint8_t* p_buf, size_t buf_len, bool is_over_br) {
if (buf_len < 1) {
LOG(WARNING) << __func__ << ": buffer is too small, size is " << buf_len;
return;
}
- uint8_t cmd;
- STREAM_TO_UINT8(cmd, p_buf);
+ uint8_t raw_cmd;
+ STREAM_TO_UINT8(raw_cmd, p_buf);
buf_len--;
uint8_t failure_reason = 0;
- if (cmd == SMP_OPCODE_PAIRING_FAILED && buf_len >= 1) {
+ if (raw_cmd == SMP_OPCODE_PAIRING_FAILED && buf_len >= 1) {
STREAM_TO_UINT8(failure_reason, p_buf);
}
+ uint16_t metric_cmd =
+ is_over_br ? SMP_METRIC_COMMAND_BR_FLAG : SMP_METRIC_COMMAND_LE_FLAG;
+ metric_cmd |= static_cast<uint16_t>(raw_cmd);
android::bluetooth::DirectionEnum direction =
is_outgoing ? android::bluetooth::DirectionEnum::DIRECTION_OUTGOING
: android::bluetooth::DirectionEnum::DIRECTION_INCOMING;
- log_smp_pairing_event(bd_addr, cmd, direction, failure_reason);
+ log_smp_pairing_event(bd_addr, metric_cmd, direction,
+ static_cast<uint16_t>(failure_reason));
}
/*******************************************************************************
@@ -352,7 +356,8 @@
SMP_TRACE_EVENT("%s", __func__);
smp_log_metrics(rem_bda, true /* outgoing */,
- p_toL2CAP->data + p_toL2CAP->offset, p_toL2CAP->len);
+ p_toL2CAP->data + p_toL2CAP->offset, p_toL2CAP->len,
+ smp_cb.smp_over_br /* is_over_br */);
l2cap_ret = L2CA_SendFixedChnlData(fixed_cid, rem_bda, p_toL2CAP);
if (l2cap_ret == L2CAP_DW_FAILED) {
@@ -980,6 +985,23 @@
smp_status_text(evt_data.cmplt.reason).c_str()));
}
+ // Log pairing complete event
+ {
+ auto direction =
+ p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD
+ ? android::bluetooth::DirectionEnum::DIRECTION_OUTGOING
+ : android::bluetooth::DirectionEnum::DIRECTION_INCOMING;
+ uint16_t metric_cmd = p_cb->smp_over_br
+ ? SMP_METRIC_COMMAND_BR_PAIRING_CMPL
+ : SMP_METRIC_COMMAND_LE_PAIRING_CMPL;
+ uint16_t metric_status = p_cb->status;
+ if (metric_status > SMP_MAX_FAIL_RSN_PER_SPEC) {
+ metric_status |= SMP_METRIC_STATUS_INTERNAL_FLAG;
+ }
+ log_smp_pairing_event(p_cb->pairing_bda, metric_cmd, direction,
+ metric_status);
+ }
+
if (p_cb->status == SMP_SUCCESS && p_cb->smp_over_br) {
btm_dev_consolidate_existing_connections(pairing_bda);
}
diff --git a/system/test/mock/mock_main_shim_metrics_api.cc b/system/test/mock/mock_main_shim_metrics_api.cc
index 30aeeb1..8330b85 100644
--- a/system/test/mock/mock_main_shim_metrics_api.cc
+++ b/system/test/mock/mock_main_shim_metrics_api.cc
@@ -128,8 +128,8 @@
raw_address, handle, cmd_status, transmit_power_level);
}
void bluetooth::shim::LogMetricSmpPairingEvent(
- const RawAddress& raw_address, uint8_t smp_cmd,
- android::bluetooth::DirectionEnum direction, uint8_t smp_fail_reason) {
+ const RawAddress& raw_address, uint16_t smp_cmd,
+ android::bluetooth::DirectionEnum direction, uint16_t smp_fail_reason) {
mock_function_count_map[__func__]++;
test::mock::main_shim_metrics_api::LogMetricSmpPairingEvent(
raw_address, smp_cmd, direction, smp_fail_reason);
diff --git a/system/test/mock/mock_main_shim_metrics_api.h b/system/test/mock/mock_main_shim_metrics_api.h
index b42529f..d85088f 100644
--- a/system/test/mock/mock_main_shim_metrics_api.h
+++ b/system/test/mock/mock_main_shim_metrics_api.h
@@ -171,19 +171,19 @@
};
extern struct LogMetricReadTxPowerLevelResult LogMetricReadTxPowerLevelResult;
// Name: LogMetricSmpPairingEvent
-// Params: const RawAddress& raw_address, uint8_t smp_cmd,
+// Params: const RawAddress& raw_address, uint16_t smp_cmd,
// android::bluetooth::DirectionEnum direction, uint8_t smp_fail_reason Returns:
// void
struct LogMetricSmpPairingEvent {
- std::function<void(const RawAddress& raw_address, uint8_t smp_cmd,
+ std::function<void(const RawAddress& raw_address, uint16_t smp_cmd,
android::bluetooth::DirectionEnum direction,
- uint8_t smp_fail_reason)>
- body{[](const RawAddress& raw_address, uint8_t smp_cmd,
+ uint16_t smp_fail_reason)>
+ body{[](const RawAddress& raw_address, uint16_t smp_cmd,
android::bluetooth::DirectionEnum direction,
- uint8_t smp_fail_reason) {}};
- void operator()(const RawAddress& raw_address, uint8_t smp_cmd,
+ uint16_t smp_fail_reason) {}};
+ void operator()(const RawAddress& raw_address, uint16_t smp_cmd,
android::bluetooth::DirectionEnum direction,
- uint8_t smp_fail_reason) {
+ uint16_t smp_fail_reason) {
body(raw_address, smp_cmd, direction, smp_fail_reason);
};
};
diff --git a/system/test/mock/mock_stack_metrics_logging.cc b/system/test/mock/mock_stack_metrics_logging.cc
index 1f51191..028636d 100644
--- a/system/test/mock/mock_stack_metrics_logging.cc
+++ b/system/test/mock/mock_stack_metrics_logging.cc
@@ -86,9 +86,9 @@
address, connection_handle, direction, link_type, hci_cmd, hci_event,
hci_ble_event, cmd_status, reason_code);
}
-void log_smp_pairing_event(const RawAddress& address, uint8_t smp_cmd,
+void log_smp_pairing_event(const RawAddress& address, uint16_t smp_cmd,
android::bluetooth::DirectionEnum direction,
- uint8_t smp_fail_reason) {
+ uint16_t smp_fail_reason) {
mock_function_count_map[__func__]++;
test::mock::stack_metrics_logging::log_smp_pairing_event(
address, smp_cmd, direction, smp_fail_reason);
diff --git a/system/test/mock/mock_stack_metrics_logging.h b/system/test/mock/mock_stack_metrics_logging.h
index 967b2f8..8b695f4 100644
--- a/system/test/mock/mock_stack_metrics_logging.h
+++ b/system/test/mock/mock_stack_metrics_logging.h
@@ -96,19 +96,19 @@
};
extern struct log_link_layer_connection_event log_link_layer_connection_event;
// Name: log_smp_pairing_event
-// Params: const RawAddress& address, uint8_t smp_cmd,
+// Params: const RawAddress& address, uint16_t smp_cmd,
// android::bluetooth::DirectionEnum direction, uint8_t smp_fail_reason Returns:
// void
struct log_smp_pairing_event {
- std::function<void(const RawAddress& address, uint8_t smp_cmd,
+ std::function<void(const RawAddress& address, uint16_t smp_cmd,
android::bluetooth::DirectionEnum direction,
- uint8_t smp_fail_reason)>
- body{[](const RawAddress& address, uint8_t smp_cmd,
+ uint16_t smp_fail_reason)>
+ body{[](const RawAddress& address, uint16_t smp_cmd,
android::bluetooth::DirectionEnum direction,
- uint8_t smp_fail_reason) {}};
- void operator()(const RawAddress& address, uint8_t smp_cmd,
+ uint16_t smp_fail_reason) {}};
+ void operator()(const RawAddress& address, uint16_t smp_cmd,
android::bluetooth::DirectionEnum direction,
- uint8_t smp_fail_reason) {
+ uint16_t smp_fail_reason) {
body(address, smp_cmd, direction, smp_fail_reason);
};
};