diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpService.java b/android/app/src/com/android/bluetooth/a2dp/A2dpService.java index cc9853764b388081e59e92b52103023e70b5be6e..f22be4abae32643c5260220b99b7407bfca9d3cf 100644 --- a/android/app/src/com/android/bluetooth/a2dp/A2dpService.java +++ b/android/app/src/com/android/bluetooth/a2dp/A2dpService.java @@ -41,7 +41,6 @@ import android.bluetooth.BufferConstraints; import android.bluetooth.IBluetoothA2dp; import android.companion.CompanionDeviceManager; import android.content.AttributionSource; -import android.content.Context; import android.content.Intent; import android.media.AudioDeviceCallback; import android.media.AudioDeviceInfo; @@ -90,18 +89,18 @@ public class A2dpService extends ProfileService { private static A2dpService sA2dpService; - private AdapterService mAdapterService; - private DatabaseManager mDatabaseManager; + private final A2dpNativeInterface mNativeInterface; + private final AdapterService mAdapterService; + private final AudioManager mAudioManager; + private final DatabaseManager mDatabaseManager; + private final CompanionDeviceManager mCompanionDeviceManager; + private HandlerThread mStateMachinesThread; private Handler mHandler = null; - private final A2dpNativeInterface mNativeInterface; @VisibleForTesting ServiceFactory mFactory = new ServiceFactory(); - @VisibleForTesting - AudioManager mAudioManager; private A2dpCodecConfig mA2dpCodecConfig; - private CompanionDeviceManager mCompanionDeviceManager; @GuardedBy("mStateMachines") private BluetoothDevice mActiveDevice; @@ -126,15 +125,20 @@ public class A2dpService extends ProfileService { private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback = new AudioManagerAudioDeviceCallback(); - public A2dpService(Context ctx) { - super(ctx); - mNativeInterface = requireNonNull(A2dpNativeInterface.getInstance()); + public A2dpService(AdapterService adapterService) { + this(adapterService, A2dpNativeInterface.getInstance()); } @VisibleForTesting - A2dpService(Context ctx, A2dpNativeInterface nativeInterface) { - super(ctx); + A2dpService(AdapterService adapterService, A2dpNativeInterface nativeInterface) { + super(requireNonNull(adapterService)); + mAdapterService = adapterService; mNativeInterface = requireNonNull(nativeInterface); + mDatabaseManager = requireNonNull(mAdapterService.getDatabase()); + mAudioManager = requireNonNull(getSystemService(AudioManager.class)); + + // Some platform may not have the FEATURE_COMPANION_DEVICE_SETUP + mCompanionDeviceManager = getSystemService(CompanionDeviceManager.class); } public static boolean isEnabled() { @@ -157,20 +161,6 @@ public class A2dpService extends ProfileService { throw new IllegalStateException("start() called twice"); } - // Step 1: Get AdapterService, DatabaseManager, AudioManager. - // None of them can be null. - mAdapterService = - requireNonNull( - AdapterService.getAdapterService(), - "AdapterService cannot be null when A2dpService starts"); - mDatabaseManager = - requireNonNull( - mAdapterService.getDatabase(), - "DatabaseManager cannot be null when A2dpService starts"); - mAudioManager = getSystemService(AudioManager.class); - mCompanionDeviceManager = getSystemService(CompanionDeviceManager.class); - requireNonNull(mAudioManager, "AudioManager cannot be null when A2dpService starts"); - // Step 2: Get maximum number of connected audio devices mMaxConnectedAudioDevices = mAdapterService.getMaxConnectedAudioDevices(); Log.i(TAG, "Max connected audio devices set to " + mMaxConnectedAudioDevices); @@ -255,10 +245,6 @@ public class A2dpService extends ProfileService { // Step 2: Reset maximum number of connected audio devices mMaxConnectedAudioDevices = 1; - - // Step 1: Clear AdapterService, AudioManager - mAudioManager = null; - mAdapterService = null; } @Override @@ -1608,6 +1594,12 @@ public class A2dpService extends ProfileService { return; } if (!hasBluetoothPrivilegedPermission(service)) { + if (service.mCompanionDeviceManager == null) { + throw new SecurityException( + "Caller should have BLUETOOTH_PRIVILEGED in order to call" + + " setCodecConfigPreference without a CompanionDeviceManager" + + " service"); + } enforceCdmAssociation(service.mCompanionDeviceManager, service, source.getPackageName(), Binder.getCallingUid(), device); } diff --git a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java index 03385dc457c78fcf79043e9bde4e333573e73ffa..5f726c294acbf609d2373e53f8a2a0806671441b 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java @@ -978,6 +978,20 @@ public class BassClientService extends ProfileService { } } + private void informConnectedDeviceAboutScanOffloadStop() { + for (BluetoothDevice device : getConnectedDevices()) { + synchronized (mStateMachines) { + BassClientStateMachine stateMachine = getOrCreateStateMachine(device); + if (stateMachine == null) { + Log.w(TAG, "informConnectedDeviceAboutScanOffloadStop: Can't get state " + + "machine for device: " + device); + continue; + } + stateMachine.sendMessage(BassClientStateMachine.STOP_SCAN_OFFLOAD); + } + } + } + void handleConnectionStateChanged(BluetoothDevice device, int fromState, int toState) { mHandler.post(() -> connectionStateChanged(device, fromState, toState)); } @@ -1339,6 +1353,7 @@ public class BassClientService extends ProfileService { public void onScanFailed(int errorCode) { Log.e(TAG, "Scan Failure:" + errorCode); + informConnectedDeviceAboutScanOffloadStop(); } }; // when starting scan, clear the previously cached broadcast scan results @@ -1364,6 +1379,19 @@ public class BassClientService extends ProfileService { .setServiceData(BassConstants.BAAS_UUID, serviceData, serviceDataMask).build()); } + + for (BluetoothDevice device : getConnectedDevices()) { + synchronized (mStateMachines) { + BassClientStateMachine stateMachine = getOrCreateStateMachine(device); + if (stateMachine == null) { + Log.w(TAG, "startSearchingForSources: Can't get state machine for " + + "device: " + device); + continue; + } + stateMachine.sendMessage(BassClientStateMachine.START_SCAN_OFFLOAD); + } + } + scanner.startScan(filters, settings, mSearchScanCallback); sEventLogger.logd(TAG, "startSearchingForSources"); mCallbacks.notifySearchStarted(BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST); @@ -1391,6 +1419,7 @@ public class BassClientService extends ProfileService { mCallbacks.notifySearchStopFailed(BluetoothStatusCodes.ERROR_UNKNOWN); return; } + informConnectedDeviceAboutScanOffloadStop(); scanner.stopScan(mSearchScanCallback); mSearchScanCallback = null; sEventLogger.logd(TAG, "stopSearchingForSources"); diff --git a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java index 9484b9c6fd2a1723277589e2c2ef27703a437a73..890f72d061f8cb8446d959d5d6f02ce3352fd0e8 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java @@ -470,8 +470,6 @@ public class BassClientStateMachine extends StateMachine { null); } catch (IllegalArgumentException ex) { Log.w(TAG, "registerSync:IllegalArgumentException"); - Message message = obtainMessage(STOP_SCAN_OFFLOAD); - sendMessage(message); mPeriodicAdvCallbacksMap.remove(tempHandle); return false; } @@ -521,9 +519,6 @@ public class BassClientStateMachine extends StateMachine { // all sources are removed, clean up removeMessages(PSYNC_ACTIVE_TIMEOUT); mService.clearNotifiedFlags(); - // trigger scan stop here - Message message = obtainMessage(STOP_SCAN_OFFLOAD); - sendMessage(message); } } } @@ -731,10 +726,6 @@ public class BassClientStateMachine extends StateMachine { Log.e(TAG, "There is no valid sync handle for this Source"); } } - } else if (state == BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED - || state == BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_NO_PAST) { - Message message = obtainMessage(STOP_SCAN_OFFLOAD); - sendMessage(message); } } @@ -1165,10 +1156,6 @@ public class BassClientStateMachine extends StateMachine { } } else { log("failed to sync to PA: " + mPASyncRetryCounter); - if (!mAutoTriggered) { - Message message = obtainMessage(STOP_SCAN_OFFLOAD); - sendMessage(message); - } mAutoTriggered = false; // remove failed sync handle mPeriodicAdvCallbacksMap.remove(BassConstants.INVALID_SYNC_HANDLE); @@ -2003,8 +1990,6 @@ public class BassClientStateMachine extends StateMachine { case ADD_BCAST_SOURCE: if (!isSuccess(status)) { cancelActiveSync(null); - Message message = obtainMessage(STOP_SCAN_OFFLOAD); - sendMessage(message); if (mPendingMetadata != null) { mService.getCallbacks() .notifySourceAddFailed(mDevice, mPendingMetadata, status); diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index cdef731cd797d41c8cfb6a908222d2ecef11963c..f4a74f359da11413a86685df65f3083b2985bb55 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -3046,7 +3046,16 @@ public class AdapterService extends Service { return BluetoothDevice.CONNECTION_STATE_DISCONNECTED; } - return service.getConnectionState(device); + if (Flags.apiGetConnectionStateUsingIdentityAddress()) { + final long token = Binder.clearCallingIdentity(); + try { + return service.getConnectionState(device); + } finally { + Binder.restoreCallingIdentity(token); + } + } else { + return service.getConnectionState(device); + } } @Override 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 8ccf2eef231fca143fb4240222add59e14205da8..fa16b4ec7c4925ea455f209e2051e69c3144db7f 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -147,6 +147,9 @@ public class LeAudioService extends ProfileService { .setSampleRate(BluetoothLeAudioCodecConfig.SAMPLE_RATE_48000) .build(); + /* 5 seconds timeout for Broadcast streaming state transition */ + private static final int DIALING_OUT_TIMEOUT_MS = 5000; + private AdapterService mAdapterService; private DatabaseManager mDatabaseManager; private HandlerThread mStateMachinesThread; @@ -167,6 +170,7 @@ public class LeAudioService extends ProfileService { boolean mBluetoothEnabled = false; BluetoothDevice mHfpHandoverDevice = null; LeAudioBroadcasterNativeInterface mLeAudioBroadcasterNativeInterface = null; + private DialingOutTimeoutEvent mDialingOutTimeoutEvent = null; @VisibleForTesting AudioManager mAudioManager; LeAudioTmapGattServer mTmapGattServer; @@ -428,6 +432,8 @@ public class LeAudioService extends ProfileService { mAwaitingBroadcastCreateResponse = false; mIsSourceStreamMonitorModeEnabled = false; + clearBroadcastTimeoutCallback(); + mHandler.removeCallbacks(this::init); removeActiveDevice(false); @@ -1084,6 +1090,11 @@ public class LeAudioService extends ProfileService { return; } if (DBG) Log.d(TAG, "startBroadcast"); + + /* Start timeout to recover from stucked/error start Broadcast operation */ + mDialingOutTimeoutEvent = new DialingOutTimeoutEvent(); + mHandler.postDelayed(mDialingOutTimeoutEvent, DIALING_OUT_TIMEOUT_MS); + mLeAudioBroadcasterNativeInterface.startBroadcast(broadcastId); } @@ -1750,12 +1761,19 @@ public class LeAudioService extends ProfileService { * @param newDevice new supported broadcast audio device * @param previousDevice previous no longer supported broadcast audio device */ - /* TODO implement unicast overlap with connected unicast device */ private void updateBroadcastActiveDevice( BluetoothDevice newDevice, BluetoothDevice previousDevice, boolean suppressNoisyIntent) { mActiveBroadcastAudioDevice = newDevice; + if (DBG) { + Log.d( + TAG, + "updateBroadcastActiveDevice: newDevice: " + + newDevice + + ", previousDevice: " + + previousDevice); + } mAudioManager.handleBluetoothActiveDeviceChanged( newDevice, previousDevice, getBroadcastProfile(suppressNoisyIntent)); } @@ -2272,6 +2290,16 @@ public class LeAudioService extends ProfileService { || mBroadcastIdDeactivatedForUnicastTransition.isPresent())) { leaveConnectedInputDevice = true; newDirections |= AUDIO_DIRECTION_INPUT_BIT; + + /* Update Broadcast device before streaming state in handover case to avoid switch + * to non LE Audio device in Audio Manager e.g. Phone Speaker. + */ + BluetoothDevice device = + mAdapterService.getDeviceFromByte( + Utils.getBytesFromAddress("FF:FF:FF:FF:FF:FF")); + if (!device.equals(mActiveBroadcastAudioDevice)) { + updateBroadcastActiveDevice(device, mActiveBroadcastAudioDevice, true); + } } descriptor.mIsActive = false; @@ -2558,8 +2586,6 @@ public class LeAudioService extends ProfileService { updateFallbackUnicastGroupIdForBroadcast(LE_AUDIO_GROUP_ID_INVALID); updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false); return; - } else { - updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, true); } if (DBG) { @@ -2573,6 +2599,21 @@ public class LeAudioService extends ProfileService { setActiveDevice(unicastDevice); } + void clearBroadcastTimeoutCallback() { + if (mHandler == null) { + Log.e(TAG, "No callback handler"); + return; + } + + /* Timeout callback already cleared */ + if (mDialingOutTimeoutEvent == null) { + return; + } + + mHandler.removeCallbacks(mDialingOutTimeoutEvent); + mDialingOutTimeoutEvent = null; + } + // Suppressed since this is part of a local process @SuppressLint("AndroidFrameworkRequiresPermission") void messageFromNative(LeAudioStackEvent stackEvent) { @@ -2786,6 +2827,11 @@ public class LeAudioService extends ProfileService { switch (groupStatus) { case LeAudioStackEvent.GROUP_STATUS_ACTIVE: { handleGroupTransitToActive(groupId); + + /* Clear possible exposed broadcast device after activating unicast */ + if (mActiveBroadcastAudioDevice != null) { + updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, true); + } break; } case LeAudioStackEvent.GROUP_STATUS_INACTIVE: { @@ -2831,6 +2877,20 @@ public class LeAudioService extends ProfileService { } else { // TODO: Improve reason reporting or extend the native stack event with reason code + Log.e( + TAG, + "EVENT_TYPE_BROADCAST_CREATED: Failed to create broadcast: " + broadcastId); + + /* Disconnect Broadcast device which was connected to avoid non LE Audio sound + * leak in handover scenario. + */ + if ((mUnicastGroupIdDeactivatedForBroadcastTransition != LE_AUDIO_GROUP_ID_INVALID) + && mCreateBroadcastQueue.isEmpty() + && (!Objects.equals(device, mActiveBroadcastAudioDevice))) { + clearBroadcastTimeoutCallback(); + updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false); + } + notifyBroadcastStartFailed(broadcastId, BluetoothStatusCodes.ERROR_UNKNOWN); } @@ -2926,11 +2986,21 @@ public class LeAudioService extends ProfileService { bassClientService.suspendReceiversSourceSynchronization(broadcastId); } - // Notify audio manager - updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, true); - /* Restore the Unicast stream from before the Broadcast was started. */ - transitionFromBroadcastToUnicast(); + if (mUnicastGroupIdDeactivatedForBroadcastTransition + != LE_AUDIO_GROUP_ID_INVALID) { + transitionFromBroadcastToUnicast(); + } else { + // Notify audio manager + if (mBroadcastDescriptors.values().stream() + .noneMatch( + d -> + d.mState.equals( + LeAudioStackEvent + .BROADCAST_STATE_STREAMING))) { + updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false); + } + } break; case LeAudioStackEvent.BROADCAST_STATE_STOPPING: if (DBG) Log.d(TAG, "Broadcast broadcastId: " + broadcastId + " stopping."); @@ -2942,6 +3012,8 @@ public class LeAudioService extends ProfileService { notifyPlaybackStarted(broadcastId, BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST); + clearBroadcastTimeoutCallback(); + if (previousState == LeAudioStackEvent.BROADCAST_STATE_PAUSED) { if (bassClientService != null) { bassClientService.resumeReceiversSourceSynchronization(); @@ -4250,6 +4322,24 @@ public class LeAudioService extends ProfileService { return audioFrameworkCalls; } + class DialingOutTimeoutEvent implements Runnable { + @Override + public void run() { + Log.w(TAG, "Failed to start Broadcast in time"); + + mDialingOutTimeoutEvent = null; + + if (getLeAudioService() == null) { + Log.e(TAG, "DialingOutTimeoutEvent: No LE Audio service"); + return; + } + + if (mActiveBroadcastAudioDevice != null) { + updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false); + } + } + } + /** * Binder object: must be a static class or memory leak may occur */ diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java index 6dacf8fe8c0d6e7e56c9e43a287c26863429a127..faa2833dfcefc09c64fcaae7371322a7a3a6dea7 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java @@ -76,7 +76,6 @@ public class A2dpServiceTest { @Mock private ActiveDeviceManager mActiveDeviceManager; @Mock private AdapterService mAdapterService; @Mock private AudioManager mAudioManager; - @Mock private Context mContext; @Mock private DatabaseManager mDatabaseManager; @Mock private SilenceDeviceManager mSilenceDeviceManager; private InOrder mInOrder = null; @@ -87,19 +86,18 @@ public class A2dpServiceTest { public void setUp() throws Exception { // Set up mocks and test assets MockitoAnnotations.initMocks(this); - mInOrder = inOrder(mContext); + mInOrder = inOrder(mAdapterService); TestUtils.mockGetSystemService( - mContext, Context.AUDIO_SERVICE, AudioManager.class, mAudioManager); + mAdapterService, Context.AUDIO_SERVICE, AudioManager.class, mAudioManager); doReturn(InstrumentationRegistry.getTargetContext().getResources()) - .when(mContext) + .when(mAdapterService) .getResources(); if (Looper.myLooper() == null) { Looper.prepare(); } - TestUtils.setAdapterService(mAdapterService); doReturn(true).when(mAdapterService).isA2dpOffloadEnabled(); doReturn(MAX_CONNECTED_AUDIO_DEVICES).when(mAdapterService).getMaxConnectedAudioDevices(); doReturn(false).when(mAdapterService).isQuietModeEnabled(); @@ -107,7 +105,7 @@ public class A2dpServiceTest { doReturn(mActiveDeviceManager).when(mAdapterService).getActiveDeviceManager(); doReturn(mSilenceDeviceManager).when(mAdapterService).getSilenceDeviceManager(); - mA2dpService = new A2dpService(mContext, mMockNativeInterface); + mA2dpService = new A2dpService(mAdapterService, mMockNativeInterface); mA2dpService.start(); mA2dpService.setAvailable(true); @@ -126,12 +124,11 @@ public class A2dpServiceTest { @After public void tearDown() throws Exception { mA2dpService.stop(); - TestUtils.clearAdapterService(mAdapterService); } @SafeVarargs private void verifyIntentSent(Matcher<Intent>... matchers) { - mInOrder.verify(mContext, timeout(TIMEOUT.toMillis() * 2)) + mInOrder.verify(mAdapterService, timeout(TIMEOUT.toMillis() * 2)) .sendBroadcast(MockitoHamcrest.argThat(AllOf.allOf(matchers)), any(), any()); } @@ -1061,7 +1058,7 @@ public class A2dpServiceTest { stackEvent.valueInt = newConnectionState; mA2dpService.messageFromNative(stackEvent); // Verify the connection state broadcast - mInOrder.verify(mContext, timeout(TIMEOUT.toMillis()).times(0)) + mInOrder.verify(mAdapterService, timeout(TIMEOUT.toMillis()).times(0)) .sendBroadcast(any(), any(), any()); } @@ -1088,7 +1085,7 @@ public class A2dpServiceTest { stackEvent.valueInt = audioStackEvent; mA2dpService.messageFromNative(stackEvent); // Verify the audio state broadcast - mInOrder.verify(mContext, timeout(TIMEOUT.toMillis()).times(0)) + mInOrder.verify(mAdapterService, timeout(TIMEOUT.toMillis()).times(0)) .sendBroadcast(any(), any(), any()); } @@ -1113,7 +1110,7 @@ public class A2dpServiceTest { stackEvent.codecStatus = codecStatus; mA2dpService.messageFromNative(stackEvent); // Verify the codec status broadcast - mInOrder.verify(mContext, timeout(TIMEOUT.toMillis()).times(0)) + mInOrder.verify(mAdapterService, timeout(TIMEOUT.toMillis()).times(0)) .sendBroadcast(any(), any(), any()); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java index 54a62dd1027031847103779da36273e789212f3d..ca5c6e527d0f40635dd4c0e7739012bc6ec5e1e6 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java @@ -79,6 +79,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.Spy; @@ -395,10 +396,20 @@ public class BassClientServiceTest { */ @Test public void testStartSearchingForSources() { + prepareConnectedDeviceGroup(); List<ScanFilter> scanFilters = new ArrayList<>(); + + assertThat(mStateMachines.size()).isEqualTo(2); + for (BassClientStateMachine sm : mStateMachines.values()) { + Mockito.clearInvocations(sm); + } + mBassClientService.startSearchingForSources(scanFilters); verify(mBluetoothLeScannerWrapper).startScan(notNull(), notNull(), notNull()); + for (BassClientStateMachine sm : mStateMachines.values()) { + verify(sm).sendMessage(BassClientStateMachine.START_SCAN_OFFLOAD); + } } /** diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java index d9b63964bc22eb56c02b27bc7de868b8837c8eee..2c41a652c8004b4842510115b0547053097c6dbe 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java @@ -794,7 +794,6 @@ public class BassClientStateMachineTest { verify(callbacks).notifySourceAdded(any(), any(), anyInt()); verify(callbacks).notifyReceiveStateChanged(any(), anyInt(), any()); - assertThat(mBassClientStateMachine.mMsgWhats).contains(STOP_SCAN_OFFLOAD); // set some values for covering more lines of processPASyncState() mBassClientStateMachine.mPendingMetadata = null; diff --git a/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorStateMachineTest.java index 1ba0431bdc1bab61bf0d083d42d14f675a581421..0c09204d334fbfd5f251b0a957d30528dd06fc1d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorStateMachineTest.java @@ -21,7 +21,6 @@ import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING; - import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -34,13 +33,10 @@ import android.content.Intent; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; -import android.test.suitebuilder.annotation.MediumTest; - +import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; - import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; - import org.hamcrest.core.IsInstanceOf; import org.junit.*; import org.junit.runner.RunWith; diff --git a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStateMachineTest.java index 6ce340c9507f22002718611ea30606f718a42c68..8e1024dbdb82af6942502baea3bb9a71f643805d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStateMachineTest.java @@ -31,13 +31,10 @@ import android.bluetooth.BluetoothProfile; import android.content.Intent; import android.os.HandlerThread; import android.os.Message; -import android.test.suitebuilder.annotation.MediumTest; - +import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; - import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; - import org.hamcrest.core.IsInstanceOf; import org.junit.After; import org.junit.Assert; diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java index 8525f7261df621e8697368124e151cbd9e555e9d..17057c9f3e931e5d4467f697ceadd38f6c251009 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java @@ -28,6 +28,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; +import android.media.BluetoothProfileConnectionInfo; import android.os.Looper; import android.os.ParcelUuid; import android.platform.test.flag.junit.SetFlagsRule; @@ -37,6 +38,7 @@ import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.TestUtils; +import com.android.bluetooth.Utils; import com.android.bluetooth.bass_client.BassClientService; import com.android.bluetooth.btservice.ActiveDeviceManager; import com.android.bluetooth.btservice.AdapterService; @@ -51,6 +53,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.Spy; @@ -67,6 +70,8 @@ public class LeAudioBroadcastServiceTest { private BluetoothAdapter mAdapter; private BluetoothDevice mDevice; + private BluetoothDevice mBroadcastDevice; + private Context mTargetContext; private LeAudioService mService; private LeAudioIntentReceiver mLeAudioIntentReceiver; @@ -228,7 +233,9 @@ public class LeAudioBroadcastServiceTest { mTargetContext.registerReceiver(mLeAudioIntentReceiver, filter); mDevice = TestUtils.getTestDevice(mAdapter, 0); - when(mLeAudioBroadcasterNativeInterface.getDevice(any(byte[].class))).thenReturn(mDevice); + mBroadcastDevice = TestUtils.getTestDevice(mAdapter, 1); + when(mAdapterService.getDeviceFromByte(Utils.getBytesFromAddress("FF:FF:FF:FF:FF:FF"))) + .thenReturn(mBroadcastDevice); mIntentQueue = new LinkedBlockingQueue<Intent>(); } @@ -794,12 +801,7 @@ public class LeAudioBroadcastServiceTest { mOnBroadcastStartFailedReason); } - @Test - public void testInCallDrivenBroadcastSwitch() { - int groupId = 1; - int broadcastId = 243; - byte[] code = {0x00, 0x01, 0x00, 0x02}; - + private void prepareHandoverStreamingBroadcast(int groupId, int broadcastId, byte[] code) { mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION); mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_AUDIO_HANDOVER_POLICIES); @@ -813,6 +815,14 @@ public class LeAudioBroadcastServiceTest { create_event.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE; mService.messageFromNative(create_event); + /* Verify Unicast input and output devices changed from null to mDevice */ + verify(mAudioManager, times(2)) + .handleBluetoothActiveDeviceChanged( + eq(mDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); + Mockito.clearInvocations(mAudioManager); + + mService.notifyActiveDeviceChanged(mDevice); + /* Prepare create broadcast */ BluetoothLeAudioContentMetadata.Builder meta_builder = new BluetoothLeAudioContentMetadata.Builder(); @@ -823,6 +833,10 @@ public class LeAudioBroadcastServiceTest { BluetoothLeBroadcastSettings settings = buildBroadcastSettingsFromMetadata(meta, code, 1); mService.createBroadcast(settings); + verify(mAudioManager, times(1)) + .handleBluetoothActiveDeviceChanged( + eq(mBroadcastDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); + /* Active group should become inactive */ int activeGroup = mService.getActiveGroupId(); Assert.assertEquals(activeGroup, LE_AUDIO_GROUP_ID_INVALID); @@ -833,6 +847,11 @@ public class LeAudioBroadcastServiceTest { create_event.valueInt2 = LeAudioStackEvent.GROUP_STATUS_INACTIVE; mService.messageFromNative(create_event); + /* Only one Unicast device should become inactive due to Sink monitor mode */ + verify(mAudioManager, times(1)) + .handleBluetoothActiveDeviceChanged( + eq(null), eq(mDevice), any(BluetoothProfileConnectionInfo.class)); + Mockito.clearInvocations(mAudioManager); List<BluetoothLeBroadcastSubgroupSettings> settingsList = settings.getSubgroupSettings(); int[] expectedQualityArray = @@ -850,6 +869,8 @@ public class LeAudioBroadcastServiceTest { eq(settings.getPublicBroadcastMetadata().getRawMetadata()), eq(expectedQualityArray), eq(expectedDataArray)); + verify(mLeAudioNativeInterface, times(1)) + .setUnicastMonitorMode(eq(LeAudioStackEvent.DIRECTION_SINK), eq(true)); activeGroup = mService.getActiveGroupId(); Assert.assertEquals(LE_AUDIO_GROUP_ID_INVALID, activeGroup); @@ -865,9 +886,19 @@ public class LeAudioBroadcastServiceTest { /* Switch to active streaming */ create_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_STATE); + create_event.device = mBroadcastDevice; create_event.valueInt1 = broadcastId; create_event.valueInt2 = LeAudioStackEvent.BROADCAST_STATE_STREAMING; mService.messageFromNative(create_event); + } + + @Test + public void testInCallDrivenBroadcastSwitch() { + int groupId = 1; + int broadcastId = 243; + byte[] code = {0x00, 0x01, 0x00, 0x02}; + + prepareHandoverStreamingBroadcast(groupId, broadcastId, code); /* Imitate setting device in call */ mService.setInCall(true); @@ -883,13 +914,21 @@ public class LeAudioBroadcastServiceTest { verify(mLeAudioNativeInterface, times(1)).setInCall(eq(true)); - create_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED); + LeAudioStackEvent create_event = + new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED); create_event.valueInt1 = groupId; create_event.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE; mService.messageFromNative(create_event); + verify(mAudioManager, times(1)) + .handleBluetoothActiveDeviceChanged( + eq(mDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); + verify(mAudioManager, times(1)) + .handleBluetoothActiveDeviceChanged( + eq(null), eq(mBroadcastDevice), any(BluetoothProfileConnectionInfo.class)); + /* Active group should become the one that was active before broadcasting */ - activeGroup = mService.getActiveGroupId(); + int activeGroup = mService.getActiveGroupId(); Assert.assertEquals(activeGroup, groupId); /* Imitate setting device not in call */ @@ -903,6 +942,14 @@ public class LeAudioBroadcastServiceTest { create_event.valueInt2 = LeAudioStackEvent.GROUP_STATUS_INACTIVE; mService.messageFromNative(create_event); + /* Only one Unicast device should become inactive due to Sink monitor mode */ + verify(mAudioManager, times(1)) + .handleBluetoothActiveDeviceChanged( + eq(null), eq(mDevice), any(BluetoothProfileConnectionInfo.class)); + verify(mAudioManager, times(1)) + .handleBluetoothActiveDeviceChanged( + eq(mBroadcastDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); + /* Verify if broadcast is auto-started on start */ verify(mLeAudioBroadcasterNativeInterface, times(2)).startBroadcast(eq(broadcastId)); } @@ -913,82 +960,14 @@ public class LeAudioBroadcastServiceTest { int broadcastId = 243; byte[] code = {0x00, 0x01, 0x00, 0x02}; - mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION); - mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_AUDIO_HANDOVER_POLICIES); - - mService.mBroadcastCallbacks.register(mCallbacks); - - prepareConnectedUnicastDevice(groupId); - - LeAudioStackEvent create_event = - new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED); - create_event.valueInt1 = groupId; - create_event.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE; - mService.messageFromNative(create_event); - - /* Prepare create broadcast */ - BluetoothLeAudioContentMetadata.Builder meta_builder = - new BluetoothLeAudioContentMetadata.Builder(); - meta_builder.setLanguage("ENG"); - meta_builder.setProgramInfo("Public broadcast info"); - BluetoothLeAudioContentMetadata meta = meta_builder.build(); - - BluetoothLeBroadcastSettings settings = buildBroadcastSettingsFromMetadata(meta, code, 1); - mService.createBroadcast(settings); - - /* Active group should become inactive */ - int activeGroup = mService.getActiveGroupId(); - Assert.assertEquals(activeGroup, LE_AUDIO_GROUP_ID_INVALID); - - /* Imitate group inactivity to cause create broadcast */ - create_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED); - create_event.valueInt1 = groupId; - create_event.valueInt2 = LeAudioStackEvent.GROUP_STATUS_INACTIVE; - mService.messageFromNative(create_event); - - List<BluetoothLeBroadcastSubgroupSettings> settingsList = settings.getSubgroupSettings(); - - int[] expectedQualityArray = - settingsList.stream().mapToInt(setting -> setting.getPreferredQuality()).toArray(); - byte[][] expectedDataArray = - settingsList.stream() - .map(setting -> setting.getContentMetadata().getRawMetadata()) - .toArray(byte[][]::new); - - verify(mLeAudioBroadcasterNativeInterface, times(1)) - .createBroadcast( - eq(true), - eq(TEST_BROADCAST_NAME), - eq(settings.getBroadcastCode()), - eq(settings.getPublicBroadcastMetadata().getRawMetadata()), - eq(expectedQualityArray), - eq(expectedDataArray)); - verify(mLeAudioNativeInterface, times(1)) - .setUnicastMonitorMode(eq(LeAudioStackEvent.DIRECTION_SINK),eq(true)); - - activeGroup = mService.getActiveGroupId(); - Assert.assertEquals(LE_AUDIO_GROUP_ID_INVALID, activeGroup); - - /* Check if broadcast is started automatically when created */ - create_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_CREATED); - create_event.valueInt1 = broadcastId; - create_event.valueBool1 = true; - mService.messageFromNative(create_event); - - /* Verify if broadcast is auto-started on start */ - verify(mLeAudioBroadcasterNativeInterface, times(1)).startBroadcast(eq(broadcastId)); - - /* Switch to active streaming */ - create_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_STATE); - create_event.valueInt1 = broadcastId; - create_event.valueInt2 = LeAudioStackEvent.BROADCAST_STATE_STREAMING; - mService.messageFromNative(create_event); + prepareHandoverStreamingBroadcast(groupId, broadcastId, code); /* Verify if broadcast is auto-started on start */ verify(mLeAudioBroadcasterNativeInterface, times(1)).startBroadcast(eq(broadcastId)); /* Imitate group change request by Bluetooth Sink HAL resume request */ - create_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_UNICAST_MONITOR_MODE_STATUS); + LeAudioStackEvent create_event = + new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_UNICAST_MONITOR_MODE_STATUS); create_event.valueInt1 = LeAudioStackEvent.DIRECTION_SINK; create_event.valueInt2 = LeAudioStackEvent.STATUS_LOCAL_STREAM_REQUESTED; mService.messageFromNative(create_event); @@ -1007,8 +986,15 @@ public class LeAudioBroadcastServiceTest { create_event.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE; mService.messageFromNative(create_event); + verify(mAudioManager, times(1)) + .handleBluetoothActiveDeviceChanged( + eq(mDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); + verify(mAudioManager, times(1)) + .handleBluetoothActiveDeviceChanged( + eq(null), eq(mBroadcastDevice), any(BluetoothProfileConnectionInfo.class)); + /* Active group should become the one that was active before broadcasting */ - activeGroup = mService.getActiveGroupId(); + int activeGroup = mService.getActiveGroupId(); Assert.assertEquals(activeGroup, groupId); /* Imitate group change request by Bluetooth Sink HAL suspend request */ @@ -1025,6 +1011,14 @@ public class LeAudioBroadcastServiceTest { create_event.valueInt2 = LeAudioStackEvent.GROUP_STATUS_INACTIVE; mService.messageFromNative(create_event); + /* Only one Unicast device should become inactive due to Sink monitor mode */ + verify(mAudioManager, times(1)) + .handleBluetoothActiveDeviceChanged( + eq(null), eq(mDevice), any(BluetoothProfileConnectionInfo.class)); + verify(mAudioManager, times(1)) + .handleBluetoothActiveDeviceChanged( + eq(mBroadcastDevice), eq(null), any(BluetoothProfileConnectionInfo.class)); + /* Verify if broadcast is auto-started on start */ verify(mLeAudioBroadcasterNativeInterface, times(2)).startBroadcast(eq(broadcastId)); } diff --git a/flags/did.aconfig b/flags/did.aconfig new file mode 100644 index 0000000000000000000000000000000000000000..200445740058fb200fc1620a2fef3a8cf4efb161 --- /dev/null +++ b/flags/did.aconfig @@ -0,0 +1,9 @@ +package: "com.android.bluetooth.flags" +container: "com.android.btservices" + +flag { + name: "load_did_config_from_sysprops" + namespace: "bluetooth" + description: "Replace bt_did.config by sysprops" + bug: "327667978" +} diff --git a/framework/tests/unit/src/android/bluetooth/BluetoothCodecConfigTest.java b/framework/tests/unit/src/android/bluetooth/BluetoothCodecConfigTest.java index b75b8f9476529f4cf4b207827da2b5470266c31e..e2c8c193d8312707df46f051efeafd42e1b56914 100644 --- a/framework/tests/unit/src/android/bluetooth/BluetoothCodecConfigTest.java +++ b/framework/tests/unit/src/android/bluetooth/BluetoothCodecConfigTest.java @@ -16,8 +16,7 @@ package android.bluetooth; -import android.test.suitebuilder.annotation.SmallTest; - +import androidx.test.filters.SmallTest; import junit.framework.TestCase; /** Unit test cases for {@link BluetoothCodecConfig}. */ diff --git a/framework/tests/unit/src/android/bluetooth/BluetoothCodecStatusTest.java b/framework/tests/unit/src/android/bluetooth/BluetoothCodecStatusTest.java index 48d5265762c97776a39b354810c428ad8aa7317e..6f53cb363326a1e77136a01a37b0c3c814e1eaa2 100644 --- a/framework/tests/unit/src/android/bluetooth/BluetoothCodecStatusTest.java +++ b/framework/tests/unit/src/android/bluetooth/BluetoothCodecStatusTest.java @@ -16,12 +16,10 @@ package android.bluetooth; -import android.test.suitebuilder.annotation.SmallTest; - -import junit.framework.TestCase; - +import androidx.test.filters.SmallTest; import java.util.List; import java.util.Objects; +import junit.framework.TestCase; /** Unit test cases for {@link BluetoothCodecStatus}. */ public class BluetoothCodecStatusTest extends TestCase { diff --git a/framework/tests/unit/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java b/framework/tests/unit/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java index b3e88970f2d47f5dfeea9fec2c8f2ae037d837df..fa0bbc6e566c235d1fe4a70d26c2094795ca085f 100644 --- a/framework/tests/unit/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java +++ b/framework/tests/unit/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java @@ -16,8 +16,7 @@ package android.bluetooth; -import android.test.suitebuilder.annotation.SmallTest; - +import androidx.test.filters.SmallTest; import junit.framework.TestCase; /** Unit test cases for {@link BluetoothLeAudioCodecConfig}. */ diff --git a/framework/tests/unit/src/android/bluetooth/BluetoothUuidTest.java b/framework/tests/unit/src/android/bluetooth/BluetoothUuidTest.java index b3d7758396e3689f1eceb6f08462aabb3505f9ff..745b73e9582cead5922d4594bdd002e6ebe0311e 100644 --- a/framework/tests/unit/src/android/bluetooth/BluetoothUuidTest.java +++ b/framework/tests/unit/src/android/bluetooth/BluetoothUuidTest.java @@ -17,8 +17,7 @@ package android.bluetooth; import android.os.ParcelUuid; -import android.test.suitebuilder.annotation.SmallTest; - +import androidx.test.filters.SmallTest; import junit.framework.TestCase; /** Unit test cases for {@link BluetoothUuid}. */ diff --git a/framework/tests/unit/src/android/bluetooth/le/ScanFilterTest.java b/framework/tests/unit/src/android/bluetooth/le/ScanFilterTest.java index fa50315ef015372024a85f9c909fd93a28f96fa4..120034c565ac63afd9e8327ce1c74f8a8c500c8e 100644 --- a/framework/tests/unit/src/android/bluetooth/le/ScanFilterTest.java +++ b/framework/tests/unit/src/android/bluetooth/le/ScanFilterTest.java @@ -18,8 +18,7 @@ package android.bluetooth.le; import android.bluetooth.BluetoothDevice; import android.os.Parcel; -import android.test.suitebuilder.annotation.SmallTest; - +import androidx.test.filters.SmallTest; import junit.framework.TestCase; public class ScanFilterTest extends TestCase { diff --git a/framework/tests/unit/src/android/bluetooth/le/ScanRecordTest.java b/framework/tests/unit/src/android/bluetooth/le/ScanRecordTest.java index 879ac56c7796d5538e8897e1693dfd9aea687f52..f226c94a026116761b64a9658df2d55deeab19da 100644 --- a/framework/tests/unit/src/android/bluetooth/le/ScanRecordTest.java +++ b/framework/tests/unit/src/android/bluetooth/le/ScanRecordTest.java @@ -17,17 +17,14 @@ package android.bluetooth.le; import android.os.ParcelUuid; -import android.test.suitebuilder.annotation.SmallTest; - +import androidx.test.filters.SmallTest; import com.android.internal.util.HexDump; import com.android.modules.utils.BytesMatcher; - -import junit.framework.TestCase; - import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.function.Predicate; +import junit.framework.TestCase; /** * Unit test cases for {@link ScanRecord}. diff --git a/framework/tests/unit/src/android/bluetooth/le/ScanSettingsTest.java b/framework/tests/unit/src/android/bluetooth/le/ScanSettingsTest.java index 8848c7273c80a81974d782cf8170f3e4e131a5ad..e6c85f66909e14c61851bc9c6dc788cea856bea4 100644 --- a/framework/tests/unit/src/android/bluetooth/le/ScanSettingsTest.java +++ b/framework/tests/unit/src/android/bluetooth/le/ScanSettingsTest.java @@ -16,8 +16,7 @@ package android.bluetooth.le; -import android.test.suitebuilder.annotation.SmallTest; - +import androidx.test.filters.SmallTest; import junit.framework.TestCase; /** Test for Bluetooth LE {@link ScanSettings}. */ diff --git a/system/bta/le_audio/audio_set_configurations.json b/system/bta/le_audio/audio_set_configurations.json index aba4a0bf62b15fc449896bce515fac4d273aa019..719a8d49e652f695f4b9512163e306f24560060e 100644 --- a/system/bta/le_audio/audio_set_configurations.json +++ b/system/bta/le_audio/audio_set_configurations.json @@ -277,16 +277,6 @@ "codec_config_name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2", "qos_config_name": ["QoS_Config_16_2_2"] }, - { - "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_Low_Latency", - "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1", - "qos_config_name": ["QoS_Config_Low_Latency"] - }, - { - "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_1", - "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1", - "qos_config_name": ["QoS_Config_16_1_1"] - }, { "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency", "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2", @@ -327,26 +317,6 @@ "codec_config_name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1", "qos_config_name": ["QoS_Config_16_1_1"] }, - { - "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_2", - "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1", - "qos_config_name": ["QoS_Config_16_1_2"] - }, - { - "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_Low_Latency", - "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_Low_Latency"] - }, - { - "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_1", - "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_16_2_1"] - }, - { - "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_2", - "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_16_2_2"] - }, { "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency", "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1", @@ -612,16 +582,6 @@ "codec_config_name": "SingleDev_OneChanStereoSnk_32_1", "qos_config_name": ["QoS_Config_Low_Latency"] }, - { - "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2_Low_Latency", - "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2", - "qos_config_name": ["QoS_Config_Low_Latency"] - }, - { - "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2_1", - "codec_config_name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2", - "qos_config_name": ["QoS_Config_32_2_1"] - }, { "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency", "codec_config_name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2", @@ -962,21 +922,6 @@ "codec_config_name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2", "qos_config_name": ["QoS_Config_Balanced_Reliability"] }, - { - "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability", - "codec_config_name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_32_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] - }, - { - "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability", - "codec_config_name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_24_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] - }, - { - "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability", - "codec_config_name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_16_2", - "qos_config_name": ["QoS_Config_Balanced_Reliability"] - }, { "name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_32_2_Balanced_Reliability", "codec_config_name": "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_32_2", @@ -2592,13 +2537,13 @@ ] }, { - "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2", + "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2", "subconfigurations": [ { - "device_cnt": 2, - "ase_cnt": 4, + "device_cnt": 1, + "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", + "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -2610,7 +2555,7 @@ "type": 1, "compound_value": { "value": [ - 3 + 6 ] } }, @@ -2628,7 +2573,7 @@ "type": 3, "compound_value": { "value": [ - 1, + 3, 0, 0, 0 @@ -2640,7 +2585,7 @@ "type": 4, "compound_value": { "value": [ - 40, + 80, 0 ] } @@ -2660,6 +2605,7 @@ "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", + "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -2671,7 +2617,7 @@ "type": 1, "compound_value": { "value": [ - 3 + 6 ] } }, @@ -2689,7 +2635,7 @@ "type": 3, "compound_value": { "value": [ - 1, + 3, 0, 0, 0 @@ -2701,7 +2647,7 @@ "type": 4, "compound_value": { "value": [ - 40, + 80, 0 ] } @@ -2720,13 +2666,13 @@ ] }, { - "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1", + "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2", "subconfigurations": [ { - "device_cnt": 2, - "ase_cnt": 4, + "device_cnt": 1, + "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", + "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -2747,7 +2693,7 @@ "type": 2, "compound_value": { "value": [ - 0 + 1 ] } }, @@ -2756,7 +2702,7 @@ "type": 3, "compound_value": { "value": [ - 1, + 3, 0, 0, 0 @@ -2768,7 +2714,7 @@ "type": 4, "compound_value": { "value": [ - 30, + 40, 0 ] } @@ -2788,6 +2734,7 @@ "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", + "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -2808,7 +2755,7 @@ "type": 2, "compound_value": { "value": [ - 0 + 1 ] } }, @@ -2817,7 +2764,7 @@ "type": 3, "compound_value": { "value": [ - 1, + 3, 0, 0, 0 @@ -2829,7 +2776,7 @@ "type": 4, "compound_value": { "value": [ - 30, + 40, 0 ] } @@ -2848,7 +2795,7 @@ ] }, { - "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2", + "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1", "subconfigurations": [ { "device_cnt": 1, @@ -2866,7 +2813,7 @@ "type": 1, "compound_value": { "value": [ - 6 + 3 ] } }, @@ -2875,7 +2822,7 @@ "type": 2, "compound_value": { "value": [ - 1 + 0 ] } }, @@ -2896,7 +2843,7 @@ "type": 4, "compound_value": { "value": [ - 80, + 30, 0 ] } @@ -2928,7 +2875,7 @@ "type": 1, "compound_value": { "value": [ - 6 + 3 ] } }, @@ -2937,7 +2884,7 @@ "type": 2, "compound_value": { "value": [ - 1 + 0 ] } }, @@ -2958,7 +2905,7 @@ "type": 4, "compound_value": { "value": [ - 80, + 30, 0 ] } @@ -2977,7 +2924,7 @@ ] }, { - "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2", + "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2", "subconfigurations": [ { "device_cnt": 1, @@ -3045,7 +2992,6 @@ "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -3075,7 +3021,7 @@ "type": 3, "compound_value": { "value": [ - 3, + 1, 0, 0, 0 @@ -3106,7 +3052,7 @@ ] }, { - "name": "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1", + "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1", "subconfigurations": [ { "device_cnt": 1, @@ -3174,7 +3120,6 @@ "device_cnt": 1, "ase_cnt": 1, "direction": "SOURCE", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -3204,7 +3149,7 @@ "type": 3, "compound_value": { "value": [ - 3, + 1, 0, 0, 0 @@ -3235,13 +3180,13 @@ ] }, { - "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2", + "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2", "subconfigurations": [ { "device_cnt": 1, - "ase_cnt": 1, + "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", + "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -3271,7 +3216,7 @@ "type": 3, "compound_value": { "value": [ - 3, + 1, 0, 0, 0 @@ -3363,13 +3308,13 @@ ] }, { - "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1", + "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1", "subconfigurations": [ { "device_cnt": 1, - "ase_cnt": 1, + "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", + "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -3399,7 +3344,7 @@ "type": 3, "compound_value": { "value": [ - 3, + 1, 0, 0, 0 @@ -3491,13 +3436,12 @@ ] }, { - "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2", + "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2", "subconfigurations": [ { "device_cnt": 1, - "ase_cnt": 2, + "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -3619,13 +3563,12 @@ ] }, { - "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1", + "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1", "subconfigurations": [ { "device_cnt": 1, - "ase_cnt": 2, + "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -3747,12 +3690,12 @@ ] }, { - "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2", + "name": "DualDev_OneChanMonoSrc_16_2", "subconfigurations": [ { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SINK", + "device_cnt": 2, + "ase_cnt": 2, + "direction": "SOURCE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -3809,7 +3752,12 @@ } } ] - }, + } + ] + }, + { + "name": "SingleDev_OneChanMonoSrc_48_4", + "subconfigurations": [ { "device_cnt": 1, "ase_cnt": 1, @@ -3825,7 +3773,7 @@ "type": 1, "compound_value": { "value": [ - 3 + 8 ] } }, @@ -3855,7 +3803,7 @@ "type": 4, "compound_value": { "value": [ - 40, + 120, 0 ] } @@ -3874,12 +3822,12 @@ ] }, { - "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1", + "name": "SingleDev_OneChanMonoSrc_48_3", "subconfigurations": [ { "device_cnt": 1, "ase_cnt": 1, - "direction": "SINK", + "direction": "SOURCE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -3891,7 +3839,7 @@ "type": 1, "compound_value": { "value": [ - 3 + 8 ] } }, @@ -3921,7 +3869,7 @@ "type": 4, "compound_value": { "value": [ - 30, + 90, 0 ] } @@ -3936,7 +3884,12 @@ } } ] - }, + } + ] + }, + { + "name": "SingleDev_OneChanMonoSrc_48_2", + "subconfigurations": [ { "device_cnt": 1, "ase_cnt": 1, @@ -3952,7 +3905,7 @@ "type": 1, "compound_value": { "value": [ - 3 + 8 ] } }, @@ -3961,7 +3914,7 @@ "type": 2, "compound_value": { "value": [ - 0 + 1 ] } }, @@ -3982,7 +3935,7 @@ "type": 4, "compound_value": { "value": [ - 30, + 100, 0 ] } @@ -4001,11 +3954,11 @@ ] }, { - "name": "DualDev_OneChanMonoSrc_16_2", + "name": "SingleDev_OneChanMonoSrc_48_1", "subconfigurations": [ { - "device_cnt": 2, - "ase_cnt": 2, + "device_cnt": 1, + "ase_cnt": 1, "direction": "SOURCE", "codec_id": { "coding_format": 6, @@ -4018,7 +3971,7 @@ "type": 1, "compound_value": { "value": [ - 3 + 8 ] } }, @@ -4027,7 +3980,7 @@ "type": 2, "compound_value": { "value": [ - 1 + 0 ] } }, @@ -4048,7 +4001,7 @@ "type": 4, "compound_value": { "value": [ - 40, + 75, 0 ] } @@ -4067,7 +4020,7 @@ ] }, { - "name": "SingleDev_OneChanMonoSrc_48_4", + "name": "SingleDev_OneChanMonoSrc_32_2", "subconfigurations": [ { "device_cnt": 1, @@ -4084,7 +4037,7 @@ "type": 1, "compound_value": { "value": [ - 8 + 6 ] } }, @@ -4114,7 +4067,7 @@ "type": 4, "compound_value": { "value": [ - 120, + 80, 0 ] } @@ -4133,7 +4086,7 @@ ] }, { - "name": "SingleDev_OneChanMonoSrc_48_3", + "name": "SingleDev_OneChanMonoSrc_32_1", "subconfigurations": [ { "device_cnt": 1, @@ -4150,7 +4103,7 @@ "type": 1, "compound_value": { "value": [ - 8 + 6 ] } }, @@ -4180,7 +4133,7 @@ "type": 4, "compound_value": { "value": [ - 90, + 60, 0 ] } @@ -4199,7 +4152,7 @@ ] }, { - "name": "SingleDev_OneChanMonoSrc_48_2", + "name": "SingleDev_OneChanMonoSrc_24_2", "subconfigurations": [ { "device_cnt": 1, @@ -4216,7 +4169,7 @@ "type": 1, "compound_value": { "value": [ - 8 + 5 ] } }, @@ -4246,7 +4199,7 @@ "type": 4, "compound_value": { "value": [ - 100, + 60, 0 ] } @@ -4265,7 +4218,7 @@ ] }, { - "name": "SingleDev_OneChanMonoSrc_48_1", + "name": "SingleDev_OneChanMonoSrc_24_1", "subconfigurations": [ { "device_cnt": 1, @@ -4282,7 +4235,7 @@ "type": 1, "compound_value": { "value": [ - 8 + 5 ] } }, @@ -4312,7 +4265,7 @@ "type": 4, "compound_value": { "value": [ - 75, + 45, 0 ] } @@ -4331,7 +4284,7 @@ ] }, { - "name": "SingleDev_OneChanMonoSrc_32_2", + "name": "SingleDev_OneChanMonoSrc_16_2", "subconfigurations": [ { "device_cnt": 1, @@ -4348,7 +4301,7 @@ "type": 1, "compound_value": { "value": [ - 6 + 3 ] } }, @@ -4378,7 +4331,7 @@ "type": 4, "compound_value": { "value": [ - 80, + 40, 0 ] } @@ -4397,7 +4350,7 @@ ] }, { - "name": "SingleDev_OneChanMonoSrc_32_1", + "name": "SingleDev_OneChanMonoSrc_16_1", "subconfigurations": [ { "device_cnt": 1, @@ -4414,7 +4367,7 @@ "type": 1, "compound_value": { "value": [ - 6 + 3 ] } }, @@ -4444,7 +4397,7 @@ "type": 4, "compound_value": { "value": [ - 60, + 30, 0 ] } @@ -4463,12 +4416,13 @@ ] }, { - "name": "SingleDev_OneChanMonoSrc_24_2", + "name": "DualDev_OneChanStereoSnk_48_4", "subconfigurations": [ { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SOURCE", + "device_cnt": 2, + "ase_cnt": 2, + "direction": "SINK", + "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -4480,7 +4434,7 @@ "type": 1, "compound_value": { "value": [ - 5 + 8 ] } }, @@ -4510,7 +4464,7 @@ "type": 4, "compound_value": { "value": [ - 60, + 120, 0 ] } @@ -4529,12 +4483,13 @@ ] }, { - "name": "SingleDev_OneChanMonoSrc_24_1", + "name": "DualDev_OneChanStereoSnk_48_3", "subconfigurations": [ { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SOURCE", + "device_cnt": 2, + "ase_cnt": 2, + "direction": "SINK", + "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -4546,7 +4501,7 @@ "type": 1, "compound_value": { "value": [ - 5 + 8 ] } }, @@ -4555,7 +4510,7 @@ "type": 2, "compound_value": { "value": [ - 0 + 1 ] } }, @@ -4576,7 +4531,7 @@ "type": 4, "compound_value": { "value": [ - 45, + 90, 0 ] } @@ -4595,12 +4550,13 @@ ] }, { - "name": "SingleDev_OneChanMonoSrc_16_2", + "name": "DualDev_OneChanStereoSnk_48_2", "subconfigurations": [ { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SOURCE", + "device_cnt": 2, + "ase_cnt": 2, + "direction": "SINK", + "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -4612,7 +4568,7 @@ "type": 1, "compound_value": { "value": [ - 3 + 8 ] } }, @@ -4642,7 +4598,7 @@ "type": 4, "compound_value": { "value": [ - 40, + 100, 0 ] } @@ -4661,73 +4617,7 @@ ] }, { - "name": "SingleDev_OneChanMonoSrc_16_1", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SOURCE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 3 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 0 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 30, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "DualDev_OneChanStereoSnk_48_4", + "name": "DualDev_OneChanStereoSnk_48_1", "subconfigurations": [ { "device_cnt": 2, @@ -4754,77 +4644,10 @@ "type": 2, "compound_value": { "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 120, 0 ] } }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "DualDev_OneChanStereoSnk_48_3", - "subconfigurations": [ - { - "device_cnt": 2, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 8 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, { "name": "audio_channel_allocation", "type": 3, @@ -4842,7 +4665,7 @@ "type": 4, "compound_value": { "value": [ - 90, + 75, 0 ] } @@ -4861,13 +4684,13 @@ ] }, { - "name": "DualDev_OneChanStereoSnk_48_2", + "name": "SingleDev_OneChanStereoSnk_48_4", "subconfigurations": [ { - "device_cnt": 2, + "device_cnt": 1, "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", + "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -4909,74 +4732,7 @@ "type": 4, "compound_value": { "value": [ - 100, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "DualDev_OneChanStereoSnk_48_1", - "subconfigurations": [ - { - "device_cnt": 2, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 8 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 0 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 75, + 120, 0 ] } @@ -4995,7 +4751,7 @@ ] }, { - "name": "SingleDev_OneChanStereoSnk_48_4", + "name": "SingleDev_OneChanStereoSnk_48_3", "subconfigurations": [ { "device_cnt": 1, @@ -5043,7 +4799,7 @@ "type": 4, "compound_value": { "value": [ - 120, + 90, 0 ] } @@ -5062,7 +4818,7 @@ ] }, { - "name": "SingleDev_OneChanStereoSnk_48_3", + "name": "SingleDev_OneChanStereoSnk_48_2", "subconfigurations": [ { "device_cnt": 1, @@ -5110,7 +4866,7 @@ "type": 4, "compound_value": { "value": [ - 90, + 100, 0 ] } @@ -5129,7 +4885,7 @@ ] }, { - "name": "SingleDev_OneChanStereoSnk_48_2", + "name": "SingleDev_OneChanStereoSnk_48_1", "subconfigurations": [ { "device_cnt": 1, @@ -5156,7 +4912,7 @@ "type": 2, "compound_value": { "value": [ - 1 + 0 ] } }, @@ -5177,7 +4933,7 @@ "type": 4, "compound_value": { "value": [ - 100, + 75, 0 ] } @@ -5196,13 +4952,13 @@ ] }, { - "name": "SingleDev_OneChanStereoSnk_48_1", + "name": "SingleDev_TwoChanStereoSnk_48_4", "subconfigurations": [ { "device_cnt": 1, - "ase_cnt": 2, + "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", + "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -5223,7 +4979,7 @@ "type": 2, "compound_value": { "value": [ - 0 + 1 ] } }, @@ -5232,7 +4988,7 @@ "type": 3, "compound_value": { "value": [ - 1, + 3, 0, 0, 0 @@ -5244,7 +5000,7 @@ "type": 4, "compound_value": { "value": [ - 75, + 120, 0 ] } @@ -5263,7 +5019,7 @@ ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_4", + "name": "SingleDev_TwoChanStereoSnk_48_3", "subconfigurations": [ { "device_cnt": 1, @@ -5311,7 +5067,7 @@ "type": 4, "compound_value": { "value": [ - 120, + 90, 0 ] } @@ -5330,7 +5086,7 @@ ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_3", + "name": "SingleDev_TwoChanStereoSnk_48_2", "subconfigurations": [ { "device_cnt": 1, @@ -5378,7 +5134,7 @@ "type": 4, "compound_value": { "value": [ - 90, + 100, 0 ] } @@ -5397,7 +5153,7 @@ ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_2", + "name": "SingleDev_TwoChanStereoSnk_48_1", "subconfigurations": [ { "device_cnt": 1, @@ -5424,7 +5180,7 @@ "type": 2, "compound_value": { "value": [ - 1 + 0 ] } }, @@ -5445,7 +5201,7 @@ "type": 4, "compound_value": { "value": [ - 100, + 75, 0 ] } @@ -5464,74 +5220,7 @@ ] }, { - "name": "SingleDev_TwoChanStereoSnk_48_1", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 8 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 0 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 75, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_OneChanMonoSnk_48_4", + "name": "SingleDev_OneChanMonoSnk_48_4", "subconfigurations": [ { "device_cnt": 1, @@ -5558,409 +5247,7 @@ "type": 2, "compound_value": { "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 120, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_OneChanMonoSnk_48_3", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 8 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 90, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_OneChanMonoSnk_48_2", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 8 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 100, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "SingleDev_OneChanMonoSnk_48_1", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 8 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 0 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 75, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_1", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 8 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 0 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 3, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 100, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "VND_DualDev_OneChanStereoSnk_48khz_100octs_1", - "subconfigurations": [ - { - "device_cnt": 2, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 8 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 0 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 100, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, - { - "name": "VND_SingleDev_OneChanStereoSnk_48khz_100octs_1", - "subconfigurations": [ - { - "device_cnt": 1, - "ase_cnt": 2, - "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 8 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 0 + 1 ] } }, @@ -5981,7 +5268,7 @@ "type": 4, "compound_value": { "value": [ - 100, + 120, 0 ] } @@ -6000,13 +5287,13 @@ ] }, { - "name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_1", + "name": "SingleDev_OneChanMonoSnk_48_3", "subconfigurations": [ { "device_cnt": 1, "ase_cnt": 1, "direction": "SINK", - "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", + "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -6027,7 +5314,7 @@ "type": 2, "compound_value": { "value": [ - 0 + 1 ] } }, @@ -6036,7 +5323,7 @@ "type": 3, "compound_value": { "value": [ - 3, + 1, 0, 0, 0 @@ -6048,7 +5335,7 @@ "type": 4, "compound_value": { "value": [ - 75, + 90, 0 ] } @@ -6067,12 +5354,13 @@ ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_32_2", + "name": "SingleDev_OneChanMonoSnk_48_2", "subconfigurations": [ { - "device_cnt": 2, - "ase_cnt": 2, + "device_cnt": 1, + "ase_cnt": 1, "direction": "SINK", + "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -6114,7 +5402,7 @@ "type": 4, "compound_value": { "value": [ - 120, + 100, 0 ] } @@ -6129,11 +5417,17 @@ } } ] - }, + } + ] + }, + { + "name": "SingleDev_OneChanMonoSnk_48_1", + "subconfigurations": [ { - "device_cnt": 2, - "ase_cnt": 2, - "direction": "SOURCE", + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SINK", + "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -6145,7 +5439,7 @@ "type": 1, "compound_value": { "value": [ - 6 + 8 ] } }, @@ -6154,7 +5448,7 @@ "type": 2, "compound_value": { "value": [ - 1 + 0 ] } }, @@ -6175,7 +5469,7 @@ "type": 4, "compound_value": { "value": [ - 80, + 75, 0 ] } @@ -6194,12 +5488,13 @@ ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_24_2", + "name": "VND_SingleDev_TwoChanStereoSnk_48khz_100octs_1", "subconfigurations": [ { - "device_cnt": 2, - "ase_cnt": 2, + "device_cnt": 1, + "ase_cnt": 1, "direction": "SINK", + "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -6220,7 +5515,7 @@ "type": 2, "compound_value": { "value": [ - 1 + 0 ] } }, @@ -6229,7 +5524,7 @@ "type": 3, "compound_value": { "value": [ - 1, + 3, 0, 0, 0 @@ -6241,7 +5536,7 @@ "type": 4, "compound_value": { "value": [ - 120, + 100, 0 ] } @@ -6256,11 +5551,17 @@ } } ] - }, + } + ] + }, + { + "name": "VND_DualDev_OneChanStereoSnk_48khz_100octs_1", + "subconfigurations": [ { "device_cnt": 2, "ase_cnt": 2, - "direction": "SOURCE", + "direction": "SINK", + "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -6272,7 +5573,7 @@ "type": 1, "compound_value": { "value": [ - 5 + 8 ] } }, @@ -6281,7 +5582,7 @@ "type": 2, "compound_value": { "value": [ - 1 + 0 ] } }, @@ -6302,7 +5603,7 @@ "type": 4, "compound_value": { "value": [ - 80, + 100, 0 ] } @@ -6321,12 +5622,13 @@ ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_16_2", + "name": "VND_SingleDev_OneChanStereoSnk_48khz_100octs_1", "subconfigurations": [ { - "device_cnt": 2, + "device_cnt": 1, "ase_cnt": 2, "direction": "SINK", + "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -6347,7 +5649,7 @@ "type": 2, "compound_value": { "value": [ - 1 + 0 ] } }, @@ -6368,7 +5670,7 @@ "type": 4, "compound_value": { "value": [ - 120, + 100, 0 ] } @@ -6383,11 +5685,17 @@ } } ] - }, + } + ] + }, + { + "name": "VND_SingleDev_TwoChanStereoSnk_48khz_75octs_1", + "subconfigurations": [ { - "device_cnt": 2, - "ase_cnt": 2, - "direction": "SOURCE", + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SINK", + "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -6399,7 +5707,7 @@ "type": 1, "compound_value": { "value": [ - 3 + 8 ] } }, @@ -6408,7 +5716,7 @@ "type": 2, "compound_value": { "value": [ - 1 + 0 ] } }, @@ -6417,7 +5725,7 @@ "type": 3, "compound_value": { "value": [ - 1, + 3, 0, 0, 0 @@ -6429,7 +5737,7 @@ "type": 4, "compound_value": { "value": [ - 80, + 75, 0 ] } @@ -6448,7 +5756,7 @@ ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2", + "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_32_2", "subconfigurations": [ { "device_cnt": 2, @@ -6512,8 +5820,8 @@ ] }, { - "device_cnt": 1, - "ase_cnt": 1, + "device_cnt": 2, + "ase_cnt": 2, "direction": "SOURCE", "codec_id": { "coding_format": 6, @@ -6575,7 +5883,7 @@ ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2", + "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_24_2", "subconfigurations": [ { "device_cnt": 2, @@ -6639,8 +5947,8 @@ ] }, { - "device_cnt": 1, - "ase_cnt": 1, + "device_cnt": 2, + "ase_cnt": 2, "direction": "SOURCE", "codec_id": { "coding_format": 6, @@ -6702,7 +6010,7 @@ ] }, { - "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2", + "name": "DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_16_2", "subconfigurations": [ { "device_cnt": 2, @@ -6766,8 +6074,8 @@ ] }, { - "device_cnt": 1, - "ase_cnt": 1, + "device_cnt": 2, + "ase_cnt": 2, "direction": "SOURCE", "codec_id": { "coding_format": 6, @@ -6829,13 +6137,12 @@ ] }, { - "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_32_2", + "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2", "subconfigurations": [ { "device_cnt": 2, - "ase_cnt": 4, + "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -6957,13 +6264,12 @@ ] }, { - "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_24_2", + "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2", "subconfigurations": [ { "device_cnt": 2, - "ase_cnt": 4, + "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -7085,13 +6391,12 @@ ] }, { - "name": "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_16_2", + "name": "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2", "subconfigurations": [ { "device_cnt": 2, - "ase_cnt": 4, + "ase_cnt": 2, "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", "codec_id": { "coding_format": 6, "vendor_company_id": 0, @@ -10053,134 +9358,6 @@ } ] }, - { - "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2", - "subconfigurations": [ - { - "device_cnt": 2, - "ase_cnt": 4, - "direction": "SINK", - "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 6 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 80, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - }, - { - "device_cnt": 1, - "ase_cnt": 1, - "direction": "SOURCE", - "codec_id": { - "coding_format": 6, - "vendor_company_id": 0, - "vendor_codec_id": 0 - }, - "codec_configuration": [ - { - "name": "sampling_frequency", - "type": 1, - "compound_value": { - "value": [ - 6 - ] - } - }, - { - "name": "frame_duration", - "type": 2, - "compound_value": { - "value": [ - 1 - ] - } - }, - { - "name": "audio_channel_allocation", - "type": 3, - "compound_value": { - "value": [ - 1, - 0, - 0, - 0 - ] - } - }, - { - "name": "octets_per_codec_frame", - "type": 4, - "compound_value": { - "value": [ - 80, - 0 - ] - } - }, - { - "name": "codec_frame_blocks_per_sdu", - "type": 5, - "compound_value": { - "value": [ - 1 - ] - } - } - ] - } - ] - }, { "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2", "subconfigurations": [ diff --git a/system/bta/le_audio/audio_set_scenarios.json b/system/bta/le_audio/audio_set_scenarios.json index 9fa3409e3d855419095bb3d7342f23595cba3ca1..b7788aa32848eda0ef5bef12021d063c3b3eb200 100644 --- a/system/bta/le_audio/audio_set_scenarios.json +++ b/system/bta/le_audio/audio_set_scenarios.json @@ -22,12 +22,6 @@ "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1", "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency", "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1", - "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2_1", - "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2_Low_Latency", - "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_Low_Latency", - "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_1", - "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_Low_Latency", - "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_1", "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency", "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_1", "SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency", @@ -240,9 +234,6 @@ "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability", "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability", "DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability", - "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability", - "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability", - "DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability", "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_16_2_Balanced_Reliability", "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_24_2_Balanced_Reliability", "SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_32_2_Balanced_Reliability", diff --git a/system/btif/co/bta_av_co.cc b/system/btif/co/bta_av_co.cc index f68656584f83bee3cd246276d9237a4c11c537b6..a567296a9e9b0cf380e3bda42cf6ee6a2f4c5d6c 100644 --- a/system/btif/co/bta_av_co.cc +++ b/system/btif/co/bta_av_co.cc @@ -25,7 +25,6 @@ #include "btif/include/bta_av_co.h" -#include <base/logging.h> #include <bluetooth/log.h> #include <mutex> @@ -62,6 +61,25 @@ const uint8_t bta_av_co_cp_scmst[AVDT_CP_INFO_LEN] = {0x02, 0x02, 0x00}; static const bool kContentProtectEnabled = false; static BtaAvCo bta_av_co_cb(kContentProtectEnabled, new BtaAvCoPeerCache()); +void BtaAvCoState::setActivePeer(BtaAvCoPeer* peer) { active_peer_ = peer; } + +BtaAvCoPeer* BtaAvCoState::getActivePeer() const { return active_peer_; } + +uint8_t* BtaAvCoState::getCodecConfig() { return codec_config_; } + +void BtaAvCoState::setCodecConfig(const uint8_t* codec_config) { + memcpy(codec_config_, codec_config, AVDT_CODEC_SIZE); +} + +void BtaAvCoState::clearCodecConfig() { + memset(codec_config_, 0, AVDT_CODEC_SIZE); +} + +void BtaAvCoState::Reset() { + active_peer_ = nullptr; + clearCodecConfig(); +} + void BtaAvCo::Init( const std::vector<btav_a2dp_codec_config_t>& codec_priorities, std::vector<btav_a2dp_codec_info_t>* supported_codecs) { @@ -86,9 +104,8 @@ void BtaAvCo::Init( } void BtaAvCo::Reset() { - active_peer_ = nullptr; + bta_av_legacy_state_.Reset(); content_protect_flag_ = 0; - memset(codec_config_, 0, sizeof(codec_config_)); if (ContentProtectEnabled()) { SetContentProtectFlag(AVDT_CP_SCMS_COPY_NEVER); @@ -113,10 +130,11 @@ bool BtaAvCo::IsSupportedCodec(btav_a2dp_codec_index_t codec_index) { A2dpCodecConfig* BtaAvCo::GetActivePeerCurrentCodec() { std::lock_guard<std::recursive_mutex> lock(peer_cache_->codec_lock_); - if (active_peer_ == nullptr || active_peer_->GetCodecs() == nullptr) { + BtaAvCoPeer* active_peer = bta_av_legacy_state_.getActivePeer(); + if (active_peer == nullptr || active_peer->GetCodecs() == nullptr) { return nullptr; } - return active_peer_->GetCodecs()->getCurrentCodecConfig(); + return active_peer->GetCodecs()->getCurrentCodecConfig(); } A2dpCodecConfig* BtaAvCo::GetPeerCurrentCodec(const RawAddress& peer_address) { @@ -579,8 +597,9 @@ void BtaAvCo::ProcessOpen(tBTA_AV_HNDL bta_av_handle, p_peer->mtu = mtu; // The first connected peer becomes the active peer - if (active_peer_ == nullptr) { - active_peer_ = p_peer; + BtaAvCoPeer* active_peer = bta_av_legacy_state_.getActivePeer(); + if (active_peer == nullptr) { + bta_av_legacy_state_.setActivePeer(p_peer); } } @@ -599,8 +618,9 @@ void BtaAvCo::ProcessClose(tBTA_AV_HNDL bta_av_handle, return; } // Reset the active peer - if (active_peer_ == p_peer) { - active_peer_ = nullptr; + BtaAvCoPeer* active_peer = bta_av_legacy_state_.getActivePeer(); + if (active_peer == p_peer) { + bta_av_legacy_state_.setActivePeer(nullptr); } // Mark the peer closed and clean the peer info p_peer->Init(peer_cache_->codec_priorities_); @@ -666,10 +686,11 @@ BT_HDR* BtaAvCo::GetNextSourceDataPacket(const uint8_t* p_codec_info, return nullptr; } + BtaAvCoPeer* active_peer = bta_av_legacy_state_.getActivePeer(); // if offset is 0, the decremental operation may result in // underflow and OOB access - if (ContentProtectEnabled() && (active_peer_ != nullptr) && - active_peer_->ContentProtectActive() && p_buf->offset > 0) { + if (ContentProtectEnabled() && (active_peer != nullptr) && + active_peer->ContentProtectActive() && p_buf->offset > 0) { p_buf->len++; p_buf->offset--; uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset; @@ -715,10 +736,11 @@ bool BtaAvCo::SetActivePeer(const RawAddress& peer_address) { std::lock_guard<std::recursive_mutex> lock(peer_cache_->codec_lock_); + BtaAvCoState* reference_state = &bta_av_legacy_state_; if (peer_address.IsEmpty()) { // Reset the active peer; - active_peer_ = nullptr; - memset(codec_config_, 0, sizeof(codec_config_)); + reference_state->setActivePeer(nullptr); + reference_state->clearCodecConfig(); return true; } @@ -728,16 +750,17 @@ bool BtaAvCo::SetActivePeer(const RawAddress& peer_address) { return false; } - active_peer_ = p_peer; - memcpy(codec_config_, active_peer_->codec_config, AVDT_CODEC_SIZE); - log::info("codec = {}", A2DP_CodecInfoString(codec_config_)); + reference_state->setActivePeer(p_peer); + reference_state->setCodecConfig(p_peer->codec_config); + log::info("codec = {}", + A2DP_CodecInfoString(reference_state->getCodecConfig())); // report the selected codec configuration of this new active peer. - ReportSourceCodecState(active_peer_); + ReportSourceCodecState(p_peer); return true; } void BtaAvCo::SaveCodec(const uint8_t* new_codec_config) { - memcpy(codec_config_, new_codec_config, sizeof(codec_config_)); + bta_av_legacy_state_.setCodecConfig(new_codec_config); } void BtaAvCo::GetPeerEncoderParameters( @@ -770,7 +793,7 @@ void BtaAvCo::GetPeerEncoderParameters( const tA2DP_ENCODER_INTERFACE* BtaAvCo::GetSourceEncoderInterface() { std::lock_guard<std::recursive_mutex> lock(peer_cache_->codec_lock_); - return A2DP_GetEncoderInterface(codec_config_); + return A2DP_GetEncoderInterface(bta_av_legacy_state_.getCodecConfig()); } bool BtaAvCo::SetCodecUserConfig( @@ -862,8 +885,11 @@ done: // would always know the result. // NOTE: Currently, the input is restarted by sending an upcall // and informing the Media Framework about the change. + + // Find the peer that is currently open + BtaAvCoPeer* active_peer = bta_av_legacy_state_.getActivePeer(); if (p_peer != nullptr && - (!restart_output || !success || p_peer != active_peer_)) { + (!restart_output || !success || p_peer != active_peer)) { return ReportSourceCodecState(p_peer); } @@ -879,7 +905,7 @@ bool BtaAvCo::SetCodecAudioConfig( log::verbose("codec_audio_config: {}", codec_audio_config.ToString()); // Find the peer that is currently open - BtaAvCoPeer* p_peer = active_peer_; + BtaAvCoPeer* p_peer = bta_av_legacy_state_.getActivePeer(); if (p_peer == nullptr) { log::error("no active peer to configure"); return false; @@ -936,7 +962,8 @@ bool BtaAvCo::SetCodecAudioConfig( int BtaAvCo::GetSourceEncoderEffectiveFrameSize() { std::lock_guard<std::recursive_mutex> lock(peer_cache_->codec_lock_); - return A2DP_GetEecoderEffectiveFrameSize(codec_config_); + return A2DP_GetEecoderEffectiveFrameSize( + bta_av_legacy_state_.getCodecConfig()); } bool BtaAvCo::ReportSourceCodecState(BtaAvCoPeer* p_peer) { @@ -989,18 +1016,19 @@ void BtaAvCo::DebugDump(int fd) { // // Active peer codec-specific stats // - if (active_peer_ != nullptr) { - A2dpCodecs* a2dp_codecs = active_peer_->GetCodecs(); + if (bta_av_legacy_state_.getActivePeer() != nullptr) { + A2dpCodecs* a2dp_codecs = bta_av_legacy_state_.getActivePeer()->GetCodecs(); if (a2dp_codecs != nullptr) { a2dp_codecs->debug_codec_dump(fd); } } dprintf(fd, "\nA2DP Peers State:\n"); - dprintf(fd, " Active peer: %s\n", - (active_peer_ != nullptr) - ? ADDRESS_TO_LOGGABLE_CSTR(active_peer_->addr) - : "null"); + dprintf( + fd, " Active peer: %s\n", + (bta_av_legacy_state_.getActivePeer() != nullptr) + ? ADDRESS_TO_LOGGABLE_CSTR(bta_av_legacy_state_.getActivePeer()->addr) + : "null"); for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(peer_cache_->peers_); i++) { const BtaAvCoPeer& peer = peer_cache_->peers_[i]; @@ -1295,8 +1323,7 @@ void BtaAvCo::SaveNewCodecConfig(BtaAvCoPeer* p_peer, log::verbose("codec: {}", A2DP_CodecInfoString(new_codec_config)); std::lock_guard<std::recursive_mutex> lock(peer_cache_->codec_lock_); - - memcpy(codec_config_, new_codec_config, sizeof(codec_config_)); + bta_av_legacy_state_.setCodecConfig(new_codec_config); memcpy(p_peer->codec_config, new_codec_config, AVDT_CODEC_SIZE); if (ContentProtectEnabled()) { diff --git a/system/btif/include/bta_av_co.h b/system/btif/include/bta_av_co.h index 7571bc12e3561da88d5a1f8c5b4fae6545e18206..fe7ca50f59e711b9f6e2d0db1c3f6d5639be964c 100644 --- a/system/btif/include/bta_av_co.h +++ b/system/btif/include/bta_av_co.h @@ -20,12 +20,59 @@ #include "btif/include/bta_av_co_peer.h" +/** + * BTA AV codec callouts state. + */ +class BtaAvCoState { + public: + BtaAvCoState() = default; + + /** + * Set the active peer for the state. + * @param peer + */ + void setActivePeer(BtaAvCoPeer* peer); + + /** + * Gets the active peer for the state. + * @return pointer to the active peer. + */ + BtaAvCoPeer* getActivePeer() const; + + /** + * Gets the codec config for the state. + * @return the active codec config. + */ + uint8_t* getCodecConfig(); + + /** + * Updates the codec config + * @param codec_config codec config that needs to be updated. + */ + void setCodecConfig(const uint8_t* codec_config); + + /** + * Clears the codec config. + */ + void clearCodecConfig(); + + /** + * Resets the state. + */ + void Reset(); + virtual ~BtaAvCoState() = default; + + private: + // The current active peer + BtaAvCoPeer* active_peer_; + // Current codec configuration + uint8_t codec_config_[AVDT_CODEC_SIZE]; +}; + class BtaAvCo { public: BtaAvCo(bool content_protect_enabled, BtaAvCoPeerCache* bta_av_co_peer_bank) : peer_cache_(bta_av_co_peer_bank), - active_peer_(nullptr), - codec_config_{}, content_protect_enabled_(content_protect_enabled), content_protect_flag_(0) { Reset(); @@ -495,9 +542,7 @@ class BtaAvCo { bool ContentProtectEnabled() const { return content_protect_enabled_; } - // TODO: Remove active peer once no longer needed. - BtaAvCoPeer* active_peer_; // The current active peer - uint8_t codec_config_[AVDT_CODEC_SIZE]; // Current codec configuration - const bool content_protect_enabled_; // True if Content Protect is enabled - uint8_t content_protect_flag_; // Content Protect flag + const bool content_protect_enabled_; // True if Content Protect is enabled + uint8_t content_protect_flag_; // Content Protect flag + BtaAvCoState bta_av_legacy_state_; }; diff --git a/system/log/include/bluetooth/log.h b/system/log/include/bluetooth/log.h index 6f71ae7087273ecd11926d85ced329bedef06849..81106fcdfa93fad8ab8d1b15d6f6d6d508bcbe14 100644 --- a/system/log/include/bluetooth/log.h +++ b/system/log/include/bluetooth/log.h @@ -44,13 +44,37 @@ void vlog(Level level, char const* tag, char const* file_name, int line, char const* function_name, fmt::string_view fmt, fmt::format_args vargs); +/// Capture invalid parameter values that would cause runtime +/// formatting errors. +template <class T> +[[maybe_unused]] static inline T& format_replace(T& arg) { + return arg; +} + +/// Specialization of format_replace for nullptr string parameters. +template <> +char const*& format_replace(char const*& arg) { + static char const* nullptr_str = "(nullptr)"; + if (arg) return arg; + return nullptr_str; +} + +/// Specialization of format_replace for nullptr string parameters. +template <> +char*& format_replace(char*& arg) { + static char* nullptr_str = (char*)"(nullptr)"; + if (arg) return arg; + return nullptr_str; +} + template <Level level, typename... T> struct log { log(fmt::format_string<T...> fmt, T&&... args, char const* file_name = __builtin_FILE(), int line = __builtin_LINE(), char const* function_name = __builtin_FUNCTION()) { vlog(level, LOG_TAG, file_name, line, function_name, - static_cast<fmt::string_view>(fmt), fmt::make_format_args(args...)); + static_cast<fmt::string_view>(fmt), + fmt::make_format_args(format_replace(args)...)); } }; diff --git a/system/log/src/vlog_test.cc b/system/log/src/vlog_test.cc index 026dd737081099dca73f0c298865932dfdd2448a..f5f41b6c5dfb19355f94f22851c4e8dcdb1b3760 100644 --- a/system/log/src/vlog_test.cc +++ b/system/log/src/vlog_test.cc @@ -112,3 +112,23 @@ TEST(BluetoothLoggerTest, error) { EXPECT_EQ(androidLogMessage->line, 105); EXPECT_STREQ(androidLogMessage->message, "TestBody: error test"); } + +TEST(BluetoothLoggerTest, null_string_parameter) { + androidLogMessage.reset(); + + char const* const_null_str = nullptr; + log::info("input: {}", const_null_str); + EXPECT_STREQ(androidLogMessage->message, "TestBody: input: (nullptr)"); + + androidLogMessage.reset(); + + char* null_str = nullptr; + log::info("input: {}", null_str); + EXPECT_STREQ(androidLogMessage->message, "TestBody: input: (nullptr)"); + + androidLogMessage.reset(); + + char const* nonnull_str = "hello world"; + log::info("input: {}", nonnull_str); + EXPECT_STREQ(androidLogMessage->message, "TestBody: input: hello world"); +}