diff options
84 files changed, 1142 insertions, 4061 deletions
diff --git a/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java b/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java index 53b82ac023..e7d4ed900d 100644 --- a/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java +++ b/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java @@ -37,6 +37,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.ParcelUuid; +import android.os.UserHandle; import android.sysprop.BluetoothProperties; import android.util.Log; @@ -662,7 +663,7 @@ public class HearingAidService extends ProfileService { intent.addFlags( Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - sendBroadcast(intent, BLUETOOTH_CONNECT); + sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_CONNECT); } /* Notifications of audio device disconnection events. */ diff --git a/android/app/src/com/android/bluetooth/hearingaid/HearingAidStateMachine.java b/android/app/src/com/android/bluetooth/hearingaid/HearingAidStateMachine.java index 4fc71b373f..3a701d5c65 100644 --- a/android/app/src/com/android/bluetooth/hearingaid/HearingAidStateMachine.java +++ b/android/app/src/com/android/bluetooth/hearingaid/HearingAidStateMachine.java @@ -37,6 +37,7 @@ import android.bluetooth.BluetoothProfile; import android.content.Intent; import android.os.Looper; import android.os.Message; +import android.os.UserHandle; import android.util.Log; import com.android.bluetooth.Utils; @@ -556,8 +557,11 @@ final class HearingAidStateMachine extends StateMachine { intent.addFlags( Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - mService.sendBroadcast( - intent, BLUETOOTH_CONNECT, Utils.getTempBroadcastOptions().toBundle()); + mService.sendBroadcastAsUser( + intent, + UserHandle.ALL, + BLUETOOTH_CONNECT, + Utils.getTempBroadcastOptions().toBundle()); } private static String messageWhatToString(int what) { diff --git a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java index 264a8267db..04873a0514 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -1831,7 +1831,11 @@ public class LeAudioService extends ProfileService { intent.addFlags( Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - sendBroadcast(intent, BLUETOOTH_CONNECT, Utils.getTempBroadcastOptions().toBundle()); + sendBroadcastAsUser( + intent, + UserHandle.ALL, + BLUETOOTH_CONNECT, + Utils.getTempBroadcastOptions().toBundle()); } void sentActiveDeviceChangeIntent(BluetoothDevice device) { @@ -1840,8 +1844,9 @@ public class LeAudioService extends ProfileService { intent.addFlags( Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - sendBroadcastWithMultiplePermissions( - intent, new String[] {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}); + createContextAsUser(UserHandle.ALL, /* flags= */ 0) + .sendBroadcastWithMultiplePermissions( + intent, new String[] {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}); } void notifyVolumeControlServiceAboutActiveGroup(BluetoothDevice device) { diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index 1128a79f36..87adb315f9 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -805,24 +805,27 @@ public class VolumeControlService extends ProfileService { + (", mute: " + mute) + (", flags: " + flags)); /* We are here, because system has just started and LeAudio device is connected. If - * remote device has User Persistent flag set or the volume != 0, Android sets the - * volume to local cache and to the audio system. If Reset Flag is set and remote has - * volume set to 0, then Android sets to remote devices either cached volume volume - * taken from audio manager. Note, to match BR/EDR behavior, don't show volume change in - * UI here + * remote device has User Persistent flag set, Android sets the volume to local cache + * and to the audio system. + * If Reset Flag is set, then Android sets to remote devices either cached volume volume + * taken from audio manager. + * Note, to match BR/EDR behavior, don't show volume change in UI here */ - if ((flags & VOLUME_FLAGS_PERSISTED_USER_SET_VOLUME_MASK) == 0x01 || (volume != 0)) { + if ((flags & VOLUME_FLAGS_PERSISTED_USER_SET_VOLUME_MASK) == 0x01) { updateGroupCacheAndAudioSystem(groupId, volume, mute, false); + return; + } + + // Reset flag is used + if (groupVolume != IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME) { + Log.i(TAG, "Setting volume: " + groupVolume + " to the group: " + groupId); + setGroupVolume(groupId, groupVolume); } else { - if (groupVolume != IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME) { - Log.i(TAG, "Setting volume: " + groupVolume + " to the group: " + groupId); - setGroupVolume(groupId, groupVolume); - } else { - int vol = getBleVolumeFromCurrentStream(); - Log.i(TAG, "Setting system volume: " + vol + " to the group: " + groupId); - setGroupVolume(groupId, getBleVolumeFromCurrentStream()); - } + int vol = getBleVolumeFromCurrentStream(); + Log.i(TAG, "Setting system volume: " + vol + " to the group: " + groupId); + setGroupVolume(groupId, getBleVolumeFromCurrentStream()); } + return; } diff --git a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceTest.java index 7c7a166f2a..5b1dceb486 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceTest.java @@ -43,6 +43,7 @@ import android.media.AudioManager; import android.media.BluetoothProfileConnectionInfo; import android.os.Looper; import android.os.ParcelUuid; +import android.os.UserHandle; import android.platform.test.flag.junit.SetFlagsRule; import androidx.test.filters.MediumTest; @@ -166,7 +167,11 @@ public class HearingAidServiceTest { @SafeVarargs private void verifyIntentSent(Matcher<Intent>... matchers) { mInOrder.verify(mContext, timeout(TIMEOUT.toMillis() * 2)) - .sendBroadcast(MockitoHamcrest.argThat(AllOf.allOf(matchers)), any(), any()); + .sendBroadcastAsUser( + MockitoHamcrest.argThat(AllOf.allOf(matchers)), + eq(UserHandle.ALL), + any(), + any()); } private void verifyConnectionStateIntent(BluetoothDevice device, int newState, int prevState) { @@ -1253,9 +1258,10 @@ public class HearingAidServiceTest { mService.messageFromNative(stackEvent); // Verify the connection state broadcast mInOrder.verify(mContext, times(0)) - .sendBroadcast( + .sendBroadcastAsUser( MockitoHamcrest.argThat( hasAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED)), + eq(UserHandle.ALL), any(), any()); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java index 64b7573555..301051fed4 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java @@ -24,6 +24,7 @@ import android.bluetooth.BluetoothProfile; import android.content.Intent; import android.os.Bundle; import android.os.HandlerThread; +import android.os.UserHandle; import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; @@ -118,7 +119,8 @@ public class HearingAidStateMachineTest { // Verify that no connection state broadcast is executed verify(mHearingAidService, after(TIMEOUT_MS).never()) - .sendBroadcast(any(Intent.class), anyString(), any(Bundle.class)); + .sendBroadcastAsUser( + any(Intent.class), eq(UserHandle.ALL), anyString(), any(Bundle.class)); // Check that we are in Disconnected state Assert.assertThat( mHearingAidStateMachine.getCurrentState(), @@ -140,7 +142,11 @@ public class HearingAidStateMachineTest { // Verify that one connection state broadcast is executed ArgumentCaptor<Intent> intentArgument1 = ArgumentCaptor.forClass(Intent.class); verify(mHearingAidService, timeout(TIMEOUT_MS).times(1)) - .sendBroadcast(intentArgument1.capture(), anyString(), any(Bundle.class)); + .sendBroadcastAsUser( + intentArgument1.capture(), + eq(UserHandle.ALL), + anyString(), + any(Bundle.class)); Assert.assertEquals( BluetoothProfile.STATE_CONNECTING, intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); @@ -161,7 +167,11 @@ public class HearingAidStateMachineTest { // - two calls to broadcastConnectionState(): Disconnected -> Conecting -> Connected ArgumentCaptor<Intent> intentArgument2 = ArgumentCaptor.forClass(Intent.class); verify(mHearingAidService, timeout(TIMEOUT_MS).times(2)) - .sendBroadcast(intentArgument2.capture(), anyString(), any(Bundle.class)); + .sendBroadcastAsUser( + intentArgument2.capture(), + eq(UserHandle.ALL), + anyString(), + any(Bundle.class)); // Check that we are in Connected state Assert.assertThat( mHearingAidStateMachine.getCurrentState(), @@ -186,7 +196,11 @@ public class HearingAidStateMachineTest { // Verify that one connection state broadcast is executed ArgumentCaptor<Intent> intentArgument1 = ArgumentCaptor.forClass(Intent.class); verify(mHearingAidService, timeout(TIMEOUT_MS).times(1)) - .sendBroadcast(intentArgument1.capture(), anyString(), any(Bundle.class)); + .sendBroadcastAsUser( + intentArgument1.capture(), + eq(UserHandle.ALL), + anyString(), + any(Bundle.class)); Assert.assertEquals( BluetoothProfile.STATE_CONNECTING, intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); @@ -199,7 +213,11 @@ public class HearingAidStateMachineTest { // Verify that one connection state broadcast is executed ArgumentCaptor<Intent> intentArgument2 = ArgumentCaptor.forClass(Intent.class); verify(mHearingAidService, timeout(HearingAidStateMachine.sConnectTimeoutMs * 2L).times(2)) - .sendBroadcast(intentArgument2.capture(), anyString(), any(Bundle.class)); + .sendBroadcastAsUser( + intentArgument2.capture(), + eq(UserHandle.ALL), + anyString(), + any(Bundle.class)); Assert.assertEquals( BluetoothProfile.STATE_DISCONNECTED, intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); @@ -233,7 +251,11 @@ public class HearingAidStateMachineTest { // Verify that one connection state broadcast is executed ArgumentCaptor<Intent> intentArgument1 = ArgumentCaptor.forClass(Intent.class); verify(mHearingAidService, timeout(TIMEOUT_MS).times(1)) - .sendBroadcast(intentArgument1.capture(), anyString(), any(Bundle.class)); + .sendBroadcastAsUser( + intentArgument1.capture(), + eq(UserHandle.ALL), + anyString(), + any(Bundle.class)); Assert.assertEquals( BluetoothProfile.STATE_CONNECTING, intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); @@ -246,7 +268,11 @@ public class HearingAidStateMachineTest { // Verify that one connection state broadcast is executed ArgumentCaptor<Intent> intentArgument2 = ArgumentCaptor.forClass(Intent.class); verify(mHearingAidService, timeout(HearingAidStateMachine.sConnectTimeoutMs * 2L).times(2)) - .sendBroadcast(intentArgument2.capture(), anyString(), any(Bundle.class)); + .sendBroadcastAsUser( + intentArgument2.capture(), + eq(UserHandle.ALL), + anyString(), + any(Bundle.class)); Assert.assertEquals( BluetoothProfile.STATE_DISCONNECTED, intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java index f617bfea5b..441fdaa753 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java @@ -804,79 +804,15 @@ public class VolumeControlServiceTest { verify(mAudioManager, times(1)).setStreamVolume(anyInt(), eq(expectedAfVol), anyInt()); } - /** Test if phone will set volume which is read from the buds */ - @Test - public void testConnectedDeviceWithResetFlagSetWithNonZeroVolume() throws Exception { + private void testConnectedDeviceWithResetFlag( + int resetVolumeDeviceOne, int resetVolumeDeviceTwo) { int groupId = 1; - int volumeDevice = 56; - int volumeDeviceTwo = 100; - int flags = 0; - boolean initialMuteState = false; - boolean initialAutonomousFlag = true; - - // Both devices are in the same group - when(mCsipService.getGroupId(mDevice, BluetoothUuid.CAP)).thenReturn(groupId); - when(mCsipService.getGroupId(mDeviceTwo, BluetoothUuid.CAP)).thenReturn(groupId); - - // Update the device policy so okToConnect() returns true - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - when(mDatabaseManager.getProfileConnectionPolicy( - any(BluetoothDevice.class), eq(BluetoothProfile.VOLUME_CONTROL))) - .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED); - doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class)); - doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class)); - - generateDeviceAvailableMessageFromNative(mDevice, 1); - generateConnectionMessageFromNative( - mDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDevice)); - Assert.assertTrue(mService.getDevices().contains(mDevice)); - - // Group is not active, AF will not be notified - generateVolumeStateChanged( - mDevice, groupId, volumeDevice, flags, initialMuteState, initialAutonomousFlag); - verify(mAudioManager, times(0)).setStreamVolume(anyInt(), anyInt(), anyInt()); - - // Make device Active now. This will trigger setting volume to AF - when(mLeAudioService.getActiveGroupId()).thenReturn(groupId); - mServiceBinder.setGroupActive(groupId, true, mAttributionSource); - int expectedAfVol = - (int) Math.round((double) (volumeDevice * MEDIA_MAX_VOL) / BT_LE_AUDIO_MAX_VOL); - verify(mAudioManager, times(1)).setStreamVolume(anyInt(), eq(expectedAfVol), anyInt()); - - // Connect second device and read different volume. Expect it will be set to AF and to - // another set member - generateDeviceAvailableMessageFromNative(mDeviceTwo, 1); - generateConnectionMessageFromNative( - mDeviceTwo, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDeviceTwo)); - Assert.assertTrue(mService.getDevices().contains(mDeviceTwo)); - - // Group is now active, AF will be notified. Native will take care to sync the volume - generateVolumeStateChanged( - mDeviceTwo, - groupId, - volumeDeviceTwo, - flags, - initialMuteState, - initialAutonomousFlag); - expectedAfVol = - (int) Math.round((double) (volumeDeviceTwo * MEDIA_MAX_VOL) / BT_LE_AUDIO_MAX_VOL); - verify(mAudioManager, times(1)).setStreamVolume(anyInt(), eq(expectedAfVol), anyInt()); - } + int streamVolume = 30; + int streamMaxVolume = 100; + int resetFlag = 0; - /** Test if phone will set volume to buds which has no volume */ - @Test - public void testConnectedDeviceWithResetFlagSetWithZeroVolume() throws Exception { - int groupId = 1; - int volumeDevice = 0; - int volumeDeviceTwo = 0; - int flags = 0; boolean initialMuteState = false; boolean initialAutonomousFlag = true; - int streamVolume = 50; - int streamMaxVolume = 100; // Both devices are in the same group when(mCsipService.getGroupId(mDevice, BluetoothUuid.CAP)).thenReturn(groupId); @@ -899,19 +835,25 @@ public class VolumeControlServiceTest { Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(mDevice)); Assert.assertTrue(mService.getDevices().contains(mDevice)); - // Group is not active, AF will not be notified but device will get phone volume - int expectedDeviceVol = + int expectedAfVol = (int) Math.round((double) streamVolume * BT_LE_AUDIO_MAX_VOL / streamMaxVolume); + + // Group is not active, AF will not be notified generateVolumeStateChanged( - mDevice, groupId, volumeDevice, flags, initialMuteState, initialAutonomousFlag); + mDevice, + groupId, + resetVolumeDeviceOne, + resetFlag, + initialMuteState, + initialAutonomousFlag); verify(mAudioManager, times(0)).setStreamVolume(anyInt(), anyInt(), anyInt()); - verify(mNativeInterface, times(1)).setGroupVolume(eq(groupId), eq(expectedDeviceVol)); // Make device Active now. This will trigger setting volume to AF when(mLeAudioService.getActiveGroupId()).thenReturn(groupId); mServiceBinder.setGroupActive(groupId, true, mAttributionSource); verify(mAudioManager, times(1)).setStreamVolume(anyInt(), eq(streamVolume), anyInt()); + verify(mNativeInterface, times(1)).setGroupVolume(eq(groupId), eq(expectedAfVol)); // Connect second device and read different volume. Expect it will be set to AF and to // another set member @@ -926,13 +868,25 @@ public class VolumeControlServiceTest { generateVolumeStateChanged( mDeviceTwo, groupId, - volumeDeviceTwo, - flags, + resetVolumeDeviceTwo, + resetFlag, initialMuteState, initialAutonomousFlag); verify(mAudioManager, times(1)).setStreamVolume(anyInt(), anyInt(), anyInt()); - verify(mNativeInterface, times(2)).setGroupVolume(eq(groupId), eq(expectedDeviceVol)); + verify(mNativeInterface, times(2)).setGroupVolume(eq(groupId), eq(expectedAfVol)); + } + + /** Test if phone will set volume which is read from the buds */ + @Test + public void testConnectedDeviceWithResetFlagSetWithNonZeroVolume() throws Exception { + testConnectedDeviceWithResetFlag(56, 100); + } + + /** Test if phone will set volume to buds which has no volume */ + @Test + public void testConnectedDeviceWithResetFlagSetWithZeroVolume() throws Exception { + testConnectedDeviceWithResetFlag(0, 0); } /** diff --git a/flags/bta_dm.aconfig b/flags/bta_dm.aconfig index 1d74b37df1..c882038d6f 100644 --- a/flags/bta_dm.aconfig +++ b/flags/bta_dm.aconfig @@ -23,13 +23,6 @@ flag { } flag { - name: "separate_service_and_device_discovery" - namespace: "bluetooth" - description: "Separate service and device discovery state machines such that one does not block on another" - bug: "335732980" -} - -flag { name: "bta_dm_discover_both" namespace: "bluetooth" description: "perform both LE and Classic service discovery simulteanously on capable devices" diff --git a/flags/hci.aconfig b/flags/hci.aconfig index d6175fff84..8c5180a298 100644 --- a/flags/hci.aconfig +++ b/flags/hci.aconfig @@ -10,3 +10,10 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "encryption_change_v2" + namespace: "bluetooth" + description: "Enable encryption change V2 event" + bug: "366018699" +} diff --git a/framework/tests/bumble/src/android/bluetooth/PandoraDevice.java b/framework/tests/bumble/src/android/bluetooth/PandoraDevice.java index 00799fbfa0..9933101913 100644 --- a/framework/tests/bumble/src/android/bluetooth/PandoraDevice.java +++ b/framework/tests/bumble/src/android/bluetooth/PandoraDevice.java @@ -37,6 +37,7 @@ import pandora.HostGrpc; import pandora.HostProto; import pandora.HostProto.AdvertiseRequest; import pandora.HostProto.OwnAddressType; +import pandora.OOBGrpc; import pandora.RFCOMMGrpc; import pandora.SecurityGrpc; import pandora.l2cap.L2CAPGrpc; @@ -198,6 +199,11 @@ public final class PandoraDevice extends ExternalResource { return SecurityGrpc.newStub(mChannel); } + /** Get Pandora OOB blocking service */ + public OOBGrpc.OOBBlockingStub oobBlocking() { + return OOBGrpc.newBlockingStub(mChannel); + } + /** Get Pandora GATT service */ public GATTGrpc.GATTStub gatt() { return GATTGrpc.newStub(mChannel); diff --git a/framework/tests/bumble/src/android/bluetooth/pairing/OobPairingTest.java b/framework/tests/bumble/src/android/bluetooth/pairing/OobPairingTest.java new file mode 100644 index 0000000000..64c196bc5e --- /dev/null +++ b/framework/tests/bumble/src/android/bluetooth/pairing/OobPairingTest.java @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2024 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 android.bluetooth.pairing; + +import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; +import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.timeout; + +import android.annotation.SuppressLint; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothAdapter.OobDataCallback; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothManager; +import android.bluetooth.OobData; +import android.bluetooth.PandoraDevice; +import android.bluetooth.Utils; +import android.bluetooth.cts.EnableBluetoothRule; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.util.Log; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.compatibility.common.util.AdoptShellPermissionsRule; + +import com.google.common.primitives.Bytes; +import com.google.protobuf.ByteString; + +import org.hamcrest.Matcher; +import org.hamcrest.core.AllOf; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.hamcrest.MockitoHamcrest; +import org.mockito.stubbing.Answer; + +import pandora.HostProto.AdvertiseRequest; +import pandora.HostProto.OwnAddressType; +import pandora.OobProto.OobDataRequest; +import pandora.OobProto.OobDataResponse; + +import java.time.Duration; +import java.util.Arrays; + +@RunWith(AndroidJUnit4.class) +public class OobPairingTest { + private static final String TAG = OobPairingTest.class.getSimpleName(); + private static final Duration INTENT_TIMEOUT = Duration.ofSeconds(10); + private BluetoothDevice mDevice; + private final Context mContext = + InstrumentationRegistry.getInstrumentation().getTargetContext(); + private final BluetoothAdapter mAdapter = + mContext.getSystemService(BluetoothManager.class).getAdapter(); + private OobDataResponse mRemoteOobData; + + private static final int HASH_START_POSITION = 0; + private static final int HASH_END_POSITION = 16; + private static final int RANDOMIZER_START_POSITION = 16; + private static final int RANDOMIZER_END_POSITION = 32; + + @Rule(order = 0) + public final AdoptShellPermissionsRule mPermissionRule = new AdoptShellPermissionsRule(); + + @Rule(order = 1) + public final PandoraDevice mBumble = new PandoraDevice(); + + @Rule(order = 3) + public final EnableBluetoothRule enableBluetoothRule = new EnableBluetoothRule(false, true); + + @Mock private BroadcastReceiver mReceiver; + private InOrder mInOrder = null; + + @SuppressLint("MissingPermission") + private final Answer<Void> mIntentHandler = + inv -> { + Log.i(TAG, "onReceive(): intent=" + Arrays.toString(inv.getArguments())); + Intent intent = inv.getArgument(1); + String action = intent.getAction(); + if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) { + BluetoothDevice device = + intent.getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class); + int bondState = + intent.getIntExtra( + BluetoothDevice.EXTRA_BOND_STATE, BluetoothAdapter.ERROR); + int prevBondState = + intent.getIntExtra( + BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, + BluetoothAdapter.ERROR); + Log.i( + TAG, + "onReceive(): device " + + device + + " bond state changed from " + + prevBondState + + " to " + + bondState); + } else { + Log.i(TAG, "onReceive(): unknown intent action " + action); + } + return null; + }; + + private OobData buildOobData() { + + byte[] confirmationHash = + mRemoteOobData + .getOob() + .substring(HASH_START_POSITION, HASH_END_POSITION) + .toByteArray(); + byte[] randomizer = + mRemoteOobData + .getOob() + .substring(RANDOMIZER_START_POSITION, RANDOMIZER_END_POSITION) + .toByteArray(); + byte[] address = Utils.addressBytesFromString(Utils.BUMBLE_RANDOM_ADDRESS); + byte[] addressType = {BluetoothDevice.ADDRESS_TYPE_RANDOM}; + + OobData p256 = + new OobData.LeBuilder( + confirmationHash, + Bytes.concat(address, addressType), + OobData.LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL) + .setRandomizerHash(randomizer) + .build(); + return p256; + } + + private void startAdvertise() throws Exception { + AdvertiseRequest request = + AdvertiseRequest.newBuilder() + .setLegacy(true) + .setConnectable(true) + .setOwnAddressType(OwnAddressType.RANDOM) + .build(); + mBumble.hostBlocking().advertise(request); + } + + private final OobDataCallback mGenerateOobDataCallback = + new OobDataCallback() { + @Override + public void onError(int error) { + Log.i(TAG, "onError: " + error); + } + + @Override + public void onOobData(int transport, OobData data) { + Log.d(TAG, "OobData: " + data); + data.getConfirmationHash(); + data.getRandomizerHash(); + byte[] localData = + Bytes.concat(data.getConfirmationHash(), data.getRandomizerHash()); + OobDataRequest localOobData = + OobDataRequest.newBuilder() + .setOob(ByteString.copyFrom(localData)) + .build(); + mRemoteOobData = mBumble.oobBlocking().shareOobData(localOobData); + OobData p256 = buildOobData(); + mDevice.createBondOutOfBand(BluetoothDevice.TRANSPORT_LE, null, p256); + } + }; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mInOrder = inOrder(mReceiver); + doAnswer(mIntentHandler).when(mReceiver).onReceive(any(), any()); + final IntentFilter filter = new IntentFilter(); + filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); + mContext.registerReceiver(mReceiver, filter); + mDevice = + mAdapter.getRemoteLeDevice( + Utils.BUMBLE_RANDOM_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM); + } + + @After + public void tearDown() throws Exception { + if (mDevice.getBondState() == BluetoothDevice.BOND_BONDED) { + mDevice.removeBond(); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE)); + } + mContext.unregisterReceiver(mReceiver); + } + + /** + * Test OOB pairing: Configuration: Initiator: Locali, Local OOB: No, Remote OOB: Yes ,Secure + * Connections: Yes + * + * <ol> + * <li>1. Android gets OOB Data from Bumble. + * <li>2. Android creates bond with remote OOB data + * <li>5. Android verifies bonded intent + * </ol> + */ + @Test + public void createBondWithRemoteOob() throws Exception { + + startAdvertise(); + OobDataRequest noLocalOobData = + OobDataRequest.newBuilder().setOob(ByteString.EMPTY).build(); + mRemoteOobData = mBumble.oobBlocking().shareOobData(noLocalOobData); + OobData p256 = buildOobData(); + mDevice.createBondOutOfBand(BluetoothDevice.TRANSPORT_LE, null, p256); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDING)); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDED)); + } + + /** + * Test OOB pairing: Configuration: Initiator - Local, Local OOB - Yes, Remote OOB - Yes, Secure + * Connections - Yes + * + * <ol> + * <li>1. Android gets OOB Data from Bumble. + * <li>2. Android creates bond with remote OOB data + * <li>5. Android verifies bonded intent + * </ol> + */ + @Test + public void createBondWithRemoteAndLocalOob() throws Exception { + + startAdvertise(); + mAdapter.generateLocalOobData( + BluetoothDevice.TRANSPORT_LE, mContext.getMainExecutor(), mGenerateOobDataCallback); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDING)); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDED)); + } + + @SafeVarargs + private void verifyIntentReceived(Matcher<Intent>... matchers) { + mInOrder.verify(mReceiver, timeout(INTENT_TIMEOUT.toMillis())) + .onReceive(any(Context.class), MockitoHamcrest.argThat(AllOf.allOf(matchers))); + } +} diff --git a/framework/tests/bumble/src/bumble_server.py b/framework/tests/bumble/src/bumble_server.py index 227d05de14..8f5a39f8f2 100644 --- a/framework/tests/bumble/src/bumble_server.py +++ b/framework/tests/bumble/src/bumble_server.py @@ -26,6 +26,7 @@ from bumble_experimental.gatt import GATTService from bumble_experimental.rfcomm import RFCOMMService from bumble_experimental.avrcp import AvrcpService from bumble_experimental.hid import HIDService +from bumble_experimental.oob import OOBService from pandora_experimental.asha_grpc_aio import add_AshaServicer_to_server from pandora_experimental.dck_grpc_aio import add_DckServicer_to_server @@ -33,6 +34,7 @@ from pandora_experimental.gatt_grpc_aio import add_GATTServicer_to_server from pandora_experimental.rfcomm_grpc_aio import add_RFCOMMServicer_to_server from pandora_experimental.avrcp_grpc_aio import add_AVRCPServicer_to_server from pandora_experimental.hid_grpc_aio import add_HIDServicer_to_server +from pandora_experimental.oob_grpc_aio import add_OOBServicer_to_server from typing import Any, Dict @@ -85,6 +87,8 @@ def register_experimental_services() -> None: lambda bumble, _, server: add_RFCOMMServicer_to_server(RFCOMMService(bumble.device), server)) bumble_server.register_servicer_hook( lambda bumble, _, server: add_HIDServicer_to_server(HIDService(bumble.device), server)) + bumble_server.register_servicer_hook( + lambda bumble, _, server: add_OOBServicer_to_server(OOBService(bumble.device), server)) def retrieve_config(config: str) -> Dict[str, Any]: diff --git a/pandora/interfaces/pandora_experimental/oob.proto b/pandora/interfaces/pandora_experimental/oob.proto new file mode 100644 index 0000000000..e34c444f91 --- /dev/null +++ b/pandora/interfaces/pandora_experimental/oob.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; + +package pandora; + +option java_outer_classname = "OobProto"; + + +service OOB { + // Share OOB data + rpc ShareOobData(OobDataRequest) returns (OobDataResponse); +} + +// Local Device OOB data. +message OobDataRequest { + // OOB data Pairing Hash and Randomizer - 32 bytes. + bytes oob = 1; +} + +// Remote Device OOB data. +message OobDataResponse { + // OOB data Pairing Hash and Randomizer - 32 bytes. + bytes oob = 1; +} + diff --git a/pandora/interfaces/python/Android.bp b/pandora/interfaces/python/Android.bp index 4893f597c2..cffb61990a 100644 --- a/pandora/interfaces/python/Android.bp +++ b/pandora/interfaces/python/Android.bp @@ -66,6 +66,10 @@ genrule { "pandora_experimental/mediaplayer_grpc_aio.py", "pandora_experimental/mediaplayer_pb2.py", "pandora_experimental/mediaplayer_pb2.pyi", + "pandora_experimental/oob_grpc.py", + "pandora_experimental/oob_grpc_aio.py", + "pandora_experimental/oob_pb2.py", + "pandora_experimental/oob_pb2.pyi", "pandora_experimental/opp_grpc.py", "pandora_experimental/opp_grpc_aio.py", "pandora_experimental/opp_pb2.py", @@ -113,6 +117,7 @@ filegroup { ":pandora_experimental-python-gen-src{pandora_experimental/le_audio_pb2.pyi}", ":pandora_experimental-python-gen-src{pandora_experimental/map_pb2.pyi}", ":pandora_experimental-python-gen-src{pandora_experimental/mediaplayer_pb2.pyi}", + ":pandora_experimental-python-gen-src{pandora_experimental/oob_pb2.pyi}", ":pandora_experimental-python-gen-src{pandora_experimental/opp_pb2.pyi}", ":pandora_experimental-python-gen-src{pandora_experimental/os_pb2.pyi}", ":pandora_experimental-python-gen-src{pandora_experimental/pan_pb2.pyi}", diff --git a/pandora/server/bumble_experimental/oob.py b/pandora/server/bumble_experimental/oob.py new file mode 100644 index 0000000000..7fca914ba2 --- /dev/null +++ b/pandora/server/bumble_experimental/oob.py @@ -0,0 +1,53 @@ +from __future__ import annotations +import grpc +import grpc.aio +import logging + +from pandora_experimental.oob_grpc_aio import OOBServicer +from pandora_experimental.oob_pb2 import ( + OobDataRequest, + OobDataResponse, +) + +from bumble.smp import OobContext, OobSharedData +from bumble.pairing import PairingConfig, PairingDelegate +from bumble.device import Device +from bumble.pandora import utils + + +# This class implements the Hid Pandora interface. +class OOBService(OOBServicer): + + def __init__(self, device: Device) -> None: + super().__init__() + self.log = utils.BumbleServerLoggerAdapter(logging.getLogger(), {'service_name': 'oob', 'device': device}) + self.device = device + + def configure_oob_pairing(self, peer_oob: OobSharedData) -> str: + our_oob_context = OobContext() + share_oob = our_oob_context.share().__str__() + self.log.debug(f"Local oob data: {share_oob}") + oob_contexts = PairingConfig.OobConfig(our_context=our_oob_context, peer_data=peer_oob, legacy_context=None) + self.device.pairing_config_factory = lambda connection: PairingConfig( + sc=True, + mitm=True, + bonding=True, + oob=oob_contexts, + ) + + return share_oob + + @utils.rpc + async def ShareOobData(self, request: OobDataRequest, context: grpc.ServicerContext) -> OobDataResponse: + + if request.oob: + data = str(bytes(request.oob).hex()) + oob_c, oob_r = data[:len(data) // 2], data[len(data) // 2:] + peer_oob = OobSharedData(c=bytearray.fromhex(oob_c), r=bytearray.fromhex(oob_r)) + self.log.debug(f'peer oob data {peer_oob}') + else: + peer_oob = None + share_oob = self.configure_oob_pairing(peer_oob) + # Extract data from string `OOB(C=XXXXXXXXXXXXXXXX, R=YYYYYYYYYYYYYYYY)` + extracted_oob = share_oob.strip("OOB()C=").replace(", R=", "") + return OobDataResponse(oob=bytes(bytearray.fromhex(extracted_oob))) diff --git a/service/src/com/android/server/bluetooth/BluetoothManagerService.java b/service/src/com/android/server/bluetooth/BluetoothManagerService.java index 6d61cea76a..bf867fe9f2 100644 --- a/service/src/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/src/com/android/server/bluetooth/BluetoothManagerService.java @@ -84,7 +84,6 @@ import android.util.proto.ProtoOutputStream; import androidx.annotation.RequiresApi; import com.android.bluetooth.flags.Flags; -import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.expresslog.Counter; import com.android.modules.expresslog.Histogram; @@ -116,7 +115,6 @@ import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import java.util.concurrent.locks.ReentrantReadWriteLock; class BluetoothManagerService { private static final String TAG = BluetoothManagerService.class.getSimpleName(); @@ -188,9 +186,6 @@ class BluetoothManagerService { new RemoteCallbackList<IBluetoothManagerCallback>(); private final BluetoothServiceBinder mBinder; - private final ReentrantReadWriteLock mAdapterLock = new ReentrantReadWriteLock(); - - @GuardedBy("mAdapterLock") private AdapterBinder mAdapter = null; // used inside handler thread @@ -267,22 +262,14 @@ class BluetoothManagerService { // Clear registered LE apps to force shut-off Bluetooth clearBleApps(); int state = getState(); - mAdapterLock.readLock().lock(); - try { - if (mAdapter == null) { - return false; - } - if (state == STATE_BLE_ON) { - ActiveLogs.add(ENABLE_DISABLE_REASON_FACTORY_RESET, false); - bleOnToOff(); - return true; - } else if (state == STATE_ON) { - ActiveLogs.add(ENABLE_DISABLE_REASON_FACTORY_RESET, false); - onToBleOn(); - return true; - } - } finally { - mAdapterLock.readLock().unlock(); + if (state == STATE_BLE_ON) { + ActiveLogs.add(ENABLE_DISABLE_REASON_FACTORY_RESET, false); + bleOnToOff(); + return true; + } else if (state == STATE_ON) { + ActiveLogs.add(ENABLE_DISABLE_REASON_FACTORY_RESET, false); + onToBleOn(); + return true; } return false; } @@ -405,31 +392,15 @@ class BluetoothManagerService { } if (currentState == STATE_ON) { - mAdapterLock.readLock().lock(); - try { - if (mAdapter == null) { - return; - } - mEnable = false; - ActiveLogs.add(reason, false); - onToBleOn(); - } finally { - mAdapterLock.readLock().unlock(); - } + mEnable = false; + ActiveLogs.add(reason, false); + onToBleOn(); } else if (currentState == STATE_BLE_ON) { // If currentState is BLE_ON make sure we trigger stopBle - mAdapterLock.readLock().lock(); - try { - if (mAdapter == null) { - return; - } - mEnable = false; - mEnableExternal = false; - ActiveLogs.add(reason, false); - bleOnToOff(); - } finally { - mAdapterLock.readLock().unlock(); - } + mEnable = false; + mEnableExternal = false; + ActiveLogs.add(reason, false); + bleOnToOff(); } } @@ -544,20 +515,12 @@ class BluetoothManagerService { } else if (action.equals(Intent.ACTION_SHUTDOWN)) { Log.i(TAG, "Device is shutting down."); mShutdownInProgress = true; - mAdapterLock.readLock().lock(); - try { - mEnable = false; - mEnableExternal = false; - if (mAdapter == null) { - return; - } - if (mState.oneOf(STATE_BLE_ON)) { - bleOnToOff(); - } else if (mState.oneOf(STATE_ON)) { - onToBleOn(); - } - } finally { - mAdapterLock.readLock().unlock(); + mEnable = false; + mEnableExternal = false; + if (mState.oneOf(STATE_BLE_ON)) { + bleOnToOff(); + } else if (mState.oneOf(STATE_ON)) { + onToBleOn(); } } } @@ -781,11 +744,14 @@ class BluetoothManagerService { Log.d(TAG, logHeader + "Completed successfully"); } + // Called from unsafe binder thread IBluetooth registerAdapter(IBluetoothManagerCallback callback) { synchronized (mCallbacks) { mCallbacks.register(callback); } - return mAdapter != null ? mAdapter.getAdapterBinder() : null; + // Copy to local variable to avoid race condition when checking for null + AdapterBinder adapter = mAdapter; + return adapter != null ? adapter.getAdapterBinder() : null; } void unregisterAdapter(IBluetoothManagerCallback callback) { @@ -805,15 +771,13 @@ class BluetoothManagerService { * @param userId is the foreground user id we are propagating to the Bluetooth process */ private void propagateForegroundUserId(int userId) { - mAdapterLock.readLock().lock(); + if (mAdapter == null) { + return; + } try { - if (mAdapter != null) { - mAdapter.setForegroundUserId(userId, mContext.getAttributionSource()); - } + mAdapter.setForegroundUserId(userId, mContext.getAttributionSource()); } catch (RemoteException e) { Log.e(TAG, "Unable to set foreground user id", e); - } finally { - mAdapterLock.readLock().unlock(); } } @@ -875,7 +839,7 @@ class BluetoothManagerService { } boolean isMediaProfileConnected() { - if (mAdapter == null || !mState.oneOf(STATE_ON)) { + if (!mState.oneOf(STATE_ON)) { return false; } return mAdapter.isMediaProfileConnected(mContext.getAttributionSource()); @@ -894,14 +858,9 @@ class BluetoothManagerService { // BLE scan is not available. disableBleScanMode(); clearBleApps(); - mAdapterLock.readLock().lock(); - try { - if (mAdapter != null) { - ActiveLogs.add(ENABLE_DISABLE_REASON_APPLICATION_REQUEST, false); - bleOnToOff(); - } - } finally { - mAdapterLock.readLock().unlock(); + if (mState.oneOf(STATE_BLE_ON)) { + ActiveLogs.add(ENABLE_DISABLE_REASON_APPLICATION_REQUEST, false); + bleOnToOff(); } } }; @@ -914,14 +873,9 @@ class BluetoothManagerService { // Disable ble scan only mode. private void disableBleScanMode() { - mAdapterLock.writeLock().lock(); - try { - if (mAdapter != null && mState.oneOf(STATE_ON)) { - Log.d(TAG, "disableBleScanMode: Resetting the mEnable flag for clean disable"); - mEnable = false; - } - } finally { - mAdapterLock.writeLock().unlock(); + if (mState.oneOf(STATE_ON)) { + Log.d(TAG, "disableBleScanMode: Resetting the mEnable flag for clean disable"); + mEnable = false; } } @@ -1045,30 +999,25 @@ class BluetoothManagerService { * BLE should be off */ private void continueFromBleOnState() { - mAdapterLock.readLock().lock(); - try { - if (mAdapter == null) { - Log.e(TAG, "continueFromBleOnState: Adapter is null"); - return; - } - if (!mEnableExternal && !isBleAppPresent()) { - // TODO(b/262605980): this code is unlikely to be trigger and will never be once - // enableBle & disableBle are executed on the handler - Log.i(TAG, "continueFromBleOnState: Disabled while enabling BLE, disable BLE now"); - mEnable = false; - bleOnToOff(); - return; - } - if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { - Log.i(TAG, "continueFromBleOnState: Starting br edr"); - // This triggers transition to STATE_ON - bleOnToOn(); - setBluetoothPersistedState(BLUETOOTH_ON_BLUETOOTH); - } else { - Log.i(TAG, "continueFromBleOnState: Staying in BLE_ON"); - } - } finally { - mAdapterLock.readLock().unlock(); + if (!mState.oneOf(STATE_BLE_ON)) { + Log.e(TAG, "continueFromBleOnState: Impossible transition from " + mState); + return; + } + if (!mEnableExternal && !isBleAppPresent()) { + // TODO(b/262605980): this code is unlikely to be trigger and will never be once + // enableBle & disableBle are executed on the handler + Log.i(TAG, "continueFromBleOnState: Disabled while enabling BLE, disable BLE now"); + mEnable = false; + bleOnToOff(); + return; + } + if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { + Log.i(TAG, "continueFromBleOnState: Starting br edr"); + // This triggers transition to STATE_ON + bleOnToOn(); + setBluetoothPersistedState(BLUETOOTH_ON_BLUETOOTH); + } else { + Log.i(TAG, "continueFromBleOnState: Staying in BLE_ON"); } } @@ -1077,26 +1026,23 @@ class BluetoothManagerService { * if no LE app needs it */ private void sendBrEdrDownCallback() { - mAdapterLock.readLock().lock(); - try { - if (mAdapter == null) { - Log.w(TAG, "sendBrEdrDownCallback: mAdapter is null"); - return; - } - boolean scanIsAllowed = - !Flags.respectBleScanSetting() || BleScanSettingListener.isScanAllowed(); - if (!AirplaneModeListener.isOn() && isBleAppPresent() && scanIsAllowed) { - // Need to stay at BLE ON. Disconnect all Gatt connections - Log.i(TAG, "sendBrEdrDownCallback: Staying in BLE_ON"); + if (mAdapter == null) { + Log.d(TAG, "sendBrEdrDownCallback: mAdapter is null"); + return; + } + boolean scanIsAllowed = + !Flags.respectBleScanSetting() || BleScanSettingListener.isScanAllowed(); + if (!AirplaneModeListener.isOn() && isBleAppPresent() && scanIsAllowed) { + // Need to stay at BLE ON. Disconnect all Gatt connections + Log.i(TAG, "sendBrEdrDownCallback: Staying in BLE_ON"); + try { mAdapter.unregAllGattClient(mContext.getAttributionSource()); - } else { - Log.i(TAG, "sendBrEdrDownCallback: Stopping ble"); - bleOnToOff(); + } catch (RemoteException e) { + Log.e(TAG, "sendBrEdrDownCallback: failed to call unregAllGattClient()", e); } - } catch (RemoteException e) { - Log.e(TAG, "sendBrEdrDownCallback: Call to mAdapter failed.", e); - } finally { - mAdapterLock.readLock().unlock(); + } else { + Log.i(TAG, "sendBrEdrDownCallback: Stopping ble"); + bleOnToOff(); } } @@ -1187,67 +1133,59 @@ class BluetoothManagerService { void unbindAndFinish() { Log.d(TAG, "unbindAndFinish(): mAdapter=" + mAdapter + " isBinding=" + isBinding()); - mAdapterLock.writeLock().lock(); - try { - mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); - if (mAdapter == null) { - return; - } - long currentTimeMs = System.currentTimeMillis(); + mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); + long currentTimeMs = System.currentTimeMillis(); - try { - mAdapter.unregisterCallback(mBluetoothCallback, mContext.getAttributionSource()); - } catch (RemoteException e) { - Log.e(TAG, "Unable to unregister BluetoothCallback", e); - } + try { + mAdapter.unregisterCallback(mBluetoothCallback, mContext.getAttributionSource()); + } catch (RemoteException e) { + Log.e(TAG, "unbindAndFinish(): Unable to unregister BluetoothCallback", e); + } - CompletableFuture<Void> binderDead = new CompletableFuture<>(); - try { - mAdapter.getAdapterBinder() - .asBinder() - .linkToDeath( - () -> { - Log.i(TAG, "Successfully received Bluetooth death"); - binderDead.complete(null); - }, - 0); - } catch (RemoteException e) { - Log.e(TAG, "Failed to linkToDeath", e); - binderDead.complete(null); - } + CompletableFuture<Void> binderDead = new CompletableFuture<>(); + try { + mAdapter.getAdapterBinder() + .asBinder() + .linkToDeath( + () -> { + Log.i(TAG, "Successfully received Bluetooth death"); + binderDead.complete(null); + }, + 0); + } catch (RemoteException e) { + Log.e(TAG, "unbindAndFinish(): Failed to linkToDeath", e); + binderDead.complete(null); + } - // Unbind first to avoid receiving unwanted "onServiceDisconnected" - mContext.unbindService(mConnection); + // Unbind first to avoid receiving unwanted "onServiceDisconnected" + mContext.unbindService(mConnection); - try { - // Force kill Bluetooth to make sure its process is not reused. - // Note: In a perfect world, we should be able to re-init the same process. - // Unfortunately, this requires an heavy rework of the Bluetooth app - // TODO: b/339501753 - Properly stop Bluetooth without killing it - mAdapter.killBluetoothProcess(); - - binderDead.get(2_000, TimeUnit.MILLISECONDS); - } catch (android.os.DeadObjectException e) { - // Reduce exception to info and skip waiting (Bluetooth is dead as wanted) - Log.i(TAG, "Bluetooth already dead 💀"); - } catch (RemoteException e) { - Log.e(TAG, "Unexpected RemoteException when calling killBluetoothProcess", e); - } catch (TimeoutException | InterruptedException | ExecutionException e) { - Log.e(TAG, "Bluetooth death not received correctly after > 2000ms", e); - } + try { + // Force kill Bluetooth to make sure its process is not reused. + // Note: In a perfect world, we should be able to re-init the same process. + // Unfortunately, this requires an heavy rework of the Bluetooth app + // TODO: b/339501753 - Properly stop Bluetooth without killing it + mAdapter.killBluetoothProcess(); + + binderDead.get(2_000, TimeUnit.MILLISECONDS); + } catch (android.os.DeadObjectException e) { + // Reduce exception to info and skip waiting (Bluetooth is dead as wanted) + Log.i(TAG, "unbindAndFinish(): Bluetooth already dead 💀"); + } catch (RemoteException e) { + Log.e(TAG, "unbindAndFinish(): Unable to call killBluetoothProcess", e); + } catch (TimeoutException | InterruptedException | ExecutionException e) { + Log.e(TAG, "unbindAndFinish(): Bluetooth death not received after > 2000ms", e); + } - long timeSpentForShutdown = System.currentTimeMillis() - currentTimeMs; - mShutdownLatencyHistogram.logSample((float) timeSpentForShutdown); + long timeSpentForShutdown = System.currentTimeMillis() - currentTimeMs; + mShutdownLatencyHistogram.logSample((float) timeSpentForShutdown); - // TODO: b/356931756 - Remove sleep - Log.d(TAG, "Force sleep 100 ms for propagating Bluetooth app death"); - SystemClock.sleep(100); // required to let the ActivityManager be notified of BT death + // TODO: b/356931756 - Remove sleep + Log.d(TAG, "Force sleep 100 ms for propagating Bluetooth app death"); + SystemClock.sleep(100); // required to let the ActivityManager be notified of BT death - mAdapter = null; - mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); - } finally { - mAdapterLock.writeLock().unlock(); - } + mAdapter = null; // Don't call resetAdapter as we already call unbindService + mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); } /** @@ -1349,58 +1287,47 @@ class BluetoothManagerService { /** Inform BluetoothAdapter instances that Adapter service is up */ private void sendBluetoothServiceUpCallback() { synchronized (mCallbacks) { - mAdapterLock.readLock().lock(); - try { - int n = mCallbacks.beginBroadcast(); - Log.d(TAG, "sendBluetoothServiceUpCallback(): to " + n + " receivers"); - for (int i = 0; i < n; i++) { - try { - mCallbacks - .getBroadcastItem(i) - .onBluetoothServiceUp(mAdapter.getAdapterBinder().asBinder()); - } catch (RemoteException e) { - Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); - } + int n = mCallbacks.beginBroadcast(); + Log.d(TAG, "sendBluetoothServiceUpCallback(): to " + n + " receivers"); + for (int i = 0; i < n; i++) { + try { + mCallbacks + .getBroadcastItem(i) + .onBluetoothServiceUp(mAdapter.getAdapterBinder().asBinder()); + } catch (RemoteException e) { + Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); } - } finally { - mCallbacks.finishBroadcast(); - mAdapterLock.readLock().unlock(); } + mCallbacks.finishBroadcast(); } } /** Inform BluetoothAdapter instances that Adapter service is down */ private void sendBluetoothServiceDownCallback() { synchronized (mCallbacks) { - try { - int n = mCallbacks.beginBroadcast(); - Log.d(TAG, "sendBluetoothServiceDownCallback(): to " + n + " receivers"); - for (int i = 0; i < n; i++) { - try { - mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); - } catch (RemoteException e) { - Log.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); - } + int n = mCallbacks.beginBroadcast(); + Log.d(TAG, "sendBluetoothServiceDownCallback(): to " + n + " receivers"); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); + } catch (RemoteException e) { + Log.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); } - } finally { - mCallbacks.finishBroadcast(); } + mCallbacks.finishBroadcast(); } } + // Called from unsafe binder thread String getAddress() { - mAdapterLock.readLock().lock(); - try { - if (mAdapter != null) { + // Copy to local variable to avoid race condition when checking for null + AdapterBinder adapter = mAdapter; + if (adapter != null) { + try { return mAdapter.getAddress(mContext.getAttributionSource()); + } catch (RemoteException e) { + Log.e(TAG, "getAddress(): Returning cached address", e); } - } catch (RemoteException e) { - Log.e( - TAG, - "getAddress(): Unable to retrieve address remotely. Returning cached address", - e); - } finally { - mAdapterLock.readLock().unlock(); } // mAddress is accessed from outside. @@ -1409,16 +1336,16 @@ class BluetoothManagerService { return mAddress; } + // Called from unsafe binder thread String getName() { - mAdapterLock.readLock().lock(); - try { - if (mAdapter != null) { + // Copy to local variable to avoid race condition when checking for null + AdapterBinder adapter = mAdapter; + if (adapter != null) { + try { return mAdapter.getName(mContext.getAttributionSource()); + } catch (RemoteException e) { + Log.e(TAG, "getName(): Returning cached name", e); } - } catch (RemoteException e) { - Log.e(TAG, "getName(): Unable to retrieve name remotely. Returning cached name", e); - } finally { - mAdapterLock.readLock().unlock(); } // mName is accessed from outside. @@ -1468,27 +1395,22 @@ class BluetoothManagerService { switch (msg.what) { case MESSAGE_GET_NAME_AND_ADDRESS: Log.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS"); - mAdapterLock.writeLock().lock(); - try { - if (mAdapter == null && !isBinding()) { - Log.d(TAG, "Binding to service to get name and address"); - mGetNameAddressOnly = true; - bindToAdapter(); - } else if (mAdapter != null) { - try { - storeNameAndAddress( - mAdapter.getName(mContext.getAttributionSource()), - mAdapter.getAddress(mContext.getAttributionSource())); - } catch (RemoteException e) { - Log.e(TAG, "Unable to grab names", e); - } - if (mGetNameAddressOnly && !mEnable) { - unbindAndFinish(); - } - mGetNameAddressOnly = false; + if (mAdapter == null && !isBinding()) { + Log.d(TAG, "Binding to service to get name and address"); + mGetNameAddressOnly = true; + bindToAdapter(); + } else if (mAdapter != null) { + try { + storeNameAndAddress( + mAdapter.getName(mContext.getAttributionSource()), + mAdapter.getAddress(mContext.getAttributionSource())); + } catch (RemoteException e) { + Log.e(TAG, "Unable to grab name or address", e); + } + if (mGetNameAddressOnly && !mEnable) { + unbindAndFinish(); } - } finally { - mAdapterLock.writeLock().unlock(); + mGetNameAddressOnly = false; } break; @@ -1600,42 +1522,36 @@ class BluetoothManagerService { IBinder service = (IBinder) msg.obj; Log.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_CONNECTED: service=" + service); - mAdapterLock.writeLock().lock(); - try { - // Remove timeout - mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); + // Remove timeout + mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); - mAdapter = BluetoothServerProxy.getInstance().createAdapterBinder(service); + mAdapter = BluetoothServerProxy.getInstance().createAdapterBinder(service); - int foregroundUserId = ActivityManager.getCurrentUser(); - propagateForegroundUserId(foregroundUserId); + propagateForegroundUserId(ActivityManager.getCurrentUser()); - if (!isNameAndAddressSet()) { - mHandler.sendEmptyMessage(MESSAGE_GET_NAME_AND_ADDRESS); - if (mGetNameAddressOnly) { - return; - } + if (!isNameAndAddressSet()) { + mHandler.sendEmptyMessage(MESSAGE_GET_NAME_AND_ADDRESS); + if (mGetNameAddressOnly) { + return; } + } - // Register callback object - try { - mAdapter.registerCallback( - mBluetoothCallback, mContext.getAttributionSource()); - } catch (RemoteException e) { - Log.e(TAG, "Unable to register BluetoothCallback", e); - } - // Inform BluetoothAdapter instances that service is up - if (!Flags.fastBindToApp()) { - sendBluetoothServiceUpCallback(); - } + // Register callback object + try { + mAdapter.registerCallback( + mBluetoothCallback, mContext.getAttributionSource()); + } catch (RemoteException e) { + Log.e(TAG, "Unable to register BluetoothCallback", e); + } + // Inform BluetoothAdapter instances that service is up + if (!Flags.fastBindToApp()) { + sendBluetoothServiceUpCallback(); + } - // Do enable request - offToBleOn(); - if (Flags.fastBindToApp()) { - sendBluetoothServiceUpCallback(); - } - } finally { - mAdapterLock.writeLock().unlock(); + // Do enable request + offToBleOn(); + if (Flags.fastBindToApp()) { + sendBluetoothServiceUpCallback(); } if (!mEnable) { @@ -1657,13 +1573,11 @@ class BluetoothManagerService { // unbind and rebind bluetooth service and enable bluetooth if ((prevState == STATE_BLE_TURNING_ON) && (newState == STATE_OFF) - && (mAdapter != null) && mEnable) { recoverBluetoothServiceFromError(false); } if ((prevState == STATE_TURNING_ON) && (newState == STATE_BLE_ON) - && (mAdapter != null) && mEnable) { recoverBluetoothServiceFromError(true); } @@ -1689,16 +1603,9 @@ class BluetoothManagerService { case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: Log.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED"); - mAdapterLock.writeLock().lock(); - try { - // if service is unbinded already, do nothing and return - if (mAdapter == null) { - break; - } - mContext.unbindService(mConnection); - mAdapter = null; - } finally { - mAdapterLock.writeLock().unlock(); + + if (!resetAdapter()) { + break; } // log the unexpected crash @@ -1737,11 +1644,9 @@ class BluetoothManagerService { * service restarts */ mEnable = true; ActiveLogs.add(ENABLE_DISABLE_REASON_RESTARTED, true); - handleEnable(mQuietEnable); + handleEnable(); } else { - mAdapterLock.writeLock().lock(); - mAdapter = null; - mAdapterLock.writeLock().unlock(); + resetAdapter(); Log.e(TAG, "Reach maximum retry to restart Bluetooth!"); } break; @@ -1762,7 +1667,7 @@ class BluetoothManagerService { mCurrentUserContext = mContext.createContextAsUser(userTo, 0); /* disable and enable BT when detect a user switch */ - if (mAdapter != null && mState.oneOf(STATE_ON)) { + if (mState.oneOf(STATE_ON)) { restartForNewUser(userTo); } else if (isBinding() || mAdapter != null) { Message userMsg = Message.obtain(msg); @@ -1790,28 +1695,19 @@ class BluetoothManagerService { // reason; maybe the Bluetooth service wasn't encryption // aware, so try binding again. Log.d(TAG, "Enabled but not bound; retrying after unlock"); - handleEnable(mQuietEnable); + handleEnable(); } break; } } private void restartForNewUser(UserHandle unusedNewUser) { - mAdapterLock.readLock().lock(); try { - if (mAdapter != null) { - mAdapter.unregisterCallback( - mBluetoothCallback, mContext.getAttributionSource()); - } + mAdapter.unregisterCallback(mBluetoothCallback, mContext.getAttributionSource()); } catch (RemoteException e) { Log.e(TAG, "Unable to unregister", e); - } finally { - mAdapterLock.readLock().unlock(); } - // This method is always called while bluetooth is in STATE_ON - assert (mState.oneOf(STATE_ON)); - // disable ActiveLogs.add(ENABLE_DISABLE_REASON_USER_SWITCH, false); onToBleOn(); @@ -1840,7 +1736,7 @@ class BluetoothManagerService { ActiveLogs.add(ENABLE_DISABLE_REASON_USER_SWITCH, true); // mEnable flag could have been reset on stopBle. Reenable it. mEnable = true; - handleEnable(mQuietEnable); + handleEnable(); } } @@ -1870,59 +1766,43 @@ class BluetoothManagerService { setBluetoothPersistedState(BLUETOOTH_ON_BLUETOOTH); } - // Use service interface to get the exact state - mAdapterLock.readLock().lock(); - try { - if (mAdapter != null) { - boolean isHandled = true; - switch (mState.get()) { - case STATE_BLE_ON: - if (isBle == 1) { - Log.i(TAG, "Already at BLE_ON State"); - } else { - Log.w(TAG, "BT Enable in BLE_ON State, going to ON"); - bleOnToOn(); - } - break; - case STATE_BLE_TURNING_ON: - case STATE_TURNING_ON: - case STATE_ON: - Log.i(TAG, "MESSAGE_ENABLE: already enabled"); - break; - default: - isHandled = false; - break; - } - if (isHandled) return; - } - } finally { - mAdapterLock.readLock().unlock(); + if (mState.oneOf(STATE_BLE_TURNING_ON, STATE_TURNING_ON, STATE_ON)) { + Log.i(TAG, "MESSAGE_ENABLE: already enabled. Current state=" + mState); + return; } - mQuietEnable = (quietEnable == 1); - if (mAdapter == null) { - handleEnable(mQuietEnable); - } else { + if (mState.oneOf(STATE_BLE_ON) && isBle == 1) { + Log.i(TAG, "MESSAGE_ENABLE: Already in BLE_ON while being requested to go to BLE_ON"); + return; + } + + if (mState.oneOf(STATE_BLE_ON)) { + Log.i(TAG, "MESSAGE_ENABLE: Bluetooth transition from STATE_BLE_ON to STATE_ON"); + bleOnToOn(); + return; + } + + if (mAdapter != null) { + // TODO: b/339548431 - Adapt this after removal of Flags.explicitKillFromSystemServer // - // We need to wait until transitioned to STATE_OFF and - // the previous Bluetooth process has exited. The - // waiting period has three components: - // (a) Wait until the local state is STATE_OFF. This - // is accomplished by sending delay a message - // MESSAGE_HANDLE_ENABLE_DELAYED - // (b) Wait until the STATE_OFF state is updated to - // all components. - // (c) Wait until the Bluetooth process exits, and - // ActivityManager detects it. - // The waiting for (b) and (c) is accomplished by - // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE - // message. The delay time is backed off if Bluetooth - // continuously failed to turn on itself. + // We need to wait until transitioned to STATE_OFF and the previous Bluetooth process + // has exited. The waiting period has three components: + // (a) Wait until the local state is STATE_OFF. This is accomplished by sending delay a + // message MESSAGE_HANDLE_ENABLE_DELAYED + // (b) Wait until the STATE_OFF state is updated to all components. + // (c) Wait until the Bluetooth process exits, and ActivityManager detects it. // + // The waiting for (b) and (c) is accomplished by delaying the + // MESSAGE_RESTART_BLUETOOTH_SERVICE message. The delay time is backed off if Bluetooth + // continuously failed to turn on itself. mWaitForEnableRetry = 0; mHandler.sendEmptyMessageDelayed( MESSAGE_HANDLE_ENABLE_DELAYED, ENABLE_DISABLE_DELAY_MS); + return; } + + mQuietEnable = (quietEnable == 1); + handleEnable(); } private void handleDisableMessage() { @@ -1966,19 +1846,21 @@ class BluetoothManagerService { } } - private void handleEnable(boolean quietMode) { - mQuietEnable = quietMode; + private boolean resetAdapter() { + if (mAdapter == null) { + return false; + } + mAdapter = null; + mContext.unbindService(mConnection); + return true; + } - mAdapterLock.writeLock().lock(); - try { - if (mAdapter == null && !isBinding()) { - bindToAdapter(); - } else if (!Flags.fastBindToApp() && mAdapter != null) { - // Enable bluetooth - offToBleOn(); - } - } finally { - mAdapterLock.writeLock().unlock(); + private void handleEnable() { + if (mAdapter == null && !isBinding()) { + bindToAdapter(); + } else if (!Flags.fastBindToApp() && mAdapter != null) { + // Enable bluetooth + offToBleOn(); } } @@ -2157,16 +2039,13 @@ class BluetoothManagerService { mHandler.removeCallbacksAndMessages(ON_AIRPLANE_MODE_CHANGED_TOKEN); repeatAirplaneRunnable = true; } - mAdapterLock.readLock().lock(); - try { - if (mAdapter != null) { - // Unregister callback object + + if (mAdapter != null) { + try { mAdapter.unregisterCallback(mBluetoothCallback, mContext.getAttributionSource()); + } catch (RemoteException e) { + Log.e(TAG, "Unable to unregister", e); } - } catch (RemoteException e) { - Log.e(TAG, "Unable to unregister", e); - } finally { - mAdapterLock.readLock().unlock(); } Log.d(TAG, "Force sleep 500 ms for recovering from error"); @@ -2180,16 +2059,7 @@ class BluetoothManagerService { sendBluetoothServiceDownCallback(); - mAdapterLock.writeLock().lock(); - try { - if (mAdapter != null) { - mAdapter = null; - // Unbind - mContext.unbindService(mConnection); - } - } finally { - mAdapterLock.writeLock().unlock(); - } + resetAdapter(); mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); mState.set(STATE_OFF); @@ -2566,42 +2436,22 @@ class BluetoothManagerService { this::enableFromAutoOn))); } - /** - * Check if BLE is supported by this platform - * - * @param context current device context - * @return true if BLE is supported, false otherwise - */ + /** Check if BLE is supported by this platform */ private static boolean isBleSupported(Context context) { return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE); } - /** - * Check if this is an automotive device - * - * @param context current device context - * @return true if this Android device is an automotive device, false otherwise - */ + /** Check if this is an automotive device */ private static boolean isAutomotive(Context context) { return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); } - /** - * Check if this is a watch device - * - * @param context current device context - * @return true if this Android device is a watch device, false otherwise - */ + /** Check if this is a watch device */ private static boolean isWatch(Context context) { return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH); } - /** - * Check if this is a TV device - * - * @param context current device context - * @return true if this Android device is a TV device, false otherwise - */ + /** Check if this is a TV device */ private static boolean isTv(Context context) { PackageManager pm = context.getPackageManager(); return pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION) diff --git a/system/bta/Android.bp b/system/bta/Android.bp index 8d05b06336..2a045eb947 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -41,7 +41,6 @@ filegroup { "dm/bta_dm_ci.cc", "dm/bta_dm_device_search.cc", "dm/bta_dm_disc.cc", - "dm/bta_dm_disc_legacy.cc", "dm/bta_dm_disc_sdp.cc", "dm/bta_dm_gatt_client.cc", "dm/bta_dm_main.cc", diff --git a/system/bta/BUILD.gn b/system/bta/BUILD.gn index f8009f830d..306aaae1e9 100644 --- a/system/bta/BUILD.gn +++ b/system/bta/BUILD.gn @@ -45,7 +45,6 @@ static_library("bta") { "dm/bta_dm_ci.cc", "dm/bta_dm_device_search.cc", "dm/bta_dm_disc.cc", - "dm/bta_dm_disc_legacy.cc", "dm/bta_dm_disc_sdp.cc", "dm/bta_dm_gatt_client.cc", "dm/bta_dm_main.cc", diff --git a/system/bta/av/bta_av_aact.cc b/system/bta/av/bta_av_aact.cc index a263d9b336..b6ade3ff1d 100644 --- a/system/bta/av/bta_av_aact.cc +++ b/system/bta/av/bta_av_aact.cc @@ -56,7 +56,6 @@ #include "stack/include/btm_client_interface.h" #include "stack/include/btm_log_history.h" #include "stack/include/btm_status.h" -#include "stack/include/l2c_api.h" #include "stack/include/l2cap_interface.h" #include "storage/config_keys.h" #include "types/hci_role.h" @@ -2592,16 +2591,17 @@ void bta_av_rcfg_str_ok(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) { if (com::android::bluetooth::flags::fix_avdt_rconfig_not_setting_l2cap()) { /* Set the media channel as high priority */ - if (!L2CA_SetTxPriority(p_scb->l2c_cid, L2CAP_CHNL_PRIORITY_HIGH)) { + if (!stack::l2cap::get_interface().L2CA_SetTxPriority(p_scb->l2c_cid, + L2CAP_CHNL_PRIORITY_HIGH)) { log::warn("Unable to set L2CAP Tx priority peer:{} cid:{}", p_scb->PeerAddress(), p_scb->l2c_cid); } - if (!L2CA_SetChnlFlushability(p_scb->l2c_cid, true)) { + if (!stack::l2cap::get_interface().L2CA_SetChnlFlushability(p_scb->l2c_cid, true)) { log::warn("Unable to set L2CAP flush peer:{} cid:{}", p_scb->PeerAddress(), p_scb->l2c_cid); } - L2CA_SetMediaStreamChannel(p_scb->l2c_cid, true); + stack::l2cap::get_interface().L2CA_SetMediaStreamChannel(p_scb->l2c_cid, true); } /* rc listen */ diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc index bcf0dcbfc1..237da0097d 100644 --- a/system/bta/dm/bta_dm_act.cc +++ b/system/bta/dm/bta_dm_act.cc @@ -319,12 +319,9 @@ void bta_dm_disable() { bta_dm_disable_pm(); } - if (com::android::bluetooth::flags::separate_service_and_device_discovery()) { - bta_dm_disc_disable_search(); - bta_dm_disc_disable_disc(); - } else { - bta_dm_disc_disable_search_and_disc(); - } + bta_dm_disc_disable_search(); + bta_dm_disc_disable_disc(); + bta_dm_cb.disabling = true; connection_manager::reset(false); @@ -574,6 +571,10 @@ void bta_dm_remove_device(const RawAddress& target) { RawAddress identity_addr = target; bool le_connected = get_btm_client_interface().peer.BTM_ReadConnectedTransportAddress( &pseudo_addr, BT_TRANSPORT_LE); + if (pseudo_addr.IsEmpty()) { + pseudo_addr = target; + } + bool bredr_connected = get_btm_client_interface().peer.BTM_ReadConnectedTransportAddress( &identity_addr, BT_TRANSPORT_BR_EDR); /* If connection not found with identity address, check with pseudo address if different */ @@ -582,9 +583,6 @@ void bta_dm_remove_device(const RawAddress& target) { bredr_connected = get_btm_client_interface().peer.BTM_ReadConnectedTransportAddress( &identity_addr, BT_TRANSPORT_BR_EDR); } - if (pseudo_addr.IsEmpty()) { - pseudo_addr = target; - } if (identity_addr.IsEmpty()) { identity_addr = target; } @@ -889,8 +887,6 @@ static void bta_dm_acl_down_(const RawAddress& bd_addr, tBT_TRANSPORT transport) bta_dm_cb.device_list.le_count--; } - bta_dm_disc_acl_down(bd_addr, transport); - if (bta_dm_cb.disabling) { if (!BTM_GetNumAclLinks()) { /* @@ -952,7 +948,6 @@ static void bta_dm_acl_down(const RawAddress& bd_addr, tBT_TRANSPORT transport) bta_dm_cb.device_list.le_count--; } - bta_dm_disc_acl_down(bd_addr, transport); if (bta_dm_cb.disabling && !BTM_GetNumAclLinks()) { /* * Start a timer to make sure that the profiles diff --git a/system/bta/dm/bta_dm_device_search.cc b/system/bta/dm/bta_dm_device_search.cc index 9f8769fe9c..bc3fde0d91 100644 --- a/system/bta/dm/bta_dm_device_search.cc +++ b/system/bta/dm/bta_dm_device_search.cc @@ -30,7 +30,6 @@ #include <vector> #include "bta/dm/bta_dm_device_search_int.h" -#include "bta/dm/bta_dm_disc_legacy.h" #include "common/circular_buffer.h" #include "common/strings.h" #include "device/include/interop.h" @@ -67,7 +66,6 @@ static bool bta_dm_read_remote_device_name(const RawAddress& bd_addr, tBT_TRANSP static void bta_dm_discover_name(const RawAddress& remote_bd_addr); static void bta_dm_execute_queued_search_request(); static void bta_dm_search_cancel_notify(); -static void bta_dm_disable_search(); static void bta_dm_search_sm_execute(tBTA_DM_DEV_SEARCH_EVT event, std::unique_ptr<tBTA_DM_SEARCH_MSG> msg); @@ -89,14 +87,6 @@ static void post_search_evt(tBTA_DM_DEV_SEARCH_EVT event, std::unique_ptr<tBTA_D } } -void bta_dm_disc_disable_search() { - if (!com::android::bluetooth::flags::separate_service_and_device_discovery()) { - log::info("no-op when flag is disabled"); - return; - } - bta_dm_disable_search(); -} - /******************************************************************************* * * Function bta_dm_search_start @@ -559,12 +549,7 @@ static void bta_dm_discover_name(const RawAddress& remote_bd_addr) { * Returns bool * ******************************************************************************/ -bool bta_dm_is_search_request_queued() { - if (!com::android::bluetooth::flags::separate_service_and_device_discovery()) { - return bta_dm_disc_legacy::bta_dm_is_search_request_queued(); - } - return bta_dm_search_cb.p_pending_search != NULL; -} +bool bta_dm_is_search_request_queued() { return bta_dm_search_cb.p_pending_search != NULL; } /******************************************************************************* * @@ -869,7 +854,7 @@ static void bta_dm_search_sm_execute(tBTA_DM_DEV_SEARCH_EVT event, } } -static void bta_dm_disable_search(void) { +void bta_dm_disc_disable_search(void) { switch (bta_dm_search_get_state()) { case BTA_DM_SEARCH_IDLE: break; @@ -885,19 +870,11 @@ static void bta_dm_disable_search(void) { } void bta_dm_disc_start_device_discovery(tBTA_DM_SEARCH_CBACK* p_cback) { - if (!com::android::bluetooth::flags::separate_service_and_device_discovery()) { - bta_dm_disc_legacy::bta_dm_disc_start_device_discovery(p_cback); - return; - } bta_dm_search_sm_execute(BTA_DM_API_SEARCH_EVT, std::make_unique<tBTA_DM_SEARCH_MSG>( tBTA_DM_API_SEARCH{.p_cback = p_cback})); } void bta_dm_disc_stop_device_discovery() { - if (!com::android::bluetooth::flags::separate_service_and_device_discovery()) { - bta_dm_disc_legacy::bta_dm_disc_stop_device_discovery(); - return; - } bta_dm_search_sm_execute(BTA_DM_API_SEARCH_CANCEL_EVT, nullptr); } @@ -911,28 +888,12 @@ static void bta_dm_search_reset() { bta_dm_disc_init_search_cb(::bta_dm_search_cb); } -void bta_dm_search_stop() { - if (!com::android::bluetooth::flags::separate_service_and_device_discovery()) { - log::info("no-op when flag is disabled"); - return; - } - bta_dm_search_reset(); -} +void bta_dm_search_stop() { bta_dm_search_reset(); } -void bta_dm_disc_discover_next_device() { - if (!com::android::bluetooth::flags::separate_service_and_device_discovery()) { - bta_dm_disc_legacy::bta_dm_disc_discover_next_device(); - return; - } - bta_dm_discover_next_device(); -} +void bta_dm_disc_discover_next_device() { bta_dm_discover_next_device(); } #define DUMPSYS_TAG "shim::legacy::bta::dm" void DumpsysBtaDmSearch(int fd) { - if (!com::android::bluetooth::flags::separate_service_and_device_discovery()) { - log::info("no-op when flag is disabled"); - return; - } auto copy = search_state_history_.Pull(); LOG_DUMPSYS(fd, " last %zu search state transitions", copy.size()); for (const auto& it : copy) { diff --git a/system/bta/dm/bta_dm_disc.cc b/system/bta/dm/bta_dm_disc.cc index aa82c80f59..c84c0f4388 100644 --- a/system/bta/dm/bta_dm_disc.cc +++ b/system/bta/dm/bta_dm_disc.cc @@ -30,7 +30,6 @@ #include <vector> #include "bta/dm/bta_dm_disc_int.h" -#include "bta/dm/bta_dm_disc_legacy.h" #include "bta/include/bta_gatt_api.h" #include "common/circular_buffer.h" #include "common/strings.h" @@ -93,8 +92,6 @@ static void post_disc_evt(tBTA_DM_DISC_EVT event, std::unique_ptr<tBTA_DM_MSG> m } static void bta_dm_gatt_disc_complete(uint16_t conn_id, tGATT_STATUS status); -static void bta_dm_disable_disc(void); -static void bta_dm_gattc_register(void); static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data); static void bta_dm_execute_queued_discovery_request(); static void bta_dm_close_gatt_conn(); @@ -149,27 +146,7 @@ gatt_interface_t& get_gatt_interface() { return *gatt_interface; } } // namespace -void bta_dm_disc_disable_search_and_disc() { - if (com::android::bluetooth::flags::separate_service_and_device_discovery()) { - log::info("No one should be calling this when flag is enabled"); - return; - } - bta_dm_disc_legacy::bta_dm_disc_disable_search_and_disc(); -} - -void bta_dm_disc_disable_disc() { - if (!com::android::bluetooth::flags::separate_service_and_device_discovery()) { - log::info("no-op when flag is disabled"); - return; - } - bta_dm_disable_disc(); -} - void bta_dm_disc_gatt_cancel_open(const RawAddress& bd_addr) { - if (!com::android::bluetooth::flags::separate_service_and_device_discovery()) { - bta_dm_disc_legacy::bta_dm_disc_gatt_cancel_open(bd_addr); - return; - } get_gatt_interface().BTA_GATTC_CancelOpen(0, bd_addr, false); if (com::android::bluetooth::flags::cancel_open_discovery_client() && bta_dm_discovery_cb.client_if != BTA_GATTS_INVALID_IF) { @@ -178,18 +155,10 @@ void bta_dm_disc_gatt_cancel_open(const RawAddress& bd_addr) { } void bta_dm_disc_gatt_refresh(const RawAddress& bd_addr) { - if (!com::android::bluetooth::flags::separate_service_and_device_discovery()) { - bta_dm_disc_legacy::bta_dm_disc_gatt_refresh(bd_addr); - return; - } get_gatt_interface().BTA_GATTC_Refresh(bd_addr); } void bta_dm_disc_remove_device(const RawAddress& bd_addr) { - if (!com::android::bluetooth::flags::separate_service_and_device_discovery()) { - bta_dm_disc_legacy::bta_dm_disc_remove_device(bd_addr); - return; - } if (bta_dm_discovery_cb.service_discovery_state == BTA_DM_DISCOVER_ACTIVE && bta_dm_discovery_cb.peer_bdaddr == bd_addr) { log::info("Device removed while service discovery was pending, conclude the service discovery"); @@ -197,14 +166,6 @@ void bta_dm_disc_remove_device(const RawAddress& bd_addr) { } } -void bta_dm_disc_gattc_register() { - if (!com::android::bluetooth::flags::separate_service_and_device_discovery()) { - bta_dm_disc_legacy::bta_dm_disc_gattc_register(); - return; - } - bta_dm_gattc_register(); -} - static void bta_dm_discovery_set_state(tBTA_DM_SERVICE_DISCOVERY_STATE state) { bta_dm_discovery_cb.service_discovery_state = state; } @@ -217,15 +178,14 @@ static void bta_dm_discovery_cancel() {} /******************************************************************************* * - * Function bta_dm_disable_search_and_disc + * Function bta_dm_disc_disable_disc * - * Description Cancels an ongoing search or discovery for devices in case - * of a Bluetooth disable + * Description Cancels an ongoing discovery in case of a Bluetooth disable * * Returns void * ******************************************************************************/ -static void bta_dm_disable_disc(void) { +void bta_dm_disc_disable_disc(void) { switch (bta_dm_discovery_get_state()) { case BTA_DM_DISCOVER_IDLE: break; @@ -305,7 +265,7 @@ static void bta_dm_disc_result(tBTA_DM_SVC_RES& disc_result) { if (!r.gatt_uuids.empty()) { log::info("Sending GATT services discovered using SDP"); // send GATT result back to app, if any - bta_dm_discovery_cb.service_search_cbacks.on_gatt_results(r.bd_addr, BD_NAME{}, r.gatt_uuids, + bta_dm_discovery_cb.service_search_cbacks.on_gatt_results(r.bd_addr, r.gatt_uuids, /* transport_le */ false); } bta_dm_discovery_cb.service_search_cbacks.on_service_discovery_results(r.bd_addr, r.uuids, @@ -315,7 +275,7 @@ static void bta_dm_disc_result(tBTA_DM_SVC_RES& disc_result) { GAP_BleReadPeerPrefConnParams(bta_dm_discovery_cb.peer_bdaddr); bta_dm_discovery_cb.service_search_cbacks.on_gatt_results(bta_dm_discovery_cb.peer_bdaddr, - BD_NAME{}, disc_result.gatt_uuids, + disc_result.gatt_uuids, /* transport_le */ true); } @@ -395,7 +355,7 @@ static tBT_TRANSPORT bta_dm_determine_discovery_transport(const RawAddress& remo /* Discovers services on a remote device */ static void bta_dm_discover_services(tBTA_DM_API_DISCOVER& discover) { - bta_dm_gattc_register(); + bta_dm_disc_gattc_register(); RawAddress bd_addr = discover.bd_addr; tBT_TRANSPORT transport = (discover.transport == BT_TRANSPORT_AUTO) @@ -478,7 +438,7 @@ void bta_dm_disc_override_gatt_performer_for_testing( /******************************************************************************* * - * Function bta_dm_gattc_register + * Function bta_dm_disc_gattc_register * * Description Register with GATTC in DM if BLE is needed. * @@ -486,7 +446,7 @@ void bta_dm_disc_override_gatt_performer_for_testing( * Returns void * ******************************************************************************/ -static void bta_dm_gattc_register(void) { +void bta_dm_disc_gattc_register(void) { if (bta_dm_discovery_cb.client_if != BTA_GATTS_INVALID_IF) { // Already registered return; @@ -847,37 +807,16 @@ static void bta_dm_disc_reset() { } void bta_dm_disc_start(bool delay_close_gatt) { - if (!com::android::bluetooth::flags::separate_service_and_device_discovery()) { - bta_dm_disc_legacy::bta_dm_disc_start(delay_close_gatt); - return; - } bta_dm_disc_reset(); bta_dm_discovery_cb.gatt_close_timer = delay_close_gatt ? alarm_new("bta_dm_search.gatt_close_timer") : nullptr; bta_dm_discovery_cb.pending_discovery_queue = {}; } -void bta_dm_disc_acl_down(const RawAddress& bd_addr, tBT_TRANSPORT transport) { - if (!com::android::bluetooth::flags::separate_service_and_device_discovery()) { - bta_dm_disc_legacy::bta_dm_disc_acl_down(bd_addr, transport); - return; - } -} - -void bta_dm_disc_stop() { - if (!com::android::bluetooth::flags::separate_service_and_device_discovery()) { - bta_dm_disc_legacy::bta_dm_disc_stop(); - return; - } - bta_dm_disc_reset(); -} +void bta_dm_disc_stop() { bta_dm_disc_reset(); } void bta_dm_disc_start_service_discovery(service_discovery_callbacks cbacks, const RawAddress& bd_addr, tBT_TRANSPORT transport) { - if (!com::android::bluetooth::flags::separate_service_and_device_discovery()) { - bta_dm_disc_legacy::bta_dm_disc_start_service_discovery(cbacks, bd_addr, transport); - return; - } bta_dm_disc_sm_execute(BTA_DM_API_DISCOVER_EVT, std::make_unique<tBTA_DM_MSG>(tBTA_DM_API_DISCOVER{ .bd_addr = bd_addr, .cbacks = cbacks, .transport = transport})); @@ -885,10 +824,6 @@ void bta_dm_disc_start_service_discovery(service_discovery_callbacks cbacks, #define DUMPSYS_TAG "shim::legacy::bta::dm" void DumpsysBtaDmDisc(int fd) { - if (!com::android::bluetooth::flags::separate_service_and_device_discovery()) { - bta_dm_disc_legacy::DumpsysBtaDmDisc(fd); - return; - } auto copy = discovery_state_history_.Pull(); LOG_DUMPSYS(fd, " last %zu discovery state transitions", copy.size()); for (const auto& it : copy) { diff --git a/system/bta/dm/bta_dm_disc.h b/system/bta/dm/bta_dm_disc.h index 4190fa1ce7..a243b785d9 100644 --- a/system/bta/dm/bta_dm_disc.h +++ b/system/bta/dm/bta_dm_disc.h @@ -34,13 +34,7 @@ void bta_dm_disc_start_service_discovery(service_discovery_callbacks cbacks, const RawAddress& bd_addr, tBT_TRANSPORT transport); // Bta subsystem entrypoint and lifecycle -// Remove when separate_service_and_device_discovery rolls out -void bta_dm_disc_disable_search_and_disc(); void bta_dm_disc_disable_disc(); -void bta_dm_disc_disable_search(); -// Indication that an acl has gone down and to examine the current -// service discovery procedure, if any. -void bta_dm_disc_acl_down(const RawAddress& bd_addr, tBT_TRANSPORT transport); // LE observe and scan interface void bta_dm_ble_scan(bool start, uint8_t duration_sec); diff --git a/system/bta/dm/bta_dm_disc_int_legacy.h b/system/bta/dm/bta_dm_disc_int_legacy.h deleted file mode 100644 index b8c3ad2567..0000000000 --- a/system/bta/dm/bta_dm_disc_int_legacy.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2023 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. - */ - -#pragma once - -#include <base/strings/stringprintf.h> -#include <bluetooth/log.h> - -#include <queue> -#include <string> - -#include "bta/include/bta_api.h" -#include "bta/sys/bta_sys.h" -#include "macros.h" -#include "stack/btm/neighbor_inquiry.h" -#include "stack/include/sdp_status.h" -#include "stack/sdp/sdp_discovery_db.h" -#include "types/bluetooth/uuid.h" -#include "types/raw_address.h" - -#define BTA_SERVICE_ID_TO_SERVICE_MASK(id) (1 << (id)) - -// TODO: Remove this file after flag separate_service_and_device_discovery rolls -// out -namespace bta_dm_disc_legacy { - -/* DM search events */ -typedef enum : uint16_t { - /* DM search API events */ - BTA_DM_API_SEARCH_EVT, - BTA_DM_API_SEARCH_CANCEL_EVT, - BTA_DM_API_DISCOVER_EVT, - BTA_DM_INQUIRY_CMPL_EVT, - BTA_DM_REMT_NAME_EVT, - BTA_DM_SDP_RESULT_EVT, - BTA_DM_SEARCH_CMPL_EVT, - BTA_DM_DISCOVERY_RESULT_EVT, - BTA_DM_DISC_CLOSE_TOUT_EVT, -} tBTA_DM_EVT; - -inline std::string bta_dm_event_text(const tBTA_DM_EVT& event) { - switch (event) { - CASE_RETURN_TEXT(BTA_DM_API_SEARCH_EVT); - CASE_RETURN_TEXT(BTA_DM_API_SEARCH_CANCEL_EVT); - CASE_RETURN_TEXT(BTA_DM_API_DISCOVER_EVT); - CASE_RETURN_TEXT(BTA_DM_INQUIRY_CMPL_EVT); - CASE_RETURN_TEXT(BTA_DM_REMT_NAME_EVT); - CASE_RETURN_TEXT(BTA_DM_SDP_RESULT_EVT); - CASE_RETURN_TEXT(BTA_DM_SEARCH_CMPL_EVT); - CASE_RETURN_TEXT(BTA_DM_DISCOVERY_RESULT_EVT); - CASE_RETURN_TEXT(BTA_DM_DISC_CLOSE_TOUT_EVT); - default: - return base::StringPrintf("UNKNOWN[0x%04x]", event); - } -} - -/* data type for BTA_DM_API_SEARCH_EVT */ -typedef struct { - tBTA_DM_SEARCH_CBACK* p_cback; -} tBTA_DM_API_SEARCH; - -/* data type for BTA_DM_API_DISCOVER_EVT */ -typedef struct { - RawAddress bd_addr; - service_discovery_callbacks cbacks; - tBT_TRANSPORT transport; -} tBTA_DM_API_DISCOVER; - -typedef struct { -} tBTA_DM_API_DISCOVERY_CANCEL; - -typedef struct { - RawAddress bd_addr; - BD_NAME bd_name; /* Name of peer device. */ - tHCI_STATUS hci_status; -} tBTA_DM_REMOTE_NAME; - -/* data type for tBTA_DM_DISC_RESULT */ -typedef struct { - tBTA_DM_SEARCH result; -} tBTA_DM_DISC_RESULT; - -/* data type for BTA_DM_INQUIRY_CMPL_EVT */ -typedef struct { - uint8_t num; -} tBTA_DM_INQUIRY_CMPL; - -/* data type for BTA_DM_SDP_RESULT_EVT */ -typedef struct { - tSDP_RESULT sdp_result; -} tBTA_DM_SDP_RESULT; - -typedef struct { - bool enable; -} tBTA_DM_API_BLE_FEATURE; - -typedef struct { - RawAddress bd_addr; /* BD address peer device. */ - tBTA_SERVICE_MASK services; /* Services found on peer device. */ - tBT_DEVICE_TYPE device_type; /* device type in case it is BLE device */ - std::vector<bluetooth::Uuid> uuids; - tBTA_STATUS result; - tHCI_STATUS hci_status; -} tBTA_DM_SVC_RES; - -using tBTA_DM_MSG = std::variant<tBTA_DM_API_SEARCH, tBTA_DM_API_DISCOVER, tBTA_DM_REMOTE_NAME, - tBTA_DM_DISC_RESULT, tBTA_DM_INQUIRY_CMPL, tBTA_DM_SDP_RESULT, - tBTA_DM_SVC_RES>; - -/* DM search state */ -typedef enum { - - BTA_DM_SEARCH_IDLE, - BTA_DM_SEARCH_ACTIVE, - BTA_DM_SEARCH_CANCELLING, - BTA_DM_DISCOVER_ACTIVE - -} tBTA_DM_STATE; - -inline std::string bta_dm_state_text(const tBTA_DM_STATE& state) { - switch (state) { - CASE_RETURN_TEXT(BTA_DM_SEARCH_IDLE); - CASE_RETURN_TEXT(BTA_DM_SEARCH_ACTIVE); - CASE_RETURN_TEXT(BTA_DM_SEARCH_CANCELLING); - CASE_RETURN_TEXT(BTA_DM_DISCOVER_ACTIVE); - default: - return base::StringPrintf("UNKNOWN[%d]", state); - } -} - -/* DM search control block */ -typedef struct { - tBTA_DM_SEARCH_CBACK* p_device_search_cback; - service_discovery_callbacks service_search_cbacks; - tBTM_INQ_INFO* p_btm_inq_info; - tBTA_SERVICE_MASK services_to_search; - tBTA_SERVICE_MASK services_found; - tSDP_DISCOVERY_DB* p_sdp_db; - tBTA_DM_STATE state; - RawAddress peer_bdaddr; - bool name_discover_done; - BD_NAME peer_name; - alarm_t* search_timer; - uint8_t service_index; - std::unique_ptr<tBTA_DM_MSG> p_pending_search; - std::queue<tBTA_DM_API_DISCOVER> pending_discovery_queue; - bool wait_disc; - bool sdp_results; - bluetooth::Uuid uuid; - uint8_t peer_scn; - tBT_TRANSPORT transport; - tBTA_DM_SEARCH_CBACK* p_csis_scan_cback; - tGATT_IF client_if; - uint8_t uuid_to_search; - bool gatt_disc_active; - uint16_t conn_id; - alarm_t* gatt_close_timer; /* GATT channel close delay timer */ - RawAddress pending_close_bda; /* pending GATT channel remote device address */ - -} tBTA_DM_SEARCH_CB; - -extern const uint32_t bta_service_id_to_btm_srv_id_lkup_tbl[]; -extern const uint16_t bta_service_id_to_uuid_lkup_tbl[]; - -} // namespace bta_dm_disc_legacy - -namespace fmt { -template <> -struct formatter<bta_dm_disc_legacy::tBTA_DM_EVT> - : enum_formatter<bta_dm_disc_legacy::tBTA_DM_EVT> {}; -template <> -struct formatter<bta_dm_disc_legacy::tBTA_DM_STATE> - : enum_formatter<bta_dm_disc_legacy::tBTA_DM_STATE> {}; -} // namespace fmt diff --git a/system/bta/dm/bta_dm_disc_legacy.cc b/system/bta/dm/bta_dm_disc_legacy.cc deleted file mode 100644 index 5bac53bfad..0000000000 --- a/system/bta/dm/bta_dm_disc_legacy.cc +++ /dev/null @@ -1,2080 +0,0 @@ -/* - * Copyright 2023 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. - */ - -#define LOG_TAG "bt_bta_dm" - -#include "bta/dm/bta_dm_disc_legacy.h" - -#include <base/functional/bind.h> -#include <base/strings/stringprintf.h> -#include <bluetooth/log.h> -#include <com_android_bluetooth_flags.h> -#include <stddef.h> - -#include <cstdint> -#include <string> -#include <variant> -#include <vector> - -#include "bta/dm/bta_dm_disc_int_legacy.h" -#include "bta/include/bta_gatt_api.h" -#include "bta/include/bta_sdp_api.h" -#include "btif/include/btif_config.h" -#include "common/circular_buffer.h" -#include "common/strings.h" -#include "device/include/interop.h" -#include "internal_include/bt_target.h" -#include "main/shim/dumpsys.h" -#include "os/logging/log_adapter.h" -#include "osi/include/allocator.h" -#include "stack/btm/btm_int_types.h" // TimestampedStringCircularBuffer -#include "stack/btm/neighbor_inquiry.h" -#include "stack/include/bt_dev_class.h" -#include "stack/include/bt_name.h" -#include "stack/include/bt_uuid16.h" -#include "stack/include/btm_client_interface.h" -#include "stack/include/btm_inq.h" -#include "stack/include/btm_log_history.h" -#include "stack/include/btm_status.h" -#include "stack/include/gap_api.h" // GAP_BleReadPeerPrefConnParams -#include "stack/include/hidh_api.h" -#include "stack/include/main_thread.h" -#include "stack/include/rnr_interface.h" -#include "stack/include/sdp_status.h" -#include "stack/rnr/remote_name_request.h" -#include "stack/sdp/sdpint.h" // is_sdp_pbap_pce_disabled -#include "storage/config_keys.h" -#include "types/raw_address.h" - -#ifdef TARGET_FLOSS -#include "stack/include/srvc_api.h" -#endif - -// TODO: Remove this file after flag separate_service_and_device_discovery rolls -// out -namespace bta_dm_disc_legacy { - -using ::bluetooth::Uuid; -using namespace ::bluetooth::legacy::stack::sdp; -using namespace ::bluetooth; - -tBTM_CONTRL_STATE bta_dm_pm_obtain_controller_state(void); - -namespace { -constexpr char kBtmLogTag[] = "SDP"; - -tBTA_DM_SEARCH_CB bta_dm_search_cb; -} // namespace - -static void bta_dm_search_sm_execute(tBTA_DM_EVT event, std::unique_ptr<tBTA_DM_MSG> msg); -static void post_disc_evt(tBTA_DM_EVT event, std::unique_ptr<tBTA_DM_MSG> msg) { - if (do_in_main_thread(base::BindOnce(&bta_dm_search_sm_execute, event, std::move(msg))) != - BT_STATUS_SUCCESS) { - log::error("post_disc_evt failed"); - } -} - -static void bta_dm_gatt_disc_complete(uint16_t conn_id, tGATT_STATUS status); -static void bta_dm_inq_results_cb(tBTM_INQ_RESULTS* p_inq, const uint8_t* p_eir, uint16_t eir_len); -static void bta_dm_inq_cmpl(); -static void bta_dm_inq_cmpl_cb(void* p_result); -static void bta_dm_service_search_remname_cback(const RawAddress& bd_addr, DEV_CLASS dc, - BD_NAME bd_name); -static void bta_dm_remname_cback(const tBTM_REMOTE_DEV_NAME* p); -static void bta_dm_find_services(const RawAddress& bd_addr); -static void bta_dm_discover_next_device(void); -static void bta_dm_sdp_callback(const RawAddress& bd_addr, tSDP_STATUS sdp_status); - -static bool bta_dm_read_remote_device_name(const RawAddress& bd_addr, tBT_TRANSPORT transport); -static void bta_dm_discover_name(const RawAddress& remote_bd_addr); -static void bta_dm_discover_services(const RawAddress& remote_bd_addr); - -static void bta_dm_disable_search_and_disc(void); - -static void bta_dm_gattc_register(void); -static void btm_dm_start_gatt_discovery(const RawAddress& bd_addr); -static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data); -static void bta_dm_search_cmpl(); -static void bta_dm_free_sdp_db(); -static void bta_dm_execute_queued_request(); -static void bta_dm_search_cancel_notify(); -static void bta_dm_close_gatt_conn(); - -TimestampedStringCircularBuffer disc_gatt_history_{50}; - -namespace { - -struct gatt_interface_t { - void (*BTA_GATTC_CancelOpen)(tGATT_IF client_if, const RawAddress& remote_bda, bool is_direct); - void (*BTA_GATTC_Refresh)(const RawAddress& remote_bda); - void (*BTA_GATTC_GetGattDb)(uint16_t conn_id, uint16_t start_handle, uint16_t end_handle, - btgatt_db_element_t** db, int* count); - void (*BTA_GATTC_AppRegister)(tBTA_GATTC_CBACK* p_client_cb, BtaAppRegisterCallback cb, - bool eatt_support); - void (*BTA_GATTC_Close)(uint16_t conn_id); - void (*BTA_GATTC_ServiceSearchRequest)(uint16_t conn_id, const bluetooth::Uuid* p_srvc_uuid); - void (*BTA_GATTC_Open)(tGATT_IF client_if, const RawAddress& remote_bda, - tBTM_BLE_CONN_TYPE connection_type, bool opportunistic); -} default_gatt_interface = { - .BTA_GATTC_CancelOpen = - [](tGATT_IF client_if, const RawAddress& remote_bda, bool is_direct) { - disc_gatt_history_.Push(base::StringPrintf( - "%-32s bd_addr:%s client_if:%hu is_direct:%c", "GATTC_CancelOpen", - ADDRESS_TO_LOGGABLE_CSTR(remote_bda), client_if, - (is_direct) ? 'T' : 'F')); - BTA_GATTC_CancelOpen(client_if, remote_bda, is_direct); - }, - .BTA_GATTC_Refresh = - [](const RawAddress& remote_bda) { - disc_gatt_history_.Push(base::StringPrintf("%-32s bd_addr:%s", "GATTC_Refresh", - ADDRESS_TO_LOGGABLE_CSTR(remote_bda))); - BTA_GATTC_Refresh(remote_bda); - }, - .BTA_GATTC_GetGattDb = - [](uint16_t conn_id, uint16_t start_handle, uint16_t end_handle, - btgatt_db_element_t** db, int* count) { - disc_gatt_history_.Push( - base::StringPrintf("%-32s conn_id:%hu start_handle:%hu end:handle:%hu", - "GATTC_GetGattDb", conn_id, start_handle, end_handle)); - BTA_GATTC_GetGattDb(conn_id, start_handle, end_handle, db, count); - }, - .BTA_GATTC_AppRegister = - [](tBTA_GATTC_CBACK* p_client_cb, BtaAppRegisterCallback cb, bool eatt_support) { - disc_gatt_history_.Push(base::StringPrintf("%-32s eatt_support:%c", - "GATTC_AppRegister", - (eatt_support) ? 'T' : 'F')); - BTA_GATTC_AppRegister(p_client_cb, cb, eatt_support); - }, - .BTA_GATTC_Close = - [](uint16_t conn_id) { - disc_gatt_history_.Push( - base::StringPrintf("%-32s conn_id:%hu", "GATTC_Close", conn_id)); - BTA_GATTC_Close(conn_id); - }, - .BTA_GATTC_ServiceSearchRequest = - [](uint16_t conn_id, const bluetooth::Uuid* p_srvc_uuid) { - disc_gatt_history_.Push(base::StringPrintf( - "%-32s conn_id:%hu", "GATTC_ServiceSearchRequest", conn_id)); - if (p_srvc_uuid) { - BTA_GATTC_ServiceSearchRequest(conn_id, *p_srvc_uuid); - } else { - BTA_GATTC_ServiceSearchAllRequest(conn_id); - } - }, - .BTA_GATTC_Open = - [](tGATT_IF client_if, const RawAddress& remote_bda, - tBTM_BLE_CONN_TYPE connection_type, bool opportunistic) { - disc_gatt_history_.Push(base::StringPrintf( - "%-32s bd_addr:%s client_if:%hu type:0x%x opportunistic:%c", "GATTC_Open", - ADDRESS_TO_LOGGABLE_CSTR(remote_bda), client_if, connection_type, - (opportunistic) ? 'T' : 'F')); - BTA_GATTC_Open(client_if, remote_bda, connection_type, opportunistic); - }, -}; - -gatt_interface_t* gatt_interface = &default_gatt_interface; - -gatt_interface_t& get_gatt_interface() { return *gatt_interface; } - -} // namespace - -void bta_dm_disc_disable_search_and_disc() { bta_dm_disable_search_and_disc(); } - -void bta_dm_disc_gatt_cancel_open(const RawAddress& bd_addr) { - get_gatt_interface().BTA_GATTC_CancelOpen(0, bd_addr, false); - if (com::android::bluetooth::flags::cancel_open_discovery_client() && - bta_dm_search_cb.client_if != BTA_GATTS_INVALID_IF) { - get_gatt_interface().BTA_GATTC_CancelOpen(bta_dm_search_cb.client_if, bd_addr, true); - } -} - -void bta_dm_disc_gatt_refresh(const RawAddress& bd_addr) { - get_gatt_interface().BTA_GATTC_Refresh(bd_addr); -} - -void bta_dm_disc_remove_device(const RawAddress& bd_addr) { - if (bta_dm_search_cb.state == BTA_DM_DISCOVER_ACTIVE && bta_dm_search_cb.peer_bdaddr == bd_addr) { - log::info("Device removed while service discovery was pending, conclude the service discovery"); - bta_dm_gatt_disc_complete((uint16_t)GATT_INVALID_CONN_ID, (tGATT_STATUS)GATT_ERROR); - } -} - -void bta_dm_disc_discover_next_device() { bta_dm_discover_next_device(); } - -void bta_dm_disc_gattc_register() { bta_dm_gattc_register(); } - -const uint16_t bta_service_id_to_uuid_lkup_tbl[BTA_MAX_SERVICE_ID] = { - UUID_SERVCLASS_PNP_INFORMATION, /* Reserved */ - UUID_SERVCLASS_SERIAL_PORT, /* BTA_SPP_SERVICE_ID */ - UUID_SERVCLASS_DIALUP_NETWORKING, /* BTA_DUN_SERVICE_ID */ - UUID_SERVCLASS_AUDIO_SOURCE, /* BTA_A2DP_SOURCE_SERVICE_ID */ - UUID_SERVCLASS_LAN_ACCESS_USING_PPP, /* BTA_LAP_SERVICE_ID */ - UUID_SERVCLASS_HEADSET, /* BTA_HSP_HS_SERVICE_ID */ - UUID_SERVCLASS_HF_HANDSFREE, /* BTA_HFP_HS_SERVICE_ID */ - UUID_SERVCLASS_OBEX_OBJECT_PUSH, /* BTA_OPP_SERVICE_ID */ - UUID_SERVCLASS_OBEX_FILE_TRANSFER, /* BTA_FTP_SERVICE_ID */ - UUID_SERVCLASS_CORDLESS_TELEPHONY, /* BTA_CTP_SERVICE_ID */ - UUID_SERVCLASS_INTERCOM, /* BTA_ICP_SERVICE_ID */ - UUID_SERVCLASS_IRMC_SYNC, /* BTA_SYNC_SERVICE_ID */ - UUID_SERVCLASS_DIRECT_PRINTING, /* BTA_BPP_SERVICE_ID */ - UUID_SERVCLASS_IMAGING_RESPONDER, /* BTA_BIP_SERVICE_ID */ - UUID_SERVCLASS_PANU, /* BTA_PANU_SERVICE_ID */ - UUID_SERVCLASS_NAP, /* BTA_NAP_SERVICE_ID */ - UUID_SERVCLASS_GN, /* BTA_GN_SERVICE_ID */ - UUID_SERVCLASS_SAP, /* BTA_SAP_SERVICE_ID */ - UUID_SERVCLASS_AUDIO_SINK, /* BTA_A2DP_SERVICE_ID */ - UUID_SERVCLASS_AV_REMOTE_CONTROL, /* BTA_AVRCP_SERVICE_ID */ - UUID_SERVCLASS_HUMAN_INTERFACE, /* BTA_HID_SERVICE_ID */ - UUID_SERVCLASS_VIDEO_SINK, /* BTA_VDP_SERVICE_ID */ - UUID_SERVCLASS_PBAP_PSE, /* BTA_PBAP_SERVICE_ID */ - UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY, /* BTA_HSP_SERVICE_ID */ - UUID_SERVCLASS_AG_HANDSFREE, /* BTA_HFP_SERVICE_ID */ - UUID_SERVCLASS_MESSAGE_ACCESS, /* BTA_MAP_SERVICE_ID */ - UUID_SERVCLASS_MESSAGE_NOTIFICATION, /* BTA_MN_SERVICE_ID */ - UUID_SERVCLASS_HDP_PROFILE, /* BTA_HDP_SERVICE_ID */ - UUID_SERVCLASS_PBAP_PCE, /* BTA_PCE_SERVICE_ID */ - UUID_PROTOCOL_ATT /* BTA_GATT_SERVICE_ID */ -}; - -#define MAX_DISC_RAW_DATA_BUF (4096) -static uint8_t g_disc_raw_data_buf[MAX_DISC_RAW_DATA_BUF]; - -static void bta_dm_search_set_state(tBTA_DM_STATE state) { bta_dm_search_cb.state = state; } -static tBTA_DM_STATE bta_dm_search_get_state() { return bta_dm_search_cb.state; } - -/******************************************************************************* - * - * Function bta_dm_search_start - * - * Description Starts an inquiry - * - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_search_start(tBTA_DM_API_SEARCH& search) { - bta_dm_gattc_register(); - - if (get_btm_client_interface().db.BTM_ClearInqDb(nullptr) != tBTM_STATUS::BTM_SUCCESS) { - log::warn("Unable to clear inquiry db for device discovery"); - } - - /* save search params */ - bta_dm_search_cb.p_device_search_cback = search.p_cback; - - const tBTM_STATUS btm_status = BTM_StartInquiry(bta_dm_inq_results_cb, bta_dm_inq_cmpl_cb); - switch (btm_status) { - case tBTM_STATUS::BTM_CMD_STARTED: - // Completion callback will be executed when controller inquiry - // timer pops or is cancelled by the user - break; - default: - log::warn("Unable to start device discovery search btm_status:{}", - btm_status_text(btm_status)); - // Not started so completion callback is executed now - bta_dm_inq_cmpl(); - break; - } -} - -/******************************************************************************* - * - * Function bta_dm_search_cancel - * - * Description Cancels an ongoing search for devices - * - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_search_cancel() { - if (BTM_IsInquiryActive()) { - BTM_CancelInquiry(); - bta_dm_search_cancel_notify(); - bta_dm_search_cmpl(); - } - /* If no Service Search going on then issue cancel remote name in case it is - active */ - else if (!bta_dm_search_cb.name_discover_done) { - if (get_stack_rnr_interface().BTM_CancelRemoteDeviceName() != tBTM_STATUS::BTM_CMD_STARTED) { - log::warn("Unable to cancel RNR"); - } - /* bta_dm_search_cmpl is called when receiving the remote name cancel evt */ - if (!com::android::bluetooth::flags:: - bta_dm_defer_device_discovery_state_change_until_rnr_complete()) { - bta_dm_search_cmpl(); - } - } else { - bta_dm_inq_cmpl(); - } -} - -/******************************************************************************* - * - * Function bta_dm_discover - * - * Description Discovers services on a remote device - * - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_discover(tBTA_DM_API_DISCOVER& discover) { - bta_dm_gattc_register(); - - bta_dm_search_cb.service_search_cbacks = discover.cbacks; - bta_dm_search_cb.services_to_search = BTA_ALL_SERVICE_MASK; - bta_dm_search_cb.service_index = 0; - bta_dm_search_cb.services_found = 0; - bta_dm_search_cb.peer_name[0] = 0; - bta_dm_search_cb.p_btm_inq_info = get_btm_client_interface().db.BTM_InqDbRead(discover.bd_addr); - bta_dm_search_cb.transport = discover.transport; - - bta_dm_search_cb.name_discover_done = false; - - log::info("bta_dm_discovery: starting service discovery to {} , transport: {}", discover.bd_addr, - bt_transport_text(discover.transport)); - bta_dm_discover_services(discover.bd_addr); -} - -/******************************************************************************* - * - * Function bta_dm_disable_search_and_disc - * - * Description Cancels an ongoing search or discovery for devices in case - * of a Bluetooth disable - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_disable_search_and_disc(void) { - switch (bta_dm_search_get_state()) { - case BTA_DM_SEARCH_IDLE: - break; - case BTA_DM_SEARCH_ACTIVE: - case BTA_DM_SEARCH_CANCELLING: - case BTA_DM_DISCOVER_ACTIVE: - default: - log::debug("Search state machine is not idle so issuing search cancel current state:{}", - bta_dm_state_text(bta_dm_search_get_state())); - bta_dm_search_cancel(); - } -} - -/******************************************************************************* - * - * Function bta_dm_read_remote_device_name - * - * Description Initiate to get remote device name - * - * Returns true if started to get remote name - * - ******************************************************************************/ -static bool bta_dm_read_remote_device_name(const RawAddress& bd_addr, tBT_TRANSPORT transport) { - tBTM_STATUS btm_status; - - log::verbose(""); - - bta_dm_search_cb.peer_bdaddr = bd_addr; - bta_dm_search_cb.peer_name[0] = 0; - - btm_status = get_stack_rnr_interface().BTM_ReadRemoteDeviceName(bta_dm_search_cb.peer_bdaddr, - bta_dm_remname_cback, transport); - - if (btm_status == tBTM_STATUS::BTM_CMD_STARTED) { - log::verbose("BTM_ReadRemoteDeviceName is started"); - - return true; - } else if (btm_status == tBTM_STATUS::BTM_BUSY) { - log::verbose("BTM_ReadRemoteDeviceName is busy"); - - /* Remote name discovery is on going now so BTM cannot notify through - * "bta_dm_remname_cback" */ - /* adding callback to get notified that current reading remote name done */ - - get_stack_rnr_interface().BTM_SecAddRmtNameNotifyCallback(&bta_dm_service_search_remname_cback); - - return true; - } else { - log::warn("BTM_ReadRemoteDeviceName returns 0x{:02X}", btm_status); - - return false; - } -} - -/******************************************************************************* - * - * Function bta_dm_inq_cmpl - * - * Description Process the inquiry complete event from BTM - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_inq_cmpl() { - if (bta_dm_search_get_state() == BTA_DM_SEARCH_CANCELLING) { - bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); - bta_dm_execute_queued_request(); - return; - } - - if (bta_dm_search_get_state() != BTA_DM_SEARCH_ACTIVE) { - return; - } - - log::verbose("bta_dm_inq_cmpl"); - - bta_dm_search_cb.p_btm_inq_info = get_btm_client_interface().db.BTM_InqDbFirst(); - if (bta_dm_search_cb.p_btm_inq_info != NULL) { - /* start name discovery from the first device on inquiry result - */ - bta_dm_search_cb.name_discover_done = false; - bta_dm_search_cb.peer_name[0] = 0; - bta_dm_discover_name(bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr); - } else { - bta_dm_search_cmpl(); - } -} - -static void bta_dm_remote_name_cmpl(const tBTA_DM_REMOTE_NAME& remote_name_msg) { - BTM_LogHistory(kBtmLogTag, remote_name_msg.bd_addr, "Remote name completed", - base::StringPrintf("status:%s state:%s name:\"%s\"", - hci_status_code_text(remote_name_msg.hci_status).c_str(), - bta_dm_state_text(bta_dm_search_get_state()).c_str(), - PRIVATE_NAME(remote_name_msg.bd_name))); - - tBTM_INQ_INFO* p_btm_inq_info = - get_btm_client_interface().db.BTM_InqDbRead(remote_name_msg.bd_addr); - if (!bd_name_is_empty(remote_name_msg.bd_name) && p_btm_inq_info) { - p_btm_inq_info->appl_knows_rem_name = true; - } - - // Callback with this property - if (bta_dm_search_cb.p_device_search_cback != nullptr || - bta_dm_search_cb.service_search_cbacks.on_name_read != nullptr) { - // Both device and service search callbacks end up sending event to java. - // It's enough to send callback to just one of them. - if (bta_dm_search_cb.p_device_search_cback != nullptr) { - tBTA_DM_SEARCH search_data = { - .name_res = {.bd_addr = remote_name_msg.bd_addr, .bd_name = {}}, - }; - if (remote_name_msg.hci_status == HCI_SUCCESS) { - bd_name_copy(search_data.name_res.bd_name, remote_name_msg.bd_name); - } - bta_dm_search_cb.p_device_search_cback(BTA_DM_NAME_READ_EVT, &search_data); - } else if (bta_dm_search_cb.service_search_cbacks.on_name_read != nullptr) { - bta_dm_search_cb.service_search_cbacks.on_name_read( - remote_name_msg.bd_addr, remote_name_msg.hci_status, remote_name_msg.bd_name); - } - } else { - log::warn("Received remote name complete without callback"); - } - - switch (bta_dm_search_get_state()) { - case BTA_DM_SEARCH_ACTIVE: - bta_dm_discover_name(bta_dm_search_cb.peer_bdaddr); - break; - case BTA_DM_DISCOVER_ACTIVE: - /* TODO: Get rid of this case when Name and Service discovery state - * machines are separated */ - bta_dm_discover_name(remote_name_msg.bd_addr); - break; - case BTA_DM_SEARCH_IDLE: - case BTA_DM_SEARCH_CANCELLING: - log::warn("Received remote name request in state:{}", - bta_dm_state_text(bta_dm_search_get_state())); - break; - } -} - -static void store_avrcp_profile_feature(tSDP_DISC_REC* sdp_rec) { - tSDP_DISC_ATTR* p_attr = get_legacy_stack_sdp_api()->record.SDP_FindAttributeInRec( - sdp_rec, ATTR_ID_SUPPORTED_FEATURES); - if (p_attr == NULL) { - return; - } - - uint16_t avrcp_features = p_attr->attr_value.v.u16; - if (avrcp_features == 0) { - return; - } - - if (btif_config_set_bin(sdp_rec->remote_bd_addr.ToString().c_str(), - BTIF_STORAGE_KEY_AV_REM_CTRL_FEATURES, (const uint8_t*)&avrcp_features, - sizeof(avrcp_features))) { - log::info("Saving avrcp_features: 0x{:x}", avrcp_features); - } else { - log::info("Failed to store avrcp_features 0x{:x} for {}", avrcp_features, - sdp_rec->remote_bd_addr); - } -} - -static void bta_dm_store_audio_profiles_version() { - struct AudioProfile { - const uint16_t servclass_uuid; - const uint16_t btprofile_uuid; - const char* profile_key; - void (*store_audio_profile_feature)(tSDP_DISC_REC*); - }; - - std::array<AudioProfile, 1> audio_profiles = {{ - { - .servclass_uuid = UUID_SERVCLASS_AV_REMOTE_CONTROL, - .btprofile_uuid = UUID_SERVCLASS_AV_REMOTE_CONTROL, - .profile_key = BTIF_STORAGE_KEY_AVRCP_CONTROLLER_VERSION, - .store_audio_profile_feature = store_avrcp_profile_feature, - }, - }}; - - for (const auto& audio_profile : audio_profiles) { - tSDP_DISC_REC* sdp_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb( - bta_dm_search_cb.p_sdp_db, audio_profile.servclass_uuid, NULL); - if (sdp_rec == NULL) { - continue; - } - - if (get_legacy_stack_sdp_api()->record.SDP_FindAttributeInRec( - sdp_rec, ATTR_ID_BT_PROFILE_DESC_LIST) == NULL) { - continue; - } - - uint16_t profile_version = 0; - /* get profile version (if failure, version parameter is not updated) */ - if (!get_legacy_stack_sdp_api()->record.SDP_FindProfileVersionInRec( - sdp_rec, audio_profile.btprofile_uuid, &profile_version)) { - log::warn("Unable to find SDP profile version in record peer:{}", sdp_rec->remote_bd_addr); - } - if (profile_version != 0) { - if (btif_config_set_bin(sdp_rec->remote_bd_addr.ToString().c_str(), audio_profile.profile_key, - (const uint8_t*)&profile_version, sizeof(profile_version))) { - } else { - log::info("Failed to store peer profile version for {}", sdp_rec->remote_bd_addr); - } - } - audio_profile.store_audio_profile_feature(sdp_rec); - } -} - -/******************************************************************************* - * - * Function bta_dm_sdp_result - * - * Description Process the discovery result from sdp - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_sdp_result(tBTA_DM_SDP_RESULT& sdp_event) { - tSDP_DISC_REC* p_sdp_rec = NULL; - bool scn_found = false; - uint16_t service = 0xFFFF; - tSDP_PROTOCOL_ELEM pe; - - std::vector<Uuid> uuid_list; - - const tSDP_RESULT sdp_result = sdp_event.sdp_result; - - if ((sdp_event.sdp_result == tSDP_STATUS::SDP_SUCCESS) || - (sdp_event.sdp_result == tSDP_STATUS::SDP_NO_RECS_MATCH) || - (sdp_event.sdp_result == tSDP_STATUS::SDP_DB_FULL)) { - log::verbose("sdp_result::0x{:x}", sdp_event.sdp_result); - do { - p_sdp_rec = NULL; - if (bta_dm_search_cb.service_index == (BTA_USER_SERVICE_ID + 1)) { - if (p_sdp_rec && get_legacy_stack_sdp_api()->record.SDP_FindProtocolListElemInRec( - p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe)) { - bta_dm_search_cb.peer_scn = (uint8_t)pe.params[0]; - scn_found = true; - } - } else { - service = bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index - 1]; - p_sdp_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb(bta_dm_search_cb.p_sdp_db, - service, p_sdp_rec); - } - /* finished with BR/EDR services, now we check the result for GATT based - * service UUID */ - if (bta_dm_search_cb.service_index == BTA_MAX_SERVICE_ID) { - /* all GATT based services */ - - std::vector<Uuid> gatt_uuids; - - do { - /* find a service record, report it */ - p_sdp_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb(bta_dm_search_cb.p_sdp_db, - 0, p_sdp_rec); - if (p_sdp_rec) { - Uuid service_uuid; - if (get_legacy_stack_sdp_api()->record.SDP_FindServiceUUIDInRec(p_sdp_rec, - &service_uuid)) { - gatt_uuids.push_back(service_uuid); - } - } - } while (p_sdp_rec); - - if (!gatt_uuids.empty()) { - log::info("GATT services discovered using SDP"); - - // send all result back to app - BD_NAME bd_name; - bd_name_from_char_pointer(bd_name, bta_dm_get_remname()); - - bta_dm_search_cb.service_search_cbacks.on_gatt_results(bta_dm_search_cb.peer_bdaddr, - bd_name, gatt_uuids, - /* transport_le */ false); - } - } else { - if (p_sdp_rec != NULL) { - if (service != UUID_SERVCLASS_PNP_INFORMATION) { - bta_dm_search_cb.services_found |= (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK( - bta_dm_search_cb.service_index - 1)); - uint16_t tmp_svc = bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index - 1]; - /* Add to the list of UUIDs */ - uuid_list.push_back(Uuid::From16Bit(tmp_svc)); - } - } - } - - if (bta_dm_search_cb.services_to_search == 0) { - bta_dm_search_cb.service_index++; - } else { /* regular one service per search or PNP search */ - break; - } - - } while (bta_dm_search_cb.service_index <= BTA_MAX_SERVICE_ID); - - log::verbose("services_found = {:04x}", bta_dm_search_cb.services_found); - - /* Collect the 128-bit services here and put them into the list */ - p_sdp_rec = NULL; - do { - /* find a service record, report it */ - p_sdp_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb_128bit( - bta_dm_search_cb.p_sdp_db, p_sdp_rec); - if (p_sdp_rec) { - // SDP_FindServiceUUIDInRec_128bit is used only once, refactor? - Uuid temp_uuid; - if (get_legacy_stack_sdp_api()->record.SDP_FindServiceUUIDInRec_128bit(p_sdp_rec, - &temp_uuid)) { - uuid_list.push_back(temp_uuid); - } - } - } while (p_sdp_rec); - - if (bta_dm_search_cb.services_to_search == 0) { - bta_dm_store_audio_profiles_version(); - } - -#if TARGET_FLOSS - tSDP_DI_GET_RECORD di_record; - if (get_legacy_stack_sdp_api()->device_id.SDP_GetDiRecord( - 1, &di_record, bta_dm_search_cb.p_sdp_db) == tSDP_STATUS::SDP_SUCCESS) { - bta_dm_search_cb.service_search_cbacks.on_did_received( - bta_dm_search_cb.peer_bdaddr, di_record.rec.vendor_id_source, di_record.rec.vendor, - di_record.rec.product, di_record.rec.version); - } -#endif - - /* if there are more services to search for */ - if (bta_dm_search_cb.services_to_search) { - /* Free up the p_sdp_db before checking the next one */ - bta_dm_free_sdp_db(); - bta_dm_find_services(bta_dm_search_cb.peer_bdaddr); - } else { - /* callbacks */ - /* start next bd_addr if necessary */ - - get_stack_rnr_interface().BTM_SecDeleteRmtNameNotifyCallback( - &bta_dm_service_search_remname_cback); - - BTM_LogHistory( - kBtmLogTag, bta_dm_search_cb.peer_bdaddr, "Discovery completed", - base::StringPrintf("Result:%s services_found:0x%x service_index:0x%d", - sdp_result_text(sdp_result).c_str(), - bta_dm_search_cb.services_found, bta_dm_search_cb.service_index)); - - auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{}); - auto& disc_result = std::get<tBTA_DM_SVC_RES>(*msg); - - disc_result.result = BTA_SUCCESS; - disc_result.uuids = std::move(uuid_list); - // Copy the raw_data to the discovery result structure - if (bta_dm_search_cb.p_sdp_db != NULL && bta_dm_search_cb.p_sdp_db->raw_used != 0 && - bta_dm_search_cb.p_sdp_db->raw_data != NULL) { - log::verbose("raw_data used = 0x{:x} raw_data_ptr = 0x{}", - bta_dm_search_cb.p_sdp_db->raw_used, - fmt::ptr(bta_dm_search_cb.p_sdp_db->raw_data)); - - bta_dm_search_cb.p_sdp_db->raw_data = - NULL; // no need to free this - it is a global assigned. - bta_dm_search_cb.p_sdp_db->raw_used = 0; - bta_dm_search_cb.p_sdp_db->raw_size = 0; - } else { - log::verbose("raw data size is 0 or raw_data is null!!"); - } - /* Done with p_sdp_db. Free it */ - bta_dm_free_sdp_db(); - disc_result.services = bta_dm_search_cb.services_found; - - // Piggy back the SCN over result field - if (scn_found) { - disc_result.result = static_cast<tBTA_STATUS>(3 + bta_dm_search_cb.peer_scn); - disc_result.services |= BTA_USER_SERVICE_MASK; - - log::verbose("Piggy back the SCN over result field SCN={}", bta_dm_search_cb.peer_scn); - } - disc_result.bd_addr = bta_dm_search_cb.peer_bdaddr; - - bta_dm_search_sm_execute(BTA_DM_DISCOVERY_RESULT_EVT, std::move(msg)); - } - } else { - BTM_LogHistory(kBtmLogTag, bta_dm_search_cb.peer_bdaddr, "Discovery failed", - base::StringPrintf("Result:%s", sdp_result_text(sdp_result).c_str())); - log::error("SDP connection failed {}", sdp_status_text(sdp_result)); - if (sdp_event.sdp_result == tSDP_STATUS::SDP_CONN_FAILED) { - bta_dm_search_cb.wait_disc = false; - } - - /* not able to connect go to next device */ - if (bta_dm_search_cb.p_sdp_db) { - osi_free_and_reset((void**)&bta_dm_search_cb.p_sdp_db); - } - - get_stack_rnr_interface().BTM_SecDeleteRmtNameNotifyCallback( - &bta_dm_service_search_remname_cback); - - auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{}); - auto& disc_result = std::get<tBTA_DM_SVC_RES>(*msg); - - disc_result.result = BTA_FAILURE; - disc_result.services = bta_dm_search_cb.services_found; - disc_result.bd_addr = bta_dm_search_cb.peer_bdaddr; - - bta_dm_search_sm_execute(BTA_DM_DISCOVERY_RESULT_EVT, std::move(msg)); - } -} - -/** Callback of peer's DIS reply. This is only called for floss */ -#if TARGET_FLOSS -static void bta_dm_read_dis_cmpl(const RawAddress& addr, tDIS_VALUE* p_dis_value) { - if (!p_dis_value) { - log::warn("read DIS failed"); - } else { - bta_dm_search_cb.service_search_cbacks.on_did_received( - addr, p_dis_value->pnp_id.vendor_id_src, p_dis_value->pnp_id.vendor_id, - p_dis_value->pnp_id.product_id, p_dis_value->pnp_id.product_version); - } - - bta_dm_execute_queued_request(); -} -#endif - -/******************************************************************************* - * - * Function bta_dm_search_cmpl - * - * Description Sends event to application - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_search_cmpl() { - bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); - - uint16_t conn_id = bta_dm_search_cb.conn_id; - - std::vector<Uuid> gatt_services; - - bool send_gatt_results = bta_dm_search_cb.gatt_disc_active; - - /* no BLE connection, i.e. Classic service discovery end */ - if (conn_id == GATT_INVALID_CONN_ID) { - if (bta_dm_search_cb.gatt_disc_active) { - log::warn("GATT active but no BLE connection, likely disconnected midway through"); - } else { - log::info("No BLE connection, processing classic results"); - } - } else { - btgatt_db_element_t* db = NULL; - int count = 0; - get_gatt_interface().BTA_GATTC_GetGattDb(conn_id, 0x0000, 0xFFFF, &db, &count); - if (count != 0) { - for (int i = 0; i < count; i++) { - // we process service entries only - if (db[i].type == BTGATT_DB_PRIMARY_SERVICE) { - gatt_services.push_back(db[i].uuid); - } - } - osi_free(db); - log::info("GATT services discovered using LE Transport, will always send to upper layer"); - send_gatt_results = true; - } else { - log::warn("Empty GATT database - no BLE services discovered"); - } - } - - // send all result back to app - if (send_gatt_results) { - if (bta_dm_search_cb.service_search_cbacks.on_gatt_results != nullptr) { - log::info("Sending GATT results to upper layer"); - - BD_NAME bd_name; - bd_name_from_char_pointer(bd_name, bta_dm_get_remname()); - bta_dm_search_cb.service_search_cbacks.on_gatt_results(bta_dm_search_cb.peer_bdaddr, bd_name, - gatt_services, - /* transport_le */ true); - } else { - log::warn("on_gatt_results is nullptr!"); - } - } - - if (bta_dm_search_cb.p_device_search_cback) { - bta_dm_search_cb.p_device_search_cback(BTA_DM_DISC_CMPL_EVT, nullptr); - } - bta_dm_search_cb.gatt_disc_active = false; - -#if TARGET_FLOSS - if (conn_id != GATT_INVALID_CONN_ID && - DIS_ReadDISInfo(bta_dm_search_cb.peer_bdaddr, bta_dm_read_dis_cmpl, DIS_ATTR_PNP_ID_BIT)) { - return; - } -#endif - - bta_dm_execute_queued_request(); -} - -/******************************************************************************* - * - * Function bta_dm_disc_result - * - * Description Service discovery result when discovering services on a - * device - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_disc_result(tBTA_DM_SVC_RES& disc_result) { - log::verbose(""); - - /* disc_res.device_type is set only when GATT discovery is finished in - * bta_dm_gatt_disc_complete */ - bool is_gatt_over_ble = ((disc_result.device_type & BT_DEVICE_TYPE_BLE) != 0); - - /* if any BR/EDR service discovery has been done, report the event */ - if (!is_gatt_over_ble) { - auto& r = disc_result; - bta_dm_search_cb.service_search_cbacks.on_service_discovery_results(r.bd_addr, r.uuids, - r.result); - } - - /* Services were discovered while device search is in progress. - * Don't execute bta_dm_search_cmpl, as it would also finish the device - * search. It will be executed later when device search is finished. */ - if (bta_dm_search_get_state() != BTA_DM_SEARCH_ACTIVE) { - get_gatt_interface().BTA_GATTC_CancelOpen(0, bta_dm_search_cb.peer_bdaddr, true); - - bta_dm_search_cmpl(); - } -} - -/******************************************************************************* - * - * Function bta_dm_free_sdp_db - * - * Description Frees SDP data base - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_free_sdp_db() { osi_free_and_reset((void**)&bta_dm_search_cb.p_sdp_db); } - -/******************************************************************************* - * - * Function bta_dm_queue_search - * - * Description Queues search command - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_queue_search(tBTA_DM_API_SEARCH& search) { - if (bta_dm_search_cb.p_pending_search) { - log::warn("Overwrote previous device discovery inquiry scan request"); - } - bta_dm_search_cb.p_pending_search.reset(new tBTA_DM_MSG(search)); - log::info("Queued device discovery inquiry scan request"); -} - -/******************************************************************************* - * - * Function bta_dm_queue_disc - * - * Description Queues discovery command - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_queue_disc(tBTA_DM_API_DISCOVER& discovery) { - log::info("bta_dm_discovery: queuing service discovery to {}", discovery.bd_addr); - bta_dm_search_cb.pending_discovery_queue.push(discovery); -} - -/******************************************************************************* - * - * Function bta_dm_execute_queued_request - * - * Description Executes queued request if one exists - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_execute_queued_request() { - if (!bta_dm_search_cb.pending_discovery_queue.empty()) { - tBTA_DM_API_DISCOVER pending_discovery = bta_dm_search_cb.pending_discovery_queue.front(); - bta_dm_search_cb.pending_discovery_queue.pop(); - log::info("Start pending discovery"); - post_disc_evt(BTA_DM_API_DISCOVER_EVT, - std::make_unique<tBTA_DM_MSG>(tBTA_DM_API_DISCOVER{pending_discovery})); - } else if (bta_dm_search_cb.p_pending_search) { - log::info("Start pending search"); - post_disc_evt(BTA_DM_API_SEARCH_EVT, std::move(bta_dm_search_cb.p_pending_search)); - bta_dm_search_cb.p_pending_search.reset(); - } -} - -/******************************************************************************* - * - * Function bta_dm_is_search_request_queued - * - * Description Checks if there is a queued search request - * - * Returns bool - * - ******************************************************************************/ -bool bta_dm_is_search_request_queued() { return bta_dm_search_cb.p_pending_search != NULL; } - -/******************************************************************************* - * - * Function bta_dm_search_clear_queue - * - * Description Clears the queue if API search cancel is called - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_search_clear_queue() { bta_dm_search_cb.p_pending_search.reset(); } - -/******************************************************************************* - * - * Function bta_dm_search_cancel_notify - * - * Description Notify application that search has been cancelled - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_search_cancel_notify() { - if (bta_dm_search_cb.p_device_search_cback) { - bta_dm_search_cb.p_device_search_cback(BTA_DM_SEARCH_CANCEL_CMPL_EVT, NULL); - } - switch (bta_dm_search_get_state()) { - case BTA_DM_SEARCH_ACTIVE: - case BTA_DM_SEARCH_CANCELLING: - if (!bta_dm_search_cb.name_discover_done) { - if (get_stack_rnr_interface().BTM_CancelRemoteDeviceName() != - tBTM_STATUS::BTM_CMD_STARTED) { - log::warn("Unable to cancel RNR"); - } - } - break; - case BTA_DM_SEARCH_IDLE: - case BTA_DM_DISCOVER_ACTIVE: - // Nothing to do - break; - } -} - -/******************************************************************************* - * - * Function bta_dm_find_services - * - * Description Starts discovery on a device - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_find_services(const RawAddress& bd_addr) { - while (bta_dm_search_cb.service_index < BTA_MAX_SERVICE_ID) { - Uuid uuid = Uuid::kEmpty; - if (bta_dm_search_cb.services_to_search & - (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index))) { - bta_dm_search_cb.p_sdp_db = (tSDP_DISCOVERY_DB*)osi_malloc(BTA_DM_SDP_DB_SIZE); - - /* try to search all services by search based on L2CAP UUID */ - log::info("services_to_search={:08x}", bta_dm_search_cb.services_to_search); - if (bta_dm_search_cb.services_to_search & BTA_RES_SERVICE_MASK) { - uuid = Uuid::From16Bit(bta_service_id_to_uuid_lkup_tbl[0]); - bta_dm_search_cb.services_to_search &= ~BTA_RES_SERVICE_MASK; - } else { - uuid = Uuid::From16Bit(UUID_PROTOCOL_L2CAP); - bta_dm_search_cb.services_to_search = 0; - } - - log::info("search UUID = {}", uuid.ToString()); - if (!get_legacy_stack_sdp_api()->service.SDP_InitDiscoveryDb( - bta_dm_search_cb.p_sdp_db, BTA_DM_SDP_DB_SIZE, 1, &uuid, 0, NULL)) { - log::warn("Unable to initialize SDP service discovery db peer:{}", bd_addr); - } - - memset(g_disc_raw_data_buf, 0, sizeof(g_disc_raw_data_buf)); - bta_dm_search_cb.p_sdp_db->raw_data = g_disc_raw_data_buf; - - bta_dm_search_cb.p_sdp_db->raw_size = MAX_DISC_RAW_DATA_BUF; - - if (!get_legacy_stack_sdp_api()->service.SDP_ServiceSearchAttributeRequest( - bd_addr, bta_dm_search_cb.p_sdp_db, &bta_dm_sdp_callback)) { - log::warn("Unable to start SDP service search attribute request peer:{}", bd_addr); - /* - * If discovery is not successful with this device, then - * proceed with the next one. - */ - osi_free_and_reset((void**)&bta_dm_search_cb.p_sdp_db); - bta_dm_search_cb.service_index = BTA_MAX_SERVICE_ID; - - } else { - if (uuid == Uuid::From16Bit(UUID_PROTOCOL_L2CAP)) { - if (!is_sdp_pbap_pce_disabled(bd_addr)) { - log::debug("SDP search for PBAP Client"); - BTA_SdpSearch(bd_addr, Uuid::From16Bit(UUID_SERVCLASS_PBAP_PCE)); - } - } - bta_dm_search_cb.service_index++; - return; - } - } - - bta_dm_search_cb.service_index++; - } - - /* no more services to be discovered */ - if (bta_dm_search_cb.service_index >= BTA_MAX_SERVICE_ID) { - auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{}); - auto& disc_result = std::get<tBTA_DM_SVC_RES>(*msg); - disc_result.services = bta_dm_search_cb.services_found; - disc_result.bd_addr = bta_dm_search_cb.peer_bdaddr; - - post_disc_evt(BTA_DM_DISCOVERY_RESULT_EVT, std::move(msg)); - } -} - -/******************************************************************************* - * - * Function bta_dm_discover_next_device - * - * Description Starts discovery on the next device in Inquiry data base - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_discover_next_device(void) { - log::verbose("bta_dm_discover_next_device"); - - /* searching next device on inquiry result */ - bta_dm_search_cb.p_btm_inq_info = - get_btm_client_interface().db.BTM_InqDbNext(bta_dm_search_cb.p_btm_inq_info); - if (bta_dm_search_cb.p_btm_inq_info != NULL) { - bta_dm_search_cb.name_discover_done = false; - bta_dm_search_cb.peer_name[0] = 0; - bta_dm_discover_name(bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr); - } else { - post_disc_evt(BTA_DM_SEARCH_CMPL_EVT, nullptr); - } -} - -/******************************************************************************* - * - * Function bta_dm_determine_discovery_transport - * - * Description Starts name and service discovery on the device - * - * Returns void - * - ******************************************************************************/ -static tBT_TRANSPORT bta_dm_determine_discovery_transport(const RawAddress& remote_bd_addr) { - tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR; - if (bta_dm_search_cb.transport == BT_TRANSPORT_AUTO) { - tBT_DEVICE_TYPE dev_type; - tBLE_ADDR_TYPE addr_type; - - get_btm_client_interface().peer.BTM_ReadDevInfo(remote_bd_addr, &dev_type, &addr_type); - if (dev_type == BT_DEVICE_TYPE_BLE || addr_type == BLE_ADDR_RANDOM) { - transport = BT_TRANSPORT_LE; - } else if (dev_type == BT_DEVICE_TYPE_DUMO) { - if (get_btm_client_interface().peer.BTM_IsAclConnectionUp(remote_bd_addr, - BT_TRANSPORT_BR_EDR)) { - transport = BT_TRANSPORT_BR_EDR; - } else if (get_btm_client_interface().peer.BTM_IsAclConnectionUp(remote_bd_addr, - BT_TRANSPORT_LE)) { - transport = BT_TRANSPORT_LE; - } - } - } else { - transport = bta_dm_search_cb.transport; - } - return transport; -} - -static void bta_dm_discover_name(const RawAddress& remote_bd_addr) { - const tBT_TRANSPORT transport = bta_dm_determine_discovery_transport(remote_bd_addr); - - log::verbose("BDA: {}", remote_bd_addr); - - bta_dm_search_cb.peer_bdaddr = remote_bd_addr; - - log::verbose("name_discover_done = {} p_btm_inq_info 0x{} state = {}, transport={}", - bta_dm_search_cb.name_discover_done, fmt::ptr(bta_dm_search_cb.p_btm_inq_info), - bta_dm_search_get_state(), transport); - - if (bta_dm_search_cb.p_btm_inq_info) { - log::verbose("appl_knows_rem_name {}", bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name); - } - if (((bta_dm_search_cb.p_btm_inq_info) && - (bta_dm_search_cb.p_btm_inq_info->results.device_type == BT_DEVICE_TYPE_BLE) && - (bta_dm_search_get_state() == BTA_DM_SEARCH_ACTIVE)) || - (transport == BT_TRANSPORT_LE && - interop_match_addr(INTEROP_DISABLE_NAME_REQUEST, &bta_dm_search_cb.peer_bdaddr))) { - /* Do not perform RNR for LE devices at inquiry complete*/ - bta_dm_search_cb.name_discover_done = true; - } - // If we already have the name we can skip getting the name - if (get_stack_rnr_interface().BTM_IsRemoteNameKnown(remote_bd_addr, transport)) { - log::debug("Security record already known skipping read remote name peer:{}", remote_bd_addr); - bta_dm_search_cb.name_discover_done = true; - } - - /* if name discovery is not done and application needs remote name */ - if ((!bta_dm_search_cb.name_discover_done) && - ((bta_dm_search_cb.p_btm_inq_info == NULL) || - (bta_dm_search_cb.p_btm_inq_info && - (!bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name)))) { - if (bta_dm_read_remote_device_name(bta_dm_search_cb.peer_bdaddr, transport)) { - if (bta_dm_search_get_state() != BTA_DM_DISCOVER_ACTIVE) { - log::debug("Reset transport state for next discovery"); - bta_dm_search_cb.transport = BT_TRANSPORT_AUTO; - } - BTM_LogHistory(kBtmLogTag, bta_dm_search_cb.peer_bdaddr, "Read remote name", - base::StringPrintf("Transport:%s", bt_transport_text(transport).c_str())); - return; - } else { - log::error("Unable to start read remote device name"); - } - - /* starting name discovery failed */ - bta_dm_search_cb.name_discover_done = true; - } - - /* Reset transport state for next discovery */ - bta_dm_search_cb.transport = BT_TRANSPORT_AUTO; - - /* name discovery is done for this device */ - if (bta_dm_search_get_state() == BTA_DM_SEARCH_ACTIVE) { - // if p_btm_inq_info is nullptr, there is no more inquiry results to - // discover name for - if (bta_dm_search_cb.p_btm_inq_info) { - bta_dm_discover_next_device(); - } else { - log::info("end of parsing inquiry result"); - } - } else { - log::info("name discovery finished in bad state: {}", - bta_dm_state_text(bta_dm_search_get_state())); - } -} - -static void bta_dm_discover_services(const RawAddress& remote_bd_addr) { - const tBT_TRANSPORT transport = bta_dm_determine_discovery_transport(remote_bd_addr); - - log::verbose("BDA: {}, transport={}, state = {}", remote_bd_addr, transport, - bta_dm_search_get_state()); - - bta_dm_search_cb.peer_bdaddr = remote_bd_addr; - - /* Reset transport state for next discovery */ - bta_dm_search_cb.transport = BT_TRANSPORT_AUTO; - - bool sdp_disable = HID_HostSDPDisable(remote_bd_addr); - if (sdp_disable) { - log::debug("peer:{} with HIDSDPDisable attribute.", remote_bd_addr); - } - - /* if application wants to discover service and HIDSDPDisable attribute is - false. - Classic mouses with this attribute should not start SDP here, because the - SDP has been done during bonding. SDP request here will interleave with - connections to the Control or Interrupt channels */ - if (!sdp_disable) { - BTM_LogHistory(kBtmLogTag, remote_bd_addr, "Discovery started ", - base::StringPrintf("Transport:%s", bt_transport_text(transport).c_str())); - - /* initialize variables */ - bta_dm_search_cb.service_index = 0; - bta_dm_search_cb.services_found = 0; - bta_dm_search_cb.services_to_search = BTA_ALL_SERVICE_MASK; - - /* if seaching with EIR is not completed */ - if (bta_dm_search_cb.services_to_search) { - /* check whether connection already exists to the device - if connection exists, we don't have to wait for ACL - link to go down to start search on next device */ - if (transport == BT_TRANSPORT_BR_EDR) { - if (get_btm_client_interface().peer.BTM_IsAclConnectionUp(bta_dm_search_cb.peer_bdaddr, - BT_TRANSPORT_BR_EDR)) { - bta_dm_search_cb.wait_disc = false; - } else { - bta_dm_search_cb.wait_disc = true; - } - } - - if (transport == BT_TRANSPORT_LE) { - if (bta_dm_search_cb.services_to_search & BTA_BLE_SERVICE_MASK) { - log::info("bta_dm_discovery: starting GATT discovery on {}", - bta_dm_search_cb.peer_bdaddr); - // set the raw data buffer here - memset(g_disc_raw_data_buf, 0, sizeof(g_disc_raw_data_buf)); - /* start GATT for service discovery */ - btm_dm_start_gatt_discovery(bta_dm_search_cb.peer_bdaddr); - return; - } - } else { - log::info("bta_dm_discovery: starting SDP discovery on {}", bta_dm_search_cb.peer_bdaddr); - bta_dm_search_cb.sdp_results = false; - bta_dm_find_services(bta_dm_search_cb.peer_bdaddr); - return; - } - } - } - - /* service discovery is done for this device */ - auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{}); - auto& svc_result = std::get<tBTA_DM_SVC_RES>(*msg); - - /* initialize the data structure */ - svc_result.result = BTA_SUCCESS; - svc_result.services = bta_dm_search_cb.services_found; - svc_result.bd_addr = bta_dm_search_cb.peer_bdaddr; - - bta_dm_search_sm_execute(BTA_DM_DISCOVERY_RESULT_EVT, std::move(msg)); -} - -/******************************************************************************* - * - * Function bta_dm_sdp_callback - * - * Description Callback from sdp with discovery status - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_sdp_callback(const RawAddress& /* bd_addr */, tSDP_STATUS sdp_status) { - post_disc_evt(BTA_DM_SDP_RESULT_EVT, - std::make_unique<tBTA_DM_MSG>(tBTA_DM_SDP_RESULT{.sdp_result = sdp_status})); -} - -/******************************************************************************* - * - * Function bta_dm_inq_results_cb - * - * Description Inquiry results callback from BTM - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_inq_results_cb(tBTM_INQ_RESULTS* p_inq, const uint8_t* p_eir, uint16_t eir_len) { - tBTA_DM_SEARCH result; - tBTM_INQ_INFO* p_inq_info; - uint16_t service_class; - - result.inq_res.bd_addr = p_inq->remote_bd_addr; - - // Pass the original address to GattService#onScanResult - result.inq_res.original_bda = p_inq->original_bda; - - result.inq_res.dev_class = p_inq->dev_class; - BTM_COD_SERVICE_CLASS(service_class, p_inq->dev_class); - result.inq_res.is_limited = (service_class & BTM_COD_SERVICE_LMTD_DISCOVER) ? true : false; - result.inq_res.rssi = p_inq->rssi; - - result.inq_res.ble_addr_type = p_inq->ble_addr_type; - result.inq_res.inq_result_type = p_inq->inq_result_type; - result.inq_res.device_type = p_inq->device_type; - result.inq_res.flag = p_inq->flag; - result.inq_res.include_rsi = p_inq->include_rsi; - result.inq_res.clock_offset = p_inq->clock_offset; - - /* application will parse EIR to find out remote device name */ - result.inq_res.p_eir = const_cast<uint8_t*>(p_eir); - result.inq_res.eir_len = eir_len; - - result.inq_res.ble_evt_type = p_inq->ble_evt_type; - - p_inq_info = get_btm_client_interface().db.BTM_InqDbRead(p_inq->remote_bd_addr); - if (p_inq_info != NULL) { - /* initialize remt_name_not_required to false so that we get the name by - * default */ - result.inq_res.remt_name_not_required = false; - } - - if (bta_dm_search_cb.p_device_search_cback) { - bta_dm_search_cb.p_device_search_cback(BTA_DM_INQ_RES_EVT, &result); - } - - if (p_inq_info) { - /* application indicates if it knows the remote name, inside the callback - copy that to the inquiry data base*/ - if (result.inq_res.remt_name_not_required) { - p_inq_info->appl_knows_rem_name = true; - } - } -} - -/******************************************************************************* - * - * Function bta_dm_inq_cmpl_cb - * - * Description Inquiry complete callback from BTM - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_inq_cmpl_cb(void* /* p_result */) { - log::verbose(""); - - bta_dm_inq_cmpl(); -} - -/******************************************************************************* - * - * Function bta_dm_service_search_remname_cback - * - * Description Remote name call back from BTM during service discovery - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_service_search_remname_cback(const RawAddress& bd_addr, DEV_CLASS /* dc */, - BD_NAME bd_name) { - tBTM_REMOTE_DEV_NAME rem_name = {}; - tBTM_STATUS btm_status; - - log::verbose("name=<{}>", reinterpret_cast<char const*>(bd_name)); - - /* if this is what we are looking for */ - if (bta_dm_search_cb.peer_bdaddr == bd_addr) { - rem_name.bd_addr = bd_addr; - bd_name_copy(rem_name.remote_bd_name, bd_name); - rem_name.btm_status = tBTM_STATUS::BTM_SUCCESS; - rem_name.hci_status = HCI_SUCCESS; - bta_dm_remname_cback(&rem_name); - } else { - /* get name of device */ - btm_status = get_stack_rnr_interface().BTM_ReadRemoteDeviceName( - bta_dm_search_cb.peer_bdaddr, bta_dm_remname_cback, BT_TRANSPORT_BR_EDR); - if (btm_status == tBTM_STATUS::BTM_BUSY) { - /* wait for next chance(notification of remote name discovery done) */ - log::verbose("BTM_ReadRemoteDeviceName is busy"); - } else if (btm_status != tBTM_STATUS::BTM_CMD_STARTED) { - /* if failed to start getting remote name then continue */ - log::warn("BTM_ReadRemoteDeviceName returns 0x{:02X}", btm_status); - - // needed so our response is not ignored, since this corresponds to the - // actual peer_bdaddr - rem_name.bd_addr = bta_dm_search_cb.peer_bdaddr; - rem_name.remote_bd_name[0] = 0; - rem_name.btm_status = btm_status; - rem_name.hci_status = HCI_SUCCESS; - bta_dm_remname_cback(&rem_name); - } - } -} - -/******************************************************************************* - * - * Function bta_dm_remname_cback - * - * Description Remote name complete call back from BTM - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_remname_cback(const tBTM_REMOTE_DEV_NAME* p_remote_name) { - log::assert_that(p_remote_name != nullptr, "assert failed: p_remote_name != nullptr"); - - log::info( - "Remote name request complete peer:{} btm_status:{} hci_status:{} name[0]:{:c} length:{}", - p_remote_name->bd_addr, btm_status_text(p_remote_name->btm_status), - hci_error_code_text(p_remote_name->hci_status), p_remote_name->remote_bd_name[0], - strnlen((const char*)p_remote_name->remote_bd_name, BD_NAME_LEN)); - - if (bta_dm_search_cb.peer_bdaddr == p_remote_name->bd_addr) { - get_stack_rnr_interface().BTM_SecDeleteRmtNameNotifyCallback( - &bta_dm_service_search_remname_cback); - } else { - // if we got a different response, maybe ignore it - // we will have made a request directly from BTM_ReadRemoteDeviceName so we - // expect a dedicated response for us - if (p_remote_name->hci_status == HCI_ERR_CONNECTION_EXISTS) { - get_stack_rnr_interface().BTM_SecDeleteRmtNameNotifyCallback( - &bta_dm_service_search_remname_cback); - log::info("Assume command failed due to disconnection hci_status:{} peer:{}", - hci_error_code_text(p_remote_name->hci_status), p_remote_name->bd_addr); - } else { - log::info("Ignored remote name response for the wrong address exp:{} act:{}", - bta_dm_search_cb.peer_bdaddr, p_remote_name->bd_addr); - return; - } - } - - /* remote name discovery is done but it could be failed */ - bta_dm_search_cb.name_discover_done = true; - bd_name_copy(bta_dm_search_cb.peer_name, p_remote_name->remote_bd_name); - - if (bta_dm_search_cb.transport == BT_TRANSPORT_LE) { - GAP_BleReadPeerPrefConnParams(bta_dm_search_cb.peer_bdaddr); - } - - auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_REMOTE_NAME{}); - auto& rmt_name_msg = std::get<tBTA_DM_REMOTE_NAME>(*msg); - rmt_name_msg.bd_addr = bta_dm_search_cb.peer_bdaddr; - rmt_name_msg.hci_status = p_remote_name->hci_status; - bd_name_copy(rmt_name_msg.bd_name, p_remote_name->remote_bd_name); - - post_disc_evt(BTA_DM_REMT_NAME_EVT, std::move(msg)); -} - -/******************************************************************************* - * - * Function bta_dm_get_remname - * - * Description Returns a pointer to the remote name stored in the DM - * control block if it exists, or from the BTM memory. - * - * Returns char * - Pointer to the remote device name - ******************************************************************************/ -const char* bta_dm_get_remname(void) { - const char* p_name = (const char*)bta_dm_search_cb.peer_name; - - /* If the name isn't already stored, try retrieving from BTM */ - if (*p_name == '\0') { - const char* p_temp = - get_btm_client_interface().security.BTM_SecReadDevName(bta_dm_search_cb.peer_bdaddr); - if (p_temp != NULL) { - p_name = (const char*)p_temp; - } - } - - return p_name; -} - -#ifndef BTA_DM_GATT_CLOSE_DELAY_TOUT -#define BTA_DM_GATT_CLOSE_DELAY_TOUT 1000 -#endif - -/******************************************************************************* - * - * Function bta_dm_gattc_register - * - * Description Register with GATTC in DM if BLE is needed. - * - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_gattc_register(void) { - if (bta_dm_search_cb.client_if != BTA_GATTS_INVALID_IF) { - // Already registered - return; - } - get_gatt_interface().BTA_GATTC_AppRegister( - bta_dm_gattc_callback, base::Bind([](uint8_t client_id, uint8_t status) { - tGATT_STATUS gatt_status = static_cast<tGATT_STATUS>(status); - disc_gatt_history_.Push(base::StringPrintf("%-32s client_id:%hu status:%s", - "GATTC_RegisteredCallback", client_id, - gatt_status_text(gatt_status).c_str())); - if (static_cast<tGATT_STATUS>(status) == GATT_SUCCESS) { - log::info("Registered device discovery search gatt client tGATT_IF:{}", client_id); - bta_dm_search_cb.client_if = client_id; - } else { - log::warn( - "Failed to register device discovery search gatt client " - "gatt_status:{} previous tGATT_IF:{}", - bta_dm_search_cb.client_if, status); - bta_dm_search_cb.client_if = BTA_GATTS_INVALID_IF; - } - }), - false); -} - -static void gatt_close_timer_cb(void*) { - bta_dm_search_sm_execute(BTA_DM_DISC_CLOSE_TOUT_EVT, nullptr); -} - -/******************************************************************************* - * - * Function bta_dm_gatt_disc_complete - * - * Description This function process the GATT service search complete. - * - * Parameters: - * - ******************************************************************************/ -static void bta_dm_gatt_disc_complete(uint16_t conn_id, tGATT_STATUS status) { - log::verbose("conn_id = {}", conn_id); - - auto msg = std::make_unique<tBTA_DM_MSG>(tBTA_DM_SVC_RES{}); - auto& svc_result = std::get<tBTA_DM_SVC_RES>(*msg); - - /* no more services to be discovered */ - svc_result.result = (status == GATT_SUCCESS) ? BTA_SUCCESS : BTA_FAILURE; - log::verbose("service found: 0x{:08x}", bta_dm_search_cb.services_found); - svc_result.services = bta_dm_search_cb.services_found; - svc_result.bd_addr = bta_dm_search_cb.peer_bdaddr; - svc_result.device_type |= BT_DEVICE_TYPE_BLE; - - bta_dm_search_sm_execute(BTA_DM_DISCOVERY_RESULT_EVT, std::move(msg)); - - if (conn_id != GATT_INVALID_CONN_ID) { - bta_dm_search_cb.pending_close_bda = bta_dm_search_cb.peer_bdaddr; - // Gatt will be close immediately if bluetooth.gatt.delay_close.enabled is - // set to false. If property is true / unset there will be a delay - if (bta_dm_search_cb.gatt_close_timer != nullptr) { - /* start a GATT channel close delay timer */ - alarm_set_on_mloop(bta_dm_search_cb.gatt_close_timer, BTA_DM_GATT_CLOSE_DELAY_TOUT, - gatt_close_timer_cb, 0); - } else { - bta_dm_search_sm_execute(BTA_DM_DISC_CLOSE_TOUT_EVT, nullptr); - } - } else { - log::info("Discovery complete for invalid conn ID. Will pick up next job"); - if (com::android::bluetooth::flags::cancel_open_discovery_client()) { - bta_dm_close_gatt_conn(); - } else { - bta_dm_search_cb.conn_id = GATT_INVALID_CONN_ID; - } - bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); - bta_dm_free_sdp_db(); - bta_dm_execute_queued_request(); - } -} - -/******************************************************************************* - * - * Function bta_dm_close_gatt_conn - * - * Description This function close the GATT connection after delay - *timeout. - * - * Parameters: - * - ******************************************************************************/ -static void bta_dm_close_gatt_conn() { - if (bta_dm_search_cb.conn_id != GATT_INVALID_CONN_ID) { - BTA_GATTC_Close(bta_dm_search_cb.conn_id); - } - - bta_dm_search_cb.pending_close_bda = RawAddress::kEmpty; - bta_dm_search_cb.conn_id = GATT_INVALID_CONN_ID; -} -/******************************************************************************* - * - * Function btm_dm_start_gatt_discovery - * - * Description This is GATT initiate the service search by open a GATT - * connection first. - * - * Parameters: - * - ******************************************************************************/ -static void btm_dm_start_gatt_discovery(const RawAddress& bd_addr) { - constexpr bool kUseOpportunistic = true; - - bta_dm_search_cb.gatt_disc_active = true; - - /* connection is already open */ - if (bta_dm_search_cb.pending_close_bda == bd_addr && - bta_dm_search_cb.conn_id != GATT_INVALID_CONN_ID) { - bta_dm_search_cb.pending_close_bda = RawAddress::kEmpty; - alarm_cancel(bta_dm_search_cb.gatt_close_timer); - get_gatt_interface().BTA_GATTC_ServiceSearchRequest(bta_dm_search_cb.conn_id, nullptr); - } else { - if (get_btm_client_interface().peer.BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_LE)) { - log::debug( - "Use existing gatt client connection for discovery peer:{} " - "transport:{} opportunistic:{:c}", - bd_addr, bt_transport_text(BT_TRANSPORT_LE), (kUseOpportunistic) ? 'T' : 'F'); - get_gatt_interface().BTA_GATTC_Open(bta_dm_search_cb.client_if, bd_addr, - BTM_BLE_DIRECT_CONNECTION, kUseOpportunistic); - } else { - log::debug( - "Opening new gatt client connection for discovery peer:{} " - "transport:{} opportunistic:{:c}", - bd_addr, bt_transport_text(BT_TRANSPORT_LE), (!kUseOpportunistic) ? 'T' : 'F'); - get_gatt_interface().BTA_GATTC_Open(bta_dm_search_cb.client_if, bd_addr, - BTM_BLE_DIRECT_CONNECTION, !kUseOpportunistic); - } - } -} - -/******************************************************************************* - * - * Function bta_dm_proc_open_evt - * - * Description process BTA_GATTC_OPEN_EVT in DM. - * - * Parameters: - * - ******************************************************************************/ -static void bta_dm_proc_open_evt(tBTA_GATTC_OPEN* p_data) { - log::verbose("DM Search state= {} search_cb.peer_dbaddr:{} connected_bda={}", - bta_dm_search_get_state(), bta_dm_search_cb.peer_bdaddr, p_data->remote_bda); - - log::debug("BTA_GATTC_OPEN_EVT conn_id = {} client_if={} status = {}", p_data->conn_id, - p_data->client_if, p_data->status); - - disc_gatt_history_.Push(base::StringPrintf( - "%-32s bd_addr:%s conn_id:%hu client_if:%hu event:%s", "GATTC_EventCallback", - ADDRESS_TO_LOGGABLE_CSTR(p_data->remote_bda), p_data->conn_id, p_data->client_if, - gatt_client_event_text(BTA_GATTC_OPEN_EVT).c_str())); - - bta_dm_search_cb.conn_id = p_data->conn_id; - - if (p_data->status == GATT_SUCCESS) { - get_gatt_interface().BTA_GATTC_ServiceSearchRequest(p_data->conn_id, nullptr); - } else { - bta_dm_gatt_disc_complete(GATT_INVALID_CONN_ID, p_data->status); - } -} - -/******************************************************************************* - * - * Function bta_dm_gattc_callback - * - * Description This is GATT client callback function used in DM. - * - * Parameters: - * - ******************************************************************************/ -static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) { - log::verbose("bta_dm_gattc_callback event = {}", event); - - switch (event) { - case BTA_GATTC_OPEN_EVT: - bta_dm_proc_open_evt(&p_data->open); - break; - - case BTA_GATTC_SEARCH_CMPL_EVT: - switch (bta_dm_search_get_state()) { - case BTA_DM_SEARCH_IDLE: - break; - case BTA_DM_SEARCH_ACTIVE: - case BTA_DM_SEARCH_CANCELLING: - case BTA_DM_DISCOVER_ACTIVE: - bta_dm_gatt_disc_complete(p_data->search_cmpl.conn_id, p_data->search_cmpl.status); - break; - } - disc_gatt_history_.Push(base::StringPrintf( - "%-32s conn_id:%hu status:%s", "GATTC_EventCallback", p_data->search_cmpl.conn_id, - gatt_status_text(p_data->search_cmpl.status).c_str())); - break; - - case BTA_GATTC_CLOSE_EVT: - log::info("BTA_GATTC_CLOSE_EVT reason = {}", p_data->close.reason); - - if (p_data->close.remote_bda == bta_dm_search_cb.peer_bdaddr) { - bta_dm_search_cb.conn_id = GATT_INVALID_CONN_ID; - } - - switch (bta_dm_search_get_state()) { - case BTA_DM_SEARCH_IDLE: - case BTA_DM_SEARCH_ACTIVE: - break; - - case BTA_DM_SEARCH_CANCELLING: - case BTA_DM_DISCOVER_ACTIVE: - /* in case of disconnect before search is completed */ - if (p_data->close.remote_bda == bta_dm_search_cb.peer_bdaddr) { - bta_dm_gatt_disc_complete((uint16_t)GATT_INVALID_CONN_ID, (tGATT_STATUS)GATT_ERROR); - } - } - break; - - case BTA_GATTC_CANCEL_OPEN_EVT: - case BTA_GATTC_CFG_MTU_EVT: - case BTA_GATTC_CONGEST_EVT: - case BTA_GATTC_CONN_UPDATE_EVT: - case BTA_GATTC_DEREG_EVT: - case BTA_GATTC_ENC_CMPL_CB_EVT: - case BTA_GATTC_EXEC_EVT: - case BTA_GATTC_NOTIF_EVT: - case BTA_GATTC_PHY_UPDATE_EVT: - case BTA_GATTC_SEARCH_RES_EVT: - case BTA_GATTC_SRVC_CHG_EVT: - case BTA_GATTC_SRVC_DISC_DONE_EVT: - case BTA_GATTC_SUBRATE_CHG_EVT: - disc_gatt_history_.Push(base::StringPrintf("%-32s event:%s", "GATTC_EventCallback", - gatt_client_event_text(event).c_str())); - break; - } -} - -namespace bluetooth { -namespace legacy { -namespace testing { - -void bta_dm_remname_cback(const tBTM_REMOTE_DEV_NAME* p) { - ::bta_dm_disc_legacy::bta_dm_remname_cback(p); -} - -tBT_TRANSPORT bta_dm_determine_discovery_transport(const RawAddress& bd_addr) { - return ::bta_dm_disc_legacy::bta_dm_determine_discovery_transport(bd_addr); -} - -void bta_dm_remote_name_cmpl(const tBTA_DM_REMOTE_NAME& remote_name_msg) { - ::bta_dm_disc_legacy::bta_dm_remote_name_cmpl(remote_name_msg); -} - -void bta_dm_sdp_result(tBTA_DM_SDP_RESULT& sdp_event) { - ::bta_dm_disc_legacy::bta_dm_sdp_result(sdp_event); -} - -} // namespace testing -} // namespace legacy -} // namespace bluetooth - -namespace { -constexpr size_t kSearchStateHistorySize = 50; -constexpr char kTimeFormatString[] = "%Y-%m-%d %H:%M:%S"; - -constexpr unsigned MillisPerSecond = 1000; -std::string EpochMillisToString(long long time_ms) { - time_t time_sec = time_ms / MillisPerSecond; - struct tm tm; - localtime_r(&time_sec, &tm); - std::string s = ::bluetooth::common::StringFormatTime(kTimeFormatString, tm); - return base::StringPrintf("%s.%03u", s.c_str(), - static_cast<unsigned int>(time_ms % MillisPerSecond)); -} - -} // namespace - -struct tSEARCH_STATE_HISTORY { - const tBTA_DM_STATE state; - const tBTA_DM_EVT event; - std::string ToString() const { - return base::StringPrintf("state:%25s event:%s", bta_dm_state_text(state).c_str(), - bta_dm_event_text(event).c_str()); - } -}; - -::bluetooth::common::TimestampedCircularBuffer<tSEARCH_STATE_HISTORY> search_state_history_( - kSearchStateHistorySize); - -/******************************************************************************* - * - * Function bta_dm_search_sm_execute - * - * Description State machine event handling function for DM - * - * - * Returns void - * - ******************************************************************************/ -static void bta_dm_search_sm_execute(tBTA_DM_EVT event, std::unique_ptr<tBTA_DM_MSG> msg) { - log::info("state:{}, event:{}[0x{:x}]", bta_dm_state_text(bta_dm_search_get_state()), - bta_dm_event_text(event), event); - search_state_history_.Push({ - .state = bta_dm_search_get_state(), - .event = event, - }); - - switch (bta_dm_search_get_state()) { - case BTA_DM_SEARCH_IDLE: - switch (event) { - case BTA_DM_API_SEARCH_EVT: - bta_dm_search_set_state(BTA_DM_SEARCH_ACTIVE); - log::assert_that(std::holds_alternative<tBTA_DM_API_SEARCH>(*msg), "bad message type: {}", - msg->index()); - - bta_dm_search_start(std::get<tBTA_DM_API_SEARCH>(*msg)); - break; - case BTA_DM_API_DISCOVER_EVT: - bta_dm_search_set_state(BTA_DM_DISCOVER_ACTIVE); - log::assert_that(std::holds_alternative<tBTA_DM_API_DISCOVER>(*msg), - "bad message type: {}", msg->index()); - - bta_dm_discover(std::get<tBTA_DM_API_DISCOVER>(*msg)); - break; - case BTA_DM_API_SEARCH_CANCEL_EVT: - bta_dm_search_clear_queue(); - bta_dm_search_cancel_notify(); - break; - case BTA_DM_SDP_RESULT_EVT: - bta_dm_free_sdp_db(); - break; - case BTA_DM_DISC_CLOSE_TOUT_EVT: - bta_dm_close_gatt_conn(); - break; - default: - log::info("Received unexpected event {}[0x{:x}] in state {}", bta_dm_event_text(event), - event, bta_dm_state_text(bta_dm_search_get_state())); - } - break; - case BTA_DM_SEARCH_ACTIVE: - switch (event) { - case BTA_DM_REMT_NAME_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_REMOTE_NAME>(*msg), - "bad message type: {}", msg->index()); - - bta_dm_remote_name_cmpl(std::get<tBTA_DM_REMOTE_NAME>(*msg)); - break; - case BTA_DM_SEARCH_CMPL_EVT: - bta_dm_search_cmpl(); - break; - case BTA_DM_DISCOVERY_RESULT_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_SVC_RES>(*msg), "bad message type: {}", - msg->index()); - - bta_dm_disc_result(std::get<tBTA_DM_SVC_RES>(*msg)); - break; - case BTA_DM_DISC_CLOSE_TOUT_EVT: - bta_dm_close_gatt_conn(); - break; - case BTA_DM_API_DISCOVER_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_API_DISCOVER>(*msg), - "bad message type: {}", msg->index()); - - bta_dm_queue_disc(std::get<tBTA_DM_API_DISCOVER>(*msg)); - break; - case BTA_DM_API_SEARCH_CANCEL_EVT: - bta_dm_search_clear_queue(); - bta_dm_search_set_state(BTA_DM_SEARCH_CANCELLING); - bta_dm_search_cancel(); - break; - default: - log::info("Received unexpected event {}[0x{:x}] in state {}", bta_dm_event_text(event), - event, bta_dm_state_text(bta_dm_search_get_state())); - } - break; - case BTA_DM_SEARCH_CANCELLING: - switch (event) { - case BTA_DM_API_SEARCH_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_API_SEARCH>(*msg), "bad message type: {}", - msg->index()); - - bta_dm_queue_search(std::get<tBTA_DM_API_SEARCH>(*msg)); - break; - case BTA_DM_API_DISCOVER_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_API_DISCOVER>(*msg), - "bad message type: {}", msg->index()); - - bta_dm_queue_disc(std::get<tBTA_DM_API_DISCOVER>(*msg)); - break; - case BTA_DM_API_SEARCH_CANCEL_EVT: - bta_dm_search_clear_queue(); - bta_dm_search_cancel_notify(); - break; - case BTA_DM_SDP_RESULT_EVT: - case BTA_DM_REMT_NAME_EVT: - case BTA_DM_SEARCH_CMPL_EVT: - case BTA_DM_DISCOVERY_RESULT_EVT: - bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); - bta_dm_free_sdp_db(); - bta_dm_search_cancel_notify(); - bta_dm_execute_queued_request(); - break; - case BTA_DM_DISC_CLOSE_TOUT_EVT: - bta_dm_close_gatt_conn(); - break; - default: - log::info("Received unexpected event {}[0x{:x}] in state {}", bta_dm_event_text(event), - event, bta_dm_state_text(bta_dm_search_get_state())); - } - break; - case BTA_DM_DISCOVER_ACTIVE: - switch (event) { - case BTA_DM_REMT_NAME_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_REMOTE_NAME>(*msg), - "bad message type: {}", msg->index()); - - bta_dm_remote_name_cmpl(std::get<tBTA_DM_REMOTE_NAME>(*msg)); - break; - case BTA_DM_SDP_RESULT_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_SDP_RESULT>(*msg), "bad message type: {}", - msg->index()); - - bta_dm_sdp_result(std::get<tBTA_DM_SDP_RESULT>(*msg)); - break; - case BTA_DM_SEARCH_CMPL_EVT: - bta_dm_search_cmpl(); - break; - case BTA_DM_DISCOVERY_RESULT_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_SVC_RES>(*msg), "bad message type: {}", - msg->index()); - - bta_dm_disc_result(std::get<tBTA_DM_SVC_RES>(*msg)); - break; - case BTA_DM_API_SEARCH_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_API_SEARCH>(*msg), "bad message type: {}", - msg->index()); - - bta_dm_queue_search(std::get<tBTA_DM_API_SEARCH>(*msg)); - break; - case BTA_DM_API_DISCOVER_EVT: - log::assert_that(std::holds_alternative<tBTA_DM_API_DISCOVER>(*msg), - "bad message type: {}", msg->index()); - - bta_dm_queue_disc(std::get<tBTA_DM_API_DISCOVER>(*msg)); - break; - case BTA_DM_API_SEARCH_CANCEL_EVT: - bta_dm_search_clear_queue(); - bta_dm_search_set_state(BTA_DM_SEARCH_CANCELLING); - bta_dm_search_cancel_notify(); - break; - case BTA_DM_DISC_CLOSE_TOUT_EVT: - bta_dm_close_gatt_conn(); - break; - default: - log::info("Received unexpected event {}[0x{:x}] in state {}", bta_dm_event_text(event), - event, bta_dm_state_text(bta_dm_search_get_state())); - } - break; - } -} - -static void bta_dm_disc_init_search_cb(tBTA_DM_SEARCH_CB& bta_dm_search_cb) { - bta_dm_search_cb = {}; - bta_dm_search_cb.state = BTA_DM_SEARCH_IDLE; - bta_dm_search_cb.conn_id = GATT_INVALID_CONN_ID; - bta_dm_search_cb.transport = BT_TRANSPORT_AUTO; -} - -static void bta_dm_disc_reset() { - alarm_free(bta_dm_search_cb.search_timer); - alarm_free(bta_dm_search_cb.gatt_close_timer); - bta_dm_search_cb.p_pending_search.reset(); - bta_dm_search_cb.pending_discovery_queue = {}; - bta_dm_disc_init_search_cb(bta_dm_search_cb); -} - -void bta_dm_disc_start(bool delay_close_gatt) { - bta_dm_disc_reset(); - bta_dm_search_cb.search_timer = alarm_new("bta_dm_search.search_timer"); - bta_dm_search_cb.gatt_close_timer = - delay_close_gatt ? alarm_new("bta_dm_search.gatt_close_timer") : nullptr; - bta_dm_search_cb.pending_discovery_queue = {}; -} - -void bta_dm_disc_acl_down(const RawAddress& bd_addr, tBT_TRANSPORT transport) { - switch (transport) { - case BT_TRANSPORT_BR_EDR: - if (bta_dm_search_cb.wait_disc && bta_dm_search_cb.peer_bdaddr == bd_addr) { - bta_dm_search_cb.wait_disc = false; - - if (bta_dm_search_cb.sdp_results) { - log::verbose("timer stopped"); - alarm_cancel(bta_dm_search_cb.search_timer); - bta_dm_disc_discover_next_device(); - } - } - break; - - case BT_TRANSPORT_LE: - default: - break; - } -} - -void bta_dm_disc_stop() { bta_dm_disc_reset(); } - -void bta_dm_disc_start_device_discovery(tBTA_DM_SEARCH_CBACK* p_cback) { - bta_dm_search_sm_execute(BTA_DM_API_SEARCH_EVT, - std::make_unique<tBTA_DM_MSG>(tBTA_DM_API_SEARCH{.p_cback = p_cback})); -} - -void bta_dm_disc_stop_device_discovery() { - bta_dm_search_sm_execute(BTA_DM_API_SEARCH_CANCEL_EVT, nullptr); -} - -void bta_dm_disc_start_service_discovery(service_discovery_callbacks cbacks, - const RawAddress& bd_addr, tBT_TRANSPORT transport) { - bta_dm_search_sm_execute(BTA_DM_API_DISCOVER_EVT, - std::make_unique<tBTA_DM_MSG>(tBTA_DM_API_DISCOVER{ - .bd_addr = bd_addr, .cbacks = cbacks, .transport = transport})); -} - -#define DUMPSYS_TAG "shim::legacy::bta::dm" -void DumpsysBtaDmDisc(int fd) { - auto copy = search_state_history_.Pull(); - LOG_DUMPSYS(fd, " last %zu search state transitions", copy.size()); - for (const auto& it : copy) { - LOG_DUMPSYS(fd, " %s %s", EpochMillisToString(it.timestamp).c_str(), - it.entry.ToString().c_str()); - } - LOG_DUMPSYS(fd, " current bta_dm_search_state:%s", - bta_dm_state_text(bta_dm_search_get_state()).c_str()); -} -#undef DUMPSYS_TAG - -namespace bluetooth { -namespace legacy { -namespace testing { - -void bta_dm_disc_init_search_cb(tBTA_DM_SEARCH_CB& bta_dm_search_cb) { - ::bta_dm_disc_legacy::bta_dm_disc_init_search_cb(bta_dm_search_cb); -} -tBTA_DM_SEARCH_CB bta_dm_disc_get_search_cb() { - tBTA_DM_SEARCH_CB search_cb = {}; - ::bta_dm_disc_legacy::bta_dm_disc_init_search_cb(search_cb); - return search_cb; -} -tBTA_DM_SEARCH_CB& bta_dm_disc_search_cb() { return ::bta_dm_disc_legacy::bta_dm_search_cb; } -bool bta_dm_read_remote_device_name(const RawAddress& bd_addr, tBT_TRANSPORT transport) { - return ::bta_dm_disc_legacy::bta_dm_read_remote_device_name(bd_addr, transport); -} -void bta_dm_discover_next_device() { ::bta_dm_disc_legacy::bta_dm_discover_next_device(); } - -void bta_dm_execute_queued_request() { ::bta_dm_disc_legacy::bta_dm_execute_queued_request(); } -void bta_dm_find_services(const RawAddress& bd_addr) { - ::bta_dm_disc_legacy::bta_dm_find_services(bd_addr); -} -void bta_dm_inq_cmpl() { ::bta_dm_disc_legacy::bta_dm_inq_cmpl(); } -void bta_dm_inq_cmpl_cb(void* p_result) { ::bta_dm_disc_legacy::bta_dm_inq_cmpl_cb(p_result); } - -void bta_dm_queue_search(tBTA_DM_API_SEARCH& search) { - ::bta_dm_disc_legacy::bta_dm_queue_search(search); -} - -void bta_dm_service_search_remname_cback(const RawAddress& bd_addr, DEV_CLASS dc, BD_NAME bd_name) { - ::bta_dm_disc_legacy::bta_dm_service_search_remname_cback(bd_addr, dc, bd_name); -} - -void store_avrcp_profile_feature(tSDP_DISC_REC* sdp_rec) { - ::bta_dm_disc_legacy::store_avrcp_profile_feature(sdp_rec); -} - -} // namespace testing -} // namespace legacy -} // namespace bluetooth - -} // namespace bta_dm_disc_legacy diff --git a/system/bta/dm/bta_dm_disc_legacy.h b/system/bta/dm/bta_dm_disc_legacy.h deleted file mode 100644 index 724c7f94bd..0000000000 --- a/system/bta/dm/bta_dm_disc_legacy.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2023 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. - */ - -#pragma once - -#include "bta/include/bta_api.h" // tBTA_DM_SEARCH_CBACK -#include "stack/include/bt_hdr.h" -#include "types/bt_transport.h" -#include "types/raw_address.h" - -// TODO: Remove this file after flag separate_service_and_device_discovery rolls -// out -namespace bta_dm_disc_legacy { - -// Bta module start and stop entry points -void bta_dm_disc_start(bool delay_close_gatt); -void bta_dm_disc_stop(); - -// Bta device discovery start and stop entry points -void bta_dm_disc_start_device_discovery(tBTA_DM_SEARCH_CBACK*); -void bta_dm_disc_stop_device_discovery(); - -// Bta service discovery start and stop entry points -void bta_dm_disc_start_service_discovery(service_discovery_callbacks cbacks, - const RawAddress& bd_addr, tBT_TRANSPORT transport); - -// Bta subsystem entrypoint and lifecycle -void bta_dm_disc_disable_search_and_disc(); -// Indication that an acl has gone down and to examine the current -// service discovery procedure, if any. -void bta_dm_disc_acl_down(const RawAddress& bd_addr, tBT_TRANSPORT transport); - -// Return most recent remote name -const char* bta_dm_get_remname(void); - -// Checks if there is a device discovery request queued -bool bta_dm_is_search_request_queued(); - -// Proceed to execute service discovery on next device in queue -void bta_dm_disc_discover_next_device(); - -// GATT service discovery -void bta_dm_disc_gattc_register(); -void bta_dm_disc_gatt_cancel_open(const RawAddress& bd_addr); -void bta_dm_disc_gatt_refresh(const RawAddress& bd_addr); - -// Stop service discovery procedure, if any, for removed device -void bta_dm_disc_remove_device(const RawAddress& bd_addr); - -// Provide data for the dumpsys procedure -void DumpsysBtaDmDisc(int fd); - -} // namespace bta_dm_disc_legacy diff --git a/system/bta/include/bta_api.h b/system/bta/include/bta_api.h index e3b51f3f1b..43f5fc1d72 100644 --- a/system/bta/include/bta_api.h +++ b/system/bta/include/bta_api.h @@ -272,22 +272,15 @@ typedef union { /* Search callback */ typedef void(tBTA_DM_SEARCH_CBACK)(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH* p_data); -// TODO: delete bd_name parameter after separate_service_and_device_discovery -// rolls out -typedef void(tBTA_DM_GATT_DISC_CBACK)(RawAddress bd_addr, BD_NAME bd_name, - std::vector<bluetooth::Uuid>& services, bool transport_le); +typedef void(tBTA_DM_GATT_DISC_CBACK)(RawAddress bd_addr, std::vector<bluetooth::Uuid>& services, + bool transport_le); typedef void(tBTA_DM_DID_RES_CBACK)(RawAddress bd_addr, uint8_t vendor_id_src, uint16_t vendor_id, uint16_t product_id, uint16_t version); -// TODO: delete after separate_service_and_device_discovery rolls out -typedef void(tBTA_DM_NAME_READ_CBACK)(RawAddress bd_addr, tHCI_ERROR_CODE hci_status, - const BD_NAME bd_name); typedef void(tBTA_DM_DISC_CBACK)(RawAddress bd_addr, const std::vector<bluetooth::Uuid>& uuids, tBTA_STATUS result); struct service_discovery_callbacks { tBTA_DM_GATT_DISC_CBACK* on_gatt_results; tBTA_DM_DID_RES_CBACK* on_did_received; - // TODO: delete after separate_service_and_device_discovery rolls out - tBTA_DM_NAME_READ_CBACK* on_name_read; tBTA_DM_DISC_CBACK* on_service_discovery_results; }; diff --git a/system/bta/include/bta_jv_api.h b/system/bta/include/bta_jv_api.h index a57c25db78..4bf5cbe490 100644 --- a/system/bta/include/bta_jv_api.h +++ b/system/bta/include/bta_jv_api.h @@ -32,7 +32,6 @@ #include "include/macros.h" #include "internal_include/bt_target.h" #include "stack/include/bt_hdr.h" -#include "stack/include/l2c_api.h" #include "stack/include/l2cap_interface.h" #include "stack/include/rfcdefs.h" #include "types/bluetooth/uuid.h" diff --git a/system/bta/test/bta_disc_test.cc b/system/bta/test/bta_disc_test.cc index f92cadb1aa..f9db1733f1 100644 --- a/system/bta/test/bta_disc_test.cc +++ b/system/bta/test/bta_disc_test.cc @@ -176,7 +176,7 @@ TEST_F(BtaInitializedTest, bta_dm_disc_stop_device_discovery) { TEST_F(BtaInitializedTest, bta_dm_disc_start_service_discovery__BT_TRANSPORT_AUTO) { bta_dm_disc_start_service_discovery( - {nullptr, nullptr, nullptr, + {nullptr, nullptr, [](RawAddress, const std::vector<bluetooth::Uuid>&, tBTA_STATUS) {}}, kRawAddress, BT_TRANSPORT_AUTO); } @@ -184,9 +184,7 @@ TEST_F(BtaInitializedTest, bta_dm_disc_start_service_discovery__BT_TRANSPORT_AUT // must be global, as capturing lambda can't be treated as function int service_cb_call_cnt = 0; -TEST_F_WITH_FLAGS(BtaInitializedTest, bta_dm_disc_start_service_discovery__BT_TRANSPORT_BR_EDR, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, - separate_service_and_device_discovery))) { +TEST_F(BtaInitializedTest, bta_dm_disc_start_service_discovery__BT_TRANSPORT_BR_EDR) { bta_dm_disc_start(true); int sdp_call_cnt = 0; base::RepeatingCallback<void(tBTA_DM_SDP_STATE*)> sdp_performer = @@ -198,7 +196,7 @@ TEST_F_WITH_FLAGS(BtaInitializedTest, bta_dm_disc_start_service_discovery__BT_TR bta_dm_disc_override_sdp_performer_for_testing(sdp_performer); service_cb_call_cnt = 0; - bta_dm_disc_start_service_discovery({nullptr, nullptr, nullptr, + bta_dm_disc_start_service_discovery({nullptr, nullptr, [](RawAddress addr, const std::vector<bluetooth::Uuid>&, tBTA_STATUS) { service_cb_call_cnt++; }}, kRawAddress, BT_TRANSPORT_BR_EDR); @@ -212,9 +210,7 @@ TEST_F_WITH_FLAGS(BtaInitializedTest, bta_dm_disc_start_service_discovery__BT_TR // must be global, as capturing lambda can't be treated as function int gatt_service_cb_call_cnt = 0; -TEST_F_WITH_FLAGS(BtaInitializedTest, bta_dm_disc_start_service_discovery__BT_TRANSPORT_LE, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, - separate_service_and_device_discovery))) { +TEST_F(BtaInitializedTest, bta_dm_disc_start_service_discovery__BT_TRANSPORT_LE) { bta_dm_disc_start(true); int gatt_call_cnt = 0; base::RepeatingCallback<void(const RawAddress&)> gatt_performer = @@ -225,9 +221,9 @@ TEST_F_WITH_FLAGS(BtaInitializedTest, bta_dm_disc_start_service_discovery__BT_TR bta_dm_disc_override_gatt_performer_for_testing(gatt_performer); gatt_service_cb_call_cnt = 0; - bta_dm_disc_start_service_discovery({[](RawAddress, BD_NAME, std::vector<bluetooth::Uuid>&, + bta_dm_disc_start_service_discovery({[](RawAddress, std::vector<bluetooth::Uuid>&, bool) { gatt_service_cb_call_cnt++; }, - nullptr, nullptr, nullptr}, + nullptr, nullptr}, kRawAddress, BT_TRANSPORT_LE); EXPECT_EQ(gatt_call_cnt, 1); @@ -244,8 +240,6 @@ int gatt_service_cb_both_call_cnt = 0; * dual-mode, CTKD capable device on LE transport. */ TEST_F_WITH_FLAGS(BtaInitializedTest, bta_dm_disc_both_transports_flag_disabled, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, - separate_service_and_device_discovery)), REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(TEST_BT, bta_dm_discover_both))) { bta_dm_disc_start(true); @@ -267,7 +261,7 @@ TEST_F_WITH_FLAGS(BtaInitializedTest, bta_dm_disc_both_transports_flag_disabled, service_cb_both_call_cnt = 0; bta_dm_disc_start_service_discovery( - {[](RawAddress, BD_NAME, std::vector<bluetooth::Uuid>&, bool) {}, nullptr, nullptr, + {[](RawAddress, std::vector<bluetooth::Uuid>&, bool) {}, nullptr, [](RawAddress addr, const std::vector<bluetooth::Uuid>&, tBTA_STATUS) { service_cb_both_call_cnt++; }}, @@ -275,10 +269,10 @@ TEST_F_WITH_FLAGS(BtaInitializedTest, bta_dm_disc_both_transports_flag_disabled, EXPECT_EQ(sdp_call_cnt, 1); bta_dm_disc_start_service_discovery( - {[](RawAddress, BD_NAME, std::vector<bluetooth::Uuid>&, bool) { + {[](RawAddress, std::vector<bluetooth::Uuid>&, bool) { gatt_service_cb_both_call_cnt++; }, - nullptr, nullptr, + nullptr, [](RawAddress addr, const std::vector<bluetooth::Uuid>&, tBTA_STATUS) {}}, kRawAddress, BT_TRANSPORT_LE); @@ -318,17 +312,17 @@ TEST_F_WITH_FLAGS(BtaInitializedTest, bta_dm_disc_both_transports_flag_enabled, gatt_service_cb_both_call_cnt = 0; service_cb_both_call_cnt = 0; - bta_dm_disc_start_service_discovery({[](RawAddress, BD_NAME, std::vector<bluetooth::Uuid>&, + bta_dm_disc_start_service_discovery({[](RawAddress, std::vector<bluetooth::Uuid>&, bool) { gatt_service_cb_both_call_cnt++; }, - nullptr, nullptr, + nullptr, [](RawAddress addr, const std::vector<bluetooth::Uuid>&, tBTA_STATUS) { service_cb_both_call_cnt++; }}, kRawAddress, BT_TRANSPORT_BR_EDR); EXPECT_EQ(sdp_call_cnt, 1); - bta_dm_disc_start_service_discovery({[](RawAddress, BD_NAME, std::vector<bluetooth::Uuid>&, + bta_dm_disc_start_service_discovery({[](RawAddress, std::vector<bluetooth::Uuid>&, bool) { gatt_service_cb_both_call_cnt++; }, - nullptr, nullptr, + nullptr, [](RawAddress addr, const std::vector<bluetooth::Uuid>&, tBTA_STATUS) { service_cb_both_call_cnt++; }}, kRawAddress, BT_TRANSPORT_LE); diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index b832dccf3e..abbf784179 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -1708,8 +1708,8 @@ static void btif_on_service_discovery_results(RawAddress bd_addr, } } -void btif_on_gatt_results(RawAddress bd_addr, BD_NAME bd_name, - std::vector<bluetooth::Uuid>& services, bool is_transport_le) { +void btif_on_gatt_results(RawAddress bd_addr, std::vector<bluetooth::Uuid>& services, + bool is_transport_le) { std::vector<bt_property_t> prop; std::vector<uint8_t> property_value; std::set<Uuid> uuids; @@ -1821,16 +1821,6 @@ void btif_on_gatt_results(RawAddress bd_addr, BD_NAME bd_name, bt_status_t ret = btif_storage_set_remote_device_property(&bd_addr, &prop[0]); ASSERTC(ret == BT_STATUS_SUCCESS, "storing remote services failed", ret); - /* Remote name update */ - if (!com::android::bluetooth::flags::separate_service_and_device_discovery() && - strnlen((const char*)bd_name, BD_NAME_LEN)) { - prop.push_back(bt_property_t{BT_PROPERTY_BDNAME, - static_cast<int>(strnlen((char*)bd_name, BD_NAME_LEN)), bd_name}); - - ret = btif_storage_set_remote_device_property(&bd_addr, &prop[1]); - ASSERTC(ret == BT_STATUS_SUCCESS, "failed to save remote device property", ret); - } - if (!is_transport_le) { /* If services were returned as part of SDP discovery, we will immediately * send them with rest of SDP results in on_service_discovery_results */ @@ -1852,14 +1842,6 @@ void btif_on_gatt_results(RawAddress bd_addr, BD_NAME bd_name, static void btif_on_name_read(RawAddress bd_addr, tHCI_ERROR_CODE hci_status, const BD_NAME bd_name, bool during_device_search) { - // Differentiate between merged callbacks - if (!during_device_search - // New fix after refactor, this callback is needed for the fix to work - && !com::android::bluetooth::flags::separate_service_and_device_discovery()) { - log::info("Skipping name read event - called on bad callback."); - return; - } - if (hci_status != HCI_SUCCESS) { log::warn("Received RNR event with bad status addr:{} hci_status:{}", bd_addr, hci_error_code_text(hci_status)); @@ -1964,9 +1946,7 @@ void BTIF_dm_enable() { log::info("Local BLE Privacy enabled:{}", ble_privacy_enabled); BTA_DmBleConfigLocalPrivacy(ble_privacy_enabled); - if (com::android::bluetooth::flags::separate_service_and_device_discovery()) { - get_stack_rnr_interface().BTM_SecAddRmtNameNotifyCallback(btif_on_name_read_from_btm); - } + get_stack_rnr_interface().BTM_SecAddRmtNameNotifyCallback(btif_on_name_read_from_btm); /* for each of the enabled services in the mask, trigger the profile * enable */ @@ -1992,9 +1972,7 @@ void BTIF_dm_enable() { } void BTIF_dm_disable() { - if (com::android::bluetooth::flags::separate_service_and_device_discovery()) { - get_stack_rnr_interface().BTM_SecDeleteRmtNameNotifyCallback(&btif_on_name_read_from_btm); - } + get_stack_rnr_interface().BTM_SecDeleteRmtNameNotifyCallback(&btif_on_name_read_from_btm); /* for each of the enabled services in the mask, trigger the profile * disable */ @@ -2805,11 +2783,6 @@ bt_status_t btif_dm_get_adapter_property(bt_property_t* prop) { return BT_STATUS_SUCCESS; } -static void btif_on_name_read_legacy(RawAddress bd_addr, tHCI_ERROR_CODE hci_status, - const BD_NAME bd_name) { - btif_on_name_read(bd_addr, hci_status, bd_name, false /* during_device_search */); -} - /******************************************************************************* * * Function btif_dm_get_remote_services @@ -2829,7 +2802,6 @@ void btif_dm_get_remote_services(RawAddress remote_addr, const tBT_TRANSPORT tra service_discovery_callbacks{ .on_gatt_results = btif_on_gatt_results, .on_did_received = btif_on_did_received, - .on_name_read = btif_on_name_read_legacy, .on_service_discovery_results = btif_on_service_discovery_results}, transport); } diff --git a/system/gd/hci/controller.cc b/system/gd/hci/controller.cc index b5e2d00006..523a20bbca 100644 --- a/system/gd/hci/controller.cc +++ b/system/gd/hci/controller.cc @@ -56,6 +56,10 @@ struct Controller::impl { handler->BindOn(this, &Controller::impl::NumberOfCompletedPackets)); set_event_mask(kDefaultEventMask); + if (com::android::bluetooth::flags::encryption_change_v2()) { + set_event_mask_page_2(kDefaultEventMaskPage2); + } + write_le_host_support(Enable::ENABLED, Enable::DISABLED); hci_->EnqueueCommand( ReadLocalNameBuilder::Create(), @@ -766,6 +770,13 @@ struct Controller::impl { module_.GetHandler()->BindOnce(check_complete<SetEventMaskCompleteView>)); } + void set_event_mask_page_2(uint64_t event_mask_page_2) { + std::unique_ptr<SetEventMaskPage2Builder> packet = + SetEventMaskPage2Builder::Create(event_mask_page_2); + hci_->EnqueueCommand(std::move(packet), module_.GetHandler()->BindOnce( + check_complete<SetEventMaskPage2CompleteView>)); + } + void write_le_host_support(Enable enable, Enable deprecated_host_bit) { if (deprecated_host_bit == Enable::ENABLED) { // Since Bluetooth Core Spec 4.1, this bit should be 0 diff --git a/system/gd/hci/controller.h b/system/gd/hci/controller.h index 9eaa026b23..498546ef3a 100644 --- a/system/gd/hci/controller.h +++ b/system/gd/hci/controller.h @@ -202,6 +202,7 @@ public: static const ModuleFactory Factory; static constexpr uint64_t kDefaultEventMask = 0x3dbfffffffffffff; + static constexpr uint64_t kDefaultEventMaskPage2 = 0x2000000; static constexpr uint64_t kDefaultLeEventMask = 0x000000074d02fe7f; static constexpr uint64_t kLeCSEventMask = 0x0007f80000000000; diff --git a/system/gd/hci/security_interface.h b/system/gd/hci/security_interface.h index d1126bd4ab..ad7a628b73 100644 --- a/system/gd/hci/security_interface.h +++ b/system/gd/hci/security_interface.h @@ -39,6 +39,7 @@ constexpr hci::EventCode SecurityEvents[] = { hci::EventCode::KEYPRESS_NOTIFICATION, hci::EventCode::USER_CONFIRMATION_REQUEST, hci::EventCode::USER_PASSKEY_REQUEST, + hci::EventCode::ENCRYPTION_CHANGE_V2, }; typedef CommandInterface<SecurityCommandBuilder> SecurityInterface; diff --git a/system/gd/rust/common/src/logging.rs b/system/gd/rust/common/src/logging.rs index 4207114d92..71c60da64b 100644 --- a/system/gd/rust/common/src/logging.rs +++ b/system/gd/rust/common/src/logging.rs @@ -1,7 +1,7 @@ /// Inits logging for Android #[cfg(target_os = "android")] pub fn init_logging() { - android_logger::init_once(android_logger::Config::default().with_tag("bt")); + android_logger::init_once(android_logger::Config::default().with_tag("bluetooth")); } /// Inits logging for host diff --git a/system/gd/rust/topshim/src/btif.rs b/system/gd/rust/topshim/src/btif.rs index c7ca1e9082..e1ec1ed946 100644 --- a/system/gd/rust/topshim/src/btif.rs +++ b/system/gd/rust/topshim/src/btif.rs @@ -14,6 +14,7 @@ use std::hash::{Hash, Hasher}; use std::mem; use std::os::fd::RawFd; use std::os::raw::c_char; +use std::ptr::NonNull; use std::sync::{Arc, Mutex}; use std::vec::Vec; use topshim_macros::{cb_variant, gen_cxx_extern_trivial}; @@ -788,9 +789,12 @@ impl BluetoothProperty { // TODO(abps) - Check that sizes are correct when given a BtProperty impl From<bindings::bt_property_t> for BluetoothProperty { fn from(prop: bindings::bt_property_t) -> Self { - let slice: &[u8] = - unsafe { std::slice::from_raw_parts(prop.val as *mut u8, prop.len as usize) }; + // Property values may be null, which isn't valid to pass for `slice::from_raw_parts`. + // Choose a dangling pointer in that case. + let prop_val_ptr = + NonNull::new(prop.val as *mut u8).unwrap_or(NonNull::dangling()).as_ptr(); let len = prop.len as usize; + let slice: &[u8] = unsafe { std::slice::from_raw_parts(prop_val_ptr, len) }; match BtPropertyType::from(prop.type_) { BtPropertyType::BdName => BluetoothProperty::BdName(ascii_to_string(slice, len)), diff --git a/system/gd/security/channel/security_manager_channel_unittest.cc b/system/gd/security/channel/security_manager_channel_unittest.cc index b3feb5d499..c1680c3760 100644 --- a/system/gd/security/channel/security_manager_channel_unittest.cc +++ b/system/gd/security/channel/security_manager_channel_unittest.cc @@ -82,6 +82,7 @@ public: bool receivedUserPasskeyRequest = false; bool receivedKeypressNotification = false; bool receivedUserConfirmationRequest = false; + bool receivedEncryptionChangeV2 = false; void OnReceive(hci::AddressWithType device, hci::ChangeConnectionLinkKeyCompleteView packet) { ASSERT_TRUE(packet.IsValid()); @@ -147,6 +148,10 @@ public: ASSERT_TRUE(packet.IsValid()); receivedUserPasskeyRequest = true; } + void OnReceive(hci::AddressWithType device, hci::EncryptionChangeV2View packet) { + ASSERT_TRUE(packet.IsValid()); + receivedEncryptionChangeV2 = true; + } void OnHciEventReceived(EventView packet) override { auto event = EventView::Create(packet); @@ -201,6 +206,9 @@ public: case hci::EventCode::USER_PASSKEY_REQUEST: OnReceive(hci::AddressWithType(), hci::UserPasskeyRequestView::Create(event)); break; + case hci::EventCode::ENCRYPTION_CHANGE_V2: + OnReceive(hci::AddressWithType(), hci::EncryptionChangeV2View::Create(event)); + break; default: log::fatal("Cannot handle received packet: {}", hci::EventCodeText(code)); break; @@ -584,6 +592,14 @@ TEST_F(SecurityManagerChannelTest, recv_encryption_change) { ASSERT_TRUE(callback_->receivedEncryptionChange); } +TEST_F(SecurityManagerChannelTest, recv_encryption_change_v2) { + uint16_t connection_handle = 0x0; + hci_layer_->IncomingEvent(hci::EncryptionChangeV2Builder::Create( + hci::ErrorCode::SUCCESS, connection_handle, hci::EncryptionEnabled::ON, 0x10)); + synchronize(); + ASSERT_TRUE(callback_->receivedEncryptionChangeV2); +} + TEST_F(SecurityManagerChannelTest, recv_encryption_key_refresh) { uint16_t connection_handle = 0x0; hci_layer_->IncomingEvent(hci::EncryptionKeyRefreshCompleteBuilder::Create( diff --git a/system/main/shim/hci_layer.cc b/system/main/shim/hci_layer.cc index 95c00cea4d..95794f0492 100644 --- a/system/main/shim/hci_layer.cc +++ b/system/main/shim/hci_layer.cc @@ -77,6 +77,7 @@ bool register_event_code(bluetooth::hci::EventCode event_code) { case bluetooth::hci::EventCode::USER_PASSKEY_NOTIFICATION: case bluetooth::hci::EventCode::USER_CONFIRMATION_REQUEST: case bluetooth::hci::EventCode::USER_PASSKEY_REQUEST: + case bluetooth::hci::EventCode::ENCRYPTION_CHANGE_V2: return true; default: return false; diff --git a/system/pdl/hci/hci_packets.pdl b/system/pdl/hci/hci_packets.pdl index cbda6ff235..9225204045 100644 --- a/system/pdl/hci/hci_packets.pdl +++ b/system/pdl/hci/hci_packets.pdl @@ -862,6 +862,7 @@ enum EventCode : 8 { LE_META_EVENT = 0x3e, NUMBER_OF_COMPLETED_DATA_BLOCKS = 0x48, AUTHENTICATED_PAYLOAD_TIMEOUT_EXPIRED = 0x57, + ENCRYPTION_CHANGE_V2 = 0x59, VENDOR_SPECIFIC = 0xFF, } @@ -6327,6 +6328,14 @@ packet AuthenticatedPayloadTimeoutExpired : Event (event_code = AUTHENTICATED_PA _reserved_ : 4, } +packet EncryptionChangeV2 : Event (event_code = ENCRYPTION_CHANGE_V2) { + status : ErrorCode, + connection_handle : 12, + _reserved_ : 4, + encryption_enabled : EncryptionEnabled, + key_size : 8, +} + // LE Events packet LeConnectionComplete : LeMetaEvent (subevent_code = CONNECTION_COMPLETE) { status : ErrorCode, diff --git a/system/stack/avct/avct_api.cc b/system/stack/avct/avct_api.cc index 926db22e49..10c441d876 100644 --- a/system/stack/avct/avct_api.cc +++ b/system/stack/avct/avct_api.cc @@ -31,8 +31,6 @@ #include "avct_int.h" #include "bta/include/bta_sec_api.h" #include "internal_include/bt_target.h" -#include "l2c_api.h" -#include "l2cdefs.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" #include "stack/include/l2cap_interface.h" @@ -106,6 +104,9 @@ void AVCT_Deregister(void) { /* deregister PSM with L2CAP */ stack::l2cap::get_interface().L2CA_Deregister(AVCT_PSM); + + /* deregister AVCT_BR_PSM with L2CAP */ + stack::l2cap::get_interface().L2CA_Deregister(AVCT_BR_PSM); } /******************************************************************************* diff --git a/system/stack/avct/avct_int.h b/system/stack/avct/avct_int.h index 46bd73d793..db1528b80e 100644 --- a/system/stack/avct/avct_int.h +++ b/system/stack/avct/avct_int.h @@ -26,7 +26,6 @@ #include "avct_api.h" #include "internal_include/bt_target.h" -#include "l2c_api.h" #include "osi/include/fixed_queue.h" #include "stack/include/bt_hdr.h" #include "stack/include/l2cap_interface.h" diff --git a/system/stack/avct/avct_l2c.cc b/system/stack/avct/avct_l2c.cc index 7147ef6029..adca67c851 100644 --- a/system/stack/avct/avct_l2c.cc +++ b/system/stack/avct/avct_l2c.cc @@ -29,8 +29,6 @@ #include "avct_int.h" #include "btif/include/btif_av.h" #include "internal_include/bt_target.h" -#include "l2c_api.h" -#include "l2cdefs.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" #include "stack/include/l2cap_interface.h" diff --git a/system/stack/avct/avct_l2c_br.cc b/system/stack/avct/avct_l2c_br.cc index a8af279049..4c5ccc503b 100644 --- a/system/stack/avct/avct_l2c_br.cc +++ b/system/stack/avct/avct_l2c_br.cc @@ -31,8 +31,6 @@ #include "avct_api.h" #include "avct_int.h" #include "internal_include/bt_target.h" -#include "l2c_api.h" -#include "l2cdefs.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" #include "stack/include/l2cap_interface.h" diff --git a/system/stack/avdt/avdt_ad.cc b/system/stack/avdt/avdt_ad.cc index 3b66f66b5b..f566688ef7 100644 --- a/system/stack/avdt/avdt_ad.cc +++ b/system/stack/avdt/avdt_ad.cc @@ -31,8 +31,6 @@ #include "avdt_api.h" #include "avdt_int.h" #include "internal_include/bt_target.h" -#include "l2c_api.h" -#include "l2cdefs.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" #include "stack/include/btm_sec_api_types.h" @@ -587,7 +585,7 @@ void avdt_ad_close_req(uint8_t type, AvdtpCcb* p_ccb, AvdtpScb* p_scb) { default: lcid = p_tbl->lcid; /* call l2cap disconnect req */ - if (!L2CA_DisconnectReq(lcid)) { + if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) { log::warn("Unable to disconnect L2CAP lcid: 0x{:04x}", lcid); } avdt_ad_tc_close_ind(p_tbl); diff --git a/system/stack/avdt/avdt_int.h b/system/stack/avdt/avdt_int.h index 54e5fa9b6f..6b2b354b06 100644 --- a/system/stack/avdt/avdt_int.h +++ b/system/stack/avdt/avdt_int.h @@ -33,9 +33,8 @@ #include "avdt_api.h" #include "avdt_defs.h" #include "avdtc_api.h" +#include "include/macros.h" #include "internal_include/bt_target.h" -#include "l2c_api.h" -#include "macros.h" #include "osi/include/alarm.h" #include "osi/include/fixed_queue.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/avdt/avdt_l2c.cc b/system/stack/avdt/avdt_l2c.cc index 1f9c18517d..6eab341865 100644 --- a/system/stack/avdt/avdt_l2c.cc +++ b/system/stack/avdt/avdt_l2c.cc @@ -29,12 +29,9 @@ #include "avdt_int.h" #include "bta/include/bta_av_api.h" #include "device/include/interop.h" -#include "l2c_api.h" -#include "l2cdefs.h" #include "osi/include/allocator.h" #include "stack/include/acl_api.h" #include "stack/include/bt_hdr.h" -#include "stack/include/btm_status.h" #include "stack/include/l2cap_interface.h" #include "types/raw_address.h" @@ -226,7 +223,7 @@ static void avdt_on_l2cap_error(uint16_t lcid, uint16_t result) { AvdtpTransportChannel* p_tbl; log::warn("lcid: 0x{:04x}, result: {}", lcid, to_l2cap_result_code(result)); - if (!L2CA_DisconnectReq(lcid)) { + if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) { log::warn("Unable to disconnect L2CAP lcid: 0x{:04x}", lcid); } diff --git a/system/stack/bnep/bnep_main.cc b/system/stack/bnep/bnep_main.cc index 9d00fd63be..e0e3c4540c 100644 --- a/system/stack/bnep/bnep_main.cc +++ b/system/stack/bnep/bnep_main.cc @@ -32,8 +32,6 @@ #include "bta/include/bta_sec_api.h" #include "hci/controller_interface.h" #include "internal_include/bt_target.h" -#include "l2c_api.h" -#include "l2cdefs.h" #include "main/shim/entry.h" #include "main/shim/helpers.h" #include "osi/include/allocator.h" diff --git a/system/stack/btm/btm_dev.cc b/system/stack/btm/btm_dev.cc index 6450bf5502..76a69b5fbe 100644 --- a/system/stack/btm/btm_dev.cc +++ b/system/stack/btm/btm_dev.cc @@ -36,7 +36,6 @@ #include "btm_sec_api.h" #include "btm_sec_cb.h" #include "internal_include/bt_target.h" -#include "l2c_api.h" #include "main/shim/dumpsys.h" #include "osi/include/allocator.h" #include "rust/src/connection/ffi/connection_shim.h" diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc index 93ce8c0dfa..f310bde7bd 100644 --- a/system/stack/btm/btm_sec.cc +++ b/system/stack/btm/btm_sec.cc @@ -3174,7 +3174,8 @@ void btm_sec_auth_complete(uint16_t handle, tHCI_STATUS status) { * Returns void * ******************************************************************************/ -void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable) { +void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable, + uint8_t key_size, bool = false) { /* For transaction collision we need to wait and repeat. There is no need */ /* for random timeout because only peripheral should receive the result */ if ((status == HCI_ERR_LMP_ERR_TRANS_COLLISION) || @@ -3197,12 +3198,16 @@ void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, uint8_t encr_en const tBT_TRANSPORT transport = BTM_IsBleConnection(handle) ? BT_TRANSPORT_LE : BT_TRANSPORT_BR_EDR; + if (transport == BT_TRANSPORT_LE) { + key_size = p_dev_rec->sec_rec.ble_keys.key_size; + } + log::debug( "Security Manager encryption change request hci_status:{} request:{} " - "state: le_link:{} classic_link:{} sec_flags:0x{:x}", + "state: le_link:{} classic_link:{} sec_flags:0x{:x} key_size:{}", hci_status_code_text(status), (encr_enable) ? "encrypt" : "unencrypt", - p_dev_rec->sec_rec.le_link, p_dev_rec->sec_rec.classic_link, - p_dev_rec->sec_rec.sec_flags); + p_dev_rec->sec_rec.le_link, p_dev_rec->sec_rec.classic_link, p_dev_rec->sec_rec.sec_flags, + key_size); if (status == HCI_SUCCESS) { if (encr_enable) { @@ -3396,7 +3401,7 @@ static void read_encryption_key_size_complete_after_encryption_change(uint8_t st // good key size - succeed btm_acl_encrypt_change(handle, static_cast<tHCI_STATUS>(status), 1 /* enable */); - btm_sec_encrypt_change(handle, static_cast<tHCI_STATUS>(status), 1 /* enable */); + btm_sec_encrypt_change(handle, static_cast<tHCI_STATUS>(status), 1 /* enable */, key_size); } // TODO: Remove @@ -3411,21 +3416,29 @@ void smp_cancel_start_encryption_attempt(); * Returns void * ******************************************************************************/ -void btm_sec_encryption_change_evt(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable) { - if (status != HCI_SUCCESS || encr_enable == 0 || BTM_IsBleConnection(handle) || - !bluetooth::shim::GetController()->IsSupported( - bluetooth::hci::OpCode::READ_ENCRYPTION_KEY_SIZE)) { - if (status == HCI_ERR_CONNECTION_TOUT) { - smp_cancel_start_encryption_attempt(); +void btm_sec_encryption_change_evt(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable, + uint8_t key_size) { + if (status == HCI_SUCCESS && encr_enable != 0 && !BTM_IsBleConnection(handle)) { + if (key_size != 0) { + read_encryption_key_size_complete_after_encryption_change(status, handle, key_size); return; } - btm_acl_encrypt_change(handle, static_cast<tHCI_STATUS>(status), encr_enable); - btm_sec_encrypt_change(handle, static_cast<tHCI_STATUS>(status), encr_enable); - } else { - btsnd_hcic_read_encryption_key_size( - handle, base::Bind(&read_encryption_key_size_complete_after_encryption_change)); + if (bluetooth::shim::GetController()->IsSupported( + bluetooth::hci::OpCode::READ_ENCRYPTION_KEY_SIZE)) { + btsnd_hcic_read_encryption_key_size( + handle, base::Bind(&read_encryption_key_size_complete_after_encryption_change)); + return; + } } + + if (status == HCI_ERR_CONNECTION_TOUT) { + smp_cancel_start_encryption_attempt(); + return; + } + + btm_acl_encrypt_change(handle, static_cast<tHCI_STATUS>(status), encr_enable); + btm_sec_encrypt_change(handle, static_cast<tHCI_STATUS>(status), encr_enable, 0); } /******************************************************************************* * @@ -3948,7 +3961,7 @@ static void read_encryption_key_size_complete_after_key_refresh(uint8_t status, return; } - btm_sec_encrypt_change(handle, static_cast<tHCI_STATUS>(status), 1 /* enc_enable */); + btm_sec_encrypt_change(handle, static_cast<tHCI_STATUS>(status), 1 /* enc_enable */, key_size); } void btm_sec_encryption_key_refresh_complete(uint16_t handle, tHCI_STATUS status) { @@ -3957,7 +3970,7 @@ void btm_sec_encryption_key_refresh_complete(uint16_t handle, tHCI_STATUS status bluetooth::shim::GetController()->IsSupported( bluetooth::hci::OpCode::SET_MIN_ENCRYPTION_KEY_SIZE)) { btm_sec_encrypt_change(handle, static_cast<tHCI_STATUS>(status), - (status == HCI_SUCCESS) ? 1 : 0); + (status == HCI_SUCCESS) ? 1 : 0, 0, true); } else { btsnd_hcic_read_encryption_key_size( handle, base::Bind(&read_encryption_key_size_complete_after_key_refresh)); diff --git a/system/stack/btm/btm_sec.h b/system/stack/btm/btm_sec.h index c8a2e16c61..9646ada250 100644 --- a/system/stack/btm/btm_sec.h +++ b/system/stack/btm/btm_sec.h @@ -549,7 +549,8 @@ void btm_sec_auth_complete(uint16_t handle, tHCI_STATUS status); * Returns void * ******************************************************************************/ -void btm_sec_encryption_change_evt(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable); +void btm_sec_encryption_change_evt(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable, + uint8_t key_size); /******************************************************************************* * @@ -561,7 +562,8 @@ void btm_sec_encryption_change_evt(uint16_t handle, tHCI_STATUS status, uint8_t * Returns void * ******************************************************************************/ -void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable); +void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable, + uint8_t key_size, bool from_key_refresh); /******************************************************************************* * diff --git a/system/stack/btm/security_event_parser.cc b/system/stack/btm/security_event_parser.cc index 4de55a16cb..84d7005d16 100644 --- a/system/stack/btm/security_event_parser.cc +++ b/system/stack/btm/security_event_parser.cc @@ -68,7 +68,24 @@ static void parse_encryption_change(const EventView event) { EncryptionEnabled encr_enable = change.GetEncryptionEnabled(); btm_sec_encryption_change_evt(handle, static_cast<tHCI_STATUS>(status), - static_cast<uint8_t>(encr_enable)); + static_cast<uint8_t>(encr_enable), 0); + log_classic_pairing_event( + ToRawAddress(Address::kEmpty), handle, android::bluetooth::hci::CMD_UNKNOWN, + static_cast<uint32_t>(change.GetEventCode()), static_cast<uint16_t>(status), + android::bluetooth::hci::STATUS_UNKNOWN, 0); +} +static void parse_encryption_change_v2(const EventView event) { + auto change_opt = EncryptionChangeV2View::CreateOptional(event); + log::assert_that(change_opt.has_value(), "assert failed: change_opt.has_value()"); + auto change = change_opt.value(); + + ErrorCode status = change.GetStatus(); + uint16_t handle = change.GetConnectionHandle(); + EncryptionEnabled encr_enable = change.GetEncryptionEnabled(); + uint8_t key_size = change.GetKeySize(); + + btm_sec_encryption_change_evt(handle, static_cast<tHCI_STATUS>(status), + static_cast<uint8_t>(encr_enable), key_size); log_classic_pairing_event( ToRawAddress(Address::kEmpty), handle, android::bluetooth::hci::CMD_UNKNOWN, static_cast<uint32_t>(change.GetEventCode()), static_cast<uint16_t>(status), @@ -261,6 +278,9 @@ void SecurityEventParser::OnSecurityEvent(bluetooth::hci::EventView event) { case EventCode::USER_PASSKEY_REQUEST: parse_user_passkey_request(event); break; + case EventCode::ENCRYPTION_CHANGE_V2: + parse_encryption_change_v2(event); + break; default: log::error("Unhandled event {}", EventCodeText(event.GetEventCode())); } diff --git a/system/stack/btu/btu_hcif.cc b/system/stack/btu/btu_hcif.cc index 33cd9d05f7..d392f29fdd 100644 --- a/system/stack/btu/btu_hcif.cc +++ b/system/stack/btu/btu_hcif.cc @@ -74,6 +74,7 @@ void acl_disconnect_from_handle(uint16_t handle, tHCI_STATUS reason, /******************************************************************************/ static void btu_hcif_authentication_comp_evt(uint8_t* p); static void btu_hcif_encryption_change_evt(uint8_t* p); +static void btu_hcif_encryption_change_evt_v2(uint8_t* p); static void btu_hcif_read_rmt_ext_features_comp_evt(uint8_t* p, uint8_t evt_len); static void btu_hcif_command_complete_evt(BT_HDR* response, void* context); static void btu_hcif_command_status_evt(uint8_t status, BT_HDR* command, void* context); @@ -148,6 +149,16 @@ static void btu_hcif_log_event_metrics(uint8_t evt_code, const uint8_t* p_event) log_classic_pairing_event(bda, handle, cmd, evt_code, status, reason, encryption_enabled); break; } + case HCI_ENCRYPTION_CHANGE_EVT_V2: { + uint8_t encryption_enabled; + uint8_t key_size; + STREAM_TO_UINT8(status, p_event); + STREAM_TO_UINT16(handle, p_event); + STREAM_TO_UINT8(encryption_enabled, p_event); + STREAM_TO_UINT8(key_size, p_event); + log_classic_pairing_event(bda, handle, cmd, evt_code, status, reason, encryption_enabled); + break; + } case HCI_ESCO_CONNECTION_COMP_EVT: { uint8_t link_type; STREAM_TO_UINT8(status, p_event); @@ -220,6 +231,9 @@ void btu_hcif_process_event(uint8_t /* controller_id */, const BT_HDR* p_msg) { case HCI_ENCRYPTION_CHANGE_EVT: btu_hcif_encryption_change_evt(p); break; + case HCI_ENCRYPTION_CHANGE_EVT_V2: + btu_hcif_encryption_change_evt_v2(p); + break; case HCI_ENCRYPTION_KEY_REFRESH_COMP_EVT: btu_hcif_encryption_key_refresh_cmpl_evt(p); break; @@ -750,7 +764,30 @@ static void btu_hcif_encryption_change_evt(uint8_t* p) { STREAM_TO_UINT16(handle, p); STREAM_TO_UINT8(encr_enable, p); - btm_sec_encryption_change_evt(handle, static_cast<tHCI_STATUS>(status), encr_enable); + btm_sec_encryption_change_evt(handle, static_cast<tHCI_STATUS>(status), encr_enable, 0); +} + +/******************************************************************************* + * + * Function btu_hcif_encryption_change_evt_v2 + * + * Description Process event HCI_ENCRYPTION_CHANGE_EVT_V2 + * + * Returns void + * + ******************************************************************************/ +static void btu_hcif_encryption_change_evt_v2(uint8_t* p) { + uint8_t status; + uint16_t handle; + uint8_t encr_enable; + uint8_t key_size; + + STREAM_TO_UINT8(status, p); + STREAM_TO_UINT16(handle, p); + STREAM_TO_UINT8(encr_enable, p); + STREAM_TO_UINT8(key_size, p); + + btm_sec_encryption_change_evt(handle, static_cast<tHCI_STATUS>(status), encr_enable, key_size); } /******************************************************************************* @@ -1025,7 +1062,7 @@ static void btu_hcif_hdl_command_status(uint16_t opcode, uint8_t status, const u if (status != HCI_SUCCESS) { // Device refused to start encryption // This is treated as an encryption failure - btm_sec_encrypt_change(HCI_INVALID_HANDLE, hci_status, false); + btm_sec_encrypt_change(HCI_INVALID_HANDLE, hci_status, false, 0); } break; case HCI_READ_RMT_EXT_FEATURES: diff --git a/system/stack/fuzzers/l2cap_fuzzer.cc b/system/stack/fuzzers/l2cap_fuzzer.cc index c6cfee87ca..f8714cc3f3 100644 --- a/system/stack/fuzzers/l2cap_fuzzer.cc +++ b/system/stack/fuzzers/l2cap_fuzzer.cc @@ -30,10 +30,10 @@ #include "osi/include/allocator.h" #include "stack/btm/btm_int_types.h" #include "stack/include/bt_psm_types.h" -#include "stack/include/l2c_api.h" #include "stack/include/l2cap_acl_interface.h" #include "stack/include/l2cap_controller_interface.h" #include "stack/include/l2cap_hci_link_interface.h" +#include "stack/include/l2cap_interface.h" #include "stack/include/l2cap_module.h" #include "stack/include/l2cdefs.h" #include "test/fake/fake_osi.h" @@ -197,34 +197,37 @@ static void Fuzz(const uint8_t* data, size_t size) { tL2CAP_LE_CFG_INFO*) {}, .pL2CA_CreditBasedCollisionInd_Cb = [](const RawAddress&) {}, }; - log::assert_that(L2CA_RegisterWithSecurity(BT_PSM_ATT, appl_info, false, nullptr, L2CAP_MTU_SIZE, - 0, BTM_SEC_NONE), + log::assert_that(stack::l2cap::get_interface().L2CA_RegisterWithSecurity( + BT_PSM_ATT, appl_info, false, nullptr, L2CAP_MTU_SIZE, 0, BTM_SEC_NONE), "assert failed: L2CA_RegisterWithSecurity(BT_PSM_ATT, appl_info, " "false, nullptr, L2CAP_MTU_SIZE, 0, BTM_SEC_NONE)"); - log::assert_that(L2CA_RegisterLECoc(BT_PSM_EATT, appl_info, BTM_SEC_NONE, {}), + log::assert_that(stack::l2cap::get_interface().L2CA_RegisterLECoc(BT_PSM_EATT, appl_info, + BTM_SEC_NONE, {}), "assert failed: L2CA_RegisterLECoc(BT_PSM_EATT, appl_info, " "BTM_SEC_NONE, {{}})"); - log::assert_that(L2CA_RegisterFixedChannel(L2CAP_ATT_CID, ®), + log::assert_that(stack::l2cap::get_interface().L2CA_RegisterFixedChannel(L2CAP_ATT_CID, ®), "assert failed: L2CA_RegisterFixedChannel(L2CAP_ATT_CID, ®)"); - log::assert_that(L2CA_ConnectFixedChnl(L2CAP_ATT_CID, kAttAddr), + log::assert_that(stack::l2cap::get_interface().L2CA_ConnectFixedChnl(L2CAP_ATT_CID, kAttAddr), "assert failed: L2CA_ConnectFixedChnl(L2CAP_ATT_CID, kAttAddr)"); log::assert_that( l2cble_conn_comp(kAttHndl, HCI_ROLE_CENTRAL, kAttAddr, BLE_ADDR_PUBLIC, 100, 100, 100), "assert failed: l2cble_conn_comp(kAttHndl, HCI_ROLE_CENTRAL, kAttAddr, " "BLE_ADDR_PUBLIC, 100, 100, 100)"); - log::assert_that(L2CA_RegisterFixedChannel(L2CAP_SMP_BR_CID, ®), + log::assert_that(stack::l2cap::get_interface().L2CA_RegisterFixedChannel(L2CAP_SMP_BR_CID, ®), "assert failed: L2CA_RegisterFixedChannel(L2CAP_SMP_BR_CID, ®)"); - log::assert_that(L2CA_ConnectFixedChnl(L2CAP_SMP_BR_CID, kSmpBrAddr), - "assert failed: L2CA_ConnectFixedChnl(L2CAP_SMP_BR_CID, kSmpBrAddr)"); + log::assert_that( + stack::l2cap::get_interface().L2CA_ConnectFixedChnl(L2CAP_SMP_BR_CID, kSmpBrAddr), + "assert failed: L2CA_ConnectFixedChnl(L2CAP_SMP_BR_CID, kSmpBrAddr)"); l2c_link_hci_conn_comp(HCI_SUCCESS, kSmpBrHndl, kSmpBrAddr); - auto att_cid = L2CA_ConnectReq(BT_PSM_ATT, kAttAddr); + auto att_cid = stack::l2cap::get_interface().L2CA_ConnectReq(BT_PSM_ATT, kAttAddr); log::assert_that(att_cid != 0, "assert failed: att_cid != 0"); tL2CAP_LE_CFG_INFO cfg; - auto eatt_cid = L2CA_ConnectLECocReq(BT_PSM_EATT, kEattAddr, &cfg, 0); + auto eatt_cid = + stack::l2cap::get_interface().L2CA_ConnectLECocReq(BT_PSM_EATT, kEattAddr, &cfg, 0); log::assert_that(eatt_cid != 0, "assert failed: eatt_cid != 0"); FuzzedDataProvider fdp(data, size); @@ -245,13 +248,13 @@ static void Fuzz(const uint8_t* data, size_t size) { l2c_rcv_acl_data(hdr); } - (void)L2CA_DisconnectReq(att_cid); - (void)L2CA_DisconnectLECocReq(eatt_cid); + (void)stack::l2cap::get_interface().L2CA_DisconnectReq(att_cid); + (void)stack::l2cap::get_interface().L2CA_DisconnectLECocReq(eatt_cid); - (void)L2CA_RemoveFixedChnl(L2CAP_SMP_BR_CID, kSmpBrAddr); + (void)stack::l2cap::get_interface().L2CA_RemoveFixedChnl(L2CAP_SMP_BR_CID, kSmpBrAddr); l2c_link_hci_disc_comp(kSmpBrHndl, HCI_SUCCESS); - (void)L2CA_RemoveFixedChnl(L2CAP_ATT_CID, kAttAddr); + (void)stack::l2cap::get_interface().L2CA_RemoveFixedChnl(L2CAP_ATT_CID, kAttAddr); l2c_link_hci_disc_comp(kAttHndl, HCI_SUCCESS); l2cu_device_reset(); diff --git a/system/stack/gap/gap_conn.cc b/system/stack/gap/gap_conn.cc index ad59ebca80..1375b3e838 100644 --- a/system/stack/gap/gap_conn.cc +++ b/system/stack/gap/gap_conn.cc @@ -23,8 +23,6 @@ #include "gap_api.h" #include "hci/controller_interface.h" #include "internal_include/bt_target.h" -#include "l2c_api.h" -#include "l2cdefs.h" #include "main/shim/entry.h" #include "osi/include/allocator.h" #include "osi/include/fixed_queue.h" diff --git a/system/stack/gatt/att_protocol.cc b/system/stack/gatt/att_protocol.cc index 29e196bfea..af8cfdc7d8 100644 --- a/system/stack/gatt/att_protocol.cc +++ b/system/stack/gatt/att_protocol.cc @@ -26,7 +26,6 @@ #include "gatt_int.h" #include "internal_include/bt_target.h" -#include "l2c_api.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_types.h" diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc index 6c804e10bc..9008ee0850 100644 --- a/system/stack/gatt/gatt_api.cc +++ b/system/stack/gatt/gatt_api.cc @@ -33,7 +33,6 @@ #include "internal_include/bt_target.h" #include "internal_include/stack_config.h" -#include "l2c_api.h" #include "os/system_properties.h" #include "osi/include/allocator.h" #include "rust/src/connection/ffi/connection_shim.h" diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc index 6a195533cb..7c14d3a5a1 100644 --- a/system/stack/gatt/gatt_main.cc +++ b/system/stack/gatt/gatt_main.cc @@ -32,7 +32,6 @@ #include "device/include/interop.h" #include "internal_include/bt_target.h" #include "internal_include/stack_config.h" -#include "l2c_api.h" #include "main/shim/acl_api.h" #include "osi/include/allocator.h" #include "osi/include/properties.h" diff --git a/system/stack/gatt/gatt_sr.cc b/system/stack/gatt/gatt_sr.cc index 3efce5a466..ccb017edcc 100644 --- a/system/stack/gatt/gatt_sr.cc +++ b/system/stack/gatt/gatt_sr.cc @@ -31,7 +31,6 @@ #include "hardware/bt_gatt_types.h" #include "internal_include/bt_target.h" -#include "l2c_api.h" #include "osi/include/allocator.h" #include "stack/arbiter/acl_arbiter.h" #include "stack/eatt/eatt.h" @@ -39,7 +38,7 @@ #include "stack/include/bt_hdr.h" #include "stack/include/bt_types.h" #include "stack/include/btm_client_interface.h" -#include "stack/include/l2cdefs.h" +#include "stack/include/l2cap_types.h" #include "types/bluetooth/uuid.h" #define GATT_MTU_REQ_MIN_LEN 2 diff --git a/system/stack/hid/hidh_conn.cc b/system/stack/hid/hidh_conn.cc index 9387295a03..5205b322df 100644 --- a/system/stack/hid/hidh_conn.cc +++ b/system/stack/hid/hidh_conn.cc @@ -33,8 +33,6 @@ #include "hidh_api.h" #include "hidh_int.h" #include "internal_include/bt_target.h" -#include "l2c_api.h" -#include "l2cdefs.h" #include "osi/include/allocator.h" #include "osi/include/osi.h" #include "stack/include/acl_api.h" diff --git a/system/stack/include/bnep_api.h b/system/stack/include/bnep_api.h index fc8343ee48..a11ce06218 100644 --- a/system/stack/include/bnep_api.h +++ b/system/stack/include/bnep_api.h @@ -27,7 +27,6 @@ #include <cstdint> -#include "l2c_api.h" #include "stack/include/bt_hdr.h" #include "stack/include/l2cap_types.h" #include "types/bluetooth/uuid.h" diff --git a/system/stack/include/gap_api.h b/system/stack/include/gap_api.h index 6a3b8203d5..04329fdd9e 100644 --- a/system/stack/include/gap_api.h +++ b/system/stack/include/gap_api.h @@ -21,8 +21,6 @@ #include <cstdint> -#include "l2c_api.h" -#include "l2cdefs.h" #include "profiles_api.h" #include "stack/include/bt_hdr.h" #include "stack/include/l2cap_types.h" diff --git a/system/stack/include/hcidefs.h b/system/stack/include/hcidefs.h index e874d9fa91..7a6c4c733b 100644 --- a/system/stack/include/hcidefs.h +++ b/system/stack/include/hcidefs.h @@ -561,6 +561,7 @@ constexpr uint8_t HCI_LE_STATES_INIT_CENTRAL_PERIPHERAL_BIT = 41; #define HCI_USER_PASSKEY_NOTIFY_EVT 0x3B #define HCI_KEYPRESS_NOTIFY_EVT 0x3C #define HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT 0x3D +#define HCI_ENCRYPTION_CHANGE_EVT_V2 0x59 /* ULP HCI Event */ #define HCI_BLE_EVENT 0x3e diff --git a/system/stack/include/l2c_api.h b/system/stack/include/l2c_api.h deleted file mode 100644 index 790d6f5cac..0000000000 --- a/system/stack/include/l2c_api.h +++ /dev/null @@ -1,893 +0,0 @@ -/****************************************************************************** - * - * Copyright 1999-2012 Broadcom Corporation - * - * 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. - * - ******************************************************************************/ - -/****************************************************************************** - * - * this file contains the L2CAP API definitions - * - ******************************************************************************/ -#pragma once - -#include <bluetooth/log.h> -#include <stdbool.h> - -#include <cstdint> -#include <vector> - -#include "l2cdefs.h" -#include "stack/include/bt_hdr.h" -#include "stack/include/l2cap_interface.h" -#include "stack/include/l2cap_types.h" -#include "types/bt_transport.h" -#include "types/hci_role.h" -#include "types/raw_address.h" - -/***************************************************************************** - * Constants - ****************************************************************************/ - -/* Define the minimum offset that L2CAP needs in a buffer. This is made up of - * HCI type(1), len(2), handle(2), L2CAP len(2) and CID(2) => 9 - */ -#define L2CAP_MIN_OFFSET 13 /* plus control(2), SDU length(2) */ - -#define L2CAP_LCC_SDU_LENGTH 2 -#define L2CAP_LCC_OFFSET (L2CAP_MIN_OFFSET + L2CAP_LCC_SDU_LENGTH) /* plus SDU length(2) */ - -#define L2CAP_FCS_LENGTH 2 - -/* Values for priority parameter to L2CA_SetTxPriority */ -#define L2CAP_CHNL_PRIORITY_HIGH 0 -#define L2CAP_CHNL_PRIORITY_LOW 2 - -typedef uint8_t tL2CAP_CHNL_PRIORITY; - -/* Values for Tx/Rx data rate parameter to L2CA_SetChnlDataRate */ -#define L2CAP_CHNL_DATA_RATE_LOW 1 - -typedef uint8_t tL2CAP_CHNL_DATA_RATE; - -/* Data Packet Flags (bits 2-15 are reserved) */ -/* layer specific 14-15 bits are used for FCR SAR */ -#define L2CAP_FLUSHABLE_MASK 0x0003 -#define L2CAP_FLUSHABLE_CH_BASED 0x0000 -#define L2CAP_FLUSHABLE_PKT 0x0001 -#define L2CAP_NON_FLUSHABLE_PKT 0x0002 - -/* L2CA_FlushChannel num_to_flush definitions */ -#define L2CAP_FLUSH_CHANS_ALL 0xffff -#define L2CAP_FLUSH_CHANS_GET 0x0000 - -/* Values for 'allowed_modes' field passed in structure tL2CAP_ERTM_INFO - */ -#define L2CAP_FCR_CHAN_OPT_BASIC (1 << L2CAP_FCR_BASIC_MODE) -#define L2CAP_FCR_CHAN_OPT_ERTM (1 << L2CAP_FCR_ERTM_MODE) - -#define L2CAP_FCR_CHAN_OPT_ALL_MASK (L2CAP_FCR_CHAN_OPT_BASIC | L2CAP_FCR_CHAN_OPT_ERTM) - -/* Validity check for PSM. PSM values must be odd. Also, all PSM values must - * be assigned such that the least significant bit of the most sigificant - * octet equals zero. - */ -#define L2C_INVALID_PSM(psm) (((psm) & 0x0101) != 0x0001) -#define L2C_IS_VALID_PSM(psm) (((psm) & 0x0101) == 0x0001) -#define L2C_IS_VALID_LE_PSM(psm) (((psm) > 0x0000) && ((psm) < 0x0100)) - -#define L2CAP_NO_IDLE_TIMEOUT 0xFFFF - -/***************************************************************************** - * Type Definitions - ****************************************************************************/ - -/* Values for service_type */ -#define SVC_TYPE_BEST_EFFORT 1 -#define SVC_TYPE_GUARANTEED 2 - -// This is initial amout of credits we send, and amount to which we increase -// credits once they fall below threshold -uint16_t L2CA_LeCreditDefault(); - -// If credit count on remote fall below this value, we send back credits to -// reach default value. -uint16_t L2CA_LeCreditThreshold(); - -/********************************* - * Callback Functions Prototypes - *********************************/ - -/* Connection indication callback prototype. Parameters are - * BD Address of remote - * Local CID assigned to the connection - * PSM that the remote wants to connect to - * Identifier that the remote sent - */ -typedef void(tL2CA_CONNECT_IND_CB)(const RawAddress&, uint16_t, uint16_t, uint8_t); - -/* Connection confirmation callback prototype. Parameters are - * Local CID - * Result - 0 = connected - * If there is an error, tL2CA_ERROR_CB is invoked - */ -typedef void(tL2CA_CONNECT_CFM_CB)(uint16_t, tL2CAP_CONN); - -/* Configuration indication callback prototype. Parameters are - * Local CID assigned to the connection - * Pointer to configuration info - */ -typedef void(tL2CA_CONFIG_IND_CB)(uint16_t, tL2CAP_CFG_INFO*); - -/* Configuration confirm callback prototype. Parameters are - * Local CID assigned to the connection - * Initiator (1 for local, 0 for remote) - * Initial config from remote - * If there is an error, tL2CA_ERROR_CB is invoked - */ -typedef void(tL2CA_CONFIG_CFM_CB)(uint16_t, uint16_t, tL2CAP_CFG_INFO*); - -/* Disconnect indication callback prototype. Parameters are - * Local CID - * Boolean whether upper layer should ack this - */ -typedef void(tL2CA_DISCONNECT_IND_CB)(uint16_t, bool); - -/* Disconnect confirm callback prototype. Parameters are - * Local CID - * Result - */ -typedef void(tL2CA_DISCONNECT_CFM_CB)(uint16_t, uint16_t); - -/* Disconnect confirm callback prototype. Parameters are - * Local CID - * Result - */ -typedef void(tL2CA_DATA_IND_CB)(uint16_t, BT_HDR*); - -/* Congestion status callback protype. This callback is optional. If - * an application tries to send data when the transmit queue is full, - * the data will anyways be dropped. The parameter is: - * Local CID - * true if congested, false if uncongested - */ -typedef void(tL2CA_CONGESTION_STATUS_CB)(uint16_t, bool); - -/* Transmit complete callback protype. This callback is optional. If - * set, L2CAP will call it when packets are sent or flushed. If the - * count is 0xFFFF, it means all packets are sent for that CID (eRTM - * mode only). The parameters are: - * Local CID - * Number of SDUs sent or dropped - */ -typedef void(tL2CA_TX_COMPLETE_CB)(uint16_t, uint16_t); - -/* - * Notify the user when the remote send error result on ConnectRsp or ConfigRsp - * The parameters are: - * Local CID - * Error type (L2CAP_CONN_OTHER_ERROR for ConnectRsp, - * L2CAP_CFG_FAILED_NO_REASON for ConfigRsp) - */ -typedef void(tL2CA_ERROR_CB)(uint16_t, uint16_t); - -/* Create credit based connection request callback prototype. Parameters are - * BD Address of remote - * Vector of allocated local cids to accept - * PSM - * Peer MTU - * Identifier that the remote sent - */ -typedef void(tL2CA_CREDIT_BASED_CONNECT_IND_CB)(const RawAddress& bdaddr, - std::vector<uint16_t>& lcids, uint16_t psm, - uint16_t peer_mtu, uint8_t identifier); - -/* Collision Indication callback prototype. Used to notify upper layer that - * remote devices sent Credit Based Connection Request but it was rejected due - * to ongoing local request. Upper layer might want to sent another request when - * local request is completed. Parameters are: - * BD Address of remote - */ -typedef void(tL2CA_CREDIT_BASED_COLLISION_IND_CB)(const RawAddress& bdaddr); - -/* Credit based connection confirmation callback prototype. Parameters are - * BD Address of remote - * Connected Local CIDs - * Peer MTU - * Result - 0 = connected, non-zero means CID is not connected - */ -typedef void(tL2CA_CREDIT_BASED_CONNECT_CFM_CB)(const RawAddress& bdaddr, uint16_t lcid, - uint16_t peer_mtu, tL2CAP_LE_RESULT_CODE result); - -/* Credit based reconfiguration confirm callback prototype. Parameters are - * BD Address of remote - * Local CID assigned to the connection - * Flag indicating if this is local or peer configuration - * Pointer to configuration info - */ -typedef void(tL2CA_CREDIT_BASED_RECONFIG_COMPLETED_CB)(const RawAddress& bdaddr, uint16_t lcid, - bool is_local_cfg, - tL2CAP_LE_CFG_INFO* p_cfg); - -/***************************************************************************** - * External Function Declarations - ****************************************************************************/ - -// Also does security for you -[[nodiscard]] uint16_t L2CA_RegisterWithSecurity(uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info, - bool enable_snoop, tL2CAP_ERTM_INFO* p_ertm_info, - uint16_t my_mtu, uint16_t required_remote_mtu, - uint16_t sec_level); - -/******************************************************************************* - * - * Function L2CA_Register - * - * Description Other layers call this function to register for L2CAP - * services. - * - * Returns PSM to use or zero if error. Typically, the PSM returned - * is the same as was passed in, but for an outgoing-only - * connection to a dynamic PSM, a "virtual" PSM is returned - * and should be used in the calls to L2CA_ConnectReq() and - * BTM_SetSecurityLevel(). - * - ******************************************************************************/ -[[nodiscard]] uint16_t L2CA_Register(uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info, - bool enable_snoop, tL2CAP_ERTM_INFO* p_ertm_info, - uint16_t my_mtu, uint16_t required_remote_mtu, - uint16_t sec_level); - -/******************************************************************************* - * - * Function L2CA_Deregister - * - * Description Other layers call this function to deregister for L2CAP - * services. - * - * Returns void - * - ******************************************************************************/ -void L2CA_Deregister(uint16_t psm); - -/******************************************************************************* - * - * Function L2CA_AllocateLePSM - * - * Description Other layers call this function to find an unused LE PSM for - * L2CAP services. - * - * Returns LE_PSM to use if success. Otherwise returns 0. - * - ******************************************************************************/ -[[nodiscard]] uint16_t L2CA_AllocateLePSM(void); - -/******************************************************************************* - * - * Function L2CA_FreeLePSM - * - * Description Free an assigned LE PSM. - * - * Returns void - * - ******************************************************************************/ -void L2CA_FreeLePSM(uint16_t psm); - -[[nodiscard]] uint16_t L2CA_ConnectReqWithSecurity(uint16_t psm, const RawAddress& p_bd_addr, - uint16_t sec_level); -/******************************************************************************* - * - * Function L2CA_ConnectReq - * - * Description Higher layers call this function to create an L2CAP - * connection. - * Note that the connection is not established at this time, - * but connection establishment gets started. The callback - * will be invoked when connection establishes or fails. - * - * Returns the CID of the connection, or 0 if it failed to start - * - ******************************************************************************/ -[[nodiscard]] uint16_t L2CA_ConnectReq(uint16_t psm, const RawAddress& p_bd_addr); - -/******************************************************************************* - * - * Function L2CA_RegisterLECoc - * - * Description Other layers call this function to register for L2CAP - * Connection Oriented Channel. - * - * Returns PSM to use or zero if error. Typically, the PSM returned - * is the same as was passed in, but for an outgoing-only - * connection to a dynamic PSM, a "virtual" PSM is returned - * and should be used in the calls to L2CA_ConnectLECocReq() - * and BTM_SetSecurityLevel(). - * - ******************************************************************************/ -[[nodiscard]] uint16_t L2CA_RegisterLECoc(uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info, - uint16_t sec_level, tL2CAP_LE_CFG_INFO cfg); - -/******************************************************************************* - * - * Function L2CA_DeregisterLECoc - * - * Description Other layers call this function to deregister for L2CAP - * Connection Oriented Channel. - * - * Returns void - * - ******************************************************************************/ -void L2CA_DeregisterLECoc(uint16_t psm); - -/******************************************************************************* - * - * Function L2CA_ConnectLECocReq - * - * Description Higher layers call this function to create an L2CAP LE COC. - * Note that the connection is not established at this time, - * but connection establishment gets started. The callback - * will be invoked when connection establishes or fails. - * - * Returns the CID of the connection, or 0 if it failed to start - * - ******************************************************************************/ -[[nodiscard]] uint16_t L2CA_ConnectLECocReq(uint16_t psm, const RawAddress& p_bd_addr, - tL2CAP_LE_CFG_INFO* p_cfg, uint16_t sec_level); - -/******************************************************************************* - * - * Function L2CA_GetPeerLECocConfig - * - * Description Get peers configuration for LE Connection Oriented Channel. - * - * Return value: true if peer is connected - * - ******************************************************************************/ -[[nodiscard]] bool L2CA_GetPeerLECocConfig(uint16_t lcid, tL2CAP_LE_CFG_INFO* peer_cfg); - -/******************************************************************************* - * - * Function L2CA_GetPeerLECocCredit - * - * Description Get peers current credit for LE Connection Oriented - * Channel. - * - * Return value: Number of the peer current credit - * - ******************************************************************************/ -[[nodiscard]] uint16_t L2CA_GetPeerLECocCredit(const RawAddress& bd_addr, uint16_t lcid); - -/******************************************************************************* - * - * Function L2CA_ReconfigCreditBasedConnsReq - * - * Description Start reconfigure procedure on Connection Oriented Channel. - * - * Return value: true if peer is connected - * - ******************************************************************************/ -[[nodiscard]] bool L2CA_ReconfigCreditBasedConnsReq(const RawAddress& bd_addr, - std::vector<uint16_t>& lcids, - tL2CAP_LE_CFG_INFO* p_cfg); - -/******************************************************************************* - * - * Function L2CA_ConnectCreditBasedReq - * - * Description With this function L2CAP will initiate setup of up to 5 credit - * based connections for given psm using provided configuration. - * L2CAP will notify user on the connection result, by calling - * pL2CA_CreditBasedConnectCfm_Cb for each cid with a result. - * - * Return value: vector of allocated local cids for the connection - * - ******************************************************************************/ - -[[nodiscard]] std::vector<uint16_t> L2CA_ConnectCreditBasedReq(uint16_t psm, - const RawAddress& p_bd_addr, - tL2CAP_LE_CFG_INFO* p_cfg); - -/******************************************************************************* - * - * Function L2CA_ConnectCreditBasedRsp - * - * Description Response for the pL2CA_CreditBasedConnectInd_Cb which is the - * indication for peer requesting credit based connection. - * - * Return value: true if peer is connected - * - ******************************************************************************/ - -[[nodiscard]] bool L2CA_ConnectCreditBasedRsp(const RawAddress& p_bd_addr, uint8_t id, - std::vector<uint16_t>& accepted_lcids, - tL2CAP_LE_RESULT_CODE result, - tL2CAP_LE_CFG_INFO* p_cfg); -/******************************************************************************* - * - * Function L2CA_DisconnectReq - * - * Description Higher layers call this function to disconnect a channel. - * - * Returns true if disconnect sent, else false - * - ******************************************************************************/ -[[nodiscard]] bool L2CA_DisconnectReq(uint16_t cid); - -[[nodiscard]] bool L2CA_DisconnectLECocReq(uint16_t cid); - -/******************************************************************************* - * - * Function L2CA_DataWrite - * - * Description Higher layers call this function to write data. - * - * Returns tL2CAP_DW_RESULT::L2CAP_DW_SUCCESS, if data accepted, else - * false - * tL2CAP_DW_RESULT::L2CAP_DW_CONGESTED, if data accepted and - * the channel is congested - * tL2CAP_DW_RESULT::L2CAP_DW_FAILED, if error - * - ******************************************************************************/ -[[nodiscard]] tL2CAP_DW_RESULT L2CA_DataWrite(uint16_t cid, BT_HDR* p_data); - -[[nodiscard]] tL2CAP_DW_RESULT L2CA_LECocDataWrite(uint16_t cid, BT_HDR* p_data); - -/******************************************************************************* - * - * Function L2CA_GetRemoteChannelId - * - * Description Given a local channel identifier, |lcid|, this function - * returns the bound remote channel identifier, |rcid|. If - * |lcid| is not known or is invalid, this function returns - * false and does not modify the value pointed at by |rcid|. - * - * Parameters: lcid: Local CID - * rcid: Pointer to remote CID must NOT be nullptr - * - * Return value: true if rcid lookup was successful - * - ******************************************************************************/ -[[nodiscard]] bool L2CA_GetRemoteChannelId(uint16_t lcid, uint16_t* rcid); - -/******************************************************************************* - * - * Function L2CA_SetIdleTimeoutByBdAddr - * - * Description Higher layers call this function to set the idle timeout for - * a connection. The "idle timeout" is the amount of time that - * a connection can remain up with no L2CAP channels on it. - * A timeout of zero means that the connection will be torn - * down immediately when the last channel is removed. - * A timeout of 0xFFFF means no timeout. Values are in seconds. - * A bd_addr is the remote BD address. If bd_addr = - * RawAddress::kAny, then the idle timeouts for all active - * l2cap links will be changed. - * - * Returns true if command succeeded, false if failed - * - * NOTE This timeout applies to all logical channels active on the - * ACL link. - ******************************************************************************/ -[[nodiscard]] bool L2CA_SetIdleTimeoutByBdAddr(const RawAddress& bd_addr, uint16_t timeout, - tBT_TRANSPORT transport); - -/******************************************************************************* - * - * Function L2CA_FlushChannel - * - * Description This function flushes none, some or all buffers queued up - * for xmission for a particular CID. If called with - * L2CAP_FLUSH_CHANS_GET (0), it simply returns the number - * of buffers queued for that CID L2CAP_FLUSH_CHANS_ALL (0xffff) - * flushes all buffers. All other values specifies the maximum - * buffers to flush. - * - * Returns Number of buffers left queued for that CID - * - ******************************************************************************/ -[[nodiscard]] uint16_t L2CA_FlushChannel(uint16_t lcid, uint16_t num_to_flush); - -/******************************************************************************* - * - * Function L2CA_UseLatencyMode - * - * Description Sets use latency mode for an ACL channel. - * - * Returns true if a valid channel, else false - * - ******************************************************************************/ -[[nodiscard]] bool L2CA_UseLatencyMode(const RawAddress& bd_addr, bool use_latency_mode); - -/******************************************************************************* - * - * Function L2CA_SetAclPriority - * - * Description Sets the transmission priority for an ACL channel. - * (For initial implementation only two values are valid. - * L2CAP_PRIORITY_NORMAL and L2CAP_PRIORITY_HIGH). - * - * Returns true if a valid channel, else false - * - ******************************************************************************/ -[[nodiscard]] bool L2CA_SetAclPriority(const RawAddress& bd_addr, tL2CAP_PRIORITY priority); - -/******************************************************************************* - * - * Function L2CA_SetAclLatency - * - * Description Sets the transmission latency for a channel. - * - * Returns true if a valid channel, else false - * - ******************************************************************************/ -[[nodiscard]] bool L2CA_SetAclLatency(const RawAddress& bd_addr, tL2CAP_LATENCY latency); - -/******************************************************************************* - * - * Function L2CA_SetTxPriority - * - * Description Sets the transmission priority for a channel. (FCR Mode) - * - * Returns true if a valid channel, else false - * - ******************************************************************************/ -[[nodiscard]] bool L2CA_SetTxPriority(uint16_t cid, tL2CAP_CHNL_PRIORITY priority); - -/******************************************************************************* - * - * Function L2CA_SetChnlFlushability - * - * Description Higher layers call this function to set a channels - * flushability flags - * - * Returns true if CID found, else false - * - ******************************************************************************/ -[[nodiscard]] bool L2CA_SetChnlFlushability(uint16_t cid, bool is_flushable); - -/******************************************************************************* - * - * Function L2CA_GetPeerFeatures - * - * Description Get a peers features and fixed channel map - * - * Parameters: BD address of the peer - * Pointers to features and channel mask storage area - * - * Return value: true if peer is connected - * - ******************************************************************************/ -[[nodiscard]] bool L2CA_GetPeerFeatures(const RawAddress& bd_addr, uint32_t* p_ext_feat, - uint8_t* p_chnl_mask); - -/******************************************************************************* - * - * Fixed Channel callback prototypes - * - ******************************************************************************/ - -/* Fixed channel connected and disconnected. Parameters are - * channel - * BD Address of remote - * true if channel is connected, false if disconnected - * Reason for connection failure - * transport : physical transport, BR/EDR or LE - */ -typedef void(tL2CA_FIXED_CHNL_CB)(uint16_t, const RawAddress&, bool, uint16_t, tBT_TRANSPORT); - -/* Signalling data received. Parameters are - * channel - * BD Address of remote - * Pointer to buffer with data - */ -typedef void(tL2CA_FIXED_DATA_CB)(uint16_t, const RawAddress&, BT_HDR*); - -/* Congestion status callback protype. This callback is optional. If - * an application tries to send data when the transmit queue is full, - * the data will anyways be dropped. The parameter is: - * remote BD_ADDR - * true if congested, false if uncongested - */ -typedef void(tL2CA_FIXED_CONGESTION_STATUS_CB)(const RawAddress&, bool); - -/******************************************************************************* - * - * Function L2CA_RegisterFixedChannel - * - * Description Register a fixed channel. - * - * Parameters: Fixed Channel # - * Channel Callbacks and config - * - * Return value: true if registered OK - * - ******************************************************************************/ -[[nodiscard]] bool L2CA_RegisterFixedChannel(uint16_t fixed_cid, tL2CAP_FIXED_CHNL_REG* p_freg); - -/******************************************************************************* - * - * Function L2CA_ConnectFixedChnl - * - * Description Connect an fixed signalling channel to a remote device. - * - * Parameters: Fixed CID - * BD Address of remote - * - * Return value: true if connection started - * - ******************************************************************************/ -[[nodiscard]] bool L2CA_ConnectFixedChnl(uint16_t fixed_cid, const RawAddress& bd_addr); - -/******************************************************************************* - * - * Function L2CA_SendFixedChnlData - * - * Description Write data on a fixed signalling channel. - * - * Parameters: Fixed CID - * BD Address of remote - * Pointer to buffer of type BT_HDR - * - * Return value tL2CAP_DW_RESULT::L2CAP_DW_SUCCESS, if data accepted - * tL2CAP_DW_RESULT::L2CAP_DW_FAILED, if error - * - ******************************************************************************/ -[[nodiscard]] tL2CAP_DW_RESULT L2CA_SendFixedChnlData(uint16_t fixed_cid, const RawAddress& rem_bda, - BT_HDR* p_buf); - -/******************************************************************************* - * - * Function L2CA_RemoveFixedChnl - * - * Description Remove a fixed channel to a remote device. - * - * Parameters: Fixed CID - * BD Address of remote - * - * Return value: true if channel removed or marked for removal - * - ******************************************************************************/ -[[nodiscard]] bool L2CA_RemoveFixedChnl(uint16_t fixed_cid, const RawAddress& rem_bda); - -/******************************************************************************* - * - * Function L2CA_SetLeGattTimeout - * - * Description Higher layers call this function to set the idle timeout for - * a fixed channel. The "idle timeout" is the amount of time - * that a connection can remain up with no L2CAP channels on - * it. A timeout of zero means that the connection will be torn - * down immediately when the last channel is removed. - * A timeout of 0xFFFF means no timeout. Values are in seconds. - * A bd_addr is the remote BD address. If bd_addr = - * RawAddress::kAny, then the idle timeouts for all active - * l2cap links will be changed. - * - * Returns true if command succeeded, false if failed - * - ******************************************************************************/ -[[nodiscard]] bool L2CA_SetLeGattTimeout(const RawAddress& rem_bda, uint16_t idle_tout); - -[[nodiscard]] bool L2CA_MarkLeLinkAsActive(const RawAddress& rem_bda); - -[[nodiscard]] bool L2CA_UpdateBleConnParams(const RawAddress& rem_bda, uint16_t min_int, - uint16_t max_int, uint16_t latency, uint16_t timeout, - uint16_t min_ce_len, uint16_t max_ce_len); - -/* When called with lock=true, LE connection parameters will be locked on - * fastest value, and we won't accept request to change it from remote. When - * called with lock=false, parameters are relaxed. - */ -void L2CA_LockBleConnParamsForServiceDiscovery(const RawAddress& rem_bda, bool lock); - -/* When called with lock=true, LE connection parameters will be locked on - * fastest value, and we won't accept request to change it from remote. When - * called with lock=false, parameters are relaxed. - */ -void L2CA_LockBleConnParamsForProfileConnection(const RawAddress& rem_bda, bool lock); - -/******************************************************************************* - * - * Function L2CA_GetBleConnRole - * - * Description This function returns the connection role. - * - * Returns link role. - * - ******************************************************************************/ -void L2CA_Consolidate(const RawAddress& identity_addr, const RawAddress& rpa); -[[nodiscard]] tHCI_ROLE L2CA_GetBleConnRole(const RawAddress& bd_addr); - -void L2CA_AdjustConnectionIntervals(uint16_t* min_interval, uint16_t* max_interval, - uint16_t floor_interval); - -void L2CA_SetEcosystemBaseInterval(uint32_t base_interval); - -/** - * Check whether an ACL or LE link to the remote device is established - */ -[[nodiscard]] bool L2CA_IsLinkEstablished(const RawAddress& bd_addr, tBT_TRANSPORT transport); - -/******************************************************************************* - * - * Function L2CA_SetDefaultSubrate - * - * Description BLE Set Default Subrate. - * - * Parameters: Subrate parameters - * - * Return value: void - * - ******************************************************************************/ -void L2CA_SetDefaultSubrate(uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency, - uint16_t cont_num, uint16_t timeout); - -/******************************************************************************* - * - * Function L2CA_SubrateRequest - * - * Description BLE Subrate request. - * - * Parameters: Subrate parameters - * - * Return value: true if update started - * - ******************************************************************************/ -[[nodiscard]] bool L2CA_SubrateRequest(const RawAddress& rem_bda, uint16_t subrate_min, - uint16_t subrate_max, uint16_t max_latency, - uint16_t cont_num, uint16_t timeout); - -/******************************************************************************* -** -** Function L2CA_SetMediaStreamChannel -** -** Description This function is called to set/reset the ccb of active media -** streaming channel -** -** Parameters: local_media_cid: The local cid provided to A2DP to be used -** for streaming -** status: The status of media streaming on this channel -** -** Returns void -** -*******************************************************************************/ -void L2CA_SetMediaStreamChannel(uint16_t local_media_cid, bool status); - -/******************************************************************************* -** -** Function L2CA_isMediaChannel -** -** Description This function returns if the channel id passed as parameter -** is an A2DP streaming channel -** -** Parameters: handle: Connection handle with the remote device -** channel_id: Channel ID -** is_local_cid: Signifies if the channel id passed is local -** cid or remote cid (true if local, remote otherwise) -** -** Returns bool -** -*******************************************************************************/ -[[nodiscard]] bool L2CA_isMediaChannel(uint16_t handle, uint16_t channel_id, bool is_local_cid); - -namespace bluetooth { -namespace stack { -namespace l2cap { - -class Impl : public Interface { -public: - virtual ~Impl() = default; - - // Lifecycle methods to register BR/EDR l2cap services - [[nodiscard]] uint16_t L2CA_Register(uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info, - bool enable_snoop, tL2CAP_ERTM_INFO* p_ertm_info, - uint16_t my_mtu, uint16_t required_remote_mtu, - uint16_t sec_level) override; - [[nodiscard]] uint16_t L2CA_RegisterWithSecurity(uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info, - bool enable_snoop, tL2CAP_ERTM_INFO* p_ertm_info, - uint16_t my_mtu, uint16_t required_remote_mtu, - uint16_t sec_level) override; - void L2CA_Deregister(uint16_t psm) override; - - // Lifecycle methods to register BLE l2cap services - [[nodiscard]] uint16_t L2CA_AllocateLePSM(void) override; - void L2CA_FreeLePSM(uint16_t psm) override; - - [[nodiscard]] uint16_t L2CA_RegisterLECoc(uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info, - uint16_t sec_level, tL2CAP_LE_CFG_INFO cfg) override; - void L2CA_DeregisterLECoc(uint16_t psm) override; - - // Methods used for both BR/EDR and BLE - [[nodiscard]] bool L2CA_IsLinkEstablished(const RawAddress& bd_addr, - tBT_TRANSPORT transport) override; - [[nodiscard]] bool L2CA_SetIdleTimeoutByBdAddr(const RawAddress& bd_addr, uint16_t timeout, - tBT_TRANSPORT transport) override; - [[nodiscard]] bool L2CA_GetRemoteChannelId(uint16_t lcid, uint16_t* rcid) override; - - // Connection methods to configure and connect to peer over BR/EDR ACL - [[nodiscard]] uint16_t L2CA_ConnectReq(uint16_t psm, const RawAddress& bd_addr) override; - [[nodiscard]] uint16_t L2CA_ConnectReqWithSecurity(uint16_t psm, const RawAddress& bd_addr, - uint16_t sec_level) override; - [[nodiscard]] bool L2CA_SetAclLatency(const RawAddress& bd_addr, tL2CAP_LATENCY latency) override; - [[nodiscard]] bool L2CA_UseLatencyMode(const RawAddress& bd_addr, bool use_latency_mode) override; - [[nodiscard]] bool L2CA_GetPeerFeatures(const RawAddress& bd_addr, uint32_t* p_ext_feat, - uint8_t* p_chnl_mask) override; - [[nodiscard]] bool L2CA_SetAclPriority(const RawAddress& bd_addr, - tL2CAP_PRIORITY priority) override; - void L2CA_SetDefaultSubrate(uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency, - uint16_t cont_num, uint16_t timeout) override; - void L2CA_AdjustConnectionIntervals(uint16_t* min_interval, uint16_t* max_interval, - uint16_t floor_interval) override; - void L2CA_SetEcosystemBaseInterval(uint32_t base_interval) override; - - [[nodiscard]] bool L2CA_SubrateRequest(const RawAddress& bd_addr, uint16_t subrate_min, - uint16_t subrate_max, uint16_t max_latency, - uint16_t cont_num, uint16_t timeout) override; - [[nodiscard]] uint16_t L2CA_FlushChannel(uint16_t lcid, uint16_t num_to_flush) override; - [[nodiscard]] bool L2CA_SetTxPriority(uint16_t cid, tL2CAP_CHNL_PRIORITY priority) override; - [[nodiscard]] bool L2CA_SetChnlFlushability(uint16_t cid, bool is_flushable) override; - - // Connection methods to configure and connect to peer over BLE ACL - [[nodiscard]] uint16_t L2CA_ConnectLECocReq(uint16_t psm, const RawAddress& bd_addr, - tL2CAP_LE_CFG_INFO* p_cfg, - uint16_t sec_level) override; - [[nodiscard]] std::vector<uint16_t> L2CA_ConnectCreditBasedReq( - uint16_t psm, const RawAddress& bd_addr, tL2CAP_LE_CFG_INFO* p_cfg) override; - [[nodiscard]] bool L2CA_ConnectCreditBasedRsp(const RawAddress& bd_addr, uint8_t id, - std::vector<uint16_t>& accepted_lcids, - tL2CAP_LE_RESULT_CODE result, - tL2CAP_LE_CFG_INFO* p_cfg) override; - [[nodiscard]] uint16_t L2CA_GetPeerLECocCredit(const RawAddress& bd_addr, uint16_t lcid) override; - [[nodiscard]] bool L2CA_ReconfigCreditBasedConnsReq(const RawAddress& bd_addr, - std::vector<uint16_t>& lcids, - tL2CAP_LE_CFG_INFO* p_cfg) override; - [[nodiscard]] bool L2CA_UpdateBleConnParams(const RawAddress& bd_addr, uint16_t min_int, - uint16_t max_int, uint16_t latency, uint16_t timeout, - uint16_t min_ce_len, uint16_t max_ce_len) override; - void L2CA_LockBleConnParamsForServiceDiscovery(const RawAddress& bd_addr, bool lock) override; - void L2CA_LockBleConnParamsForProfileConnection(const RawAddress& bd_addr, bool lock) override; - [[nodiscard]] tHCI_ROLE L2CA_GetBleConnRole(const RawAddress& bd_addr) override; - [[nodiscard]] bool L2CA_SetLeGattTimeout(const RawAddress& bd_addr, uint16_t idle_tout) override; - [[nodiscard]] bool L2CA_MarkLeLinkAsActive(const RawAddress& bd_addr) override; - [[nodiscard]] bool L2CA_GetPeerLECocConfig(uint16_t lcid, tL2CAP_LE_CFG_INFO* peer_cfg) override; - // Method to consolidate two BLE addresses into a single device - void L2CA_Consolidate(const RawAddress& identity_addr, const RawAddress& rpa) override; - - // Disconnect methods an active connection for both BR/EDR and BLE - [[nodiscard]] bool L2CA_DisconnectReq(uint16_t cid) override; - [[nodiscard]] bool L2CA_DisconnectLECocReq(uint16_t cid) override; - - // Data write methods for both BR/EDR and BLE - [[nodiscard]] tL2CAP_DW_RESULT L2CA_DataWrite(uint16_t cid, BT_HDR* p_data) override; - [[nodiscard]] tL2CAP_DW_RESULT L2CA_LECocDataWrite(uint16_t cid, BT_HDR* p_data) override; - - // Fixed channel methods - [[nodiscard]] bool L2CA_RegisterFixedChannel(uint16_t fixed_cid, - tL2CAP_FIXED_CHNL_REG* p_freg) override; - [[nodiscard]] bool L2CA_ConnectFixedChnl(uint16_t fixed_cid, const RawAddress& bd_addr) override; - [[nodiscard]] tL2CAP_DW_RESULT L2CA_SendFixedChnlData(uint16_t fixed_cid, - const RawAddress& bd_addr, - BT_HDR* p_buf) override; - [[nodiscard]] bool L2CA_RemoveFixedChnl(uint16_t fixed_cid, const RawAddress& bd_addr) override; - - // Media methods - void L2CA_SetMediaStreamChannel(uint16_t local_media_cid, bool status) override; - [[nodiscard]] bool L2CA_isMediaChannel(uint16_t handle, uint16_t channel_id, - bool is_local_cid) override; -}; - -} // namespace l2cap -} // namespace stack -} // namespace bluetooth diff --git a/system/stack/include/sec_hci_link_interface.h b/system/stack/include/sec_hci_link_interface.h index eb142adfa4..0612f1b1e3 100644 --- a/system/stack/include/sec_hci_link_interface.h +++ b/system/stack/include/sec_hci_link_interface.h @@ -33,8 +33,10 @@ void btm_read_local_oob_complete(const tBTM_SP_LOC_OOB evt_data); void btm_rem_oob_req(const RawAddress bd_addr); void btm_sec_auth_complete(uint16_t handle, tHCI_STATUS status); void btm_sec_disconnected(uint16_t handle, tHCI_STATUS reason, std::string); -void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable); -void btm_sec_encryption_change_evt(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable); +void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable, + uint8_t key_size, bool from_key_refresh = false); +void btm_sec_encryption_change_evt(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable, + uint8_t key_size); void btm_sec_encryption_key_refresh_complete(uint16_t handle, tHCI_STATUS status); void btm_sec_link_key_notification(const RawAddress& p_bda, const Octet16& link_key, uint8_t key_type); diff --git a/system/stack/l2cap/internal/l2c_api.h b/system/stack/l2cap/internal/l2c_api.h index 06741bed8f..6f65f81d71 100644 --- a/system/stack/l2cap/internal/l2c_api.h +++ b/system/stack/l2cap/internal/l2c_api.h @@ -40,11 +40,6 @@ * Constants ****************************************************************************/ -/* Define the minimum offset that L2CAP needs in a buffer. This is made up of - * HCI type(1), len(2), handle(2), L2CAP len(2) and CID(2) => 9 - */ -#define L2CAP_MIN_OFFSET 13 /* plus control(2), SDU length(2) */ - #define L2CAP_LCC_SDU_LENGTH 2 #define L2CAP_LCC_OFFSET (L2CAP_MIN_OFFSET + L2CAP_LCC_SDU_LENGTH) /* plus SDU length(2) */ @@ -410,10 +405,11 @@ void L2CA_DeregisterLECoc(uint16_t psm); * Return value: true if peer is connected * ******************************************************************************/ - [[nodiscard]] bool L2CA_ConnectCreditBasedRsp(const RawAddress& p_bd_addr, uint8_t id, std::vector<uint16_t>& accepted_lcids, - uint16_t result, tL2CAP_LE_CFG_INFO* p_cfg); + tL2CAP_LE_RESULT_CODE result, + tL2CAP_LE_CFG_INFO* p_cfg); + /******************************************************************************* * * Function L2CA_DisconnectReq diff --git a/system/stack/l2cap/l2c_api.h b/system/stack/l2cap/l2c_api.h new file mode 100644 index 0000000000..f645803dad --- /dev/null +++ b/system/stack/l2cap/l2c_api.h @@ -0,0 +1,140 @@ +/****************************************************************************** + * + * Copyright 1999-2012 Broadcom Corporation + * + * 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. + * + ******************************************************************************/ +#pragma once + +#include <bluetooth/log.h> +#include <stdbool.h> + +#include <cstdint> +#include <vector> + +#include "stack/include/bt_hdr.h" +#include "stack/include/l2cap_interface.h" +#include "types/bt_transport.h" +#include "types/hci_role.h" +#include "types/raw_address.h" + +namespace bluetooth { +namespace stack { +namespace l2cap { + +class Impl : public Interface { +public: + virtual ~Impl() = default; + + // Lifecycle methods to register BR/EDR l2cap services + [[nodiscard]] uint16_t L2CA_Register(uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info, + bool enable_snoop, tL2CAP_ERTM_INFO* p_ertm_info, + uint16_t my_mtu, uint16_t required_remote_mtu, + uint16_t sec_level) override; + [[nodiscard]] uint16_t L2CA_RegisterWithSecurity(uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info, + bool enable_snoop, tL2CAP_ERTM_INFO* p_ertm_info, + uint16_t my_mtu, uint16_t required_remote_mtu, + uint16_t sec_level) override; + void L2CA_Deregister(uint16_t psm) override; + + // Lifecycle methods to register BLE l2cap services + [[nodiscard]] uint16_t L2CA_AllocateLePSM(void) override; + void L2CA_FreeLePSM(uint16_t psm) override; + + [[nodiscard]] uint16_t L2CA_RegisterLECoc(uint16_t psm, const tL2CAP_APPL_INFO& p_cb_info, + uint16_t sec_level, tL2CAP_LE_CFG_INFO cfg) override; + void L2CA_DeregisterLECoc(uint16_t psm) override; + + // Methods used for both BR/EDR and BLE + [[nodiscard]] bool L2CA_IsLinkEstablished(const RawAddress& bd_addr, + tBT_TRANSPORT transport) override; + [[nodiscard]] bool L2CA_SetIdleTimeoutByBdAddr(const RawAddress& bd_addr, uint16_t timeout, + tBT_TRANSPORT transport) override; + [[nodiscard]] bool L2CA_GetRemoteChannelId(uint16_t lcid, uint16_t* rcid) override; + + // Connection methods to configure and connect to peer over BR/EDR ACL + [[nodiscard]] uint16_t L2CA_ConnectReq(uint16_t psm, const RawAddress& bd_addr) override; + [[nodiscard]] uint16_t L2CA_ConnectReqWithSecurity(uint16_t psm, const RawAddress& bd_addr, + uint16_t sec_level) override; + [[nodiscard]] bool L2CA_SetAclLatency(const RawAddress& bd_addr, tL2CAP_LATENCY latency) override; + [[nodiscard]] bool L2CA_UseLatencyMode(const RawAddress& bd_addr, bool use_latency_mode) override; + [[nodiscard]] bool L2CA_GetPeerFeatures(const RawAddress& bd_addr, uint32_t* p_ext_feat, + uint8_t* p_chnl_mask) override; + [[nodiscard]] bool L2CA_SetAclPriority(const RawAddress& bd_addr, + tL2CAP_PRIORITY priority) override; + void L2CA_SetDefaultSubrate(uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency, + uint16_t cont_num, uint16_t timeout) override; + void L2CA_AdjustConnectionIntervals(uint16_t* min_interval, uint16_t* max_interval, + uint16_t floor_interval) override; + void L2CA_SetEcosystemBaseInterval(uint32_t base_interval) override; + + [[nodiscard]] bool L2CA_SubrateRequest(const RawAddress& bd_addr, uint16_t subrate_min, + uint16_t subrate_max, uint16_t max_latency, + uint16_t cont_num, uint16_t timeout) override; + [[nodiscard]] uint16_t L2CA_FlushChannel(uint16_t lcid, uint16_t num_to_flush) override; + [[nodiscard]] bool L2CA_SetTxPriority(uint16_t cid, tL2CAP_CHNL_PRIORITY priority) override; + [[nodiscard]] bool L2CA_SetChnlFlushability(uint16_t cid, bool is_flushable) override; + + // Connection methods to configure and connect to peer over BLE ACL + [[nodiscard]] uint16_t L2CA_ConnectLECocReq(uint16_t psm, const RawAddress& bd_addr, + tL2CAP_LE_CFG_INFO* p_cfg, + uint16_t sec_level) override; + [[nodiscard]] std::vector<uint16_t> L2CA_ConnectCreditBasedReq( + uint16_t psm, const RawAddress& bd_addr, tL2CAP_LE_CFG_INFO* p_cfg) override; + [[nodiscard]] bool L2CA_ConnectCreditBasedRsp(const RawAddress& bd_addr, uint8_t id, + std::vector<uint16_t>& accepted_lcids, + tL2CAP_LE_RESULT_CODE result, + tL2CAP_LE_CFG_INFO* p_cfg) override; + [[nodiscard]] uint16_t L2CA_GetPeerLECocCredit(const RawAddress& bd_addr, uint16_t lcid) override; + [[nodiscard]] bool L2CA_ReconfigCreditBasedConnsReq(const RawAddress& bd_addr, + std::vector<uint16_t>& lcids, + tL2CAP_LE_CFG_INFO* p_cfg) override; + [[nodiscard]] bool L2CA_UpdateBleConnParams(const RawAddress& bd_addr, uint16_t min_int, + uint16_t max_int, uint16_t latency, uint16_t timeout, + uint16_t min_ce_len, uint16_t max_ce_len) override; + void L2CA_LockBleConnParamsForServiceDiscovery(const RawAddress& bd_addr, bool lock) override; + void L2CA_LockBleConnParamsForProfileConnection(const RawAddress& bd_addr, bool lock) override; + [[nodiscard]] tHCI_ROLE L2CA_GetBleConnRole(const RawAddress& bd_addr) override; + [[nodiscard]] bool L2CA_SetLeGattTimeout(const RawAddress& bd_addr, uint16_t idle_tout) override; + [[nodiscard]] bool L2CA_MarkLeLinkAsActive(const RawAddress& bd_addr) override; + [[nodiscard]] bool L2CA_GetPeerLECocConfig(uint16_t lcid, tL2CAP_LE_CFG_INFO* peer_cfg) override; + // Method to consolidate two BLE addresses into a single device + void L2CA_Consolidate(const RawAddress& identity_addr, const RawAddress& rpa) override; + + // Disconnect methods an active connection for both BR/EDR and BLE + [[nodiscard]] bool L2CA_DisconnectReq(uint16_t cid) override; + [[nodiscard]] bool L2CA_DisconnectLECocReq(uint16_t cid) override; + + // Data write methods for both BR/EDR and BLE + [[nodiscard]] tL2CAP_DW_RESULT L2CA_DataWrite(uint16_t cid, BT_HDR* p_data) override; + [[nodiscard]] tL2CAP_DW_RESULT L2CA_LECocDataWrite(uint16_t cid, BT_HDR* p_data) override; + + // Fixed channel methods + [[nodiscard]] bool L2CA_RegisterFixedChannel(uint16_t fixed_cid, + tL2CAP_FIXED_CHNL_REG* p_freg) override; + [[nodiscard]] bool L2CA_ConnectFixedChnl(uint16_t fixed_cid, const RawAddress& bd_addr) override; + [[nodiscard]] tL2CAP_DW_RESULT L2CA_SendFixedChnlData(uint16_t fixed_cid, + const RawAddress& bd_addr, + BT_HDR* p_buf) override; + [[nodiscard]] bool L2CA_RemoveFixedChnl(uint16_t fixed_cid, const RawAddress& bd_addr) override; + + // Media methods + void L2CA_SetMediaStreamChannel(uint16_t local_media_cid, bool status) override; + [[nodiscard]] bool L2CA_isMediaChannel(uint16_t handle, uint16_t channel_id, + bool is_local_cid) override; +}; + +} // namespace l2cap +} // namespace stack +} // namespace bluetooth diff --git a/system/stack/l2cap/l2c_ble.cc b/system/stack/l2cap/l2c_ble.cc index 261bcbb51e..ab18235791 100644 --- a/system/stack/l2cap/l2c_ble.cc +++ b/system/stack/l2cap/l2c_ble.cc @@ -50,7 +50,6 @@ #include "stack/include/btm_client_interface.h" #include "stack/include/btm_log_history.h" #include "stack/include/btm_status.h" -#include "stack/include/l2c_api.h" #include "stack/include/l2cap_acl_interface.h" #include "stack/include/l2cap_interface.h" #include "stack/include/l2cdefs.h" diff --git a/system/stack/l2cap/l2c_fcr.cc b/system/stack/l2cap/l2c_fcr.cc index 6eadd80987..fdcbdb0506 100644 --- a/system/stack/l2cap/l2c_fcr.cc +++ b/system/stack/l2cap/l2c_fcr.cc @@ -31,8 +31,8 @@ #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_types.h" -#include "stack/include/l2c_api.h" #include "stack/include/l2cdefs.h" +#include "stack/l2cap/internal/l2c_api.h" #include "stack/l2cap/l2c_int.h" /* Flag passed to retransmit_i_frames() when all packets should be retransmitted diff --git a/system/stack/l2cap/l2c_link.cc b/system/stack/l2cap/l2c_link.cc index a6257941b5..d9582b65c3 100644 --- a/system/stack/l2cap/l2c_link.cc +++ b/system/stack/l2cap/l2c_link.cc @@ -32,7 +32,6 @@ #include "device/include/device_iot_config.h" #include "internal_include/bt_target.h" -#include "l2c_api.h" #include "osi/include/allocator.h" #include "stack/btm/btm_int_types.h" #include "stack/include/acl_api.h" diff --git a/system/stack/l2cap/l2c_main.cc b/system/stack/l2cap/l2c_main.cc index a2963483ee..9d5645e9c1 100644 --- a/system/stack/l2cap/l2c_main.cc +++ b/system/stack/l2cap/l2c_main.cc @@ -35,7 +35,6 @@ #include "stack/include/bt_psm_types.h" #include "stack/include/bt_types.h" #include "stack/include/hcimsgs.h" // HCID_GET_ -#include "stack/include/l2c_api.h" #include "stack/include/l2cap_hci_link_interface.h" #include "stack/include/l2cap_interface.h" #include "stack/include/l2cdefs.h" diff --git a/system/stack/l2cap/l2c_utils.cc b/system/stack/l2cap/l2c_utils.cc index 106e84e2fe..8e69744d82 100644 --- a/system/stack/l2cap/l2c_utils.cc +++ b/system/stack/l2cap/l2c_utils.cc @@ -43,7 +43,6 @@ #include "stack/include/btm_status.h" #include "stack/include/hci_error_code.h" #include "stack/include/hcidefs.h" -#include "stack/include/l2c_api.h" #include "stack/include/l2cap_acl_interface.h" #include "stack/include/l2cap_hci_link_interface.h" #include "stack/include/l2cap_interface.h" diff --git a/system/stack/l2cap/l2cap_api.cc b/system/stack/l2cap/l2cap_api.cc index 3b4159d786..94466c90e2 100644 --- a/system/stack/l2cap/l2cap_api.cc +++ b/system/stack/l2cap/l2cap_api.cc @@ -14,8 +14,9 @@ * limitations under the License. */ -#include "stack/include/l2c_api.h" #include "stack/include/l2cap_interface.h" +#include "stack/l2cap/internal/l2c_api.h" +#include "stack/l2cap/l2c_api.h" static bluetooth::stack::l2cap::Impl l2cap_impl; static bluetooth::stack::l2cap::Interface* interface_ = &l2cap_impl; diff --git a/system/stack/rfcomm/rfc_ts_frames.cc b/system/stack/rfcomm/rfc_ts_frames.cc index 7dfff833c6..b0b4b1c143 100644 --- a/system/stack/rfcomm/rfc_ts_frames.cc +++ b/system/stack/rfcomm/rfc_ts_frames.cc @@ -31,7 +31,6 @@ #include "os/logging/log_adapter.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" -#include "stack/include/l2c_api.h" #include "stack/include/rfcdefs.h" #include "stack/rfcomm/port_int.h" #include "stack/rfcomm/rfc_int.h" diff --git a/system/stack/smp/smp_api.cc b/system/stack/smp/smp_api.cc index 247d5fdb19..4485bf3fcb 100644 --- a/system/stack/smp/smp_api.cc +++ b/system/stack/smp/smp_api.cc @@ -29,8 +29,6 @@ #include <bluetooth/log.h> #include <string.h> -#include "l2c_api.h" -#include "l2cdefs.h" #include "smp_int.h" #include "stack/include/bt_octets.h" #include "stack/include/btm_sec_api_types.h" diff --git a/system/stack/test/btm/stack_btm_sec_test.cc b/system/stack/test/btm/stack_btm_sec_test.cc index 812d1563cd..daa6bfbfb4 100644 --- a/system/stack/test/btm/stack_btm_sec_test.cc +++ b/system/stack/test/btm/stack_btm_sec_test.cc @@ -30,6 +30,7 @@ #include "stack/btm/btm_sec_cb.h" #include "stack/btm/security_device_record.h" #include "stack/include/btm_status.h" +#include "stack/include/sec_hci_link_interface.h" #include "stack/test/btm/btm_test_fixtures.h" #include "test/mock/mock_main_shim_entry.h" #include "types/raw_address.h" @@ -118,18 +119,18 @@ TEST_F(StackBtmSecWithInitFreeTest, btm_sec_encrypt_change) { // Check the collision conditionals ::btm_sec_cb.collision_start_time = 0UL; - btm_sec_encrypt_change(classic_handle, HCI_ERR_LMP_ERR_TRANS_COLLISION, 0x01); + btm_sec_encrypt_change(classic_handle, HCI_ERR_LMP_ERR_TRANS_COLLISION, 0x01, 0x10); uint64_t collision_start_time = ::btm_sec_cb.collision_start_time; ASSERT_NE(0UL, collision_start_time); ::btm_sec_cb.collision_start_time = 0UL; - btm_sec_encrypt_change(classic_handle, HCI_ERR_DIFF_TRANSACTION_COLLISION, 0x01); + btm_sec_encrypt_change(classic_handle, HCI_ERR_DIFF_TRANSACTION_COLLISION, 0x01, 0x10); collision_start_time = ::btm_sec_cb.collision_start_time; ASSERT_NE(0UL, collision_start_time); // No device ::btm_sec_cb.collision_start_time = 0; - btm_sec_encrypt_change(classic_handle, HCI_SUCCESS, 0x01); + btm_sec_encrypt_change(classic_handle, HCI_SUCCESS, 0x01, 0x10); ASSERT_EQ(0UL, ::btm_sec_cb.collision_start_time); // Setup device @@ -141,21 +142,21 @@ TEST_F(StackBtmSecWithInitFreeTest, btm_sec_encrypt_change) { device_record->ble_hci_handle = ble_handle; // With classic device encryption enable - btm_sec_encrypt_change(classic_handle, HCI_SUCCESS, 0x01); + btm_sec_encrypt_change(classic_handle, HCI_SUCCESS, 0x01, 0x10); ASSERT_EQ(BTM_SEC_IN_USE | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED, device_record->sec_rec.sec_flags); // With classic device encryption disable - btm_sec_encrypt_change(classic_handle, HCI_SUCCESS, 0x00); + btm_sec_encrypt_change(classic_handle, HCI_SUCCESS, 0x00, 0x10); ASSERT_EQ(BTM_SEC_IN_USE | BTM_SEC_AUTHENTICATED, device_record->sec_rec.sec_flags); device_record->sec_rec.sec_flags = BTM_SEC_IN_USE; // With le device encryption enable - btm_sec_encrypt_change(ble_handle, HCI_SUCCESS, 0x01); + btm_sec_encrypt_change(ble_handle, HCI_SUCCESS, 0x01, 0x10); ASSERT_EQ(BTM_SEC_IN_USE | BTM_SEC_LE_ENCRYPTED, device_record->sec_rec.sec_flags); // With le device encryption disable - btm_sec_encrypt_change(ble_handle, HCI_SUCCESS, 0x00); + btm_sec_encrypt_change(ble_handle, HCI_SUCCESS, 0x00, 0x10); ASSERT_EQ(BTM_SEC_IN_USE, device_record->sec_rec.sec_flags); device_record->sec_rec.sec_flags = BTM_SEC_IN_USE; diff --git a/system/stack/test/common/mock_l2cap_layer.h b/system/stack/test/common/mock_l2cap_layer.h index 21a6038338..6c4f3ed4e7 100644 --- a/system/stack/test/common/mock_l2cap_layer.h +++ b/system/stack/test/common/mock_l2cap_layer.h @@ -22,7 +22,7 @@ #include <vector> #include "stack/include/bt_hdr.h" -#include "stack/include/l2c_api.h" +#include "stack/include/l2cap_interface.h" #include "types/raw_address.h" namespace bluetooth { diff --git a/system/stack/test/common/stack_test_packet_utils.cc b/system/stack/test/common/stack_test_packet_utils.cc index 841d331a8a..e87f3cfc77 100644 --- a/system/stack/test/common/stack_test_packet_utils.cc +++ b/system/stack/test/common/stack_test_packet_utils.cc @@ -20,10 +20,9 @@ #include <bluetooth/log.h> -#include "hci/include/hci_layer.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" -#include "stack/include/l2c_api.h" +#include "stack/include/l2cap_types.h" #include "stack/include/l2cdefs.h" namespace bluetooth { diff --git a/system/test/mock/mock_stack_btm_sec.cc b/system/test/mock/mock_stack_btm_sec.cc index 3971582d81..4be4fe51cb 100644 --- a/system/test/mock/mock_stack_btm_sec.cc +++ b/system/test/mock/mock_stack_btm_sec.cc @@ -316,13 +316,16 @@ void btm_sec_disconnected(uint16_t handle, tHCI_REASON reason, std::string comme inc_func_call_count(__func__); test::mock::stack_btm_sec::btm_sec_disconnected(handle, reason, comment); } -void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable) { +void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable, + uint8_t key_size, bool from_key_refresh) { inc_func_call_count(__func__); - test::mock::stack_btm_sec::btm_sec_encrypt_change(handle, status, encr_enable); + test::mock::stack_btm_sec::btm_sec_encrypt_change(handle, status, encr_enable, key_size, + from_key_refresh); } -void btm_sec_encryption_change_evt(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable) { +void btm_sec_encryption_change_evt(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable, + uint8_t key_size) { inc_func_call_count(__func__); - test::mock::stack_btm_sec::btm_sec_encryption_change_evt(handle, status, encr_enable); + test::mock::stack_btm_sec::btm_sec_encryption_change_evt(handle, status, encr_enable, key_size); } bool btm_sec_is_a_bonded_dev(const RawAddress& bda) { inc_func_call_count(__func__); diff --git a/system/test/mock/mock_stack_btm_sec.h b/system/test/mock/mock_stack_btm_sec.h index 7cb1354929..8f716f443b 100644 --- a/system/test/mock/mock_stack_btm_sec.h +++ b/system/test/mock/mock_stack_btm_sec.h @@ -553,25 +553,29 @@ struct btm_sec_disconnected { extern struct btm_sec_disconnected btm_sec_disconnected; // Name: btm_sec_encrypt_change -// Params: uint16_t handle, tHCI_STATUS status, uint8_t encr_enable -// Return: void +// Params: uint16_t handle, tHCI_STATUS status, uint8_t encr_enable, uint8_t key_size, bool +// from_key_refresh Return: void struct btm_sec_encrypt_change { - std::function<void(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable)> body{ - [](uint16_t /* handle */, tHCI_STATUS /* status */, uint8_t /* encr_enable */) {}}; - void operator()(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable) { - body(handle, status, encr_enable); + std::function<void(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable, uint8_t key_size, + bool from_key_refresh)> + body{[](uint16_t /* handle */, tHCI_STATUS /* status */, uint8_t /* encr_enable */, + uint8_t /* key_size */, bool /* from_key_refresh */) {}}; + void operator()(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable, uint8_t key_size, + bool from_key_refresh) { + body(handle, status, encr_enable, key_size, from_key_refresh); } }; extern struct btm_sec_encrypt_change btm_sec_encrypt_change; // Name: btm_sec_encryption_change_evt -// Params: uint16_t handle, tHCI_STATUS status, uint8_t encr_enable +// Params: uint16_t handle, tHCI_STATUS status, uint8_t encr_enable, uint8_t key_size // Return: void struct btm_sec_encryption_change_evt { - std::function<void(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable)> body{ - [](uint16_t /* handle */, tHCI_STATUS /* status */, uint8_t /* encr_enable */) {}}; - void operator()(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable) { - body(handle, status, encr_enable); + std::function<void(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable, uint8_t key_size)> + body{[](uint16_t /* handle */, tHCI_STATUS /* status */, uint8_t /* encr_enable */, + uint8_t /* key_size */) {}}; + void operator()(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable, uint8_t key_size) { + body(handle, status, encr_enable, key_size); } }; extern struct btm_sec_encryption_change_evt btm_sec_encryption_change_evt; diff --git a/system/test/mock/mock_stack_gap_conn.cc b/system/test/mock/mock_stack_gap_conn.cc index f38bb97588..0ef505d14a 100644 --- a/system/test/mock/mock_stack_gap_conn.cc +++ b/system/test/mock/mock_stack_gap_conn.cc @@ -20,7 +20,6 @@ */ #include "gap_api.h" -#include "l2c_api.h" #include "stack/include/bt_hdr.h" #include "test/common/mock_functions.h" #include "types/raw_address.h" diff --git a/system/test/mock/mock_stack_gatt_main.cc b/system/test/mock/mock_stack_gatt_main.cc index ec4ca1d9ee..66cb4a5844 100644 --- a/system/test/mock/mock_stack_gatt_main.cc +++ b/system/test/mock/mock_stack_gatt_main.cc @@ -19,7 +19,6 @@ * Functions generated:23 */ -#include "l2c_api.h" #include "stack/gatt/gatt_int.h" #include "stack/include/bt_hdr.h" #include "stack/include/l2cap_interface.h" diff --git a/system/test/mock/mock_stack_l2cap_api.h b/system/test/mock/mock_stack_l2cap_api.h index 84b36a4d9e..c2d162afd2 100644 --- a/system/test/mock/mock_stack_l2cap_api.h +++ b/system/test/mock/mock_stack_l2cap_api.h @@ -31,7 +31,7 @@ #include <cstdint> #include "stack/include/bt_hdr.h" -#include "stack/include/l2c_api.h" +#include "stack/include/l2cap_interface.h" #include "types/bt_transport.h" #include "types/raw_address.h" diff --git a/system/test/mock/mock_stack_l2cap_main.cc b/system/test/mock/mock_stack_l2cap_main.cc index 937d9d0209..fb33fed8f8 100644 --- a/system/test/mock/mock_stack_l2cap_main.cc +++ b/system/test/mock/mock_stack_l2cap_main.cc @@ -19,7 +19,6 @@ * Functions generated:9 */ -#include "l2c_api.h" #include "stack/include/bt_hdr.h" #include "stack/l2cap/l2c_int.h" #include "test/common/mock_functions.h" diff --git a/tools/rootcanal/model/controller/link_layer_controller.cc b/tools/rootcanal/model/controller/link_layer_controller.cc index 047ea9c96e..e793ac16e3 100644 --- a/tools/rootcanal/model/controller/link_layer_controller.cc +++ b/tools/rootcanal/model/controller/link_layer_controller.cc @@ -83,8 +83,16 @@ AddressWithType PeerIdentityAddress(Address address, PeerAddressType peer_addres } bool LinkLayerController::IsEventUnmasked(EventCode event) const { - uint64_t bit = UINT64_C(1) << (static_cast<uint8_t>(event) - 1); - return (event_mask_ & bit) != 0; + uint8_t evt = static_cast<uint8_t>(event); + + if (evt <= 64) { + uint64_t bit = UINT64_C(1) << (evt - 1); + return (event_mask_ & bit) != 0; + } else { + evt -= 64; + uint64_t bit = UINT64_C(1) << (evt - 1); + return (event_mask_page_2_ & bit) != 0; + } } bool LinkLayerController::IsLeEventUnmasked(SubeventCode subevent) const { @@ -5638,7 +5646,11 @@ ErrorCode LinkLayerController::LeLongTermKeyRequestReply(uint16_t handle, } } else { connections_.Encrypt(handle); - if (IsEventUnmasked(EventCode::ENCRYPTION_CHANGE)) { + if (IsEventUnmasked(EventCode::ENCRYPTION_CHANGE_V2)) { + send_event_(bluetooth::hci::EncryptionChangeV2Builder::Create( + ErrorCode::SUCCESS, handle, bluetooth::hci::EncryptionEnabled::ON, + 0x10 /* key_size */)); + } else if (IsEventUnmasked(EventCode::ENCRYPTION_CHANGE)) { send_event_(bluetooth::hci::EncryptionChangeBuilder::Create( ErrorCode::SUCCESS, handle, bluetooth::hci::EncryptionEnabled::ON)); } diff --git a/tools/rootcanal/packets/hci_packets.pdl b/tools/rootcanal/packets/hci_packets.pdl index 2b404bdff1..6cb90fea7f 100644 --- a/tools/rootcanal/packets/hci_packets.pdl +++ b/tools/rootcanal/packets/hci_packets.pdl @@ -749,6 +749,7 @@ enum EventCode : 8 { REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION = 0x3D, LE_META_EVENT = 0x3e, NUMBER_OF_COMPLETED_DATA_BLOCKS = 0x48, + ENCRYPTION_CHANGE_V2 = 0x59, VENDOR_SPECIFIC = 0xFF, } @@ -4767,6 +4768,13 @@ packet EncryptionChange : Event (event_code = ENCRYPTION_CHANGE) { encryption_enabled : EncryptionEnabled, } +packet EncryptionChangeV2 : Event (event_code = ENCRYPTION_CHANGE_V2) { + status : ErrorCode, + connection_handle : 12, + _reserved_ : 4, + encryption_enabled : EncryptionEnabled, + key_size : 8, +} packet ChangeConnectionLinkKeyComplete : Event (event_code = CHANGE_CONNECTION_LINK_KEY_COMPLETE) { status : ErrorCode, connection_handle : 12, |