Snap for 11510485 from 448440ff8193c6504a854c0294526419e3efe1f3 to 24Q2-release
Change-Id: I1b39e08556cd78329a941f6d37f4e66f5fb77844
diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
index b49597d..6b10df8 100644
--- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
+++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
@@ -2269,6 +2269,34 @@
* JNI Initialization
*/
jint JNI_OnLoad(JavaVM* jvm, void* /* reserved */) {
+ /* Set the default logging level for the process using the tag
+ * "log.tag.bluetooth" and/or "persist.log.tag.bluetooth" via the android
+ * logging framework.
+ */
+ const char* stack_default_log_tag = "bluetooth";
+ int default_prio = ANDROID_LOG_INFO;
+ if (__android_log_is_loggable(ANDROID_LOG_VERBOSE, stack_default_log_tag,
+ default_prio)) {
+ __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE);
+ log::info("Set stack default log level to 'VERBOSE'");
+ } else if (__android_log_is_loggable(ANDROID_LOG_DEBUG, stack_default_log_tag,
+ default_prio)) {
+ __android_log_set_minimum_priority(ANDROID_LOG_DEBUG);
+ log::info("Set stack default log level to 'DEBUG'");
+ } else if (__android_log_is_loggable(ANDROID_LOG_INFO, stack_default_log_tag,
+ default_prio)) {
+ __android_log_set_minimum_priority(ANDROID_LOG_INFO);
+ log::info("Set stack default log level to 'INFO'");
+ } else if (__android_log_is_loggable(ANDROID_LOG_WARN, stack_default_log_tag,
+ default_prio)) {
+ __android_log_set_minimum_priority(ANDROID_LOG_WARN);
+ log::info("Set stack default log level to 'WARN'");
+ } else if (__android_log_is_loggable(ANDROID_LOG_ERROR, stack_default_log_tag,
+ default_prio)) {
+ __android_log_set_minimum_priority(ANDROID_LOG_ERROR);
+ log::info("Set stack default log level to 'ERROR'");
+ }
+
JNIEnv* e;
int status;
diff --git a/android/app/src/com/android/bluetooth/BluetoothEventLogger.java b/android/app/src/com/android/bluetooth/BluetoothEventLogger.java
index ed682a3..22604dd 100644
--- a/android/app/src/com/android/bluetooth/BluetoothEventLogger.java
+++ b/android/app/src/com/android/bluetooth/BluetoothEventLogger.java
@@ -60,15 +60,8 @@
/** Add the event record and log debug message */
public synchronized void logd(String tag, String msg) {
- logd(true, tag, msg);
- }
-
- /** Add the event record and log debug message */
- public synchronized void logd(boolean debug, String tag, String msg) {
add(msg);
- if (debug) {
- Log.d(tag, msg);
- }
+ Log.d(tag, msg);
}
/** Add the event record and log warning message */
diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java b/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java
index 1a58e20..f4ba378 100644
--- a/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java
+++ b/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java
@@ -105,7 +105,11 @@
A2dpStateMachine(BluetoothDevice device, A2dpService a2dpService,
A2dpNativeInterface a2dpNativeInterface, Looper looper) {
super(TAG, looper);
- setDbg(DBG);
+
+ // Let the logging framework enforce the log level. TAG is set above in the parent
+ // constructor.
+ setDbg(true);
+
mDevice = device;
mA2dpService = a2dpService;
mA2dpNativeInterface = a2dpNativeInterface;
diff --git a/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java b/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java
index a7a814d..4c2ab41 100644
--- a/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java
+++ b/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java
@@ -842,11 +842,11 @@
}
}
if (isActive != mAudioPlaybackIsActive) {
- mAudioPlaybackStateLogger.logd(DEBUG, TAG, "onPlaybackConfigChanged: "
+ mAudioPlaybackStateLogger.logd(TAG, "onPlaybackConfigChanged: "
+ (mAudioPlaybackIsActive ? "Active" : "Non-active") + " -> "
+ (isActive ? "Active" : "Non-active"));
if (isActive) {
- mAudioPlaybackStateLogger.logd(DEBUG, TAG, "onPlaybackConfigChanged: "
+ mAudioPlaybackStateLogger.logd(TAG, "onPlaybackConfigChanged: "
+ "active config: " + activeConfig);
}
mAudioPlaybackIsActive = isActive;
diff --git a/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java b/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java
index 0e33c42..443e5f9 100644
--- a/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java
+++ b/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java
@@ -457,7 +457,6 @@
BluetoothDevice activeDevice = getA2dpActiveDevice();
MediaPlayerWrapper player = mMediaPlayerList.getActivePlayer();
mMediaKeyEventLogger.logd(
- DEBUG,
TAG,
"sendMediaKeyEvent:"
+ " device="
diff --git a/android/app/src/com/android/bluetooth/avrcp/AvrcpVolumeManager.java b/android/app/src/com/android/bluetooth/avrcp/AvrcpVolumeManager.java
index 780b00d..9599c86 100644
--- a/android/app/src/com/android/bluetooth/avrcp/AvrcpVolumeManager.java
+++ b/android/app/src/com/android/bluetooth/avrcp/AvrcpVolumeManager.java
@@ -179,7 +179,7 @@
void setVolume(@NonNull BluetoothDevice device, int avrcpVolume) {
int deviceVolume = avrcpToSystemVolume(avrcpVolume);
- mVolumeEventLogger.logd(DEBUG, TAG, "setVolume:"
+ mVolumeEventLogger.logd(TAG, "setVolume:"
+ " device=" + device
+ " avrcpVolume=" + avrcpVolume
+ " deviceVolume=" + deviceVolume
@@ -196,7 +196,7 @@
return;
}
int avrcpVolume = systemToAvrcpVolume(deviceVolume);
- mVolumeEventLogger.logd(DEBUG, TAG, "sendVolumeChanged:"
+ mVolumeEventLogger.logd(TAG, "sendVolumeChanged:"
+ " device=" + device
+ " avrcpVolume=" + avrcpVolume
+ " deviceVolume=" + deviceVolume
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 65e5e0d..3f5d5f5 100644
--- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java
+++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java
@@ -336,7 +336,7 @@
}
}
}
- sEventLogger.logd(DBG, TAG, "Broadcast Source Unsynced: scanDelegator= " + scanDelegator
+ sEventLogger.logd(TAG, "Broadcast Source Unsynced: scanDelegator= " + scanDelegator
+ ", syncHandle= " + syncHandle);
}
@@ -354,7 +354,7 @@
mActiveSourceMap.get(scanDelegator).add(syncHandle);
}
}
- sEventLogger.logd(DBG, TAG, "Broadcast Source Synced: scanDelegator= " + scanDelegator
+ sEventLogger.logd(TAG, "Broadcast Source Synced: scanDelegator= " + scanDelegator
+ ", syncHandle= " + syncHandle);
}
@@ -895,7 +895,7 @@
return;
}
- sEventLogger.logd(DBG, TAG, "Broadcast timeout: " + mBroadcastId);
+ sEventLogger.logd(TAG, "Broadcast timeout: " + mBroadcastId);
mLocalBroadcastReceivers.remove(mBroadcastId);
leAudioService.stopBroadcast(mBroadcastId);
}
@@ -983,7 +983,6 @@
}
sEventLogger.logd(
- DBG,
TAG,
"connectionStateChanged: fromState= "
+ BluetoothProfile.getConnectionStateName(fromState)
@@ -1298,7 +1297,7 @@
| ((broadcastIdArray[1] & 0xff) << 8)
| (broadcastIdArray[0] & 0xff));
- sEventLogger.logd(DBG, TAG, "Broadcast Source Found: Broadcast ID: "
+ sEventLogger.logd(TAG, "Broadcast Source Found: Broadcast ID: "
+ broadcastId);
if (broadcastId != BassConstants.INVALID_BROADCAST_ID
@@ -1343,7 +1342,7 @@
serviceData, serviceDataMask).build());
}
scanner.startScan(filters, settings, mSearchScanCallback);
- sEventLogger.logd(DBG, TAG, "startSearchingForSources");
+ sEventLogger.logd(TAG, "startSearchingForSources");
mCallbacks.notifySearchStarted(BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST);
}
}
@@ -1371,7 +1370,7 @@
}
scanner.stopScan(mSearchScanCallback);
mSearchScanCallback = null;
- sEventLogger.logd(DBG, TAG, "stopSearchingForSources");
+ sEventLogger.logd(TAG, "stopSearchingForSources");
mCallbacks.notifySearchStopped(BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST);
}
}
@@ -1402,7 +1401,7 @@
}
synchronized (mStateMachines) {
- sEventLogger.logd(DBG, TAG, "Select Broadcast Source");
+ sEventLogger.logd(TAG, "Select Broadcast Source");
BassClientStateMachine stateMachine = getOrCreateStateMachine(sink);
Message message = stateMachine.obtainMessage(
@@ -1474,7 +1473,6 @@
Integer sourceId = getSourceIdToRemove(device);
if (sourceId != BassConstants.INVALID_SOURCE_ID) {
sEventLogger.logd(
- DBG,
TAG,
"Switch Broadcast Source: device: "
+ device
@@ -1534,7 +1532,6 @@
}
sEventLogger.logd(
- DBG,
TAG,
"Add Broadcast Source: device: "
+ device
@@ -1547,7 +1544,7 @@
message.obj = sourceMetadata;
stateMachine.sendMessage(message);
if (code != null && code.length != 0) {
- sEventLogger.logd(DBG, TAG, "Set Broadcast Code (Add Source context)");
+ sEventLogger.logd(TAG, "Set Broadcast Code (Add Source context)");
message = stateMachine.obtainMessage(BassClientStateMachine.SET_BCAST_CODE);
message.obj = sourceMetadata;
@@ -1619,7 +1616,6 @@
}
sEventLogger.logd(
- DBG,
TAG,
"Modify Broadcast Source: device: "
+ device
@@ -1635,7 +1631,7 @@
message.obj = updatedMetadata;
stateMachine.sendMessage(message);
if (code != null && code.length != 0) {
- sEventLogger.logd(DBG, TAG, "Set Broadcast Code (Modify Source context)");
+ sEventLogger.logd(TAG, "Set Broadcast Code (Modify Source context)");
message = stateMachine.obtainMessage(BassClientStateMachine.SET_BCAST_CODE);
message.obj = updatedMetadata;
message.arg1 = BassClientStateMachine.ARGTYPE_METADATA;
@@ -1688,7 +1684,6 @@
stateMachine.getCurrentBroadcastMetadata(sourceId);
if (metaData != null && stateMachine.isSyncedToTheSource(sourceId)) {
sEventLogger.logd(
- DBG,
TAG,
"Remove Broadcast Source(Force lost PA sync): device: "
+ device
@@ -1708,7 +1703,6 @@
}
sEventLogger.logd(
- DBG,
TAG,
"Remove Broadcast Source: device: " + device + ", sourceId: " + sourceId);
@@ -1813,7 +1807,7 @@
if (store && !mPausedBroadcastSinks.isEmpty()) {
Log.w(TAG, "stopSourceReceivers(), paused broadcast sinks are replaced");
- sEventLogger.logd(DBG, TAG, "Clear broadcast sinks paused cache");
+ sEventLogger.logd(TAG, "Clear broadcast sinks paused cache");
mPausedBroadcastSinks.clear();
}
@@ -1830,7 +1824,7 @@
}
if (store && !mPausedBroadcastSinks.contains(device)) {
- sEventLogger.logd(DBG, TAG, "Add broadcast sink to paused cache: " + device);
+ sEventLogger.logd(TAG, "Add broadcast sink to paused cache: " + device);
mPausedBroadcastSinks.add(device);
}
@@ -1993,29 +1987,29 @@
/** Request receivers to suspend broadcast sources synchronization */
public void suspendReceiversSourceSynchronization(int broadcastId) {
- sEventLogger.logd(DBG, TAG, "Suspend receivers source synchronization: " + broadcastId);
+ sEventLogger.logd(TAG, "Suspend receivers source synchronization: " + broadcastId);
stopSourceReceivers(broadcastId, true);
}
/** Request all receivers to suspend broadcast sources synchronization */
public void suspendAllReceiversSourceSynchronization() {
- sEventLogger.logd(DBG, TAG, "Suspend all receivers source synchronization");
+ sEventLogger.logd(TAG, "Suspend all receivers source synchronization");
stopSourceReceivers(BassConstants.INVALID_BROADCAST_ID, true);
}
/** Request receivers to stop broadcast sources synchronization and remove them */
public void stopReceiversSourceSynchronization(int broadcastId) {
- sEventLogger.logd(DBG, TAG, "Stop receivers source synchronization: " + broadcastId);
+ sEventLogger.logd(TAG, "Stop receivers source synchronization: " + broadcastId);
stopSourceReceivers(broadcastId, false);
}
/** Request receivers to resume broadcast source synchronization */
public void resumeReceiversSourceSynchronization() {
- sEventLogger.logd(DBG, TAG, "Resume receivers source synchronization");
+ sEventLogger.logd(TAG, "Resume receivers source synchronization");
while (!mPausedBroadcastSinks.isEmpty()) {
BluetoothDevice sink = mPausedBroadcastSinks.remove();
- sEventLogger.logd(DBG, TAG, "Remove broadcast sink from paused cache: " + sink);
+ sEventLogger.logd(TAG, "Remove broadcast sink from paused cache: " + sink);
BluetoothLeBroadcastMetadata metadata = mBroadcastMetadataMap.get(sink);
if (metadata != null) {
@@ -2062,7 +2056,7 @@
}
if (mLocalBroadcastReceivers.remove(broadcastId) != null) {
- sEventLogger.logd(DBG, TAG, "Broadcast ID: " + broadcastId + ", stopped");
+ sEventLogger.logd(TAG, "Broadcast ID: " + broadcastId + ", stopped");
}
break;
case BROADCAST_STATE_CONFIGURING:
@@ -2226,7 +2220,7 @@
}
void notifySearchStarted(int reason) {
- sEventLogger.logd(DBG, TAG, "notifySearchStarted: reason: " + reason);
+ sEventLogger.logd(TAG, "notifySearchStarted: reason: " + reason);
obtainMessage(MSG_SEARCH_STARTED, reason, 0).sendToTarget();
}
@@ -2236,7 +2230,7 @@
}
void notifySearchStopped(int reason) {
- sEventLogger.logd(DBG, TAG, "notifySearchStopped: reason: " + reason);
+ sEventLogger.logd(TAG, "notifySearchStopped: reason: " + reason);
obtainMessage(MSG_SEARCH_STOPPED, reason, 0).sendToTarget();
}
@@ -2247,7 +2241,6 @@
void notifySourceFound(BluetoothLeBroadcastMetadata source) {
sEventLogger.logd(
- DBG,
TAG,
"invokeCallback: MSG_SOURCE_FOUND"
+ ", source: "
@@ -2268,7 +2261,6 @@
sService.localNotifySourceAdded(sink, recvState);
sEventLogger.logd(
- DBG,
TAG,
"notifySourceAdded: "
+ "source: "
@@ -2292,7 +2284,6 @@
void notifySourceModified(BluetoothDevice sink, int sourceId, int reason) {
sEventLogger.logd(
- DBG,
TAG,
"notifySourceModified: "
+ "source: "
@@ -2313,7 +2304,6 @@
void notifySourceRemoved(BluetoothDevice sink, int sourceId, int reason) {
sEventLogger.logd(
- DBG,
TAG,
"notifySourceRemoved: "
+ "source: "
diff --git a/android/app/src/com/android/bluetooth/gatt/ContextMap.java b/android/app/src/com/android/bluetooth/gatt/ContextMap.java
index f8f7ca8..3457ed7 100644
--- a/android/app/src/com/android/bluetooth/gatt/ContextMap.java
+++ b/android/app/src/com/android/bluetooth/gatt/ContextMap.java
@@ -50,7 +50,6 @@
* This class manages application callbacks and keeps track of GATT connections.
* @hide
*/
-@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
public class ContextMap<C, T> {
private static final String TAG = GattServiceConfig.TAG_PREFIX + "ContextMap";
diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java
index 1ef61f3..4f4dab7 100644
--- a/android/app/src/com/android/bluetooth/gatt/GattService.java
+++ b/android/app/src/com/android/bluetooth/gatt/GattService.java
@@ -2880,8 +2880,7 @@
// Check and deliver scan results for different scan clients.
private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults)
throws RemoteException {
- TransitionalScanHelper.ScannerMap.App app =
- mTransitionalScanHelper.getScannerMap().getById(client.scannerId);
+ ContextMap.App app = mTransitionalScanHelper.getScannerMap().getById(client.scannerId);
if (app == null) {
return;
}
@@ -3089,8 +3088,7 @@
}
void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException {
- TransitionalScanHelper.ScannerMap.App app =
- mTransitionalScanHelper.getScannerMap().getById(scannerId);
+ ContextMap.App app = mTransitionalScanHelper.getScannerMap().getById(scannerId);
if (app == null || app.callback == null) {
Log.e(TAG, "Advertise app or callback is null");
return;
@@ -3317,8 +3315,7 @@
scanClient.associatedDevices = getAssociatedDevices(callingPackage);
AppScanStats app = mTransitionalScanHelper.getScannerMap().getAppScanStatsById(scannerId);
- TransitionalScanHelper.ScannerMap.App cbApp =
- mTransitionalScanHelper.getScannerMap().getById(scannerId);
+ ContextMap.App cbApp = mTransitionalScanHelper.getScannerMap().getById(scannerId);
if (app != null) {
scanClient.stats = app;
boolean isFilteredScan = (filters != null) && !filters.isEmpty();
@@ -3370,7 +3367,7 @@
return;
}
- TransitionalScanHelper.ScannerMap.App app =
+ ContextMap.App app =
mTransitionalScanHelper.getScannerMap().add(uuid, null, null, piInfo, this);
app.mUserHandle = UserHandle.getUserHandleForUid(Binder.getCallingUid());
@@ -3479,8 +3476,7 @@
}
PendingIntentInfo pii = new PendingIntentInfo();
pii.intent = intent;
- TransitionalScanHelper.ScannerMap.App app =
- mTransitionalScanHelper.getScannerMap().getByContextInfo(pii);
+ ContextMap.App app = mTransitionalScanHelper.getScannerMap().getByContextInfo(pii);
if (VDBG) {
Log.d(TAG, "stopScan(PendingIntent): app found = " + app);
}
diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java b/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
index e63d83b..38db4dc 100644
--- a/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
+++ b/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
@@ -207,8 +207,11 @@
HeadsetService headsetService, AdapterService adapterService,
HeadsetNativeInterface nativeInterface, HeadsetSystemInterface systemInterface) {
super(TAG, Objects.requireNonNull(looper, "looper cannot be null"));
- // Enable/Disable StateMachine debug logs
- setDbg(DBG);
+
+ // Let the logging framework enforce the log level. TAG is set above in the parent
+ // constructor.
+ setDbg(true);
+
mDevice = Objects.requireNonNull(device, "device cannot be null");
mHeadsetService = Objects.requireNonNull(headsetService, "headsetService cannot be null");
mNativeInterface =
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 36aa3b9..8ccf2ee 100644
--- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java
+++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java
@@ -79,8 +79,7 @@
import com.android.bluetooth.btservice.ServiceFactory;
import com.android.bluetooth.btservice.storage.DatabaseManager;
import com.android.bluetooth.csip.CsipSetCoordinatorService;
-import com.android.bluetooth.flags.FeatureFlags;
-import com.android.bluetooth.flags.FeatureFlagsImpl;
+import com.android.bluetooth.flags.Flags;
import com.android.bluetooth.hap.HapClientService;
import com.android.bluetooth.hfp.HeadsetService;
import com.android.bluetooth.mcp.McpService;
@@ -91,6 +90,7 @@
import com.android.modules.utils.SynchronousResultReceiver;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
@@ -137,6 +137,16 @@
public static final String BLUETOOTH_LE_BROADCAST_FALLBACK_ACTIVE_GROUP_ID =
"bluetooth_le_broadcast_fallback_active_group_id";
+ /**
+ * Per PBP 1.0 4.3. High Quality Public Broadcast Audio, Broadcast HIGH quality audio configs
+ * are with sampling frequency 48khz
+ */
+ private static final BluetoothLeAudioCodecConfig BROADCAST_HIGH_QUALITY_CONFIG =
+ new BluetoothLeAudioCodecConfig.Builder()
+ .setCodecType(BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_LC3)
+ .setSampleRate(BluetoothLeAudioCodecConfig.SAMPLE_RATE_48000)
+ .build();
+
private AdapterService mAdapterService;
private DatabaseManager mDatabaseManager;
private HandlerThread mStateMachinesThread;
@@ -149,7 +159,6 @@
private final ReentrantReadWriteLock mGroupReadWriteLock = new ReentrantReadWriteLock();
private final Lock mGroupReadLock = mGroupReadWriteLock.readLock();
private final Lock mGroupWriteLock = mGroupReadWriteLock.writeLock();
- private FeatureFlags mFeatureFlags;
ServiceFactory mServiceFactory = new ServiceFactory();
LeAudioNativeInterface mLeAudioNativeInterface;
@@ -200,14 +209,12 @@
public LeAudioService(Context ctx) {
super(ctx);
- mFeatureFlags = new FeatureFlagsImpl();
}
@VisibleForTesting
- LeAudioService(Context ctx, LeAudioNativeInterface nativeInterface, FeatureFlags featureFlags) {
+ LeAudioService(Context ctx, LeAudioNativeInterface nativeInterface) {
super(ctx);
mLeAudioNativeInterface = nativeInterface;
- mFeatureFlags = featureFlags;
}
private class LeAudioGroupDescriptor {
@@ -467,7 +474,7 @@
sm.cleanup();
}
} finally {
- if (mFeatureFlags.leaudioApiSynchronizedBlockFix()) {
+ if (Flags.leaudioApiSynchronizedBlockFix()) {
// Upgrade to write lock
groupMutexUnlock(/* isReadOnly */ true);
groupMutexLock(/* isReadOnly */ false);
@@ -556,11 +563,6 @@
sLeAudioService = instance;
}
- @VisibleForTesting
- void setFeatureFlags(FeatureFlags featureFlags) {
- mFeatureFlags = featureFlags;
- }
-
VolumeControlService getVolumeControlService() {
if (mVolumeControlService == null) {
mVolumeControlService = mServiceFactory.getVolumeControlService();
@@ -650,7 +652,7 @@
return false;
}
- if (!mFeatureFlags.leaudioApiSynchronizedBlockFix()) {
+ if (!Flags.leaudioApiSynchronizedBlockFix()) {
sm.sendMessage(LeAudioStateMachine.CONNECT);
}
@@ -658,7 +660,7 @@
groupMutexUnlock(/* isReadOnly */ false);
}
- if (mFeatureFlags.leaudioApiSynchronizedBlockFix()) {
+ if (Flags.leaudioApiSynchronizedBlockFix()) {
sm.sendMessage(LeAudioStateMachine.CONNECT);
}
@@ -707,7 +709,7 @@
* @return true if profile disconnected, false if device not connected over LE Audio
*/
public boolean disconnect(BluetoothDevice device) {
- if (mFeatureFlags.leaudioApiSynchronizedBlockFix()) {
+ if (Flags.leaudioApiSynchronizedBlockFix()) {
return disconnectV2(device);
}
@@ -995,7 +997,7 @@
Log.i(TAG, "Unicast group is active, queueing Broadcast creation, while the Unicast"
+ " group is deactivated.");
mCreateBroadcastQueue.add(broadcastSettings);
- if (mFeatureFlags.leaudioBroadcastAudioHandoverPolicies()) {
+ if (Flags.leaudioBroadcastAudioHandoverPolicies()) {
mLeAudioNativeInterface.setUnicastMonitorMode(LeAudioStackEvent.DIRECTION_SINK,
true);
}
@@ -1026,16 +1028,52 @@
Log.i(TAG, "createBroadcast: isEncrypted=" + (isEncrypted ? "true" : "false"));
mAwaitingBroadcastCreateResponse = true;
- mLeAudioBroadcasterNativeInterface.createBroadcast(broadcastSettings.isPublicBroadcast(),
- broadcastSettings.getBroadcastName(), broadcastCode,
+ mLeAudioBroadcasterNativeInterface.createBroadcast(
+ broadcastSettings.isPublicBroadcast(),
+ broadcastSettings.getBroadcastName(),
+ broadcastCode,
publicMetadata == null ? null : publicMetadata.getRawMetadata(),
- settingsList.stream()
- .mapToInt(s -> s.getPreferredQuality()).toArray(),
+ getBroadcastAudioQualityPerSinkCapabilities(settingsList),
settingsList.stream()
.map(s -> s.getContentMetadata().getRawMetadata())
.toArray(byte[][]::new));
}
+ private int[] getBroadcastAudioQualityPerSinkCapabilities(
+ List<BluetoothLeBroadcastSubgroupSettings> settingsList) {
+ int[] preferredQualityArray =
+ settingsList.stream().mapToInt(s -> s.getPreferredQuality()).toArray();
+
+ BassClientService bassClientService = getBassClientService();
+ if (bassClientService == null) {
+ return preferredQualityArray;
+ }
+
+ for (BluetoothDevice sink : bassClientService.getConnectedDevices()) {
+ int groupId = getGroupId(sink);
+ if (groupId == LE_AUDIO_GROUP_ID_INVALID) {
+ continue;
+ }
+
+ BluetoothLeAudioCodecStatus codecStatus = getCodecStatus(groupId);
+ if (codecStatus != null
+ && !codecStatus.isInputCodecConfigSelectable(BROADCAST_HIGH_QUALITY_CONFIG)) {
+ // If any sink device does not support high quality audio config,
+ // set all subgroup audio quality to standard quality for now before multi codec
+ // config support is ready
+ Log.i(
+ TAG,
+ "Sink device doesn't support HIGH broadcast audio quality, use STANDARD"
+ + " quality");
+ Arrays.fill(
+ preferredQualityArray,
+ BluetoothLeBroadcastSubgroupSettings.QUALITY_STANDARD);
+ break;
+ }
+ }
+ return preferredQualityArray;
+ }
+
/**
* Start LeAudio Broadcast instance.
* @param broadcastId broadcast instance identifier
@@ -1150,7 +1188,7 @@
}
if (DBG) Log.d(TAG, "destroyBroadcast");
- if (mFeatureFlags.leaudioBroadcastAudioHandoverPolicies()) {
+ if (Flags.leaudioBroadcastAudioHandoverPolicies()) {
mLeAudioNativeInterface.setUnicastMonitorMode(LeAudioStackEvent.DIRECTION_SINK, false);
}
mLeAudioBroadcasterNativeInterface.destroyBroadcast(broadcastId);
@@ -1766,8 +1804,7 @@
if (notifyAndUpdateInactiveOutDeviceOnly
&& ((newSupportedAudioDirections & AUDIO_DIRECTION_INPUT_BIT) != 0)) {
newInDevice = getLeadDeviceForTheGroup(groupId);
- } else if (mFeatureFlags.leaudioBroadcastAudioHandoverPolicies()
- && wasSetSinkListeningMode()) {
+ } else if (Flags.leaudioBroadcastAudioHandoverPolicies() && wasSetSinkListeningMode()) {
mLeAudioNativeInterface.setUnicastMonitorMode(LeAudioStackEvent.DIRECTION_SINK,
false);
}
@@ -1970,7 +2007,7 @@
return false;
}
- if (!mFeatureFlags.audioRoutingCentralization()) {
+ if (!Flags.audioRoutingCentralization()) {
// If AUDIO_ROUTING_CENTRALIZATION, this will be checked inside AudioRoutingManager.
if (Utils.isDualModeAudioEnabled()) {
if (!mAdapterService.isAllSupportedClassicAudioProfilesActive(device)) {
@@ -2176,7 +2213,7 @@
1);
break;
case LeAudioStackEvent.HEALTH_RECOMMENDATION_ACTION_INACTIVATE_GROUP:
- if (mFeatureFlags.leaudioUnicastInactivateDeviceBasedOnContext()) {
+ if (Flags.leaudioUnicastInactivateDeviceBasedOnContext()) {
LeAudioGroupDescriptor groupDescriptor = getGroupDescriptor(groupId);
if (groupDescriptor != null && groupDescriptor.mIsActive) {
Log.i(
@@ -2230,7 +2267,7 @@
*/
boolean leaveConnectedInputDevice = false;
Integer newDirections = AUDIO_DIRECTION_NONE;
- if (mFeatureFlags.leaudioBroadcastAudioHandoverPolicies()
+ if (Flags.leaudioBroadcastAudioHandoverPolicies()
&& (!mCreateBroadcastQueue.isEmpty()
|| mBroadcastIdDeactivatedForUnicastTransition.isPresent())) {
leaveConnectedInputDevice = true;
@@ -2928,7 +2965,7 @@
}
// Notify broadcast assistant
- if (mFeatureFlags.leaudioBroadcastAudioHandoverPolicies()) {
+ if (Flags.leaudioBroadcastAudioHandoverPolicies()) {
if (bassClientService != null) {
bassClientService.notifyBroadcastStateChanged(descriptor.mState, broadcastId);
}
@@ -2988,11 +3025,7 @@
sm =
LeAudioStateMachine.make(
- device,
- this,
- mLeAudioNativeInterface,
- mStateMachinesThread.getLooper(),
- mFeatureFlags);
+ device, this, mLeAudioNativeInterface, mStateMachinesThread.getLooper());
descriptor.mStateMachine = sm;
return sm;
}
@@ -3049,14 +3082,14 @@
}
} finally {
// Reduce size of critical section when this feature is enabled
- if (mFeatureFlags.leaudioApiSynchronizedBlockFix()) {
+ if (Flags.leaudioApiSynchronizedBlockFix()) {
groupMutexUnlock(/* isReadOnly */ true);
}
}
removeStateMachine(device);
removeAuthorizationInfoForRelatedProfiles(device);
} finally {
- if (!mFeatureFlags.leaudioApiSynchronizedBlockFix()) {
+ if (!Flags.leaudioApiSynchronizedBlockFix()) {
groupMutexUnlock(/* isReadOnly */ true);
}
}
@@ -3086,7 +3119,7 @@
sm.cleanup();
descriptor.mStateMachine = null;
} finally {
- if (mFeatureFlags.leaudioApiSynchronizedBlockFix()) {
+ if (Flags.leaudioApiSynchronizedBlockFix()) {
// Upgrade to write lock
groupMutexUnlock(/* isReadOnly */ true);
groupMutexLock(/* isReadOnly */ false);
@@ -3232,7 +3265,7 @@
* Process a change for disconnection of a device.
*/
public synchronized void deviceDisconnected(BluetoothDevice device, boolean hasFallbackDevice) {
- if (mFeatureFlags.leaudioApiSynchronizedBlockFix()) {
+ if (Flags.leaudioApiSynchronizedBlockFix()) {
deviceDisconnectedV2(device, hasFallbackDevice);
return;
}
@@ -3388,8 +3421,7 @@
}
/* For setting inCall mode */
- if (mFeatureFlags.leaudioBroadcastAudioHandoverPolicies() && inCall
- && !areBroadcastsAllStopped()) {
+ if (Flags.leaudioBroadcastAudioHandoverPolicies() && inCall && !areBroadcastsAllStopped()) {
mQueuedInCallValue = Optional.of(true);
/* Request activation of unicast group */
@@ -3402,7 +3434,8 @@
mLeAudioNativeInterface.setInCall(inCall);
/* For clearing inCall mode */
- if (mFeatureFlags.leaudioBroadcastAudioHandoverPolicies() && !inCall
+ if (Flags.leaudioBroadcastAudioHandoverPolicies()
+ && !inCall
&& mBroadcastIdDeactivatedForUnicastTransition.isPresent()) {
handleUnicastStreamStatusChange(
LeAudioStackEvent.DIRECTION_SINK,
@@ -3640,7 +3673,7 @@
}
void removeAuthorizationInfoForRelatedProfiles(BluetoothDevice device) {
- if (!mFeatureFlags.leaudioMcsTbsAuthorizationRebondFix()) {
+ if (!Flags.leaudioMcsTbsAuthorizationRebondFix()) {
Log.i(TAG, "leaudio_mcs_tbs_authorization_rebond_fix is disabled");
return;
}
@@ -3678,7 +3711,7 @@
return;
}
} finally {
- if (!mFeatureFlags.leaudioApiSynchronizedBlockFix()) {
+ if (!Flags.leaudioApiSynchronizedBlockFix()) {
// Keep previous behavior where a lock is released and acquired immediately
groupMutexUnlock(/* isReadOnly */ true);
groupMutexLock(/* isReadOnly */ true);
@@ -3821,7 +3854,7 @@
|| Objects.equals(device, mActiveAudioInDevice)) {
handleGroupTransitToInactive(groupId);
}
- if (!mFeatureFlags.leaudioApiSynchronizedBlockFix()) {
+ if (!Flags.leaudioApiSynchronizedBlockFix()) {
mGroupDescriptors.remove(groupId);
}
@@ -3834,7 +3867,7 @@
groupMutexUnlock(/* isReadOnly */ true);
}
- if (isGroupEmpty && mFeatureFlags.leaudioApiSynchronizedBlockFix()) {
+ if (isGroupEmpty && Flags.leaudioApiSynchronizedBlockFix()) {
groupMutexLock(/* isReadOnly */ false);
try {
mGroupDescriptors.remove(groupId);
@@ -4366,7 +4399,7 @@
Objects.requireNonNull(receiver, "receiver cannot be null");
LeAudioService service = getService(source);
if (service != null) {
- if (service.mFeatureFlags.audioRoutingCentralization()) {
+ if (Flags.audioRoutingCentralization()) {
((AudioRoutingManager) service.mAdapterService.getActiveDeviceManager())
.activateDeviceProfile(device, BluetoothProfile.LE_AUDIO, receiver);
} else {
@@ -4977,7 +5010,7 @@
}
private void groupMutexLock(boolean isReadOnly) {
- if (mFeatureFlags.leaudioApiSynchronizedBlockFix()) {
+ if (Flags.leaudioApiSynchronizedBlockFix()) {
if (isReadOnly) {
mGroupReadLock.lock();
} else {
@@ -4989,7 +5022,7 @@
}
private void groupMutexUnlock(boolean isReadOnly) {
- if (mFeatureFlags.leaudioApiSynchronizedBlockFix()) {
+ if (Flags.leaudioApiSynchronizedBlockFix()) {
if (isReadOnly) {
mGroupReadLock.unlock();
} else {
diff --git a/android/app/src/com/android/bluetooth/le_audio/LeAudioStateMachine.java b/android/app/src/com/android/bluetooth/le_audio/LeAudioStateMachine.java
index d7939a3..f9a240d 100644
--- a/android/app/src/com/android/bluetooth/le_audio/LeAudioStateMachine.java
+++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioStateMachine.java
@@ -53,7 +53,7 @@
import android.util.Log;
import com.android.bluetooth.btservice.ProfileService;
-import com.android.bluetooth.flags.FeatureFlags;
+import com.android.bluetooth.flags.Flags;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
@@ -88,19 +88,16 @@
private LeAudioNativeInterface mNativeInterface;
private final BluetoothDevice mDevice;
- private final FeatureFlags mFeatureFlags;
LeAudioStateMachine(
BluetoothDevice device,
LeAudioService svc,
LeAudioNativeInterface nativeInterface,
- Looper looper,
- FeatureFlags featureFlags) {
+ Looper looper) {
super(TAG, looper);
mDevice = device;
mService = svc;
mNativeInterface = nativeInterface;
- mFeatureFlags = featureFlags;
mDisconnected = new Disconnected();
mConnecting = new Connecting();
@@ -119,11 +116,10 @@
BluetoothDevice device,
LeAudioService svc,
LeAudioNativeInterface nativeInterface,
- Looper looper,
- FeatureFlags featureFlags) {
+ Looper looper) {
Log.i(TAG, "make for device");
LeAudioStateMachine LeAudioSm =
- new LeAudioStateMachine(device, svc, nativeInterface, looper, featureFlags);
+ new LeAudioStateMachine(device, svc, nativeInterface, looper);
LeAudioSm.start();
return LeAudioSm;
}
@@ -151,7 +147,7 @@
// Don't broadcast during startup
broadcastConnectionState(BluetoothProfile.STATE_DISCONNECTED,
mLastConnectionState);
- if (mFeatureFlags.audioRoutingCentralization()) {
+ if (Flags.audioRoutingCentralization()) {
mService.deviceDisconnected(mDevice, false);
}
}
@@ -441,7 +437,7 @@
+ messageWhatToString(getCurrentMessage().what));
mConnectionState = BluetoothProfile.STATE_CONNECTED;
removeDeferredMessages(CONNECT);
- if (mFeatureFlags.audioRoutingCentralization()) {
+ if (Flags.audioRoutingCentralization()) {
mService.deviceConnected(mDevice);
}
broadcastConnectionState(BluetoothProfile.STATE_CONNECTED, mLastConnectionState);
diff --git a/android/app/src/com/android/bluetooth/mcp/MediaControlGattService.java b/android/app/src/com/android/bluetooth/mcp/MediaControlGattService.java
index 5e9d792..36c46bc 100644
--- a/android/app/src/com/android/bluetooth/mcp/MediaControlGattService.java
+++ b/android/app/src/com/android/bluetooth/mcp/MediaControlGattService.java
@@ -608,7 +608,6 @@
? op.mDescriptor.getCharacteristic().getUuid()
: null));
mEventLogger.logd(
- DBG,
TAG,
"onAuthorizedGattOperation: device= "
+ device
@@ -800,7 +799,6 @@
for (BluetoothDevice device : mAdapterService.getBondedDevices()) {
List<ParcelUuid> uuidList = mMcpService.getNotificationSubscriptions(mCcid, device);
mEventLogger.logd(
- DBG,
TAG,
"restoreCccValuesForStoredDevices: device= "
+ device
@@ -810,7 +808,6 @@
/* Restore CCCD values for device */
for (ParcelUuid uuid : uuidList) {
mEventLogger.logd(
- DBG,
TAG,
"restoreCccValuesForStoredDevices: device= " + device + ", char= " + uuid);
setCcc(device, uuid.getUuid(), 0,
@@ -1026,7 +1023,7 @@
}
private void setInitialCharacteristicValues(boolean notify) {
- mEventLogger.logd(DBG, TAG, "setInitialCharacteristicValues");
+ mEventLogger.logd(TAG, "setInitialCharacteristicValues");
updateMediaStateChar(mCurrentMediaState.getValue());
updatePlayerNameChar("", notify);
updatePlayerIconUrlChar("");
@@ -1216,7 +1213,6 @@
Request req = new Request(opcode, intVal);
mEventLogger.logd(
- DBG,
TAG,
"handleMediaControlPointRequest: sending "
+ Request.Opcodes.toString(opcode)
@@ -1262,7 +1258,7 @@
}
private boolean initGattService(UUID serviceUuid) {
- mEventLogger.logd(DBG, TAG, "initGattService: uuid= " + serviceUuid);
+ mEventLogger.logd(TAG, "initGattService: uuid= " + serviceUuid);
if (mBluetoothGattServer == null) {
BluetoothManager manager = mContext.getSystemService(BluetoothManager.class);
@@ -1334,10 +1330,10 @@
}
if (Arrays.equals(value, BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)) {
- mEventLogger.logd(DBG, TAG, "setCcc: device= " + device + ", notify: " + true);
+ mEventLogger.logd(TAG, "setCcc: device= " + device + ", notify: " + true);
mMcpService.setNotificationSubscription(mCcid, device, new ParcelUuid(charUuid), true);
} else if (Arrays.equals(value, BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE)) {
- mEventLogger.logd(DBG, TAG, "setCcc: device= " + device + ", notify: " + false);
+ mEventLogger.logd(TAG, "setCcc: device= " + device + ", notify: " + false);
mMcpService.setNotificationSubscription(mCcid, device, new ParcelUuid(charUuid), false);
} else {
mEventLogger.loge(TAG, "Not handled CCC value: " + Arrays.toString(value));
@@ -1391,7 +1387,7 @@
if (!isFeatureSupported(ServiceFeature.MEDIA_STATE)) return;
- mEventLogger.logd(DBG, TAG, "updateMediaStateChar: state= " + MediaState.toString(state));
+ mEventLogger.logd(TAG, "updateMediaStateChar: state= " + MediaState.toString(state));
BluetoothGattCharacteristic stateChar =
mCharacteristics.get(CharId.MEDIA_STATE);
@@ -1408,7 +1404,6 @@
if (!isFeatureSupported(feature)) return;
mEventLogger.logd(
- DBG,
TAG,
"updateObjectIdChar: charId= "
+ CharId.FromFeature(feature)
@@ -1625,7 +1620,6 @@
public void onDeviceAuthorizationSet(BluetoothDevice device) {
int auth = getDeviceAuthorization(device);
mEventLogger.logd(
- DBG,
TAG,
"onDeviceAuthorizationSet: device= "
+ device
@@ -1684,7 +1678,7 @@
if (notify && isFeatureSupported(ServiceFeature.PLAYING_ORDER_NOTIFY)) {
notifyCharacteristic(orderChar, null);
}
- mEventLogger.logd(DBG, TAG, "updatePlayingOrderChar: order= " + order);
+ mEventLogger.logd(TAG, "updatePlayingOrderChar: order= " + order);
}
}
@@ -1774,7 +1768,6 @@
notifyCharacteristic(characteristic, null);
}
mEventLogger.logd(
- DBG,
TAG,
"updateSeekingSpeedChar: intSpeed=" + intSpeed + ", speed= " + speed);
}
@@ -1815,7 +1808,6 @@
notifyCharacteristic(characteristic, null);
}
mEventLogger.logd(
- DBG,
TAG,
"updatePlaybackSpeedChar: intSpeed=" + intSpeed + ", speed= " + speed);
}
@@ -1847,7 +1839,6 @@
}
}
mEventLogger.logd(
- DBG,
TAG,
"updateTrackPositionChar: positionMs= " + positionMs + ", position= " + position);
}
@@ -1883,7 +1874,6 @@
notifyCharacteristic(characteristic, null);
}
mEventLogger.logd(
- DBG,
TAG,
"updateTrackDurationChar: durationMs= "
+ durationMs
@@ -1916,7 +1906,7 @@
if (notify && isFeatureSupported(ServiceFeature.TRACK_TITLE_NOTIFY)) {
notifyCharacteristic(characteristic, null);
}
- mEventLogger.logd(DBG, TAG, "updateTrackTitleChar: title= '" + title + "'");
+ mEventLogger.logd(TAG, "updateTrackTitleChar: title= '" + title + "'");
}
}
@@ -1945,7 +1935,6 @@
notifyCharacteristic(characteristic, null);
}
mEventLogger.logd(
- DBG,
TAG,
"updateSupportedOpcodesChar: opcodes= "
+ Request.SupportedOpcodes.toString(opcodes));
@@ -1959,15 +1948,13 @@
if (isFeatureSupported(ServiceFeature.PLAYING_ORDER_SUPPORTED)) {
mCharacteristics.get(CharId.PLAYING_ORDER_SUPPORTED)
.setValue(supportedOrder, BluetoothGattCharacteristic.FORMAT_UINT16, 0);
- mEventLogger.logd(
- DBG, TAG, "updatePlayingOrderSupportedChar: order= " + supportedOrder);
+ mEventLogger.logd(TAG, "updatePlayingOrderSupportedChar: order= " + supportedOrder);
}
}
private void updateIconObjIdChar(Long objId) {
if (isFeatureSupported(ServiceFeature.PLAYER_ICON_OBJ_ID)) {
mEventLogger.logd(
- DBG,
TAG,
"updateObjectIdChar charId= "
+ CharId.PLAYER_ICON_OBJ_ID
@@ -2017,7 +2004,7 @@
}
if (isFeatureSupported(ServiceFeature.PLAYER_ICON_URL)) {
mCharacteristics.get(CharId.PLAYER_ICON_URL).setValue(url);
- mEventLogger.logd(DBG, TAG, "updatePlayerIconUrlChar: " + url);
+ mEventLogger.logd(TAG, "updatePlayerIconUrlChar: " + url);
}
}
@@ -2042,7 +2029,7 @@
BluetoothGattCharacteristic characteristic =
mCharacteristics.get(CharId.PLAYER_NAME);
characteristic.setValue(name);
- mEventLogger.logd(DBG, TAG, "updatePlayerNameChar: name= '" + name + "'");
+ mEventLogger.logd(TAG, "updatePlayerNameChar: name= '" + name + "'");
if (notify && isFeatureSupported(ServiceFeature.PLAYER_NAME_NOTIFY)) {
notifyCharacteristic(characteristic, null);
}
diff --git a/android/app/src/com/android/bluetooth/mcp/MediaControlProfile.java b/android/app/src/com/android/bluetooth/mcp/MediaControlProfile.java
index c88b72c..6c7219e 100644
--- a/android/app/src/com/android/bluetooth/mcp/MediaControlProfile.java
+++ b/android/app/src/com/android/bluetooth/mcp/MediaControlProfile.java
@@ -114,7 +114,6 @@
if (metadata || state || queue) {
mEventLogger.logd(
- DBG,
TAG,
"onMediaUpdated: track_changed="
+ metadata
@@ -134,7 +133,6 @@
@Override
public void run(boolean availablePlayers, boolean addressedPlayers, boolean uids) {
mEventLogger.logd(
- DBG,
TAG,
"onFolderUpdated: available_players= "
+ availablePlayers
@@ -200,7 +198,6 @@
}
mEventLogger.logd(
- DBG,
TAG,
"onCurrentPlayerStateUpdated state= "
+ playback_state
@@ -220,7 +217,6 @@
if (metadataChanged) {
if (mCurrentData.metadata != null) {
mEventLogger.logd(
- DBG,
TAG,
"onCurrentPlayerStateUpdated metadata: title= '"
+ mCurrentData.metadata.title
@@ -288,13 +284,13 @@
@Override
public void onServiceInstanceRegistered(ServiceStatus status,
MediaControlGattServiceInterface service) {
- mEventLogger.logd(DBG, TAG, "onServiceInstanceRegistered: status= " + status);
+ mEventLogger.logd(TAG, "onServiceInstanceRegistered: status= " + status);
mGMcsService = service;
}
@Override
public void onServiceInstanceUnregistered(ServiceStatus status) {
- mEventLogger.logd(DBG, TAG, "onServiceInstanceUnregistered: status= " + status);
+ mEventLogger.logd(TAG, "onServiceInstanceUnregistered: status= " + status);
mGMcsService = null;
}
@@ -345,13 +341,13 @@
@Override
public long onGetCurrentTrackPosition() {
- mEventLogger.logd(DBG, TAG, "getCurrentTrackPosition");
+ mEventLogger.logd(TAG, "getCurrentTrackPosition");
return getLatestTrackPosition();
}
@Override
public void onTrackPositionSetRequest(long position) {
- mEventLogger.logd(DBG, TAG, "GMCS onTrackPositionSetRequest");
+ mEventLogger.logd(TAG, "GMCS onTrackPositionSetRequest");
if (mMediaPlayerList.getActivePlayer() == null) return;
if ((getCurrentPlayerSupportedActions() & PlaybackState.ACTION_SEEK_TO) != 0) {
@@ -369,40 +365,39 @@
@Override
public void onCurrentTrackMetadataRequest() {
- mEventLogger.logd(DBG, TAG, "GMCS onCurrentTrackMetadataRequest");
+ mEventLogger.logd(TAG, "GMCS onCurrentTrackMetadataRequest");
// FIXME: Seems to be not used right now
}
@Override
public void onPlayingOrderSetRequest(int order) {
- mEventLogger.logd(DBG, TAG, "GMCS onPlayingOrderSetRequest");
+ mEventLogger.logd(TAG, "GMCS onPlayingOrderSetRequest");
// Notice: MediaPlayerWrapper does not support play order control.
// Ignore the request for now.
}
@Override
public void onPlaybackSpeedSetRequest(float speed) {
- mEventLogger.logd(DBG, TAG, "GMCS onPlaybackSpeedSetRequest");
+ mEventLogger.logd(TAG, "GMCS onPlaybackSpeedSetRequest");
if (mMediaPlayerList.getActivePlayer() == null) return;
mMediaPlayerList.getActivePlayer().setPlaybackSpeed(speed);
}
@Override
public void onSetObjectIdRequest(int objField, long objectId) {
- mEventLogger.logd(DBG, TAG, "GMCS onSetObjectIdRequest");
+ mEventLogger.logd(TAG, "GMCS onSetObjectIdRequest");
// TODO: Implement once we have the Object Transfer Service
}
@Override
public void onSearchRequest(SearchRequest request) {
- mEventLogger.logd(DBG, TAG, "GMCS onSearchRequest");
+ mEventLogger.logd(TAG, "GMCS onSearchRequest");
// TODO: Implement once we have the Object Transfer Service
}
@Override
public void onMediaControlRequest(Request request) {
mEventLogger.logd(
- DBG,
TAG,
"GMCS onMediaControlRequest: opcode= "
+ Request.Opcodes.toString(request.getOpcode()));
@@ -655,7 +650,6 @@
getCurrentPlayerSupportedActions());
handled_request_map.put(settings_field, opcodes);
mEventLogger.logd(
- DBG,
TAG,
"updateSupportedOpcodes setting supported opcodes to: "
+ opcodes);
@@ -763,7 +757,6 @@
boolean isGenericMcs = appToken.equals(mContext.getPackageName());
mEventLogger.logd(
- DBG,
TAG,
"Register MediaControlGattService instance ccid= "
+ ccid
@@ -839,7 +832,7 @@
private final Map<String, MediaControlGattServiceInterface> mServiceMap;
public void unregisterServiceInstance(String appToken) {
- mEventLogger.logd(DBG, TAG, "unregisterServiceInstance");
+ mEventLogger.logd(TAG, "unregisterServiceInstance");
synchronized (mServiceMap) {
MediaControlGattServiceInterface service = mServiceMap.get(appToken);
diff --git a/android/app/src/com/android/bluetooth/tbs/TbsGatt.java b/android/app/src/com/android/bluetooth/tbs/TbsGatt.java
index 50b5f64..9ecefaf 100644
--- a/android/app/src/com/android/bluetooth/tbs/TbsGatt.java
+++ b/android/app/src/com/android/bluetooth/tbs/TbsGatt.java
@@ -1197,7 +1197,7 @@
UUID charUuid = (op.mCharacteristic != null ? op.mCharacteristic.getUuid()
: (op.mDescriptor != null ? op.mDescriptor.getCharacteristic().getUuid() : null));
- mEventLogger.logd(DBG, TAG, "onAuthorizedGattOperation device: " + device
+ mEventLogger.logd(TAG, "onAuthorizedGattOperation device: " + device
+ ", opcode= " + op.mOperation
+ ", characteristic= "
+ (charUuid != null ? tbsUuidToString(charUuid) : "UNKNOWN"));
@@ -1362,7 +1362,7 @@
*/
public void onDeviceAuthorizationSet(BluetoothDevice device) {
int auth = getDeviceAuthorization(device);
- mEventLogger.logd(DBG, TAG, "onDeviceAuthorizationSet: device= " + device
+ mEventLogger.logd(TAG, "onDeviceAuthorizationSet: device= " + device
+ ", authorization= " + (auth == BluetoothDevice.ACCESS_ALLOWED ? "ALLOWED"
: (auth == BluetoothDevice.ACCESS_REJECTED ? "REJECTED" : "UNKNOWN")));
processPendingGattOperations(device);
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java
index a8acf74..cc51199 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java
@@ -116,8 +116,8 @@
MockitoAnnotations.initMocks(this);
TestUtils.setAdapterService(mAdapterService);
// Stub system interface
- when(mSystemInterface.getHeadsetPhoneState()).thenReturn(mPhoneState);
- when(mSystemInterface.getAudioManager()).thenReturn(mAudioManager);
+ doReturn(mPhoneState).when(mSystemInterface).getHeadsetPhoneState();
+ doReturn(mAudioManager).when(mSystemInterface).getAudioManager();
// This line must be called to make sure relevant objects are initialized properly
mAdapter = BluetoothAdapter.getDefaultAdapter();
// Get a device for testing
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java
index f1ec210..f95bd87 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java
@@ -1356,9 +1356,9 @@
@Test
public void testProcessConnectMessage_onConnectingState() {
initToConnectingState();
- mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT);
assertThat(mHeadsetClientStateMachine.doesSuperHaveDeferredMessages(
HeadsetClientStateMachine.CONNECT)).isFalse();
+ mHeadsetClientStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT);
TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
Assert.assertTrue(mHeadsetClientStateMachine.doesSuperHaveDeferredMessages(
HeadsetClientStateMachine.CONNECT));
diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBinderTest.java
index ad13645..d7f7d41 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBinderTest.java
@@ -35,6 +35,7 @@
import android.content.AttributionSource;
import android.os.ParcelUuid;
import android.os.RemoteCallbackList;
+import android.platform.test.flag.junit.SetFlagsRule;
import androidx.test.InstrumentationRegistry;
@@ -42,12 +43,12 @@
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.AudioRoutingManager;
import com.android.bluetooth.btservice.storage.DatabaseManager;
-import com.android.bluetooth.flags.FakeFeatureFlagsImpl;
import com.android.bluetooth.flags.Flags;
import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiver;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
@@ -58,8 +59,9 @@
public class LeAudioBinderTest {
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
private LeAudioService mLeAudioService;
- private FakeFeatureFlagsImpl mFakeFlagsImpl;
@Mock private AdapterService mAdapterService;
@Mock private LeAudioNativeInterface mNativeInterface;
@Mock private DatabaseManager mDatabaseManager;
@@ -83,15 +85,10 @@
doReturn(mDatabaseManager).when(mAdapterService).getDatabase();
doReturn(mAudioRoutingManager).when(mAdapterService).getActiveDeviceManager();
- mFakeFlagsImpl = new FakeFeatureFlagsImpl();
- mFakeFlagsImpl.setFlag(Flags.FLAG_LEAUDIO_API_SYNCHRONIZED_BLOCK_FIX, false);
-
mLeAudioService =
spy(
new LeAudioService(
- InstrumentationRegistry.getTargetContext(),
- mNativeInterface,
- mFakeFlagsImpl));
+ InstrumentationRegistry.getTargetContext(), mNativeInterface));
mLeAudioService.start();
mAdapter = BluetoothAdapter.getDefaultAdapter();
mBinder = new LeAudioService.BluetoothLeAudioBinder(mLeAudioService);
@@ -173,12 +170,12 @@
BluetoothDevice device = TestUtils.getTestDevice(mAdapter, 0);
AttributionSource source = new AttributionSource.Builder(0).build();
- mFakeFlagsImpl.setFlag(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION, false);
+ mSetFlagsRule.disableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION);
SynchronousResultReceiver<Boolean> recv = SynchronousResultReceiver.get();
mBinder.setActiveDevice(device, source, recv);
verify(mLeAudioService).setActiveDevice(device);
- mFakeFlagsImpl.setFlag(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION, true);
+ mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION);
recv = SynchronousResultReceiver.get();
mBinder.setActiveDevice(device, source, recv);
verify(mAudioRoutingManager).activateDeviceProfile(device, BluetoothProfile.LE_AUDIO, recv);
@@ -188,12 +185,12 @@
public void setActiveDevice_withNullDevice_callsRemoveActiveDevice() {
AttributionSource source = new AttributionSource.Builder(0).build();
- mFakeFlagsImpl.setFlag(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION, false);
+ mSetFlagsRule.disableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION);
SynchronousResultReceiver<Boolean> recv = SynchronousResultReceiver.get();
mBinder.setActiveDevice(null, source, recv);
verify(mLeAudioService).removeActiveDevice(true);
- mFakeFlagsImpl.setFlag(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION, true);
+ mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION);
recv = SynchronousResultReceiver.get();
mBinder.setActiveDevice(null, source, recv);
verify(mAudioRoutingManager).activateDeviceProfile(null, BluetoothProfile.LE_AUDIO, recv);
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 81d19db..8525f72 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
@@ -30,21 +30,24 @@
import android.media.AudioManager;
import android.os.Looper;
import android.os.ParcelUuid;
+import android.platform.test.flag.junit.SetFlagsRule;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.bluetooth.TestUtils;
+import com.android.bluetooth.bass_client.BassClientService;
import com.android.bluetooth.btservice.ActiveDeviceManager;
import com.android.bluetooth.btservice.AdapterService;
+import com.android.bluetooth.btservice.ServiceFactory;
import com.android.bluetooth.btservice.storage.DatabaseManager;
-import com.android.bluetooth.flags.FakeFeatureFlagsImpl;
import com.android.bluetooth.flags.Flags;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -59,6 +62,9 @@
@RunWith(AndroidJUnit4.class)
public class LeAudioBroadcastServiceTest {
private static final int TIMEOUT_MS = 1000;
+
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
private BluetoothAdapter mAdapter;
private BluetoothDevice mDevice;
private Context mTargetContext;
@@ -75,7 +81,9 @@
@Mock private LeAudioBroadcasterNativeInterface mLeAudioBroadcasterNativeInterface;
@Mock private LeAudioNativeInterface mLeAudioNativeInterface;
@Mock private LeAudioTmapGattServer mTmapGattServer;
+ @Mock private BassClientService mBassClientService;
@Spy private LeAudioObjectsFactory mObjectsFactory = LeAudioObjectsFactory.getInstance();
+ @Spy private ServiceFactory mServiceFactory = new ServiceFactory();
private static final String TEST_MAC_ADDRESS = "00:11:22:33:44:55";
private static final int TEST_BROADCAST_ID = 42;
@@ -96,6 +104,27 @@
private static final String TEST_LANGUAGE = "deu";
private static final String TEST_BROADCAST_NAME = "Name Test";
+ private static final BluetoothLeAudioCodecConfig LC3_16KHZ_CONFIG =
+ new BluetoothLeAudioCodecConfig.Builder()
+ .setCodecType(BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_LC3)
+ .setSampleRate(BluetoothLeAudioCodecConfig.SAMPLE_RATE_16000)
+ .build();
+ private static final BluetoothLeAudioCodecConfig LC3_48KHZ_CONFIG =
+ new BluetoothLeAudioCodecConfig.Builder()
+ .setCodecType(BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_LC3)
+ .setSampleRate(BluetoothLeAudioCodecConfig.SAMPLE_RATE_48000)
+ .build();
+
+ private static final List<BluetoothLeAudioCodecConfig> INPUT_SELECTABLE_CONFIG_STANDARD =
+ List.of(LC3_16KHZ_CONFIG);
+ private static final List<BluetoothLeAudioCodecConfig> OUTPUT_SELECTABLE_CONFIG_STANDARD =
+ List.of(LC3_16KHZ_CONFIG);
+
+ private static final List<BluetoothLeAudioCodecConfig> INPUT_SELECTABLE_CONFIG_HIGH =
+ List.of(LC3_48KHZ_CONFIG);
+ private static final List<BluetoothLeAudioCodecConfig> OUTPUT_SELECTABLE_CONFIG_HIGH =
+ List.of(LC3_48KHZ_CONFIG);
+
private boolean mOnBroadcastStartedCalled = false;
private boolean mOnBroadcastStartFailedCalled = false;
private boolean mOnBroadcastStoppedCalled = false;
@@ -106,7 +135,6 @@
private boolean mOnBroadcastUpdateFailedCalled = false;
private boolean mOnBroadcastMetadataChangedCalled = false;
private int mOnBroadcastStartFailedReason = BluetoothStatusCodes.SUCCESS;
- private FakeFeatureFlagsImpl mFakeFlagsImpl;
private final IBluetoothLeBroadcastCallback mCallbacks =
new IBluetoothLeBroadcastCallback.Stub() {
@@ -188,15 +216,9 @@
LeAudioNativeInterface.setInstance(mLeAudioNativeInterface);
startService();
- mFakeFlagsImpl = new FakeFeatureFlagsImpl();
- mFakeFlagsImpl.setFlag(Flags.FLAG_LEAUDIO_UNICAST_INACTIVATE_DEVICE_BASED_ON_CONTEXT, false);
- mFakeFlagsImpl.setFlag(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION, false);
- mFakeFlagsImpl.setFlag(Flags.FLAG_LEAUDIO_BROADCAST_AUDIO_HANDOVER_POLICIES, false);
- mFakeFlagsImpl.setFlag(Flags.FLAG_LEAUDIO_API_SYNCHRONIZED_BLOCK_FIX, false);
- mService.setFeatureFlags(mFakeFlagsImpl);
-
mService.mAudioManager = mAudioManager;
-
+ mService.mServiceFactory = mServiceFactory;
+ when(mServiceFactory.getBassClientService()).thenReturn(mBassClientService);
// Set up the State Changed receiver
IntentFilter filter = new IntentFilter();
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
@@ -213,14 +235,16 @@
@After
public void tearDown() throws Exception {
- if (mService == null) {
+ if (mService == null || mAdapter == null) {
return;
}
+ if (mLeAudioIntentReceiver != null) {
+ mTargetContext.unregisterReceiver(mLeAudioIntentReceiver);
+ }
stopService();
LeAudioBroadcasterNativeInterface.setInstance(null);
LeAudioNativeInterface.setInstance(null);
- mTargetContext.unregisterReceiver(mLeAudioIntentReceiver);
TestUtils.clearAdapterService(mAdapterService);
reset(mAudioManager);
}
@@ -399,6 +423,44 @@
}
@Test
+ public void testCreateBroadcast_updateQualityToStandard() {
+ byte[] code = {0x00, 0x01, 0x00, 0x02};
+ int groupId = 1;
+ prepareConnectedUnicastDevice(groupId);
+
+ mService.mBroadcastCallbacks.register(mCallbacks);
+
+ BluetoothLeAudioContentMetadata.Builder meta_builder =
+ new BluetoothLeAudioContentMetadata.Builder();
+ BluetoothLeAudioContentMetadata meta = meta_builder.build();
+ BluetoothLeBroadcastSettings settings = buildBroadcastSettingsFromMetadata(meta, code, 1);
+
+ when(mBassClientService.getConnectedDevices()).thenReturn(List.of(mDevice));
+ // update selectable configs to be STANDARD quality
+ injectGroupSelectableCodecConfigChanged(
+ groupId, INPUT_SELECTABLE_CONFIG_STANDARD, OUTPUT_SELECTABLE_CONFIG_STANDARD);
+ injectGroupCurrentCodecConfigChanged(groupId, LC3_16KHZ_CONFIG, LC3_48KHZ_CONFIG);
+
+ mService.createBroadcast(settings);
+
+ // Test data with only one subgroup
+ // Verify quality is updated to standard per sinks capabilities
+ int[] expectedQualityArray = {BluetoothLeBroadcastSubgroupSettings.QUALITY_STANDARD};
+ byte[][] expectedDataArray = {
+ settings.getSubgroupSettings().get(0).getContentMetadata().getRawMetadata()
+ };
+
+ verify(mLeAudioBroadcasterNativeInterface, times(1))
+ .createBroadcast(
+ eq(true),
+ eq(TEST_BROADCAST_NAME),
+ eq(code),
+ eq(settings.getPublicBroadcastMetadata().getRawMetadata()),
+ eq(expectedQualityArray),
+ eq(expectedDataArray));
+ }
+
+ @Test
public void testStartStopBroadcastNative() {
int broadcastId = 243;
byte[] code = {0x00, 0x01, 0x00, 0x02};
@@ -640,6 +702,11 @@
create_event.valueInt4 = srcAudioLocation;
create_event.valueInt5 = availableContexts;
mService.messageFromNative(create_event);
+
+ // Set default codec config to HIGH quality
+ injectGroupSelectableCodecConfigChanged(
+ groupId, INPUT_SELECTABLE_CONFIG_HIGH, OUTPUT_SELECTABLE_CONFIG_HIGH);
+ injectGroupCurrentCodecConfigChanged(groupId, LC3_16KHZ_CONFIG, LC3_48KHZ_CONFIG);
}
@Test
@@ -647,7 +714,7 @@
int groupId = 1;
byte[] code = {0x00, 0x01, 0x00, 0x02};
- mFakeFlagsImpl.setFlag(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION, true);
+ mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION);
prepareConnectedUnicastDevice(groupId);
@@ -733,8 +800,8 @@
int broadcastId = 243;
byte[] code = {0x00, 0x01, 0x00, 0x02};
- mFakeFlagsImpl.setFlag(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION, true);
- mFakeFlagsImpl.setFlag(Flags.FLAG_LEAUDIO_BROADCAST_AUDIO_HANDOVER_POLICIES, true);
+ mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION);
+ mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_AUDIO_HANDOVER_POLICIES);
mService.mBroadcastCallbacks.register(mCallbacks);
@@ -846,8 +913,8 @@
int broadcastId = 243;
byte[] code = {0x00, 0x01, 0x00, 0x02};
- mFakeFlagsImpl.setFlag(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION, true);
- mFakeFlagsImpl.setFlag(Flags.FLAG_LEAUDIO_BROADCAST_AUDIO_HANDOVER_POLICIES, true);
+ mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION);
+ mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_AUDIO_HANDOVER_POLICIES);
mService.mBroadcastCallbacks.register(mCallbacks);
@@ -983,7 +1050,8 @@
BluetoothLeBroadcastSubgroupSettings.Builder subgroupBuilder =
new BluetoothLeBroadcastSubgroupSettings.Builder()
- .setContentMetadata(contentMetadata);
+ .setContentMetadata(contentMetadata)
+ .setPreferredQuality(BluetoothLeBroadcastSubgroupSettings.QUALITY_HIGH);
BluetoothLeBroadcastSettings.Builder builder = new BluetoothLeBroadcastSettings.Builder()
.setPublicBroadcast(true)
@@ -997,4 +1065,30 @@
}
return builder.build();
}
+
+ private void injectGroupCurrentCodecConfigChanged(
+ int groupId,
+ BluetoothLeAudioCodecConfig inputCodecConfig,
+ BluetoothLeAudioCodecConfig outputCodecConfig) {
+ int eventType = LeAudioStackEvent.EVENT_TYPE_AUDIO_GROUP_CURRENT_CODEC_CONFIG_CHANGED;
+
+ LeAudioStackEvent groupCodecConfigChangedEvent = new LeAudioStackEvent(eventType);
+ groupCodecConfigChangedEvent.valueInt1 = groupId;
+ groupCodecConfigChangedEvent.valueCodec1 = inputCodecConfig;
+ groupCodecConfigChangedEvent.valueCodec2 = outputCodecConfig;
+ mService.messageFromNative(groupCodecConfigChangedEvent);
+ }
+
+ private void injectGroupSelectableCodecConfigChanged(
+ int groupId,
+ List<BluetoothLeAudioCodecConfig> inputSelectableCodecConfig,
+ List<BluetoothLeAudioCodecConfig> outputSelectableCodecConfig) {
+ int eventType = LeAudioStackEvent.EVENT_TYPE_AUDIO_GROUP_SELECTABLE_CODEC_CONFIG_CHANGED;
+
+ LeAudioStackEvent groupCodecConfigChangedEvent = new LeAudioStackEvent(eventType);
+ groupCodecConfigChangedEvent.valueInt1 = groupId;
+ groupCodecConfigChangedEvent.valueCodecList1 = inputSelectableCodecConfig;
+ groupCodecConfigChangedEvent.valueCodecList2 = outputSelectableCodecConfig;
+ mService.messageFromNative(groupCodecConfigChangedEvent);
+ }
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java
index 022abb3..30bb834 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java
@@ -51,6 +51,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.ParcelUuid;
+import android.platform.test.flag.junit.SetFlagsRule;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
@@ -62,7 +63,6 @@
import com.android.bluetooth.btservice.ServiceFactory;
import com.android.bluetooth.btservice.storage.DatabaseManager;
import com.android.bluetooth.csip.CsipSetCoordinatorService;
-import com.android.bluetooth.flags.FakeFeatureFlagsImpl;
import com.android.bluetooth.flags.Flags;
import com.android.bluetooth.hap.HapClientService;
import com.android.bluetooth.hfp.HeadsetService;
@@ -72,6 +72,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -97,6 +98,8 @@
private static final int MAX_LE_AUDIO_CONNECTIONS = 5;
private static final int LE_AUDIO_GROUP_ID_INVALID = -1;
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
private BluetoothAdapter mAdapter;
private Context mTargetContext;
private LeAudioService mService;
@@ -112,7 +115,6 @@
private boolean onGroupStreamStatusCallbackCalled = false;
private boolean onGroupCodecConfChangedCallbackCalled = false;
private BluetoothLeAudioCodecStatus testCodecStatus = null;
- private FakeFeatureFlagsImpl mFakeFlagsImpl;
private BroadcastReceiver mLeAudioIntentReceiver;
@@ -195,14 +197,6 @@
LeAudioNativeInterface.setInstance(mNativeInterface);
startService();
- mFakeFlagsImpl = new FakeFeatureFlagsImpl();
- mFakeFlagsImpl.setFlag(Flags.FLAG_LEAUDIO_UNICAST_INACTIVATE_DEVICE_BASED_ON_CONTEXT, false);
- mFakeFlagsImpl.setFlag(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION, false);
- mFakeFlagsImpl.setFlag(Flags.FLAG_LEAUDIO_BROADCAST_AUDIO_HANDOVER_POLICIES, false);
- mFakeFlagsImpl.setFlag(Flags.FLAG_LEAUDIO_MCS_TBS_AUTHORIZATION_REBOND_FIX, false);
- mFakeFlagsImpl.setFlag(Flags.FLAG_LEAUDIO_API_SYNCHRONIZED_BLOCK_FIX, false);
- mService.setFeatureFlags(mFakeFlagsImpl);
-
mService.mAudioManager = mAudioManager;
mService.mMcpService = mMcpService;
mService.mTbsService = mTbsService;
@@ -811,8 +805,8 @@
/** Test that authorization info is removed from TBS and MCS after the device is unbond. */
@Test
public void testAuthorizationInfoRemovedFromTbsMcsOnUnbondEvents() {
- mFakeFlagsImpl.setFlag(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION, true);
- mFakeFlagsImpl.setFlag(Flags.FLAG_LEAUDIO_MCS_TBS_AUTHORIZATION_REBOND_FIX, true);
+ mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION);
+ mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_MCS_TBS_AUTHORIZATION_REBOND_FIX);
// Update the device priority so okToConnect() returns true
when(mDatabaseManager.getProfileConnectionPolicy(mLeftDevice, BluetoothProfile.LE_AUDIO))
@@ -942,7 +936,7 @@
@Test
public void testAuthorizationInfoRemovedFromTbsMcsOnUnbondEventsWithSynchBlockFixFlag() {
- mFakeFlagsImpl.setFlag(Flags.FLAG_LEAUDIO_API_SYNCHRONIZED_BLOCK_FIX, true);
+ mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_API_SYNCHRONIZED_BLOCK_FIX);
testAuthorizationInfoRemovedFromTbsMcsOnUnbondEvents();
}
@@ -1737,8 +1731,8 @@
@Test
public void testMediaContextUnavailableForAWhile() {
- mFakeFlagsImpl.setFlag(Flags.FLAG_LEAUDIO_UNICAST_INACTIVATE_DEVICE_BASED_ON_CONTEXT, true);
- mFakeFlagsImpl.setFlag(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION, true);
+ mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_UNICAST_INACTIVATE_DEVICE_BASED_ON_CONTEXT);
+ mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION);
doReturn(true).when(mNativeInterface).connectLeAudio(any(BluetoothDevice.class));
connectTestDevice(mSingleDevice, testGroupId);
diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioStateMachineTest.java
index 73365d6..d372c17 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioStateMachineTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioStateMachineTest.java
@@ -42,8 +42,6 @@
import com.android.bluetooth.TestUtils;
import com.android.bluetooth.btservice.AdapterService;
-import com.android.bluetooth.flags.FakeFeatureFlagsImpl;
-import com.android.bluetooth.flags.Flags;
import org.junit.After;
import org.junit.Before;
@@ -60,7 +58,6 @@
private HandlerThread mHandlerThread;
private LeAudioStateMachine mLeAudioStateMachine;
private BluetoothDevice mTestDevice;
- private FakeFeatureFlagsImpl mFakeFlagsImpl;
private static final int TIMEOUT_MS = 1000;
@Mock private AdapterService mAdapterService;
@@ -75,9 +72,6 @@
TestUtils.setAdapterService(mAdapterService);
mAdapter = BluetoothAdapter.getDefaultAdapter();
- mFakeFlagsImpl = new FakeFeatureFlagsImpl();
- mFakeFlagsImpl.setFlag(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION, false);
- mFakeFlagsImpl.setFlag(Flags.FLAG_LEAUDIO_BROADCAST_AUDIO_HANDOVER_POLICIES, false);
// Get a device for testing
mTestDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05");
@@ -92,8 +86,7 @@
mTestDevice,
mLeAudioService,
mLeAudioNativeInterface,
- mHandlerThread.getLooper(),
- mFakeFlagsImpl);
+ mHandlerThread.getLooper());
}
@After
diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceCleanupTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceCleanupTest.java
new file mode 100644
index 0000000..04ab4ee
--- /dev/null
+++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceCleanupTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 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 com.android.bluetooth.opp;
+
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageManager.DONT_KILL_APP;
+
+import android.content.ComponentName;
+import android.content.ContentValues;
+import android.content.Context;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.bluetooth.BluetoothMethodProxy;
+import com.android.bluetooth.TestUtils;
+import com.android.bluetooth.btservice.AdapterService;
+import com.android.bluetooth.flags.Flags;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class BluetoothOppServiceCleanupTest {
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+ private boolean mIsAdapterServiceSet;
+
+ private Context mTargetContext;
+
+ @Mock private AdapterService mAdapterService;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mTargetContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ TestUtils.setAdapterService(mAdapterService);
+ mIsAdapterServiceSet = true;
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ BluetoothMethodProxy.setInstanceForTesting(null);
+
+ if (mIsAdapterServiceSet) {
+ TestUtils.clearAdapterService(mAdapterService);
+ }
+ }
+
+ @Test
+ @UiThreadTest
+ public void testStopAndCleanup() {
+ mSetFlagsRule.enableFlags(
+ Flags.FLAG_OPP_SERVICE_FIX_INDEX_OUT_OF_BOUNDS_EXCEPTION_IN_UPDATE_THREAD);
+
+ // Don't need to disable again since it will be handled in OppService.stop
+ enableBtOppProvider();
+
+ // Add thousands of placeholder rows
+ for (int i = 0; i < 2000; i++) {
+ ContentValues values = new ContentValues();
+ mTargetContext.getContentResolver().insert(BluetoothShare.CONTENT_URI, values);
+ }
+
+ try {
+ BluetoothOppService service = new BluetoothOppService(mTargetContext);
+ service.start();
+ service.setAvailable(true);
+
+ // Call stop while UpdateThread is running.
+ service.stop();
+ service.cleanup();
+ } finally {
+ mTargetContext.getContentResolver().delete(BluetoothShare.CONTENT_URI, null, null);
+ }
+ }
+
+ private void enableBtOppProvider() {
+ mTargetContext
+ .getPackageManager()
+ .setApplicationEnabledSetting(
+ mTargetContext.getPackageName(),
+ COMPONENT_ENABLED_STATE_ENABLED,
+ DONT_KILL_APP);
+
+ ComponentName activityName =
+ new ComponentName(mTargetContext, BluetoothOppProvider.class.getCanonicalName());
+ mTargetContext
+ .getPackageManager()
+ .setComponentEnabledSetting(
+ activityName, COMPONENT_ENABLED_STATE_ENABLED, DONT_KILL_APP);
+ }
+}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/TestActivity.java b/android/app/tests/unit/src/com/android/bluetooth/opp/TestActivity.java
index 65c945f..2710aa1 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/opp/TestActivity.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/opp/TestActivity.java
@@ -359,9 +359,9 @@
private static final String TAG = "BtOppRfcommListener";
- private static final boolean D = Constants.DEBUG;
+ private static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
- private static final boolean V = Constants.VERBOSE;
+ private static final boolean V = Log.isLoggable(TAG, Log.VERBOSE);
private volatile boolean mInterrupted;
@@ -477,7 +477,7 @@
class TestTcpServer extends ServerRequestHandler implements Runnable {
private static final String TAG = "ServerRequestHandler";
- private static final boolean V = Constants.VERBOSE;
+ private static final boolean V = Log.isLoggable(TAG, Log.VERBOSE);
static final int PORT = 6500;
diff --git a/flags/pairing.aconfig b/flags/pairing.aconfig
new file mode 100644
index 0000000..8a9454f
--- /dev/null
+++ b/flags/pairing.aconfig
@@ -0,0 +1,9 @@
+package: "com.android.bluetooth.flags"
+container: "com.android.btservices"
+
+flag {
+ name: "clear_collision_state_on_pairing_complete"
+ namespace: "bluetooth"
+ description: "Clear authentication collision state on pairing conclusion"
+ bug: "327208896"
+}
diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java b/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java
index 00fbbe0..2d7db91 100644
--- a/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java
+++ b/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java
@@ -492,7 +492,7 @@
private BluetoothDevice mSourceDevice = null;
private int mSourceAdvertisingSid = UNKNOWN_VALUE_PLACEHOLDER;
private int mBroadcastId = UNKNOWN_VALUE_PLACEHOLDER;
- private int mPaSyncInterval = UNKNOWN_VALUE_PLACEHOLDER;
+ private int mPaSyncInterval = PA_SYNC_INTERVAL_UNKNOWN;
private boolean mIsEncrypted = false;
private boolean mIsPublicBroadcast = false;
private String mBroadcastName = null;
diff --git a/system/audio/Android.bp b/system/audio/Android.bp
index c0e3119..2fc5464 100644
--- a/system/audio/Android.bp
+++ b/system/audio/Android.bp
@@ -14,9 +14,6 @@
"asrc/asrc_resampler.cc",
"asrc/asrc_tables.cc",
],
- include_dirs: [
- "packages/modules/Bluetooth/system/gd",
- ],
shared_libs: [
"libchrome",
],
@@ -44,7 +41,6 @@
stl: "libc++_static",
include_dirs: [
"packages/modules/Bluetooth/system",
- "packages/modules/Bluetooth/system/gd",
],
generated_headers: [
"BluetoothGeneratedDumpsysDataSchema_h",
diff --git a/system/audio/asrc/asrc_resampler.cc b/system/audio/asrc/asrc_resampler.cc
index 0590b84..09e5958 100644
--- a/system/audio/asrc/asrc_resampler.cc
+++ b/system/audio/asrc/asrc_resampler.cc
@@ -19,15 +19,15 @@
#include <base/logging.h>
#include <base/strings/stringprintf.h>
+#include <algorithm>
#include <cmath>
#include <utility>
#include "asrc_tables.h"
-#include "hal/nocp_iso_clocker.h"
namespace bluetooth::audio::asrc {
-class SourceAudioHalAsrc::ClockRecovery : ::bluetooth::hal::NocpIsoHandler {
+class SourceAudioHalAsrc::ClockRecovery : public ClockHandler {
const int interval_;
std::mutex mutex_;
@@ -113,8 +113,7 @@
}
int dt_current = int(timestamp_us - link.local_time);
- if (std::abs(dt_current) < std::abs(link.decim_dt[1]))
- link.decim_dt[1] = dt_current;
+ link.decim_dt[1] = std::min(link.decim_dt[1], dt_current);
if (link.local_time - link.decim_t0 < 1000 * 1000) return;
@@ -237,11 +236,9 @@
state_{
.link = {{.state = LinkState::RESET}, {.state = LinkState::RESET}},
.active_link_id = -1},
- reference_timing_{0, 0, 0} {
- ::bluetooth::hal::NocpIsoClocker::Register(this);
- }
+ reference_timing_{0, 0, 0} {}
- ~ClockRecovery() override { ::bluetooth::hal::NocpIsoClocker::Unregister(); }
+ ~ClockRecovery() override {}
__attribute__((no_sanitize("integer"))) uint32_t Convert(
uint32_t stream_time) {
@@ -466,16 +463,16 @@
#endif
-SourceAudioHalAsrc::SourceAudioHalAsrc(int channels, int sample_rate,
- int bit_depth, int interval_us,
- int num_burst_buffers,
- int burst_delay_ms)
+SourceAudioHalAsrc::SourceAudioHalAsrc(
+ std::shared_ptr<ClockSource> clock_source, int channels, int sample_rate,
+ int bit_depth, int interval_us, int num_burst_buffers, int burst_delay_ms)
: sample_rate_(sample_rate),
bit_depth_(bit_depth),
interval_us_(interval_us),
stream_us_(0),
drift_us_(0),
out_counter_(0),
+ clock_source_(std::move(clock_source)),
resampler_pos_{0, 0} {
buffers_size_ = 0;
@@ -509,6 +506,7 @@
// when the PCM bit_depth is higher than 16 bits.
clock_recovery_ = std::make_unique<ClockRecovery>(interval_us_);
+ clock_source_->Bind(clock_recovery_.get());
resamplers_ = std::make_unique<std::vector<Resampler>>(channels, bit_depth_);
// Deduct from the PCM stream characteristics, the size of the pool buffers
diff --git a/system/audio/asrc/asrc_resampler.h b/system/audio/asrc/asrc_resampler.h
index ae9ea31..400c51c 100644
--- a/system/audio/asrc/asrc_resampler.h
+++ b/system/audio/asrc/asrc_resampler.h
@@ -23,6 +23,19 @@
namespace bluetooth::audio::asrc {
+class ClockHandler {
+ public:
+ virtual ~ClockHandler() = default;
+ virtual void OnEvent(uint32_t timestamp, int link_id,
+ int num_of_completed_packets) = 0;
+};
+
+class ClockSource {
+ public:
+ virtual ~ClockSource() = default;
+ virtual void Bind(ClockHandler*) = 0;
+};
+
class SourceAudioHalAsrc {
public:
// The Asynchronous Sample Rate Conversion (ASRC) is set up from the PCM
@@ -36,9 +49,9 @@
// `burst_delay_ms` helps to ensure that the synchronization with the
// transmission intervals is done.
- SourceAudioHalAsrc(int channels, int sample_rate, int bit_depth,
- int interval_us, int num_burst_buffers = 2,
- int burst_delay_ms = 500);
+ SourceAudioHalAsrc(std::shared_ptr<ClockSource> clock_source, int channels,
+ int sample_rate, int bit_depth, int interval_us,
+ int num_burst_buffers = 2, int burst_delay_ms = 500);
~SourceAudioHalAsrc();
@@ -74,6 +87,7 @@
class ClockRecovery;
std::unique_ptr<ClockRecovery> clock_recovery_;
+ std::shared_ptr<ClockSource> clock_source_;
class Resampler;
std::unique_ptr<std::vector<Resampler>> resamplers_;
diff --git a/system/audio/asrc/asrc_resampler_test.cc b/system/audio/asrc/asrc_resampler_test.cc
index 04bf07e..1b90e0a 100644
--- a/system/audio/asrc/asrc_resampler_test.cc
+++ b/system/audio/asrc/asrc_resampler_test.cc
@@ -19,17 +19,17 @@
#include <cstdio>
#include <iostream>
-namespace bluetooth::hal {
-void NocpIsoClocker::Register(NocpIsoHandler*) {}
-void NocpIsoClocker::Unregister() {}
-} // namespace bluetooth::hal
-
namespace bluetooth::audio::asrc {
+class MockClockSource : public ClockSource {
+ void Bind(ClockHandler*) override {}
+};
+
class SourceAudioHalAsrcTest : public SourceAudioHalAsrc {
public:
SourceAudioHalAsrcTest(int channels, int bitdepth)
- : SourceAudioHalAsrc(channels, 48000, bitdepth, 10000) {}
+ : SourceAudioHalAsrc(std::make_unique<MockClockSource>(), channels, 48000,
+ bitdepth, 10000) {}
template <typename T>
void Resample(double ratio, const T* in, size_t in_length, size_t* in_count,
diff --git a/system/audio_hal_interface/Android.bp b/system/audio_hal_interface/Android.bp
index ffa646d..fa629d3 100644
--- a/system/audio_hal_interface/Android.bp
+++ b/system/audio_hal_interface/Android.bp
@@ -88,7 +88,9 @@
name: "bluetooth-test-audio-hal-interface",
defaults: [
"fluoride_defaults",
- "latest_android_hardware_bluetooth_audio_ndk_shared",
+ "latest_android_hardware_audio_common_ndk_static",
+ "latest_android_hardware_bluetooth_audio_ndk_static",
+ "latest_android_media_audio_common_types_ndk_static",
],
include_dirs: [
"packages/modules/Bluetooth/system",
@@ -99,8 +101,6 @@
"hidl/client_interface_hidl_unittest.cc",
],
shared_libs: [
- "android.hardware.bluetooth.audio@2.0",
- "android.hardware.bluetooth.audio@2.1",
"libbase",
"libbinder_ndk",
"libcutils",
@@ -110,6 +110,11 @@
"libutils",
],
static_libs: [
+ "android.hardware.audio.common@5.0",
+ "android.hardware.bluetooth.audio@2.0",
+ "android.hardware.bluetooth.audio@2.1",
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
"libbluetooth_log",
"libbt-audio-hal-interface",
"libbt-common",
@@ -128,7 +133,9 @@
test_suites: ["general-tests"],
defaults: [
"fluoride_defaults",
- "latest_android_hardware_bluetooth_audio_ndk_shared",
+ "latest_android_hardware_audio_common_ndk_static",
+ "latest_android_hardware_bluetooth_audio_ndk_static",
+ "latest_android_media_audio_common_types_ndk_static",
"mts_defaults",
],
cflags: [
@@ -174,21 +181,28 @@
"aidl/a2dp_provider_info_unittest.cc",
],
shared_libs: [
- "libbase",
- "libbase",
+ "libbinder_ndk",
"libcutils",
- "libfmq",
+ "libhidlbase",
"liblog",
"libutils",
"server_configurable_flags",
],
static_libs: [
+ "android.hardware.bluetooth.audio@2.0",
+ "android.hardware.bluetooth.audio@2.1",
+ "android.hardware.bluetooth@1.0",
+ "android.hardware.bluetooth@1.1",
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
"bluetooth_flags_c_lib",
+ "libbase",
"libbluetooth_log",
"libbt-common",
"libbt_shim_bridge",
"libchrome",
"libflagtest",
+ "libfmq",
"libgmock",
"libosi",
],
diff --git a/system/audio_hal_interface/le_audio_software.cc b/system/audio_hal_interface/le_audio_software.cc
index 5793b44..9ec3b21 100644
--- a/system/audio_hal_interface/le_audio_software.cc
+++ b/system/audio_hal_interface/le_audio_software.cc
@@ -637,8 +637,6 @@
}
void LeAudioClientInterface::Source::ConfirmStreamingRequestV2() {
- LOG_INFO("Rymek source");
-
auto lambda = [&](StartRequestState currect_start_request_state)
-> std::pair<StartRequestState, bool> {
switch (currect_start_request_state) {
diff --git a/system/bta/hearing_aid/hearing_aid.cc b/system/bta/hearing_aid/hearing_aid.cc
index a32d7b2..3b28bdf 100644
--- a/system/bta/hearing_aid/hearing_aid.cc
+++ b/system/bta/hearing_aid/hearing_aid.cc
@@ -32,12 +32,14 @@
#include <mutex>
#include <vector>
+#include "audio/asrc/asrc_resampler.h"
#include "bta/include/bta_gatt_api.h"
#include "bta/include/bta_gatt_queue.h"
#include "bta/include/bta_hearing_aid_api.h"
#include "btm_iso_api.h"
#include "device/include/controller.h"
#include "embdrv/g722/g722_enc_dec.h"
+#include "hal/link_clocker.h"
#include "hardware/bt_gatt_types.h"
#include "include/check.h"
#include "internal_include/bt_trace.h"
@@ -275,6 +277,13 @@
const int DROP_FREQUENCY_THRESHOLD =
bluetooth::common::init_flags::get_asha_packet_drop_frequency_threshold();
+ // Resampler context for audio stream.
+ // Clock recovery uses L2CAP Flow Control Credit Ind acknowledgments
+ // from either the left or right connection, whichever is first
+ // connected.
+ std::shared_ptr<bluetooth::hal::L2capCreditIndEvents> asrc_clock_source;
+ std::unique_ptr<bluetooth::audio::asrc::SourceAudioHalAsrc> asrc;
+
public:
~HearingAidImpl() override = default;
@@ -354,6 +363,51 @@
}
}
+ // Reset and configure the ASHA resampling context using the input device
+ // devices as reference for the BT clock estimation.
+ void ConfigureAsrc() {
+ if (!IS_FLAG_ENABLED(asha_asrc)) {
+ log::info("Asha resampling disabled: feature flag off");
+ return;
+ }
+
+ // Create a new ASRC context if required.
+ if (asrc == nullptr) {
+ asrc_clock_source =
+ std::make_shared<bluetooth::hal::L2capCreditIndEvents>();
+ asrc = std::make_unique<bluetooth::audio::asrc::SourceAudioHalAsrc>(
+ asrc_clock_source, /*channels*/ 2,
+ /*sample_rate*/ codec_in_use == CODEC_G722_24KHZ ? 24000 : 16000,
+ /*bit_depth*/ 16,
+ /*interval_us*/ default_data_interval_ms * 1000,
+ /*num_burst_buffers*/ 0,
+ /*burst_delay*/ 0);
+ }
+
+ for (auto& device : hearingDevices.devices) {
+ if (!device.accepting_audio) {
+ continue;
+ }
+
+ uint16_t lcid = GAP_ConnGetL2CAPCid(device.gap_handle);
+ uint16_t rcid = 0;
+ L2CA_GetRemoteCid(lcid, &rcid);
+
+ auto conn = btm_acl_for_bda(device.address, BT_TRANSPORT_LE);
+ log::info("Updating ASRC context for handle=0x{:x}, cid=0x{:x}",
+ conn->Handle(), rcid);
+
+ asrc_clock_source->Update(device.isLeft(), conn->Handle(), rcid);
+ }
+ }
+
+ // Reset the ASHA resampling context.
+ void ResetAsrc() {
+ log::info("Resetting the Asha resampling context");
+ asrc_clock_source = nullptr;
+ asrc = nullptr;
+ }
+
uint16_t UpdateBleConnParams(const RawAddress& address) {
/* List of parameters that depends on the chosen Connection Interval */
uint16_t min_ce_len = MIN_CE_LEN_20MS_CI;
@@ -1171,6 +1225,10 @@
} else {
log::info("audio_running={}", audio_running);
}
+
+ // Close the ASRC context.
+ ResetAsrc();
+
audio_running = false;
stop_audio_ticks();
@@ -1213,6 +1271,9 @@
return;
}
+ // Open the ASRC context.
+ ConfigureAsrc();
+
// TODO: shall we also reset the encoder ?
encoder_state_release();
encoder_state_init();
@@ -1352,6 +1413,16 @@
return diff_credit < (init_credit / 2 - 1);
}
+ void OnAudioDataReadyResample(const std::vector<uint8_t>& data) {
+ if (asrc == nullptr) {
+ return OnAudioDataReady(data);
+ }
+
+ for (auto const resampled_data : asrc->Run(data)) {
+ OnAudioDataReady(*resampled_data);
+ }
+ }
+
void OnAudioDataReady(const std::vector<uint8_t>& data) {
/* For now we assume data comes in as 16bit per sample 16kHz PCM stereo */
bool need_drop = false;
@@ -1414,6 +1485,18 @@
l2cap_flush_threshold = 1;
}
+ // Skipping packets completely messes up the resampler context.
+ // The condition for skipping packets seems to be easily triggered,
+ // causing dropouts that could have been avoided.
+ //
+ // When the resampler is enabled, the flush threshold is set
+ // to the number of credits specified for the ASHA l2cap streaming
+ // channel. This will ensure it is only triggered in case of
+ // critical failure.
+ if (IS_FLAG_ENABLED(asha_asrc)) {
+ l2cap_flush_threshold = 8;
+ }
+
// TODO: monural, binarual check
// divide encoded data into packets, add header, send.
@@ -2069,7 +2152,7 @@
class HearingAidAudioReceiverImpl : public HearingAidAudioReceiver {
public:
void OnAudioDataReady(const std::vector<uint8_t>& data) override {
- if (instance) instance->OnAudioDataReady(data);
+ if (instance) instance->OnAudioDataReadyResample(data);
}
void OnAudioSuspend(const std::function<void()>& stop_audio_ticks) override {
if (instance) instance->OnAudioSuspend(stop_audio_ticks);
diff --git a/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc b/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc
index f8c87c4..f2e8b12 100644
--- a/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc
+++ b/system/bta/le_audio/audio_hal_client/audio_source_hal_client.cc
@@ -27,6 +27,7 @@
#include "bta/le_audio/codec_manager.h"
#include "common/repeating_timer.h"
#include "common/time_util.h"
+#include "gd/hal/link_clocker.h"
#include "os/log.h"
#include "osi/include/wakelock.h"
#include "stack/include/main_thread.h"
@@ -248,6 +249,7 @@
wakelock_acquire();
if (IS_FLAG_ENABLED(leaudio_hal_client_asrc)) {
asrc_ = std::make_unique<bluetooth::audio::asrc::SourceAudioHalAsrc>(
+ std::make_shared<bluetooth::hal::NocpIsoEvents>(),
source_codec_config_.num_channels, source_codec_config_.sample_rate,
source_codec_config_.bits_per_sample,
source_codec_config_.data_interval_us);
diff --git a/system/btcore/BUILD.gn b/system/btcore/BUILD.gn
index 5648584..f7b86f2 100644
--- a/system/btcore/BUILD.gn
+++ b/system/btcore/BUILD.gn
@@ -28,7 +28,10 @@
"//bt/system",
]
- configs += [ "//bt/system:target_defaults" ]
+ configs += [
+ "//bt/system:target_defaults",
+ "//bt/system/log:log_defaults",
+ ]
deps = [
"//bt/system/gd/rust/shim:init_flags_bridge_header",
@@ -57,6 +60,7 @@
configs += [
"//bt/system:external_gtest_main",
"//bt/system:target_defaults",
+ "//bt/system/log:log_defaults",
]
libs = [
diff --git a/system/btcore/src/module.cc b/system/btcore/src/module.cc
index c1d0617..b04434b 100644
--- a/system/btcore/src/module.cc
+++ b/system/btcore/src/module.cc
@@ -21,6 +21,7 @@
#include "btcore/include/module.h"
#include <base/logging.h>
+#include <bluetooth/log.h>
#include <dlfcn.h>
#include <string.h>
@@ -32,6 +33,7 @@
#include "os/log.h"
using bluetooth::common::MessageLoopThread;
+using namespace bluetooth;
typedef enum {
MODULE_STATE_NONE = 0,
@@ -63,7 +65,7 @@
CHECK(get_module_state(module) == MODULE_STATE_NONE);
if (!call_lifecycle_function(module->init)) {
- LOG_ERROR("%s Failed to initialize module \"%s\"", __func__, module->name);
+ log::error("Failed to initialize module \"{}\"", module->name);
return false;
}
@@ -81,12 +83,12 @@
CHECK(get_module_state(module) == MODULE_STATE_INITIALIZED ||
module->init == NULL);
- LOG_INFO("%s Starting module \"%s\"", __func__, module->name);
+ log::info("Starting module \"{}\"", module->name);
if (!call_lifecycle_function(module->start_up)) {
- LOG_ERROR("%s Failed to start up module \"%s\"", __func__, module->name);
+ log::error("Failed to start up module \"{}\"", module->name);
return false;
}
- LOG_INFO("%s Started module \"%s\"", __func__, module->name);
+ log::info("Started module \"{}\"", module->name);
set_module_state(module, MODULE_STATE_STARTED);
return true;
@@ -100,12 +102,12 @@
// Only something to do if the module was actually started
if (state < MODULE_STATE_STARTED) return;
- LOG_INFO("%s Shutting down module \"%s\"", __func__, module->name);
+ log::info("Shutting down module \"{}\"", module->name);
if (!call_lifecycle_function(module->shut_down)) {
- LOG_ERROR("%s Failed to shutdown module \"%s\". Continuing anyway.",
- __func__, module->name);
+ log::error("Failed to shutdown module \"{}\". Continuing anyway.",
+ module->name);
}
- LOG_INFO("%s Shutdown of module \"%s\" completed", __func__, module->name);
+ log::info("Shutdown of module \"{}\" completed", module->name);
set_module_state(module, MODULE_STATE_INITIALIZED);
}
@@ -118,12 +120,12 @@
// Only something to do if the module was actually initialized
if (state < MODULE_STATE_INITIALIZED) return;
- LOG_INFO("%s Cleaning up module \"%s\"", __func__, module->name);
+ log::info("Cleaning up module \"{}\"", module->name);
if (!call_lifecycle_function(module->clean_up)) {
- LOG_ERROR("%s Failed to cleanup module \"%s\". Continuing anyway.",
- __func__, module->name);
+ log::error("Failed to cleanup module \"{}\". Continuing anyway.",
+ module->name);
}
- LOG_INFO("%s Cleanup of module \"%s\" completed", __func__, module->name);
+ log::info("Cleanup of module \"{}\" completed", module->name);
set_module_state(module, MODULE_STATE_NONE);
}
diff --git a/system/btif/co/bta_av_co.cc b/system/btif/co/bta_av_co.cc
index 58a9608..b96e3f3 100644
--- a/system/btif/co/bta_av_co.cc
+++ b/system/btif/co/bta_av_co.cc
@@ -24,6 +24,7 @@
******************************************************************************/
#include <base/logging.h>
+#include <bluetooth/log.h>
#include <mutex>
#include <optional>
@@ -58,6 +59,8 @@
#define BTA_AV_CO_AUDIO_INDEX_TO_HANDLE(index) \
(((index) + 1) | BTA_AV_CHNL_AUDIO)
+using namespace bluetooth;
+
class BtaAvCoSep {
public:
BtaAvCoSep()
@@ -776,7 +779,7 @@
void BtaAvCo::Init(
const std::vector<btav_a2dp_codec_config_t>& codec_priorities,
std::vector<btav_a2dp_codec_info_t>* supported_codecs) {
- LOG_VERBOSE("%s", __func__);
+ log::verbose("");
std::lock_guard<std::recursive_mutex> lock(codec_lock_);
@@ -824,7 +827,7 @@
// hence we check only the first peer.
A2dpCodecs* codecs = peers_[0].GetCodecs();
if (codecs == nullptr) {
- LOG_ERROR("Peer codecs is set to null");
+ log::error("Peer codecs is set to null");
return false;
}
return codecs->isSupportedCodec(codec_index);
@@ -864,13 +867,12 @@
index = BTA_AV_CO_AUDIO_HANDLE_TO_INDEX(bta_av_handle);
- LOG_VERBOSE("%s: bta_av_handle = 0x%x index = %d", __func__, bta_av_handle,
- index);
+ log::verbose("bta_av_handle = 0x{:x} index = {}", bta_av_handle, index);
// Sanity check
if (index >= BTA_AV_CO_NUM_ELEMENTS(peers_)) {
- LOG_ERROR("%s: peer index %d for BTA AV handle 0x%x is out of bounds",
- __func__, index, bta_av_handle);
+ log::error("peer index {} for BTA AV handle 0x{:x} is out of bounds", index,
+ bta_av_handle);
return nullptr;
}
@@ -879,19 +881,19 @@
BtaAvCoPeer* BtaAvCo::FindPeerAndUpdate(tBTA_AV_HNDL bta_av_handle,
const RawAddress& peer_address) {
- LOG_VERBOSE("%s: peer %s bta_av_handle = 0x%x", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle);
+ log::verbose("peer {} bta_av_handle = 0x{:x}",
+ ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle);
BtaAvCoPeer* p_peer = FindPeer(bta_av_handle);
if (p_peer == nullptr) {
- LOG_ERROR("%s: peer entry for BTA AV handle 0x%x peer %s not found",
- __func__, bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address));
+ log::error("peer entry for BTA AV handle 0x{:x} peer {} not found",
+ bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address));
return nullptr;
}
- LOG_VERBOSE("%s: peer %s bta_av_handle = 0x%x previous address %s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::verbose("peer {} bta_av_handle = 0x{:x} previous address {}",
+ ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle,
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
p_peer->addr = peer_address;
return p_peer;
}
@@ -908,23 +910,23 @@
const RawAddress& peer_address,
uint8_t num_seps, uint8_t num_sinks,
uint8_t num_sources, uint16_t uuid_local) {
- LOG_VERBOSE(
- "%s: peer %s bta_av_handle:0x%x num_seps:%d num_sinks:%d num_sources:%d",
- __func__, ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle, num_seps,
+ log::verbose(
+ "peer {} bta_av_handle:0x{:x} num_seps:{} num_sinks:{} num_sources:{}",
+ ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle, num_seps,
num_sinks, num_sources);
// Find the peer
BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
if (p_peer == nullptr) {
- LOG_ERROR("%s: could not find peer entry for bta_av_handle 0x%x peer %s",
- __func__, bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address));
+ log::error("could not find peer entry for bta_av_handle 0x{:x} peer {}",
+ bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address));
return;
}
/* Sanity check : this should never happen */
if (p_peer->opened) {
- LOG_ERROR("%s: peer %s already opened", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(peer_address));
+ log::error("peer {} already opened",
+ ADDRESS_TO_LOGGABLE_CSTR(peer_address));
}
/* Copy the discovery results */
@@ -953,25 +955,24 @@
tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address,
uint8_t* p_codec_info, uint8_t* p_sep_info_idx, uint8_t seid,
uint8_t* p_num_protect, uint8_t* p_protect_info) {
- LOG_VERBOSE("%s: peer %s bta_av_handle:0x%x codec:%s seid:%d", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle,
- A2DP_CodecName(p_codec_info), seid);
- LOG_VERBOSE("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x", __func__,
- *p_num_protect, p_protect_info[0], p_protect_info[1],
- p_protect_info[2]);
- LOG_VERBOSE("%s: codec: %s", __func__,
- A2DP_CodecInfoString(p_codec_info).c_str());
+ log::verbose("peer {} bta_av_handle:0x{:x} codec:{} seid:{}",
+ ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle,
+ A2DP_CodecName(p_codec_info), seid);
+ log::verbose("num_protect:0x{:02x} protect_info:0x{:02x}{:02x}{:02x}",
+ *p_num_protect, p_protect_info[0], p_protect_info[1],
+ p_protect_info[2]);
+ log::verbose("codec: {}", A2DP_CodecInfoString(p_codec_info));
// Find the peer
BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
if (p_peer == nullptr) {
- LOG_ERROR("%s: could not find peer entry for bta_av_handle 0x%x peer %s",
- __func__, bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address));
+ log::error("could not find peer entry for bta_av_handle 0x{:x} peer {}",
+ bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address));
return A2DP_FAIL;
}
- LOG_VERBOSE("%s: peer(o=%d, n_sinks=%d, n_rx_sinks=%d, n_sup_sinks=%d)",
- __func__, p_peer->opened, p_peer->num_sinks, p_peer->num_rx_sinks,
- p_peer->num_sup_sinks);
+ log::verbose("peer(o={}, n_sinks={}, n_rx_sinks={}, n_sup_sinks={})",
+ p_peer->opened, p_peer->num_sinks, p_peer->num_rx_sinks,
+ p_peer->num_sup_sinks);
p_peer->num_rx_sinks++;
@@ -989,9 +990,9 @@
if (p_peer->num_sup_sinks < BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks)) {
BtaAvCoSep* p_sink = &p_peer->sinks[p_peer->num_sup_sinks++];
- LOG_VERBOSE("%s: saved caps[%x:%x:%x:%x:%x:%x]", __func__,
- p_codec_info[1], p_codec_info[2], p_codec_info[3],
- p_codec_info[4], p_codec_info[5], p_codec_info[6]);
+ log::verbose("saved caps[{:x}:{:x}:{:x}:{:x}:{:x}:{:x}]", p_codec_info[1],
+ p_codec_info[2], p_codec_info[3], p_codec_info[4],
+ p_codec_info[5], p_codec_info[6]);
memcpy(p_sink->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
p_sink->sep_info_idx = *p_sep_info_idx;
@@ -999,8 +1000,8 @@
p_sink->num_protect = *p_num_protect;
memcpy(p_sink->protect_info, p_protect_info, AVDT_CP_INFO_LEN);
} else {
- LOG_ERROR("%s: peer %s : no more room for Sink info", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::error("peer {} : no more room for Sink info",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
}
}
@@ -1010,9 +1011,9 @@
(p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) {
return A2DP_FAIL;
}
- LOG_VERBOSE("%s: last Sink codec reached for peer %s (local %s)", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr),
- p_peer->acceptor ? "acceptor" : "initiator");
+ log::verbose("last Sink codec reached for peer {} (local {})",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr),
+ p_peer->acceptor ? "acceptor" : "initiator");
bta_av_co_store_peer_codectype(p_peer);
@@ -1027,8 +1028,8 @@
}
p_sink = p_peer->p_sink;
if (p_sink == nullptr) {
- LOG_ERROR("%s: cannot find the selected codec for peer %s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::error("cannot find the selected codec for peer {}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
return A2DP_FAIL;
}
} else {
@@ -1036,8 +1037,8 @@
// Apply user preferred codec directly before first codec selected.
p_sink = FindPeerSink(p_peer, BTAV_A2DP_CODEC_INDEX_SOURCE_SBC);
if (p_sink != nullptr) {
- LOG_VERBOSE("%s: mandatory codec preferred for peer %s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::verbose("mandatory codec preferred for peer {}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
btav_a2dp_codec_config_t high_priority_mandatory{
.codec_type = BTAV_A2DP_CODEC_INDEX_SOURCE_SBC,
.codec_priority = BTAV_A2DP_CODEC_PRIORITY_HIGHEST,
@@ -1054,14 +1055,14 @@
result_codec_config, &restart_input, &restart_output,
&config_updated);
} else {
- LOG_WARN("%s: mandatory codec not found for peer %s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::warn("mandatory codec not found for peer {}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
}
}
p_sink = SelectSourceCodec(p_peer);
if (p_sink == nullptr) {
- LOG_ERROR("%s: cannot set up codec for peer %s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::error("cannot set up codec for peer {}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
return A2DP_FAIL;
}
}
@@ -1075,14 +1076,14 @@
// If acceptor -> reconfig otherwise reply for configuration
*p_sep_info_idx = p_sink->sep_info_idx;
- LOG_VERBOSE("%s: peer %s acceptor:%s reconfig_needed:%s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr),
- (p_peer->acceptor) ? "true" : "false",
- (p_peer->reconfig_needed) ? "true" : "false");
+ log::verbose("peer {} acceptor:{} reconfig_needed:{}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr),
+ (p_peer->acceptor) ? "true" : "false",
+ (p_peer->reconfig_needed) ? "true" : "false");
if (p_peer->acceptor) {
if (p_peer->reconfig_needed) {
- LOG_VERBOSE("%s: call BTA_AvReconfig(0x%x) for peer %s", __func__,
- bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::verbose("call BTA_AvReconfig(0x{:x}) for peer {}", bta_av_handle,
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
BTA_AvReconfig(bta_av_handle, true, p_sink->sep_info_idx,
p_peer->codec_config, *p_num_protect, bta_av_co_cp_scmst);
}
@@ -1091,8 +1092,8 @@
}
// report this peer selectable codecs after retrieved all its capabilities.
- LOG(INFO) << __func__ << ": retrieved " << +p_peer->num_rx_sinks
- << " capabilities from peer " << p_peer->addr;
+ log::info("retrieved {} capabilities from peer {}", p_peer->num_rx_sinks,
+ ADDRESS_TO_LOGGABLE_STR(p_peer->addr));
ReportSourceCodecState(p_peer);
return A2DP_SUCCESS;
@@ -1106,26 +1107,24 @@
uint8_t* p_protect_info) {
std::lock_guard<std::recursive_mutex> lock(codec_lock_);
- LOG_VERBOSE("%s: peer %s bta_av_handle:0x%x codec:%s seid:%d", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle,
- A2DP_CodecName(p_codec_info), seid);
- LOG_VERBOSE("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x", __func__,
- *p_num_protect, p_protect_info[0], p_protect_info[1],
- p_protect_info[2]);
- LOG_VERBOSE("%s: codec: %s", __func__,
- A2DP_CodecInfoString(p_codec_info).c_str());
+ log::verbose("peer {} bta_av_handle:0x{:x} codec:{} seid:{}",
+ ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle,
+ A2DP_CodecName(p_codec_info), seid);
+ log::verbose("num_protect:0x{:02x} protect_info:0x{:02x}{:02x}{:02x}",
+ *p_num_protect, p_protect_info[0], p_protect_info[1],
+ p_protect_info[2]);
+ log::verbose("codec: {}", A2DP_CodecInfoString(p_codec_info));
// Find the peer
BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
if (p_peer == nullptr) {
- LOG_ERROR("%s: could not find peer entry for bta_av_handle 0x%x peer %s",
- __func__, bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address));
+ log::error("could not find peer entry for bta_av_handle 0x{:x} peer {}",
+ bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address));
return A2DP_FAIL;
}
- LOG_VERBOSE(
- "%s: peer %s found (o=%d, n_sources=%d, n_rx_sources=%d, "
- "n_sup_sources=%d)",
- __func__, ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr), p_peer->opened,
+ log::verbose(
+ "peer {} found (o={}, n_sources={}, n_rx_sources={}, n_sup_sources={})",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr), p_peer->opened,
p_peer->num_sources, p_peer->num_rx_sources, p_peer->num_sup_sources);
p_peer->num_rx_sources++;
@@ -1136,9 +1135,9 @@
if (p_peer->num_sup_sources < BTA_AV_CO_NUM_ELEMENTS(p_peer->sources)) {
BtaAvCoSep* p_source = &p_peer->sources[p_peer->num_sup_sources++];
- LOG_VERBOSE("%s: saved caps[%x:%x:%x:%x:%x:%x]", __func__,
- p_codec_info[1], p_codec_info[2], p_codec_info[3],
- p_codec_info[4], p_codec_info[5], p_codec_info[6]);
+ log::verbose("saved caps[{:x}:{:x}:{:x}:{:x}:{:x}:{:x}]", p_codec_info[1],
+ p_codec_info[2], p_codec_info[3], p_codec_info[4],
+ p_codec_info[5], p_codec_info[6]);
memcpy(p_source->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
p_source->sep_info_idx = *p_sep_info_idx;
@@ -1146,8 +1145,8 @@
p_source->num_protect = *p_num_protect;
memcpy(p_source->protect_info, p_protect_info, AVDT_CP_INFO_LEN);
} else {
- LOG_ERROR("%s: peer %s : no more room for Source info", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::error("peer {} : no more room for Source info",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
}
}
@@ -1157,8 +1156,8 @@
(p_peer->num_sup_sources != BTA_AV_CO_NUM_ELEMENTS(p_peer->sources))) {
return A2DP_FAIL;
}
- LOG_VERBOSE("%s: last Source codec reached for peer %s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::verbose("last Source codec reached for peer {}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
// Select the Sink codec
const BtaAvCoSep* p_source = nullptr;
@@ -1171,15 +1170,15 @@
}
p_source = p_peer->p_source;
if (p_source == nullptr) {
- LOG_ERROR("%s: cannot find the selected codec for peer %s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::error("cannot find the selected codec for peer {}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
return A2DP_FAIL;
}
} else {
p_source = SelectSinkCodec(p_peer);
if (p_source == nullptr) {
- LOG_ERROR("%s: cannot set up codec for the peer %s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::error("cannot set up codec for the peer {}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
return A2DP_FAIL;
}
}
@@ -1193,14 +1192,14 @@
// If acceptor -> reconfig otherwise reply for configuration
*p_sep_info_idx = p_source->sep_info_idx;
- LOG_VERBOSE("%s: peer %s acceptor:%s reconfig_needed:%s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr),
- (p_peer->acceptor) ? "true" : "false",
- (p_peer->reconfig_needed) ? "true" : "false");
+ log::verbose("peer {} acceptor:{} reconfig_needed:{}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr),
+ (p_peer->acceptor) ? "true" : "false",
+ (p_peer->reconfig_needed) ? "true" : "false");
if (p_peer->acceptor) {
if (p_peer->reconfig_needed) {
- LOG_VERBOSE("%s: call BTA_AvReconfig(0x%x) for peer %s", __func__,
- bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::verbose("call BTA_AvReconfig(0x{:x}) for peer {}", bta_av_handle,
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
BTA_AvReconfig(bta_av_handle, true, p_source->sep_info_idx,
p_peer->codec_config, *p_num_protect, bta_av_co_cp_scmst);
}
@@ -1221,56 +1220,54 @@
uint8_t category = A2DP_SUCCESS;
bool reconfig_needed = false;
- LOG_VERBOSE(
- "%s: bta_av_handle=0x%x peer_address=%s seid=%d "
- "num_protect=%d t_local_sep=%d avdt_handle=%d",
- __func__, bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address), seid,
- num_protect, t_local_sep, avdt_handle);
- LOG_VERBOSE("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", __func__, p_codec_info[1],
- p_codec_info[2], p_codec_info[3], p_codec_info[4],
- p_codec_info[5], p_codec_info[6]);
- LOG_VERBOSE("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x", __func__,
- num_protect, p_protect_info[0], p_protect_info[1],
- p_protect_info[2]);
- LOG_VERBOSE("%s: codec: %s", __func__,
- A2DP_CodecInfoString(p_codec_info).c_str());
+ log::verbose(
+ "bta_av_handle=0x{:x} peer_address={} seid={} num_protect={} "
+ "t_local_sep={} avdt_handle={}",
+ bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address), seid, num_protect,
+ t_local_sep, avdt_handle);
+ log::verbose("p_codec_info[{:x}:{:x}:{:x}:{:x}:{:x}:{:x}]", p_codec_info[1],
+ p_codec_info[2], p_codec_info[3], p_codec_info[4],
+ p_codec_info[5], p_codec_info[6]);
+ log::verbose("num_protect:0x{:02x} protect_info:0x{:02x}{:02x}{:02x}",
+ num_protect, p_protect_info[0], p_protect_info[1],
+ p_protect_info[2]);
+ log::verbose("codec: {}", A2DP_CodecInfoString(p_codec_info));
// Find the peer
BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
if (p_peer == nullptr) {
- LOG_ERROR("%s: could not find peer entry for bta_av_handle 0x%x peer %s",
- __func__, bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address));
+ log::error("could not find peer entry for bta_av_handle 0x{:x} peer {}",
+ bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address));
// Call call-in rejecting the configuration
bta_av_ci_setconfig(bta_av_handle, A2DP_BUSY, AVDT_ASC_CODEC, 0, nullptr,
false, avdt_handle);
return;
}
- LOG_VERBOSE(
- "%s: peer %s found (o=%d, n_sinks=%d, n_rx_sinks=%d, "
- "n_sup_sinks=%d)",
- __func__, ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr), p_peer->opened,
- p_peer->num_sinks, p_peer->num_rx_sinks, p_peer->num_sup_sinks);
+ log::verbose(
+ "peer {} found (o={}, n_sinks={}, n_rx_sinks={}, n_sup_sinks={})",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr), p_peer->opened, p_peer->num_sinks,
+ p_peer->num_rx_sinks, p_peer->num_sup_sinks);
// Sanity check: should not be opened at this point
if (p_peer->opened) {
- LOG_ERROR("%s: peer %s already in use", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::error("peer {} already in use",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
}
if (num_protect != 0) {
if (ContentProtectEnabled()) {
if ((num_protect != 1) ||
!BtaAvCo::ContentProtectIsScmst(p_protect_info)) {
- LOG_ERROR("%s: wrong CP configuration for peer %s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::error("wrong CP configuration for peer {}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
status = A2DP_BAD_CP_TYPE;
category = AVDT_ASC_PROTECT;
}
} else {
// Do not support content protection for the time being
- LOG_ERROR("%s: wrong CP configuration for peer %s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::error("wrong CP configuration for peer {}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
status = A2DP_BAD_CP_TYPE;
category = AVDT_ASC_PROTECT;
}
@@ -1280,8 +1277,8 @@
bool codec_config_supported = false;
if (t_local_sep == AVDT_TSEP_SNK) {
- LOG_VERBOSE("%s: peer %s is A2DP Source", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::verbose("peer {} is A2DP Source",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
codec_config_supported = A2DP_IsSinkCodecSupported(p_codec_info);
if (codec_config_supported) {
// If Peer is Source, and our config subset matches with what is
@@ -1290,17 +1287,17 @@
}
}
if (t_local_sep == AVDT_TSEP_SRC) {
- LOG_VERBOSE("%s: peer %s is A2DP SINK", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::verbose("peer {} is A2DP SINK",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
// Ignore the restart_output flag: accepting the remote device's
// codec selection should not trigger codec reconfiguration.
bool dummy_restart_output = false;
if ((p_peer->GetCodecs() == nullptr) ||
!SetCodecOtaConfig(p_peer, p_codec_info, num_protect, p_protect_info,
&dummy_restart_output)) {
- LOG_ERROR("%s: cannot set source codec %s for peer %s", __func__,
- A2DP_CodecName(p_codec_info),
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::error("cannot set source codec {} for peer {}",
+ A2DP_CodecName(p_codec_info),
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
} else {
codec_config_supported = true;
// Check if reconfiguration is needed
@@ -1318,8 +1315,8 @@
}
if (status != A2DP_SUCCESS) {
- LOG_VERBOSE("%s: peer %s reject s=%d c=%d", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr), status, category);
+ log::verbose("peer {} reject s={} c={}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr), status, category);
// Call call-in rejecting the configuration
bta_av_ci_setconfig(bta_av_handle, status, category, 0, nullptr, false,
avdt_handle);
@@ -1329,8 +1326,8 @@
// Mark that this is an acceptor peer
p_peer->acceptor = true;
p_peer->reconfig_needed = reconfig_needed;
- LOG_VERBOSE("%s: peer %s accept reconf=%d", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr), reconfig_needed);
+ log::verbose("peer {} accept reconf={}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr), reconfig_needed);
// Call call-in accepting the configuration
bta_av_ci_setconfig(bta_av_handle, A2DP_SUCCESS, A2DP_SUCCESS, 0, nullptr,
reconfig_needed, avdt_handle);
@@ -1338,14 +1335,14 @@
void BtaAvCo::ProcessOpen(tBTA_AV_HNDL bta_av_handle,
const RawAddress& peer_address, uint16_t mtu) {
- LOG_VERBOSE("%s: peer %s bta_av_handle: 0x%x mtu:%d", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle, mtu);
+ log::verbose("peer {} bta_av_handle: 0x{:x} mtu:{}",
+ ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle, mtu);
// Find the peer
BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
if (p_peer == nullptr) {
- LOG_ERROR("%s: could not find peer entry for bta_av_handle 0x%x peer %s",
- __func__, bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address));
+ log::error("could not find peer entry for bta_av_handle 0x{:x} peer {}",
+ bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address));
return;
}
p_peer->opened = true;
@@ -1359,15 +1356,15 @@
void BtaAvCo::ProcessClose(tBTA_AV_HNDL bta_av_handle,
const RawAddress& peer_address) {
- LOG_VERBOSE("%s: peer %s bta_av_handle: 0x%x", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle);
+ log::verbose("peer {} bta_av_handle: 0x{:x}",
+ ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle);
btif_av_reset_audio_delay();
// Find the peer
BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
if (p_peer == nullptr) {
- LOG_ERROR("%s: could not find peer entry for bta_av_handle 0x%x peer %s",
- __func__, bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address));
+ log::error("could not find peer entry for bta_av_handle 0x{:x} peer {}",
+ bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address));
return;
}
// Reset the active peer
@@ -1381,29 +1378,29 @@
void BtaAvCo::ProcessStart(tBTA_AV_HNDL bta_av_handle,
const RawAddress& peer_address,
const uint8_t* p_codec_info, bool* p_no_rtp_header) {
- LOG_VERBOSE("%s: peer %s bta_av_handle: 0x%x", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle);
+ log::verbose("peer {} bta_av_handle: 0x{:x}",
+ ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle);
// Find the peer
BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
if (p_peer == nullptr) {
- LOG_ERROR("%s: could not find peer entry for bta_av_handle 0x%x peer %s",
- __func__, bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address));
+ log::error("could not find peer entry for bta_av_handle 0x{:x} peer {}",
+ bta_av_handle, ADDRESS_TO_LOGGABLE_CSTR(peer_address));
return;
}
bool add_rtp_header =
A2DP_UsesRtpHeader(p_peer->ContentProtectActive(), p_codec_info);
- LOG_VERBOSE("%s: bta_av_handle: 0x%x add_rtp_header: %s", __func__,
- bta_av_handle, add_rtp_header ? "true" : "false");
+ log::verbose("bta_av_handle: 0x{:x} add_rtp_header: {}", bta_av_handle,
+ add_rtp_header ? "true" : "false");
*p_no_rtp_header = !add_rtp_header;
}
void BtaAvCo::ProcessStop(tBTA_AV_HNDL bta_av_handle,
const RawAddress& peer_address) {
- LOG_VERBOSE("%s: peer %s bta_av_handle: 0x%x", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle);
+ log::verbose("peer {} bta_av_handle: 0x{:x}",
+ ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle);
// Nothing to do
}
@@ -1411,14 +1408,14 @@
uint32_t* p_timestamp) {
BT_HDR* p_buf;
- LOG_VERBOSE("%s: codec: %s", __func__, A2DP_CodecName(p_codec_info));
+ log::verbose("codec: {}", A2DP_CodecName(p_codec_info));
p_buf = btif_a2dp_source_audio_readbuf();
if (p_buf == nullptr) return nullptr;
if (p_buf->offset < 4) {
osi_free(p_buf);
- LOG_ERROR("No space for timestamp in packet, dropped");
+ log::error("No space for timestamp in packet, dropped");
return nullptr;
}
/*
@@ -1432,8 +1429,7 @@
if (!A2DP_GetPacketTimestamp(p_codec_info, (const uint8_t*)(p_buf + 1),
p_timestamp) ||
!A2DP_BuildCodecHeader(p_codec_info, p_buf, p_buf->layer_specific)) {
- LOG_ERROR("%s: unsupported codec type (%d)", __func__,
- A2DP_GetCodecType(p_codec_info));
+ log::error("unsupported codec type ({})", A2DP_GetCodecType(p_codec_info));
osi_free(p_buf);
return nullptr;
}
@@ -1453,38 +1449,36 @@
void BtaAvCo::DataPacketWasDropped(tBTA_AV_HNDL bta_av_handle,
const RawAddress& peer_address) {
- LOG_ERROR("%s: peer %s dropped audio packet on handle 0x%x", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle);
+ log::error("peer {} dropped audio packet on handle 0x{:x}",
+ ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle);
}
void BtaAvCo::ProcessAudioDelay(tBTA_AV_HNDL bta_av_handle,
const RawAddress& peer_address,
uint16_t delay) {
- LOG_VERBOSE("%s: peer %s bta_av_handle: 0x%x delay:0x%x", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle, delay);
+ log::verbose("peer {} bta_av_handle: 0x{:x} delay:0x{:x}",
+ ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle, delay);
btif_av_set_audio_delay(peer_address, delay);
}
void BtaAvCo::UpdateMtu(tBTA_AV_HNDL bta_av_handle,
const RawAddress& peer_address, uint16_t mtu) {
- LOG(INFO) << __func__ << ": peer " << ADDRESS_TO_LOGGABLE_STR(peer_address)
- << " bta_av_handle: " << loghex(bta_av_handle) << " mtu: " << mtu;
+ log::info("peer {} bta_av_handle: {} mtu: {}",
+ ADDRESS_TO_LOGGABLE_STR(peer_address), loghex(bta_av_handle), mtu);
// Find the peer
BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
if (p_peer == nullptr) {
- LOG(ERROR) << __func__ << ": could not find peer entry for bta_av_handle "
- << loghex(bta_av_handle) << " peer "
- << ADDRESS_TO_LOGGABLE_STR(peer_address);
+ log::error("could not find peer entry for bta_av_handle {} peer {}",
+ loghex(bta_av_handle), ADDRESS_TO_LOGGABLE_STR(peer_address));
return;
}
p_peer->mtu = mtu;
}
bool BtaAvCo::SetActivePeer(const RawAddress& peer_address) {
- LOG(INFO) << __func__
- << ": peer_address=" << ADDRESS_TO_LOGGABLE_STR(peer_address);
+ log::info("peer_address={}", ADDRESS_TO_LOGGABLE_STR(peer_address));
std::lock_guard<std::recursive_mutex> lock(codec_lock_);
@@ -1503,7 +1497,7 @@
active_peer_ = p_peer;
memcpy(codec_config_, active_peer_->codec_config, AVDT_CODEC_SIZE);
- LOG(INFO) << __func__ << ": codec = " << A2DP_CodecInfoString(codec_config_);
+ log::info("codec = {}", A2DP_CodecInfoString(codec_config_));
// report the selected codec configuration of this new active peer.
ReportSourceCodecState(active_peer_);
return true;
@@ -1533,11 +1527,11 @@
p_peer_params->is_peer_edr = btif_av_is_peer_edr(peer_address);
p_peer_params->peer_supports_3mbps =
btif_av_peer_supports_3mbps(peer_address);
- LOG_VERBOSE(
- "%s: peer_address=%s peer_mtu=%d is_peer_edr=%s peer_supports_3mbps=%s",
- __func__, ADDRESS_TO_LOGGABLE_CSTR(peer_address), p_peer_params->peer_mtu,
- logbool(p_peer_params->is_peer_edr).c_str(),
- logbool(p_peer_params->peer_supports_3mbps).c_str());
+ log::verbose(
+ "peer_address={} peer_mtu={} is_peer_edr={} peer_supports_3mbps={}",
+ ADDRESS_TO_LOGGABLE_CSTR(peer_address), p_peer_params->peer_mtu,
+ logbool(p_peer_params->is_peer_edr),
+ logbool(p_peer_params->peer_supports_3mbps));
}
const tA2DP_ENCODER_INTERFACE* BtaAvCo::GetSourceEncoderInterface() {
@@ -1556,17 +1550,16 @@
bool config_updated = false;
bool success = true;
- VLOG(1) << __func__ << ": peer_address="
- << ADDRESS_TO_LOGGABLE_STR(peer_address)
- << " codec_user_config={" << codec_user_config.ToString() << "}";
+ log::verbose("peer_address={} codec_user_config={{}}",
+ ADDRESS_TO_LOGGABLE_STR(peer_address),
+ codec_user_config.ToString());
*p_restart_output = false;
BtaAvCoPeer* p_peer = FindPeer(peer_address);
if (p_peer == nullptr) {
- LOG(ERROR) << __func__ << ": cannot find peer "
- << ADDRESS_TO_LOGGABLE_STR(peer_address)
- << " to configure";
+ log::error("cannot find peer {} to configure",
+ ADDRESS_TO_LOGGABLE_STR(peer_address));
success = false;
goto done;
}
@@ -1574,9 +1567,8 @@
// Don't call BTA_AvReconfig() prior to retrieving all peer's capabilities
if ((p_peer->num_rx_sinks != p_peer->num_sinks) &&
(p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) {
- LOG(WARNING) << __func__ << ": peer "
- << ADDRESS_TO_LOGGABLE_STR(p_peer->addr)
- << " : not all peer's capabilities have been retrieved";
+ log::warn("peer {} : not all peer's capabilities have been retrieved",
+ ADDRESS_TO_LOGGABLE_STR(p_peer->addr));
success = false;
goto done;
}
@@ -1589,9 +1581,9 @@
p_sink = p_peer->p_sink;
}
if (p_sink == nullptr) {
- LOG(ERROR) << __func__ << ": peer " << ADDRESS_TO_LOGGABLE_STR(p_peer->addr)
- << " : cannot find peer SEP to configure for codec type "
- << codec_user_config.codec_type;
+ log::error("peer {} : cannot find peer SEP to configure for codec type {}",
+ ADDRESS_TO_LOGGABLE_STR(p_peer->addr),
+ codec_user_config.codec_type);
success = false;
goto done;
}
@@ -1614,16 +1606,14 @@
p_sink = SelectSourceCodec(p_peer);
if (p_sink == nullptr) {
- LOG(ERROR) << __func__ << ": peer "
- << ADDRESS_TO_LOGGABLE_STR(p_peer->addr)
- << " : cannot set up codec for the peer SINK";
+ log::error("peer {} : cannot set up codec for the peer SINK",
+ ADDRESS_TO_LOGGABLE_STR(p_peer->addr));
success = false;
goto done;
}
p_peer->acceptor = false;
- VLOG(1) << __func__ << ": call BTA_AvReconfig("
- << loghex(p_peer->BtaAvHandle()) << ")";
+ log::verbose("call BTA_AvReconfig({})", loghex(p_peer->BtaAvHandle()));
BTA_AvReconfig(p_peer->BtaAvHandle(), true, p_sink->sep_info_idx,
p_peer->codec_config, num_protect, bta_av_co_cp_scmst);
*p_restart_output = true;
@@ -1652,31 +1642,28 @@
bool restart_output = false;
bool config_updated = false;
- VLOG(1) << __func__
- << ": codec_audio_config: " << codec_audio_config.ToString();
+ log::verbose("codec_audio_config: {}", codec_audio_config.ToString());
// Find the peer that is currently open
BtaAvCoPeer* p_peer = active_peer_;
if (p_peer == nullptr) {
- LOG(ERROR) << __func__ << ": no active peer to configure";
+ log::error("no active peer to configure");
return false;
}
// Don't call BTA_AvReconfig() prior to retrieving all peer's capabilities
if ((p_peer->num_rx_sinks != p_peer->num_sinks) &&
(p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) {
- LOG(WARNING) << __func__ << ": peer "
- << ADDRESS_TO_LOGGABLE_STR(p_peer->addr)
- << " : not all peer's capabilities have been retrieved";
+ log::warn("peer {} : not all peer's capabilities have been retrieved",
+ ADDRESS_TO_LOGGABLE_STR(p_peer->addr));
return false;
}
// Use the current sink codec
const BtaAvCoSep* p_sink = p_peer->p_sink;
if (p_sink == nullptr) {
- LOG(ERROR) << __func__ << ": peer "
- << ADDRESS_TO_LOGGABLE_STR(p_peer->addr)
- << " : cannot find peer SEP to configure";
+ log::error("peer {} : cannot find peer SEP to configure",
+ ADDRESS_TO_LOGGABLE_STR(p_peer->addr));
return false;
}
@@ -1698,8 +1685,7 @@
p_sink->protect_info);
p_peer->acceptor = false;
- VLOG(1) << __func__ << ": call BTA_AvReconfig("
- << loghex(p_peer->BtaAvHandle()) << ")";
+ log::verbose("call BTA_AvReconfig({})", loghex(p_peer->BtaAvHandle()));
BTA_AvReconfig(p_peer->BtaAvHandle(), true, p_sink->sep_info_idx,
p_peer->codec_config, num_protect, bta_av_co_cp_scmst);
}
@@ -1734,25 +1720,23 @@
std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities;
std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities;
- VLOG(1) << __func__ << ": peer_address="
- << ADDRESS_TO_LOGGABLE_STR(p_peer->addr);
+ log::verbose("peer_address={}", ADDRESS_TO_LOGGABLE_STR(p_peer->addr));
A2dpCodecs* codecs = p_peer->GetCodecs();
if (codecs == nullptr) {
- LOG_ERROR("Peer codecs is set to null");
+ log::error("Peer codecs is set to null");
return false;
}
if (!codecs->getCodecConfigAndCapabilities(&codec_config,
&codecs_local_capabilities,
&codecs_selectable_capabilities)) {
- LOG(WARNING) << __func__ << ": Peer "
- << ADDRESS_TO_LOGGABLE_STR(p_peer->addr)
- << " : error reporting audio source codec state: cannot get "
- "codec config and capabilities";
+ log::warn(
+ "Peer {} : error reporting audio source codec state: cannot get codec "
+ "config and capabilities",
+ ADDRESS_TO_LOGGABLE_STR(p_peer->addr));
return false;
}
- LOG(INFO) << __func__ << ": peer "
- << ADDRESS_TO_LOGGABLE_STR(p_peer->addr) << " codec_config={"
- << codec_config.ToString() << "}";
+ log::info("peer {} codec_config={{}}", ADDRESS_TO_LOGGABLE_STR(p_peer->addr),
+ codec_config.ToString());
btif_av_report_source_codec_state(p_peer->addr, codec_config,
codecs_local_capabilities,
codecs_selectable_capabilities);
@@ -1760,8 +1744,7 @@
}
bool BtaAvCo::ReportSinkCodecState(BtaAvCoPeer* p_peer) {
- LOG_VERBOSE("%s: peer_address=%s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::verbose("peer_address={}", ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
// Nothing to do (for now)
return true;
}
@@ -1809,14 +1792,14 @@
}
bool BtaAvCo::ContentProtectIsScmst(const uint8_t* p_protect_info) {
- LOG_VERBOSE("%s", __func__);
+ log::verbose("");
if (*p_protect_info >= AVDT_CP_LOSC) {
uint16_t cp_id;
p_protect_info++;
STREAM_TO_UINT16(cp_id, p_protect_info);
if (cp_id == AVDT_CP_SCMS_T_ID) {
- LOG_VERBOSE("%s: SCMS-T found", __func__);
+ log::verbose("SCMS-T found");
return true;
}
}
@@ -1825,18 +1808,18 @@
bool BtaAvCo::AudioProtectHasScmst(uint8_t num_protect,
const uint8_t* p_protect_info) {
- LOG_VERBOSE("%s", __func__);
+ log::verbose("");
while (num_protect--) {
if (BtaAvCo::ContentProtectIsScmst(p_protect_info)) return true;
// Move to the next Content Protect schema
p_protect_info += *p_protect_info + 1;
}
- LOG_VERBOSE("%s: SCMS-T not found", __func__);
+ log::verbose("SCMS-T not found");
return false;
}
bool BtaAvCo::AudioSepHasContentProtection(const BtaAvCoSep* p_sep) {
- LOG_VERBOSE("%s", __func__);
+ log::verbose("");
// Check if content protection is enabled for this stream
if (ContentProtectFlag() != AVDT_CP_SCMS_COPY_FREE) {
@@ -1844,7 +1827,7 @@
p_sep->protect_info);
}
- LOG_VERBOSE("%s: not required", __func__);
+ log::verbose("not required");
return true;
}
@@ -1878,7 +1861,7 @@
// AttemptSourceCodecSelection, except the configuration
// is provided by the HAL rather than derived locally.
- LOG_INFO("Configuration=%s", provider_codec_config.toString().c_str());
+ log::info("Configuration={}", provider_codec_config.toString());
// Identify the selected sink.
auto* p_sink =
@@ -1929,16 +1912,16 @@
const BtaAvCoSep* p_sink = FindPeerSink(p_peer, iter->codecIndex());
if (p_sink == nullptr) {
- LOG_VERBOSE("peer Sink for codec %s not found", iter->name().c_str());
+ log::verbose("peer Sink for codec {} not found", iter->name());
continue;
}
if (!p_peer->GetCodecs()->setCodecConfig(
p_sink->codec_caps, true /* is_capability */, new_codec_config,
false /* select_current_codec */)) {
- LOG_VERBOSE("cannot set source codec %s", iter->name().c_str());
+ log::verbose("cannot set source codec {}", iter->name());
} else {
- LOG_VERBOSE("feasible to set source codec %s", iter->name().c_str());
+ log::verbose("feasible to set source codec {}", iter->name());
software_codec_config = iter;
break;
}
@@ -1971,13 +1954,13 @@
// Select the codec
for (const auto& iter : p_peer->GetCodecs()->orderedSinkCodecs()) {
- LOG_VERBOSE("%s: trying codec %s", __func__, iter->name().c_str());
+ log::verbose("trying codec {}", iter->name());
p_source = AttemptSinkCodecSelection(*iter, p_peer);
if (p_source != nullptr) {
- LOG_VERBOSE("%s: selected codec %s", __func__, iter->name().c_str());
+ log::verbose("selected codec {}", iter->name());
break;
}
- LOG_VERBOSE("%s: cannot use codec %s", __func__, iter->name().c_str());
+ log::verbose("cannot use codec {}", iter->name());
}
// NOTE: Unconditionally dispatch the event to make sure a callback with
@@ -1990,8 +1973,8 @@
BtaAvCoSep* BtaAvCo::FindPeerSink(BtaAvCoPeer* p_peer,
btav_a2dp_codec_index_t codec_index) {
if (codec_index == BTAV_A2DP_CODEC_INDEX_MAX) {
- LOG_WARN("%s: invalid codec index for peer %s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::warn("invalid codec index for peer {}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
return nullptr;
}
@@ -2004,10 +1987,8 @@
continue;
}
if (!AudioSepHasContentProtection(p_sink)) {
- LOG_VERBOSE(
- "%s: peer Sink for codec %s does not support "
- "Content Protection",
- __func__, A2DP_CodecIndexStr(codec_index));
+ log::verbose("peer Sink for codec {} does not support Content Protection",
+ A2DP_CodecIndexStr(codec_index));
continue;
}
return p_sink;
@@ -2018,8 +1999,8 @@
BtaAvCoSep* BtaAvCo::FindPeerSource(BtaAvCoPeer* p_peer,
btav_a2dp_codec_index_t codec_index) {
if (codec_index == BTAV_A2DP_CODEC_INDEX_MAX) {
- LOG_WARN("%s: invalid codec index for peer %s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::warn("invalid codec index for peer {}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
return nullptr;
}
@@ -2032,10 +2013,9 @@
continue;
}
if (!AudioSepHasContentProtection(p_source)) {
- LOG_VERBOSE(
- "%s: peer Source for codec %s does not support "
- "Content Protection",
- __func__, A2DP_CodecIndexStr(codec_index));
+ log::verbose(
+ "peer Source for codec {} does not support Content Protection",
+ A2DP_CodecIndexStr(codec_index));
continue;
}
return p_source;
@@ -2047,20 +2027,18 @@
const A2dpCodecConfig& codec_config, BtaAvCoPeer* p_peer) {
uint8_t new_codec_config[AVDT_CODEC_SIZE];
- LOG_VERBOSE("%s", __func__);
+ log::verbose("");
// Find the peer Sink for the codec
BtaAvCoSep* p_sink = FindPeerSink(p_peer, codec_config.codecIndex());
if (p_sink == nullptr) {
- LOG_VERBOSE("%s: peer Sink for codec %s not found", __func__,
- codec_config.name().c_str());
+ log::verbose("peer Sink for codec {} not found", codec_config.name());
return nullptr;
}
if (!p_peer->GetCodecs()->setCodecConfig(
p_sink->codec_caps, true /* is_capability */, new_codec_config,
true /* select_current_codec */)) {
- LOG_VERBOSE("%s: cannot set source codec %s", __func__,
- codec_config.name().c_str());
+ log::verbose("cannot set source codec {}", codec_config.name());
return nullptr;
}
p_peer->p_sink = p_sink;
@@ -2075,20 +2053,18 @@
const A2dpCodecConfig& codec_config, BtaAvCoPeer* p_peer) {
uint8_t new_codec_config[AVDT_CODEC_SIZE];
- LOG_VERBOSE("%s", __func__);
+ log::verbose("");
// Find the peer Source for the codec
BtaAvCoSep* p_source = FindPeerSource(p_peer, codec_config.codecIndex());
if (p_source == nullptr) {
- LOG_VERBOSE("%s: peer Source for codec %s not found", __func__,
- codec_config.name().c_str());
+ log::verbose("peer Source for codec {} not found", codec_config.name());
return nullptr;
}
if (!p_peer->GetCodecs()->setSinkCodecConfig(
p_source->codec_caps, true /* is_capability */, new_codec_config,
true /* select_current_codec */)) {
- LOG_VERBOSE("%s: cannot set sink codec %s", __func__,
- codec_config.name().c_str());
+ log::verbose("cannot set sink codec {}", codec_config.name());
return nullptr;
}
p_peer->p_source = p_source;
@@ -2100,12 +2076,11 @@
}
size_t BtaAvCo::UpdateAllSelectableSourceCodecs(BtaAvCoPeer* p_peer) {
- LOG_VERBOSE("%s: peer %s", __func__, ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::verbose("peer {}", ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
size_t updated_codecs = 0;
for (const auto& iter : p_peer->GetCodecs()->orderedSourceCodecs()) {
- LOG_VERBOSE("%s: updating selectable codec %s", __func__,
- iter->name().c_str());
+ log::verbose("updating selectable codec {}", iter->name());
if (UpdateSelectableSourceCodec(*iter, p_peer)) {
updated_codecs++;
}
@@ -2115,7 +2090,7 @@
bool BtaAvCo::UpdateSelectableSourceCodec(const A2dpCodecConfig& codec_config,
BtaAvCoPeer* p_peer) {
- LOG_VERBOSE("%s: peer %s", __func__, ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::verbose("peer {}", ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
// Find the peer Sink for the codec
const BtaAvCoSep* p_sink = FindPeerSink(p_peer, codec_config.codecIndex());
@@ -2124,21 +2099,20 @@
return false;
}
if (!p_peer->GetCodecs()->setPeerSinkCodecCapabilities(p_sink->codec_caps)) {
- LOG_WARN("%s: cannot update peer %s codec capabilities for %s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr),
- A2DP_CodecName(p_sink->codec_caps));
+ log::warn("cannot update peer {} codec capabilities for {}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr),
+ A2DP_CodecName(p_sink->codec_caps));
return false;
}
return true;
}
size_t BtaAvCo::UpdateAllSelectableSinkCodecs(BtaAvCoPeer* p_peer) {
- LOG_VERBOSE("%s: peer %s", __func__, ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::verbose("peer {}", ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
size_t updated_codecs = 0;
for (const auto& iter : p_peer->GetCodecs()->orderedSinkCodecs()) {
- LOG_VERBOSE("%s: updating selectable codec %s", __func__,
- iter->name().c_str());
+ log::verbose("updating selectable codec {}", iter->name());
if (UpdateSelectableSinkCodec(*iter, p_peer)) {
updated_codecs++;
}
@@ -2148,7 +2122,7 @@
bool BtaAvCo::UpdateSelectableSinkCodec(const A2dpCodecConfig& codec_config,
BtaAvCoPeer* p_peer) {
- LOG_VERBOSE("%s: peer %s", __func__, ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::verbose("peer {}", ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
// Find the peer Source for the codec
const BtaAvCoSep* p_source =
@@ -2159,9 +2133,9 @@
}
if (!p_peer->GetCodecs()->setPeerSourceCodecCapabilities(
p_source->codec_caps)) {
- LOG_WARN("%s: cannot update peer %s codec capabilities for %s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr),
- A2DP_CodecName(p_source->codec_caps));
+ log::warn("cannot update peer {} codec capabilities for {}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr),
+ A2DP_CodecName(p_source->codec_caps));
return false;
}
return true;
@@ -2171,9 +2145,8 @@
const uint8_t* new_codec_config,
uint8_t num_protect,
const uint8_t* p_protect_info) {
- LOG_VERBOSE("%s: peer %s", __func__, ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
- LOG_VERBOSE("%s: codec: %s", __func__,
- A2DP_CodecInfoString(new_codec_config).c_str());
+ log::verbose("peer {}", ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
+ log::verbose("codec: {}", A2DP_CodecInfoString(new_codec_config));
std::lock_guard<std::recursive_mutex> lock(codec_lock_);
@@ -2197,9 +2170,8 @@
bool restart_output = false;
bool config_updated = false;
- LOG(INFO) << __func__ << ": peer_address="
- << ADDRESS_TO_LOGGABLE_STR(p_peer->addr)
- << ", codec: " << A2DP_CodecInfoString(p_ota_codec_config);
+ log::info("peer_address={}, codec: {}", ADDRESS_TO_LOGGABLE_STR(p_peer->addr),
+ A2DP_CodecInfoString(p_ota_codec_config));
*p_restart_output = false;
@@ -2210,9 +2182,8 @@
// There are no peer SEPs if we didn't do the discovery procedure yet.
// We have all the information we need from the peer, so we can
// proceed with the OTA codec configuration.
- LOG(ERROR) << __func__ << ": peer "
- << ADDRESS_TO_LOGGABLE_STR(p_peer->addr)
- << " : cannot find peer SEP to configure";
+ log::error("peer {} : cannot find peer SEP to configure",
+ ADDRESS_TO_LOGGABLE_STR(p_peer->addr));
return false;
}
@@ -2221,15 +2192,14 @@
if (!p_peer->GetCodecs()->setCodecOtaConfig(
p_ota_codec_config, &peer_params, result_codec_config, &restart_input,
&restart_output, &config_updated)) {
- LOG(ERROR) << __func__ << ": peer "
- << ADDRESS_TO_LOGGABLE_STR(p_peer->addr)
- << " : cannot set OTA config";
+ log::error("peer {} : cannot set OTA config",
+ ADDRESS_TO_LOGGABLE_STR(p_peer->addr));
return false;
}
if (restart_output) {
- VLOG(1) << __func__ << ": restart output for codec: "
- << A2DP_CodecInfoString(result_codec_config);
+ log::verbose("restart output for codec: {}",
+ A2DP_CodecInfoString(result_codec_config));
*p_restart_output = true;
p_peer->p_sink = p_sink;
@@ -2281,7 +2251,7 @@
static void bta_av_co_store_peer_codectype(const BtaAvCoPeer* p_peer) {
int index, peer_codec_type = 0;
const BtaAvCoSep* p_sink;
- LOG_VERBOSE("%s", __func__);
+ log::verbose("");
for (index = 0; index < p_peer->num_sup_sinks; index++) {
p_sink = &p_peer->sinks[index];
peer_codec_type |= A2DP_IotGetPeerSinkCodecType(p_sink->codec_caps);
@@ -2302,44 +2272,44 @@
// Prioritize any offload codec except SBC and AAC
if (A2DP_GetCodecType(hardware_config.codec_config) ==
A2DP_MEDIA_CT_NON_A2DP) {
- LOG_VERBOSE("select hardware codec: %s",
- A2DP_CodecIndexStr(hardware_offload_index));
+ log::verbose("select hardware codec: {}",
+ A2DP_CodecIndexStr(hardware_offload_index));
return true;
}
// Prioritize LDAC, AptX HD and AptX over AAC and SBC offload codecs
if (software_codec_index == BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC ||
software_codec_index == BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD ||
software_codec_index == BTAV_A2DP_CODEC_INDEX_SOURCE_APTX) {
- LOG_VERBOSE("select software codec: %s",
- A2DP_CodecIndexStr(software_codec_index));
+ log::verbose("select software codec: {}",
+ A2DP_CodecIndexStr(software_codec_index));
return false;
}
// Prioritize AAC offload
if (hardware_offload_index == BTAV_A2DP_CODEC_INDEX_SOURCE_AAC) {
- LOG_VERBOSE("select hardware codec: %s",
- A2DP_CodecIndexStr(hardware_offload_index));
+ log::verbose("select hardware codec: {}",
+ A2DP_CodecIndexStr(hardware_offload_index));
return true;
}
// Prioritize AAC software
if (software_codec_index == BTAV_A2DP_CODEC_INDEX_SOURCE_AAC) {
- LOG_VERBOSE("select software codec: %s",
- A2DP_CodecIndexStr(software_codec_index));
+ log::verbose("select software codec: {}",
+ A2DP_CodecIndexStr(software_codec_index));
return false;
}
// Prioritize SBC offload
if (hardware_offload_index == BTAV_A2DP_CODEC_INDEX_SOURCE_SBC) {
- LOG_VERBOSE("select hardware codec: %s",
- A2DP_CodecIndexStr(hardware_offload_index));
+ log::verbose("select hardware codec: {}",
+ A2DP_CodecIndexStr(hardware_offload_index));
return true;
}
// Prioritize SBC software
if (software_codec_index == BTAV_A2DP_CODEC_INDEX_SOURCE_SBC) {
- LOG_VERBOSE("select software codec: %s",
- A2DP_CodecIndexStr(software_codec_index));
+ log::verbose("select software codec: {}",
+ A2DP_CodecIndexStr(software_codec_index));
return false;
}
- LOG_ERROR("select unknown software codec: %s",
- A2DP_CodecIndexStr(software_codec_index));
+ log::error("select unknown software codec: {}",
+ A2DP_CodecIndexStr(software_codec_index));
return false;
}
@@ -2351,8 +2321,9 @@
uint8_t* p_protect_info) {
uint16_t peer_uuid = bta_av_co_cb.FindPeerUuid(bta_av_handle);
- LOG_VERBOSE("%s: peer %s bta_av_handle=0x%x peer_uuid=0x%x", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle, peer_uuid);
+ log::verbose("peer {} bta_av_handle=0x{:x} peer_uuid=0x{:x}",
+ ADDRESS_TO_LOGGABLE_CSTR(peer_address), bta_av_handle,
+ peer_uuid);
switch (peer_uuid) {
case UUID_SERVCLASS_AUDIO_SOURCE:
@@ -2366,9 +2337,8 @@
default:
break;
}
- LOG_ERROR("%s: peer %s : Invalid peer UUID: 0x%x for bta_av_handle 0x%x",
- __func__, ADDRESS_TO_LOGGABLE_CSTR(peer_address), peer_uuid,
- bta_av_handle);
+ log::error("peer {} : Invalid peer UUID: 0x{:x} for bta_av_handle 0x{:x}",
+ ADDRESS_TO_LOGGABLE_CSTR(peer_address), peer_uuid, bta_av_handle);
return A2DP_FAIL;
}
diff --git a/system/btif/co/bta_hh_co.cc b/system/btif/co/bta_hh_co.cc
index 8884857f..7b6a6e1 100644
--- a/system/btif/co/bta_hh_co.cc
+++ b/system/btif/co/bta_hh_co.cc
@@ -53,6 +53,8 @@
/* Max number of polling interrupt allowed */
#define BTA_HH_UHID_INTERRUPT_COUNT_MAX 100
+using namespace bluetooth;
+
static const bthh_report_type_t map_rtype_uhid_hh[] = {
BTHH_FEATURE_REPORT, BTHH_OUTPUT_REPORT, BTHH_INPUT_REPORT};
@@ -60,27 +62,25 @@
void uhid_set_non_blocking(int fd) {
int opts = fcntl(fd, F_GETFL);
- if (opts < 0)
- LOG_ERROR("%s() Getting flags failed (%s)", __func__, strerror(errno));
+ if (opts < 0) log::error("Getting flags failed ({})", strerror(errno));
opts |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, opts) < 0)
- LOG_VERBOSE("%s() Setting non-blocking flag failed (%s)", __func__,
- strerror(errno));
+ log::verbose("Setting non-blocking flag failed ({})", strerror(errno));
}
static bool uhid_feature_req_handler(btif_hh_device_t* p_dev,
struct uhid_feature_req& req) {
- LOG_DEBUG("Report type = %d, id = %d", req.rtype, req.rnum);
+ log::debug("Report type = {}, id = {}", req.rtype, req.rnum);
if (req.rtype > UHID_INPUT_REPORT) {
- LOG_ERROR("Invalid report type %d", req.rtype);
+ log::error("Invalid report type {}", req.rtype);
return false;
}
if (p_dev->get_rpt_id_queue == nullptr) {
- LOG_ERROR("Queue is not initialized");
+ log::error("Queue is not initialized");
return false;
}
@@ -89,7 +89,7 @@
if (!fixed_queue_try_enqueue(p_dev->get_rpt_id_queue, (void*)context)) {
osi_free(context);
- LOG_ERROR("Queue is full, dropping event %d", req.id);
+ log::error("Queue is full, dropping event {}", req.id);
return false;
}
@@ -100,15 +100,15 @@
#if ENABLE_UHID_SET_REPORT
static bool uhid_set_report_req_handler(btif_hh_device_t* p_dev,
struct uhid_set_report_req& req) {
- LOG_DEBUG("Report type = %d, id = %d", req.rtype, req.rnum);
+ log::debug("Report type = {}, id = {}", req.rtype, req.rnum);
if (req.rtype > UHID_INPUT_REPORT) {
- LOG_ERROR("Invalid report type %d", req.rtype);
+ log::error("Invalid report type {}", req.rtype);
return false;
}
if (p_dev->set_rpt_id_queue == nullptr) {
- LOG_ERROR("Queue is not initialized");
+ log::error("Queue is not initialized");
return false;
}
@@ -117,7 +117,7 @@
if (!fixed_queue_try_enqueue(p_dev->set_rpt_id_queue, (void*)context)) {
osi_free(context);
- LOG_ERROR("Queue is full, dropping event %d", req.id);
+ log::error("Queue is full, dropping event {}", req.id);
return false;
}
@@ -133,11 +133,10 @@
if (ret < 0) {
int rtn = -errno;
- LOG_ERROR("%s: Cannot write to uhid:%s", __func__, strerror(errno));
+ log::error("Cannot write to uhid:{}", strerror(errno));
return rtn;
} else if (ret != (ssize_t)sizeof(*ev)) {
- LOG_ERROR("%s: Wrong size written to uhid: %zd != %zu", __func__, ret,
- sizeof(*ev));
+ log::error("Wrong size written to uhid: {} != {}", ret, sizeof(*ev));
return -EFAULT;
}
@@ -155,39 +154,39 @@
OSI_NO_INTR(ret = read(p_dev->fd, &ev, sizeof(ev)));
if (ret == 0) {
- LOG_ERROR("%s: Read HUP on uhid-cdev %s", __func__, strerror(errno));
+ log::error("Read HUP on uhid-cdev {}", strerror(errno));
return -EFAULT;
} else if (ret < 0) {
- LOG_ERROR("%s: Cannot read uhid-cdev: %s", __func__, strerror(errno));
+ log::error("Cannot read uhid-cdev: {}", strerror(errno));
return -errno;
}
switch (ev.type) {
case UHID_START:
- LOG_VERBOSE("UHID_START from uhid-dev\n");
+ log::verbose("UHID_START from uhid-dev\n");
p_dev->ready_for_data = true;
break;
case UHID_STOP:
- LOG_VERBOSE("UHID_STOP from uhid-dev\n");
+ log::verbose("UHID_STOP from uhid-dev\n");
p_dev->ready_for_data = false;
break;
case UHID_OPEN:
- LOG_VERBOSE("UHID_OPEN from uhid-dev\n");
+ log::verbose("UHID_OPEN from uhid-dev\n");
p_dev->ready_for_data = true;
break;
case UHID_CLOSE:
- LOG_VERBOSE("UHID_CLOSE from uhid-dev\n");
+ log::verbose("UHID_CLOSE from uhid-dev\n");
p_dev->ready_for_data = false;
break;
case UHID_OUTPUT:
if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.output))) {
- LOG_ERROR("%s: Invalid size read from uhid-dev: %zd < %zu", __func__,
- ret, sizeof(ev.type) + sizeof(ev.u.output));
+ log::error("Invalid size read from uhid-dev: {} < {}", ret,
+ sizeof(ev.type) + sizeof(ev.u.output));
return -EFAULT;
}
- LOG_VERBOSE("UHID_OUTPUT: Report type = %d, report_size = %d",
- ev.u.output.rtype, ev.u.output.size);
+ log::verbose("UHID_OUTPUT: Report type = {}, report_size = {}",
+ ev.u.output.rtype, ev.u.output.size);
// Send SET_REPORT with feature report if the report type in output event
// is FEATURE
if (ev.u.output.rtype == UHID_FEATURE_REPORT)
@@ -196,22 +195,21 @@
else if (ev.u.output.rtype == UHID_OUTPUT_REPORT)
btif_hh_senddata(p_dev, ev.u.output.size, ev.u.output.data);
else
- LOG_ERROR("%s: UHID_OUTPUT: Invalid report type = %d", __func__,
- ev.u.output.rtype);
+ log::error("UHID_OUTPUT: Invalid report type = {}", ev.u.output.rtype);
break;
case UHID_OUTPUT_EV:
if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.output_ev))) {
- LOG_ERROR("%s: Invalid size read from uhid-dev: %zd < %zu", __func__,
- ret, sizeof(ev.type) + sizeof(ev.u.output_ev));
+ log::error("Invalid size read from uhid-dev: {} < {}", ret,
+ sizeof(ev.type) + sizeof(ev.u.output_ev));
return -EFAULT;
}
- LOG_VERBOSE("UHID_OUTPUT_EV from uhid-dev\n");
+ log::verbose("UHID_OUTPUT_EV from uhid-dev\n");
break;
case UHID_FEATURE: // UHID_GET_REPORT
if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.feature))) {
- LOG_ERROR("UHID_GET_REPORT: Invalid size read from uhid-dev: %zd < %zu",
- ret, sizeof(ev.type) + sizeof(ev.u.feature));
+ log::error("UHID_GET_REPORT: Invalid size read from uhid-dev: {} < {}",
+ ret, sizeof(ev.type) + sizeof(ev.u.feature));
return -EFAULT;
}
@@ -224,8 +222,8 @@
#if ENABLE_UHID_SET_REPORT
case UHID_SET_REPORT: {
if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.set_report))) {
- LOG_ERROR("UHID_SET_REPORT: Invalid size read from uhid-dev: %zd < %zu",
- ret, sizeof(ev.type) + sizeof(ev.u.set_report));
+ log::error("UHID_SET_REPORT: Invalid size read from uhid-dev: {} < {}",
+ ret, sizeof(ev.type) + sizeof(ev.u.set_report));
return -EFAULT;
}
@@ -237,7 +235,7 @@
#endif // ENABLE_UHID_SET_REPORT
default:
- LOG_ERROR("Invalid event from uhid-dev: %u\n", ev.type);
+ log::error("Invalid event from uhid-dev: {}\n", ev.type);
}
return 0;
@@ -254,17 +252,17 @@
******************************************************************************/
static inline pthread_t create_thread(void* (*start_routine)(void*),
void* arg) {
- LOG_VERBOSE("create_thread: entered");
+ log::verbose("create_thread: entered");
pthread_attr_t thread_attr;
pthread_attr_init(&thread_attr);
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE);
pthread_t thread_id = -1;
if (pthread_create(&thread_id, &thread_attr, start_routine, arg) != 0) {
- LOG_ERROR("pthread_create : %s", strerror(errno));
+ log::error("pthread_create : {}", strerror(errno));
return -1;
}
- LOG_VERBOSE("create_thread: thread created successfully");
+ log::verbose("create_thread: thread created successfully");
return thread_id;
}
@@ -274,8 +272,8 @@
struct uhid_event ev = {};
ev.type = UHID_DESTROY;
uhid_write(p_dev->fd, &ev);
- LOG_DEBUG("Closing fd=%d, addr:%s", p_dev->fd,
- ADDRESS_TO_LOGGABLE_CSTR(p_dev->link_spec));
+ log::debug("Closing fd={}, addr:{}", p_dev->fd,
+ ADDRESS_TO_LOGGABLE_CSTR(p_dev->link_spec));
close(p_dev->fd);
p_dev->fd = -1;
}
@@ -286,7 +284,7 @@
if (p_dev->fd < 0) {
p_dev->fd = open(dev_path, O_RDWR | O_CLOEXEC);
if (p_dev->fd < 0) {
- LOG_ERROR("Failed to open uhid, err:%s", strerror(errno));
+ log::error("Failed to open uhid, err:{}", strerror(errno));
return false;
}
}
@@ -317,7 +315,7 @@
struct sched_param sched_params;
sched_params.sched_priority = THREAD_NORMAL_PRIORITY;
if (sched_setscheduler(pid, SCHED_OTHER, &sched_params)) {
- LOG_ERROR("Failed to set thread priority to normal: %s", strerror(errno));
+ log::error("Failed to set thread priority to normal: {}", strerror(errno));
p_dev->hh_poll_thread_id = -1;
p_dev->hh_keep_polling = 0;
uhid_fd_close(p_dev);
@@ -325,8 +323,8 @@
}
pthread_setname_np(pthread_self(), BT_HH_THREAD);
- LOG_DEBUG("Host hid polling thread created name:%s pid:%d fd:%d",
- BT_HH_THREAD, pid, p_dev->fd);
+ log::debug("Host hid polling thread created name:{} pid:{} fd:{}",
+ BT_HH_THREAD, pid, p_dev->fd);
pfds[0].fd = p_dev->fd;
pfds[0].events = POLLIN;
@@ -340,29 +338,29 @@
do {
if (counter++ > BTA_HH_UHID_INTERRUPT_COUNT_MAX) {
- LOG_ERROR("Polling interrupted");
+ log::error("Polling interrupted");
break;
}
ret = poll(pfds, 1, BTA_HH_UHID_POLL_PERIOD_MS);
} while (ret == -1 && errno == EINTR);
if (ret < 0) {
- LOG_ERROR("Cannot poll for fds: %s\n", strerror(errno));
+ log::error("Cannot poll for fds: {}\n", strerror(errno));
break;
}
if (pfds[0].revents & POLLIN) {
- LOG_VERBOSE("%s: POLLIN", __func__);
+ log::verbose("POLLIN");
ret = uhid_read_event(p_dev);
if (ret != 0) {
- LOG_ERROR("Unhandled UHID event");
+ log::error("Unhandled UHID event");
break;
}
}
}
/* Todo: Disconnect if loop exited due to a failure */
- LOG_INFO("Polling thread stopped for device %s",
- ADDRESS_TO_LOGGABLE_CSTR(p_dev->link_spec));
+ log::info("Polling thread stopped for device {}",
+ ADDRESS_TO_LOGGABLE_CSTR(p_dev->link_spec));
p_dev->hh_poll_thread_id = -1;
p_dev->hh_keep_polling = 0;
uhid_fd_close(p_dev);
@@ -370,14 +368,14 @@
}
int bta_hh_co_write(int fd, uint8_t* rpt, uint16_t len) {
- LOG_VERBOSE("%s: UHID write %d", __func__, len);
+ log::verbose("UHID write {}", len);
struct uhid_event ev;
memset(&ev, 0, sizeof(ev));
ev.type = UHID_INPUT;
ev.u.input.size = len;
if (len > sizeof(ev.u.input.data)) {
- LOG_WARN("%s: Report size greater than allowed size", __func__);
+ log::warn("Report size greater than allowed size");
return -1;
}
memcpy(ev.u.input.data, rpt, len);
@@ -400,7 +398,7 @@
btif_hh_device_t* p_dev = NULL;
if (dev_handle == BTA_HH_INVALID_HANDLE) {
- LOG_WARN("dev_handle (%d) is invalid", dev_handle);
+ log::warn("dev_handle ({}) is invalid", dev_handle);
return false;
}
@@ -409,9 +407,9 @@
if (p_dev->dev_status != BTHH_CONN_STATE_UNKNOWN &&
p_dev->dev_handle == dev_handle) {
// We found a device with the same handle. Must be a device reconnected.
- LOG_INFO(
- "Found an existing device with the same handle dev_status=%d, "
- "address=%s, attr_mask=0x%04x, sub_class=0x%02x, app_id=%d",
+ log::info(
+ "Found an existing device with the same handle dev_status={}, "
+ "address={}, attr_mask=0x{:04x}, sub_class=0x{:02x}, app_id={}",
p_dev->dev_status, ADDRESS_TO_LOGGABLE_CSTR(p_dev->link_spec),
p_dev->attr_mask, p_dev->sub_class, p_dev->app_id);
@@ -449,7 +447,7 @@
}
if (p_dev == NULL) {
- LOG_ERROR("Too many HID devices are connected");
+ log::error("Too many HID devices are connected");
return false;
}
@@ -461,7 +459,7 @@
CHECK(p_dev->set_rpt_id_queue);
#endif // ENABLE_UHID_SET_REPORT
- LOG_DEBUG("Return device status %d", p_dev->dev_status);
+ log::debug("Return device status {}", p_dev->dev_status);
return true;
}
@@ -477,8 +475,9 @@
* Returns void.
******************************************************************************/
void bta_hh_co_close(btif_hh_device_t* p_dev) {
- LOG_INFO("Closing device handle=%d, status=%d, address=%s", p_dev->dev_handle,
- p_dev->dev_status, ADDRESS_TO_LOGGABLE_CSTR(p_dev->link_spec));
+ log::info("Closing device handle={}, status={}, address={}",
+ p_dev->dev_handle, p_dev->dev_status,
+ ADDRESS_TO_LOGGABLE_CSTR(p_dev->link_spec));
/* Clear the queues */
fixed_queue_flush(p_dev->get_rpt_id_queue, osi_free);
@@ -521,14 +520,14 @@
UNUSED_ATTR const tAclLinkSpec& link_spec, uint8_t app_id) {
btif_hh_device_t* p_dev;
- LOG_VERBOSE(
- "%s: dev_handle = %d, subclass = 0x%02X, mode = %d, "
- "ctry_code = %d, app_id = %d",
- __func__, dev_handle, sub_class, mode, ctry_code, app_id);
+ log::verbose(
+ "dev_handle = {}, subclass = 0x{:02X}, mode = {}, ctry_code = {}, app_id "
+ "= {}",
+ dev_handle, sub_class, mode, ctry_code, app_id);
p_dev = btif_hh_find_connected_dev_by_handle(dev_handle);
if (p_dev == NULL) {
- LOG_WARN("%s: Error: unknown HID device handle %d", __func__, dev_handle);
+ log::warn("Error: unknown HID device handle {}", dev_handle);
return;
}
@@ -546,8 +545,8 @@
if ((p_dev->fd >= 0) && p_dev->ready_for_data) {
bta_hh_co_write(p_dev->fd, p_rpt, len);
} else {
- LOG_WARN("%s: Error: fd = %d, ready %d, len = %d", __func__, p_dev->fd,
- p_dev->ready_for_data, len);
+ log::warn("Error: fd = {}, ready {}, len = {}", p_dev->fd,
+ p_dev->ready_for_data, len);
}
}
@@ -572,17 +571,16 @@
struct uhid_event ev;
if (p_dev->fd < 0) {
- LOG_WARN("%s: Error: fd = %d, dscp_len = %d", __func__, p_dev->fd,
- dscp_len);
+ log::warn("Error: fd = {}, dscp_len = {}", p_dev->fd, dscp_len);
return;
}
- LOG_WARN("%s: fd = %d, name = [%s], dscp_len = %d", __func__, p_dev->fd,
- dev_name, dscp_len);
- LOG_WARN(
- "%s: vendor_id = 0x%04x, product_id = 0x%04x, version= 0x%04x,"
- "ctry_code=0x%02x",
- __func__, vendor_id, product_id, version, ctry_code);
+ log::warn("fd = {}, name = [{}], dscp_len = {}", p_dev->fd, dev_name,
+ dscp_len);
+ log::warn(
+ "vendor_id = 0x{:04x}, product_id = 0x{:04x}, version= "
+ "0x{:04x},ctry_code=0x{:02x}",
+ vendor_id, product_id, version, ctry_code);
// Create and send hid descriptor to kernel
memset(&ev, 0, sizeof(ev));
@@ -608,11 +606,11 @@
ev.u.create.country = ctry_code;
result = uhid_write(p_dev->fd, &ev);
- LOG_WARN("%s: wrote descriptor to fd = %d, dscp_len = %d, result = %d",
- __func__, p_dev->fd, dscp_len, result);
+ log::warn("wrote descriptor to fd = {}, dscp_len = {}, result = {}",
+ p_dev->fd, dscp_len, result);
if (result) {
- LOG_WARN("%s: Error: failed to send DSCP, result = %d", __func__, result);
+ log::warn("Error: failed to send DSCP, result = {}", result);
/* The HID report descriptor is corrupted. Close the driver. */
close(p_dev->fd);
@@ -632,29 +630,29 @@
******************************************************************************/
void bta_hh_co_set_rpt_rsp(uint8_t dev_handle, uint8_t status) {
#if ENABLE_UHID_SET_REPORT
- LOG_VERBOSE("dev_handle = %d", dev_handle);
+ log::verbose("dev_handle = {}", dev_handle);
btif_hh_device_t* p_dev = btif_hh_find_connected_dev_by_handle(dev_handle);
if (p_dev == nullptr) {
- LOG_WARN("Unknown HID device handle %d", dev_handle);
+ log::warn("Unknown HID device handle {}", dev_handle);
return;
}
if (!p_dev->set_rpt_id_queue) {
- LOG_WARN("Missing UHID_SET_REPORT id queue");
+ log::warn("Missing UHID_SET_REPORT id queue");
return;
}
// Send the HID set report reply to the kernel.
if (p_dev->fd < 0) {
- LOG_ERROR("Unexpected Set Report response");
+ log::error("Unexpected Set Report response");
return;
}
uint32_t* context = (uint32_t*)fixed_queue_try_dequeue(p_dev->set_rpt_id_queue);
if (context == nullptr) {
- LOG_WARN("No pending UHID_SET_REPORT");
+ log::warn("No pending UHID_SET_REPORT");
return;
}
@@ -671,7 +669,7 @@
osi_free(context);
#else
- LOG_ERROR("UHID_SET_REPORT_REPLY not supported");
+ log::error("UHID_SET_REPORT_REPLY not supported");
#endif // ENABLE_UHID_SET_REPORT
}
@@ -689,34 +687,34 @@
const uint8_t* p_rpt, uint16_t len) {
btif_hh_device_t* p_dev;
- LOG_VERBOSE("dev_handle = %d, status = %d", dev_handle, status);
+ log::verbose("dev_handle = {}, status = {}", dev_handle, status);
p_dev = btif_hh_find_connected_dev_by_handle(dev_handle);
if (p_dev == nullptr) {
- LOG_WARN("Unknown HID device handle %d", dev_handle);
+ log::warn("Unknown HID device handle {}", dev_handle);
return;
}
if (!p_dev->get_rpt_id_queue) {
- LOG_WARN("Missing UHID_GET_REPORT id queue");
+ log::warn("Missing UHID_GET_REPORT id queue");
return;
}
// Send the HID report to the kernel.
if (p_dev->fd < 0) {
- LOG_WARN("Unexpected Get Report response");
+ log::warn("Unexpected Get Report response");
return;
}
uint32_t* context = (uint32_t*)fixed_queue_try_dequeue(p_dev->get_rpt_id_queue);
if (context == nullptr) {
- LOG_WARN("No pending UHID_GET_REPORT");
+ log::warn("No pending UHID_GET_REPORT");
return;
}
if (len == 0 || len > UHID_DATA_MAX) {
- LOG_WARN("Invalid report size = %d", len);
+ log::warn("Invalid report size = {}", len);
return;
}
@@ -774,8 +772,8 @@
idx * sizeof(tBTA_HH_RPT_CACHE_ENTRY));
btif_config_set_int(bdstr, BTIF_STORAGE_KEY_HID_REPORT_VERSION,
BTA_HH_CACHE_REPORT_VERSION);
- LOG_VERBOSE("%s() - Saving report; dev=%s, idx=%d", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(link_spec), idx);
+ log::verbose("Saving report; dev={}, idx={}",
+ ADDRESS_TO_LOGGABLE_CSTR(link_spec), idx);
}
}
@@ -819,8 +817,8 @@
*p_num_rpt = len / sizeof(tBTA_HH_RPT_CACHE_ENTRY);
- LOG_VERBOSE("%s() - Loaded %d reports; dev=%s", __func__, *p_num_rpt,
- ADDRESS_TO_LOGGABLE_CSTR(link_spec));
+ log::verbose("Loaded {} reports; dev={}", *p_num_rpt,
+ ADDRESS_TO_LOGGABLE_CSTR(link_spec));
return sReportCache;
}
@@ -843,6 +841,5 @@
btif_config_remove(bdstr, BTIF_STORAGE_KEY_HID_REPORT);
btif_config_remove(bdstr, BTIF_STORAGE_KEY_HID_REPORT_VERSION);
- LOG_VERBOSE("%s() - Reset cache for bda %s", __func__,
- ADDRESS_TO_LOGGABLE_CSTR(link_spec));
+ log::verbose("Reset cache for bda {}", ADDRESS_TO_LOGGABLE_CSTR(link_spec));
}
diff --git a/system/btif/co/bta_pan_co.cc b/system/btif/co/bta_pan_co.cc
index dd8a0b2..5f5f2f5 100644
--- a/system/btif/co/bta_pan_co.cc
+++ b/system/btif/co/bta_pan_co.cc
@@ -31,19 +31,21 @@
#include <hardware/bt_pan.h>
#include <string.h>
-#include "os/log.h"
#include "bta_api.h"
#include "bta_pan_api.h"
#include "bta_pan_ci.h"
#include "btif_pan_internal.h"
#include "btif_sock_thread.h"
#include "btif_util.h"
+#include "os/log.h"
#include "osi/include/allocator.h"
#include "osi/include/osi.h"
#include "pan_api.h"
#include "stack/include/bt_hdr.h"
#include "types/raw_address.h"
+using namespace bluetooth;
+
/*******************************************************************************
*
* Function bta_pan_co_init
@@ -55,7 +57,7 @@
*
******************************************************************************/
uint8_t bta_pan_co_init(uint8_t* q_level) {
- LOG_VERBOSE("bta_pan_co_init");
+ log::verbose("bta_pan_co_init");
/* set the q_level to 30 buffers */
*q_level = 30;
@@ -76,10 +78,10 @@
*
******************************************************************************/
void bta_pan_co_close(uint16_t handle, uint8_t app_id) {
- LOG_VERBOSE("bta_pan_co_close:app_id:%d, handle:%d", app_id, handle);
+ log::verbose("bta_pan_co_close:app_id:{}, handle:{}", app_id, handle);
btpan_conn_t* conn = btpan_find_conn_handle(handle);
if (conn && conn->state == PAN_STATE_OPEN) {
- LOG_VERBOSE("bta_pan_co_close");
+ log::verbose("bta_pan_co_close");
// let bta close event reset this handle as it needs
// the handle to find the connection upon CLOSE
@@ -119,15 +121,15 @@
bool ext;
bool forward;
- LOG_VERBOSE("%s, handle:%d, app_id:%d", __func__, handle, app_id);
+ log::verbose("handle:{}, app_id:{}", handle, app_id);
btpan_conn_t* conn = btpan_find_conn_handle(handle);
if (!conn) {
- LOG_ERROR("%s: cannot find pan connection", __func__);
+ log::error("cannot find pan connection");
return;
} else if (conn->state != PAN_STATE_OPEN) {
- LOG_ERROR("%s: conn is not opened, conn:%p, conn->state:%d", __func__, conn,
- conn->state);
+ log::error("conn is not opened, conn:{}, conn->state:{}", fmt::ptr(conn),
+ conn->state);
return;
}
@@ -135,14 +137,12 @@
/* read next data buffer from pan */
p_buf = bta_pan_ci_readbuf(handle, src, dst, &protocol, &ext, &forward);
if (p_buf) {
- LOG_VERBOSE(
- "%s, calling btapp_tap_send, "
- "p_buf->len:%d, offset:%d",
- __func__, p_buf->len, p_buf->offset);
+ log::verbose("calling btapp_tap_send, p_buf->len:{}, offset:{}",
+ p_buf->len, p_buf->offset);
if (is_empty_eth_addr(conn->eth_addr) && is_valid_bt_eth_addr(src)) {
- VLOG(1) << __func__ << " pan bt peer addr: "
- << ADDRESS_TO_LOGGABLE_STR(conn->peer)
- << " update its ethernet addr: " << src;
+ log::verbose("pan bt peer addr: {} update its ethernet addr: {}",
+ ADDRESS_TO_LOGGABLE_STR(conn->peer),
+ ADDRESS_TO_LOGGABLE_STR(src));
conn->eth_addr = src;
}
btpan_tap_send(btpan_cb.tap_fd, src, dst, protocol,
@@ -168,7 +168,7 @@
******************************************************************************/
void bta_pan_co_rx_path(UNUSED_ATTR uint16_t handle,
UNUSED_ATTR uint8_t app_id) {
- LOG_VERBOSE("bta_pan_co_rx_path not used");
+ log::verbose("bta_pan_co_rx_path not used");
}
/*******************************************************************************
@@ -187,7 +187,7 @@
******************************************************************************/
void bta_pan_co_rx_flow(UNUSED_ATTR uint16_t handle, UNUSED_ATTR uint8_t app_id,
UNUSED_ATTR bool enable) {
- LOG_VERBOSE("bta_pan_co_rx_flow, enabled:%d, not used", enable);
+ log::verbose("bta_pan_co_rx_flow, enabled:{}, not used", enable);
btpan_conn_t* conn = btpan_find_conn_handle(handle);
if (!conn || conn->state != PAN_STATE_OPEN) return;
btpan_set_flow_control(enable);
@@ -207,7 +207,7 @@
UNUSED_ATTR tBTA_PAN_STATUS result,
UNUSED_ATTR uint16_t len,
UNUSED_ATTR uint8_t* p_filters) {
- LOG_VERBOSE("bta_pan_co_pfilt_ind");
+ log::verbose("bta_pan_co_pfilt_ind");
}
/*******************************************************************************
@@ -224,5 +224,5 @@
UNUSED_ATTR tBTA_PAN_STATUS result,
UNUSED_ATTR uint16_t len,
UNUSED_ATTR uint8_t* p_filters) {
- LOG_VERBOSE("bta_pan_co_mfilt_ind");
+ log::verbose("bta_pan_co_mfilt_ind");
}
diff --git a/system/device/Android.bp b/system/device/Android.bp
index 4233340..313ce17 100644
--- a/system/device/Android.bp
+++ b/system/device/Android.bp
@@ -59,6 +59,7 @@
"test/interop_test.cc",
],
shared_libs: [
+ "libbase",
"liblog",
],
static_libs: [
@@ -95,6 +96,7 @@
"test/device_iot_config_test.cc",
],
shared_libs: [
+ "libbase",
"libdl",
"liblog",
],
diff --git a/system/device/fuzzer/Android.bp b/system/device/fuzzer/Android.bp
index 8e88d1e..a0ef51b 100644
--- a/system/device/fuzzer/Android.bp
+++ b/system/device/fuzzer/Android.bp
@@ -34,6 +34,7 @@
"libbluetooth_headers",
],
shared_libs: [
+ "libbase",
"libdl",
"liblog",
"server_configurable_flags",
diff --git a/system/gd/hal/Android.bp b/system/gd/hal/Android.bp
index 27e6b6f..c583cab 100644
--- a/system/gd/hal/Android.bp
+++ b/system/gd/hal/Android.bp
@@ -10,7 +10,7 @@
filegroup {
name: "BluetoothHalSources",
srcs: [
- "nocp_iso_clocker.cc",
+ "link_clocker.cc",
"snoop_logger.cc",
"snoop_logger_socket.cc",
"snoop_logger_socket_thread.cc",
diff --git a/system/gd/hal/BUILD.gn b/system/gd/hal/BUILD.gn
index 67034e1..affd151 100644
--- a/system/gd/hal/BUILD.gn
+++ b/system/gd/hal/BUILD.gn
@@ -16,7 +16,7 @@
source_set("BluetoothHalSources") {
sources = [
- "nocp_iso_clocker.cc",
+ "link_clocker.cc",
"snoop_logger.cc",
"snoop_logger_socket.cc",
"snoop_logger_socket_thread.cc",
diff --git a/system/gd/hal/hci_hal_android_hidl.cc b/system/gd/hal/hci_hal_android_hidl.cc
index 686b951..daef433 100644
--- a/system/gd/hal/hci_hal_android_hidl.cc
+++ b/system/gd/hal/hci_hal_android_hidl.cc
@@ -38,7 +38,7 @@
#include "common/stop_watch.h"
#include "common/strings.h"
#include "hal/hci_hal.h"
-#include "hal/nocp_iso_clocker.h"
+#include "hal/link_clocker.h"
#include "hal/snoop_logger.h"
#include "os/alarm.h"
#include "os/log.h"
@@ -83,8 +83,8 @@
class InternalHciCallbacks : public IBluetoothHciCallbacks_1_1 {
public:
- InternalHciCallbacks(SnoopLogger* btsnoop_logger, NocpIsoClocker* nocp_iso_clocker)
- : btsnoop_logger_(btsnoop_logger), nocp_iso_clocker_(nocp_iso_clocker) {
+ InternalHciCallbacks(SnoopLogger* btsnoop_logger, LinkClocker* link_clocker)
+ : btsnoop_logger_(btsnoop_logger), link_clocker_(link_clocker) {
init_promise_ = new std::promise<void>();
}
@@ -115,7 +115,7 @@
Return<void> hciEventReceived(const hidl_vec<uint8_t>& event) override {
common::StopWatch stop_watch(GetTimerText(__func__, event));
std::vector<uint8_t> received_hci_packet(event.begin(), event.end());
- nocp_iso_clocker_->OnHciEvent(received_hci_packet);
+ link_clocker_->OnHciEvent(received_hci_packet);
btsnoop_logger_->Capture(
received_hci_packet, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::EVT);
{
@@ -130,6 +130,7 @@
Return<void> aclDataReceived(const hidl_vec<uint8_t>& data) override {
common::StopWatch stop_watch(GetTimerText(__func__, data));
std::vector<uint8_t> received_hci_packet(data.begin(), data.end());
+ link_clocker_->OnAclDataReceived(received_hci_packet);
btsnoop_logger_->Capture(
received_hci_packet, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::ACL);
{
@@ -174,7 +175,7 @@
std::promise<void>* init_promise_ = nullptr;
HciHalCallbacks* callback_ = nullptr;
SnoopLogger* btsnoop_logger_ = nullptr;
- NocpIsoClocker* nocp_iso_clocker_ = nullptr;
+ LinkClocker* link_clocker_ = nullptr;
};
static constexpr char kBluetoothAidlHalServiceName[] =
@@ -182,8 +183,8 @@
class AidlHciCallbacks : public ::aidl::android::hardware::bluetooth::BnBluetoothHciCallbacks {
public:
- AidlHciCallbacks(SnoopLogger* btsnoop_logger, NocpIsoClocker* nocp_iso_clocker)
- : btsnoop_logger_(btsnoop_logger), nocp_iso_clocker_(nocp_iso_clocker) {
+ AidlHciCallbacks(SnoopLogger* btsnoop_logger, LinkClocker* link_clocker)
+ : btsnoop_logger_(btsnoop_logger), link_clocker_(link_clocker) {
init_promise_ = new std::promise<void>();
}
@@ -212,7 +213,7 @@
::ndk::ScopedAStatus hciEventReceived(const std::vector<uint8_t>& event) override {
common::StopWatch stop_watch(GetTimerText(__func__, event));
std::vector<uint8_t> received_hci_packet(event.begin(), event.end());
- nocp_iso_clocker_->OnHciEvent(received_hci_packet);
+ link_clocker_->OnHciEvent(received_hci_packet);
btsnoop_logger_->Capture(
received_hci_packet, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::EVT);
bool sent = false;
@@ -232,6 +233,7 @@
::ndk::ScopedAStatus aclDataReceived(const std::vector<uint8_t>& data) override {
common::StopWatch stop_watch(GetTimerText(__func__, data));
std::vector<uint8_t> received_hci_packet(data.begin(), data.end());
+ link_clocker_->OnAclDataReceived(received_hci_packet);
btsnoop_logger_->Capture(
received_hci_packet, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::ACL);
bool sent = false;
@@ -291,7 +293,7 @@
std::promise<void>* init_promise_ = nullptr;
HciHalCallbacks* callback_ = nullptr;
SnoopLogger* btsnoop_logger_ = nullptr;
- NocpIsoClocker* nocp_iso_clocker_ = nullptr;
+ LinkClocker* link_clocker_ = nullptr;
};
} // namespace
@@ -362,7 +364,7 @@
protected:
void ListDependencies(ModuleList* list) const {
- list->add<NocpIsoClocker>();
+ list->add<LinkClocker>();
list->add<SnoopLogger>();
}
@@ -374,7 +376,7 @@
ASSERT(bt_hci_1_1_ == nullptr);
ASSERT(aidl_hci_ == nullptr);
- nocp_iso_clocker_ = GetDependency<NocpIsoClocker>();
+ link_clocker_ = GetDependency<LinkClocker>();
btsnoop_logger_ = GetDependency<SnoopLogger>();
if (AServiceManager_isDeclared(kBluetoothAidlHalServiceName)) {
@@ -408,7 +410,7 @@
death_link == STATUS_OK, "Unable to set the death recipient for the Bluetooth HAL");
aidl_callbacks_ =
- ::ndk::SharedRefBase::make<AidlHciCallbacks>(btsnoop_logger_, nocp_iso_clocker_);
+ ::ndk::SharedRefBase::make<AidlHciCallbacks>(btsnoop_logger_, link_clocker_);
aidl_hci_->initialize(aidl_callbacks_);
}
}
@@ -448,7 +450,7 @@
ASSERT(bt_hci_ != nullptr);
auto death_link = bt_hci_->linkToDeath(hci_death_recipient_, 0);
ASSERT_LOG(death_link.isOk(), "Unable to set the death recipient for the Bluetooth HAL");
- hidl_callbacks_ = new InternalHciCallbacks(btsnoop_logger_, nocp_iso_clocker_);
+ hidl_callbacks_ = new InternalHciCallbacks(btsnoop_logger_, link_clocker_);
if (bt_hci_1_1_ != nullptr) {
bt_hci_1_1_->initialize_1_1(hidl_callbacks_);
@@ -507,7 +509,7 @@
std::shared_ptr<AidlHciCallbacks> aidl_callbacks_;
::ndk::ScopedAIBinder_DeathRecipient aidl_death_recipient_;
SnoopLogger* btsnoop_logger_;
- NocpIsoClocker* nocp_iso_clocker_;
+ LinkClocker* link_clocker_;
};
const ModuleFactory HciHal::Factory = ModuleFactory([]() { return new HciHalHidl(); });
diff --git a/system/gd/hal/hci_hal_host.cc b/system/gd/hal/hci_hal_host.cc
index 4c24c6b..e05fda0 100644
--- a/system/gd/hal/hci_hal_host.cc
+++ b/system/gd/hal/hci_hal_host.cc
@@ -30,8 +30,8 @@
#include "common/init_flags.h"
#include "hal/hci_hal.h"
+#include "hal/link_clocker.h"
#include "hal/mgmt.h"
-#include "hal/nocp_iso_clocker.h"
#include "hal/snoop_logger.h"
#include "metrics/counter_metrics.h"
#include "os/log.h"
@@ -285,7 +285,7 @@
protected:
void ListDependencies(ModuleList* list) const {
- list->add<NocpIsoClocker>();
+ list->add<LinkClocker>();
list->add<metrics::CounterMetrics>();
list->add<SnoopLogger>();
}
@@ -307,7 +307,7 @@
common::Bind(&HciHalHost::incoming_packet_received, common::Unretained(this)),
common::Bind(&HciHalHost::send_packet_ready, common::Unretained(this)));
hci_incoming_thread_.GetReactor()->ModifyRegistration(reactable_, os::Reactor::REACT_ON_READ_ONLY);
- nocp_iso_clocker_ = GetDependency<NocpIsoClocker>();
+ link_clocker_ = GetDependency<LinkClocker>();
btsnoop_logger_ = GetDependency<SnoopLogger>();
LOG_INFO("HAL opened successfully");
}
@@ -348,7 +348,7 @@
bluetooth::os::Reactor::Reactable* reactable_ = nullptr;
std::queue<std::vector<uint8_t>> hci_outgoing_queue_;
SnoopLogger* btsnoop_logger_ = nullptr;
- NocpIsoClocker* nocp_iso_clocker_ = nullptr;
+ LinkClocker* link_clocker_ = nullptr;
void write_to_fd(HciPacket packet) {
// TODO: replace this with new queue when it's ready
@@ -414,7 +414,7 @@
HciPacket receivedHciPacket;
receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciEvtHeaderSize + payload_size);
- nocp_iso_clocker_->OnHciEvent(receivedHciPacket);
+ link_clocker_->OnHciEvent(receivedHciPacket);
btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::EVT);
{
std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
@@ -440,6 +440,7 @@
HciPacket receivedHciPacket;
receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciAclHeaderSize + payload_size);
+ link_clocker_->OnAclDataReceived(receivedHciPacket);
btsnoop_logger_->Capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::ACL);
{
std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
diff --git a/system/gd/hal/link_clocker.cc b/system/gd/hal/link_clocker.cc
new file mode 100644
index 0000000..d0d09d9
--- /dev/null
+++ b/system/gd/hal/link_clocker.cc
@@ -0,0 +1,228 @@
+/*
+ * 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.
+ */
+
+#include "hal/link_clocker.h"
+
+#include <algorithm>
+
+namespace bluetooth::hal {
+
+static constexpr uint16_t kInvalidConnectionHandle = 0xFFFF;
+
+static class : public bluetooth::audio::asrc::ClockHandler {
+ void OnEvent(uint32_t, int, int) override {}
+} g_empty_handler;
+
+static std::atomic<bluetooth::audio::asrc::ClockHandler*> g_nocp_iso_handler = &g_empty_handler;
+
+static struct {
+ std::mutex mutex;
+ bluetooth::audio::asrc::ClockHandler* handler;
+ struct {
+ uint16_t connection_handle;
+ uint16_t stream_cid;
+ } links[2];
+} g_credit_ind_handler = {.handler = &g_empty_handler, .links = {{}, {}}};
+
+NocpIsoEvents::~NocpIsoEvents() {
+ g_nocp_iso_handler = &g_empty_handler;
+}
+
+void NocpIsoEvents::Bind(bluetooth::audio::asrc::ClockHandler* handler) {
+ g_nocp_iso_handler = handler;
+}
+
+L2capCreditIndEvents::~L2capCreditIndEvents() {
+ std::lock_guard<std::mutex> guard(g_credit_ind_handler.mutex);
+ g_credit_ind_handler.handler = &g_empty_handler;
+ g_credit_ind_handler.links[0].connection_handle = kInvalidConnectionHandle;
+ g_credit_ind_handler.links[1].connection_handle = kInvalidConnectionHandle;
+}
+
+void L2capCreditIndEvents::Bind(bluetooth::audio::asrc::ClockHandler* handler) {
+ std::lock_guard<std::mutex> guard(g_credit_ind_handler.mutex);
+ g_credit_ind_handler.handler = handler;
+ g_credit_ind_handler.links[0].connection_handle = kInvalidConnectionHandle;
+ g_credit_ind_handler.links[1].connection_handle = kInvalidConnectionHandle;
+}
+
+void L2capCreditIndEvents::Update(int link_id, uint16_t connection_handle, uint16_t stream_cid) {
+ std::lock_guard<std::mutex> guard(g_credit_ind_handler.mutex);
+ g_credit_ind_handler.links[link_id].connection_handle = connection_handle;
+ g_credit_ind_handler.links[link_id].stream_cid = stream_cid;
+}
+
+LinkClocker::LinkClocker() : cig_id_(-1), cis_handle_(-1) {}
+
+void LinkClocker::OnHciEvent(const HciPacket& packet) {
+ const int HCI_CMD_SET_CIG_PARAMETERS = 0x2062;
+ const int HCI_EVT_COMMAND_COMPLETE = 0x0e;
+ const int HCI_EVT_NUMBER_OF_COMPLETED_PACKETS = 0x13;
+
+ // HCI Event [Core 4.E.5.4.4]
+ // | [0] Event Code
+ // | [1] Parameter Total Length
+ // | [2+] Parameters
+
+ if (packet.size() < 2) return;
+
+ const uint8_t* payload = packet.data() + 2;
+ size_t payload_length = std::min(size_t(packet[1]), packet.size() - 2);
+
+ switch (packet[0]) {
+ // HCI Command Complete Event [Core 4.E.7.7.14]
+ // | [0] Num_HCI_Command_Packets, Ignored
+ // | [1..2] Command_Opcode, catch `HCI_LE_Set_CIG_Parameters`
+ // | [3+] Return Parameters
+
+ case HCI_EVT_COMMAND_COMPLETE: {
+ if (payload_length < 3) return;
+
+ int cmd_opcode = payload[1] | (payload[2] << 8);
+ if (cmd_opcode != HCI_CMD_SET_CIG_PARAMETERS) return;
+
+ const uint8_t* parameters = payload + 3;
+ size_t parameters_length = payload_length - 3;
+
+ // HCI LE Set CIG Parameters return parameters [4.E.7.8.97]
+ // | [0] Status, 0 when OK
+ // | [1] CIG_ID
+ // | [2] CIS_Count
+ // | [3..4] Connection_Handle[0]
+
+ if (parameters_length < 3) return;
+
+ int status = parameters[0];
+ int cig_id = parameters[1];
+ int cis_count = parameters[2];
+
+ if (status != 0) return;
+
+ if (cig_id_ >= 0 && cis_handle_ >= 0 && cig_id_ != cig_id) {
+ LOG_WARN("Multiple groups not supported");
+ return;
+ }
+
+ cig_id_ = -1;
+ cis_handle_ = -1;
+
+ if (cis_count > 0 && parameters_length >= 5) {
+ cig_id_ = cig_id;
+ cis_handle_ = (parameters[3] | (parameters[4] << 8)) & 0xfff;
+ }
+
+ break;
+ }
+
+ // HCI Number Of Completed Packets event [Core 4.E.7.7.19]
+ // | [0] Num_Handles
+ // | FOR each `Num_Handles` connection handles
+ // | | [0..1] Connection_Handle, catch the CIS Handle
+ // | | [2..3] Num_Completed_Packets
+
+ case HCI_EVT_NUMBER_OF_COMPLETED_PACKETS: {
+ if (payload_length < 1) return;
+
+ int i, num_handles = payload[0];
+ const uint8_t* item = payload + 1;
+ if (payload_length < size_t(1 + 4 * num_handles)) return;
+
+ for (i = 0; i < num_handles && ((item[0] | (item[1] << 8)) & 0xfff) != cis_handle_;
+ i++, item += 4)
+ ;
+ if (i >= num_handles) return;
+
+ auto timestamp = std::chrono::system_clock::now().time_since_epoch();
+ unsigned timestamp_us =
+ std::chrono::duration_cast<std::chrono::microseconds>(timestamp).count();
+ int num_of_completed_packets = item[2] | (item[3] << 8);
+ (*g_nocp_iso_handler).OnEvent(timestamp_us, 0, num_of_completed_packets);
+
+ break;
+ }
+ }
+}
+
+/// Filter received L2CAP PDUs for Credit acknowledgments for the registered
+/// L2CAP channels.
+void LinkClocker::OnAclDataReceived(const HciPacket& packet) {
+ const int L2CAP_LE_U_CID = 0x0005;
+ const int L2CAP_FLOW_CONTROL_CREDIT_IND = 0x16;
+
+ // HCI ACL Data Packets [4.E.5.4.2]
+ // | [0..1] Handle | PBF | BC
+ // | [2..3] Data Total Length
+ // | [4+] Data
+
+ if (packet.size() < 4) return;
+
+ uint16_t handle = packet[0] | (packet[1] << 8);
+ int packet_boundary_flag = (handle >> 12) & 0x3;
+ handle &= 0xfff;
+ uint16_t data_total_length = std::min(size_t(packet[2] | (packet[3] << 8)), packet.size() - 4);
+ const uint8_t* data = packet.data() + 4;
+
+ if (data_total_length < 4 || packet_boundary_flag == 0b01 || packet_boundary_flag == 0b11) return;
+
+ // L2CAP Signalling PDU Format [3.A.4]
+ // | [0..1] PDU Length
+ // | [2..3] Channel ID
+ // | [4+] PDU
+ uint16_t pdu_length = std::min(data[0] | (data[1] << 8), data_total_length - 4);
+ uint16_t channel_id = data[2] | (data[3] << 8);
+ data += 4;
+
+ if (channel_id != L2CAP_LE_U_CID) return;
+
+ while (pdu_length >= 4) {
+ // | FOR each command in the PDU
+ // | | [0] Command Code
+ // | | [1] Command Identifier
+ // | | [2..3] Data Length
+ // | | [4+] Data
+ uint8_t command_code = data[0];
+ uint16_t data_length = std::min(data[2] | (data[3] << 8), pdu_length - 4);
+
+ if (command_code == L2CAP_FLOW_CONTROL_CREDIT_IND && data_length == 4) {
+ // | L2CAP Flow Control Credit Ind [3.A.4.24]
+ // | | [4..5] CID
+ // | | [6..7] Credits
+ uint16_t channel_id = data[4] | (data[5] << 8);
+ uint16_t credits = data[6] | (data[7] << 8);
+
+ auto timestamp = std::chrono::system_clock::now().time_since_epoch();
+ unsigned timestamp_us =
+ std::chrono::duration_cast<std::chrono::microseconds>(timestamp).count();
+
+ {
+ std::lock_guard<std::mutex> guard(g_credit_ind_handler.mutex);
+ for (int link_id = 0; link_id < 2; link_id++) {
+ auto const& link = g_credit_ind_handler.links[link_id];
+ if (link.connection_handle == handle && link.stream_cid == channel_id) {
+ g_credit_ind_handler.handler->OnEvent(timestamp_us, link_id, credits);
+ }
+ }
+ }
+ }
+
+ data += data_length + 4;
+ pdu_length -= data_length + 4;
+ }
+}
+
+const ModuleFactory LinkClocker::Factory = ModuleFactory([]() { return new LinkClocker(); });
+
+} // namespace bluetooth::hal
diff --git a/system/gd/hal/nocp_iso_clocker.h b/system/gd/hal/link_clocker.h
similarity index 61%
rename from system/gd/hal/nocp_iso_clocker.h
rename to system/gd/hal/link_clocker.h
index a04cbd1..c0a7278 100644
--- a/system/gd/hal/nocp_iso_clocker.h
+++ b/system/gd/hal/link_clocker.h
@@ -16,25 +16,35 @@
#pragma once
+#include "audio/asrc/asrc_resampler.h"
#include "hci_hal.h"
#include "module.h"
namespace bluetooth::hal {
-class NocpIsoHandler {
+class NocpIsoEvents : public bluetooth::audio::asrc::ClockSource {
public:
- virtual ~NocpIsoHandler() = default;
- virtual void OnEvent(uint32_t timestamp_us, int link_id, int num_of_completed_packets) = 0;
+ NocpIsoEvents() = default;
+ ~NocpIsoEvents() override;
+
+ void Bind(bluetooth::audio::asrc::ClockHandler*) override;
};
-class NocpIsoClocker : public ::bluetooth::Module {
+class L2capCreditIndEvents : public bluetooth::audio::asrc::ClockSource {
+ public:
+ L2capCreditIndEvents() {}
+ ~L2capCreditIndEvents() override;
+
+ void Bind(bluetooth::audio::asrc::ClockHandler*) override;
+ void Update(int link_id, uint16_t connection_handle, uint16_t stream_cid);
+};
+
+class LinkClocker : public ::bluetooth::Module {
public:
static const ModuleFactory Factory;
void OnHciEvent(const HciPacket& packet);
-
- static void Register(NocpIsoHandler* handler);
- static void Unregister();
+ void OnAclDataReceived(const HciPacket& packet);
protected:
void ListDependencies(ModuleList*) const override{};
@@ -42,10 +52,10 @@
void Stop() override{};
std::string ToString() const override {
- return std::string("NocpIsoClocker");
+ return std::string("LinkClocker");
}
- NocpIsoClocker();
+ LinkClocker();
private:
int cig_id_;
diff --git a/system/gd/hal/nocp_iso_clocker.cc b/system/gd/hal/nocp_iso_clocker.cc
deleted file mode 100644
index b97f515..0000000
--- a/system/gd/hal/nocp_iso_clocker.cc
+++ /dev/null
@@ -1,127 +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.
- */
-
-#include "hal/nocp_iso_clocker.h"
-
-namespace bluetooth::hal {
-
-static class : public NocpIsoHandler {
- void OnEvent(uint32_t, int, int) override {}
-} g_empty_handler;
-
-static std::atomic<NocpIsoHandler*> g_handler = &g_empty_handler;
-
-NocpIsoClocker::NocpIsoClocker() : cig_id_(-1), cis_handle_(-1) {}
-
-void NocpIsoClocker::OnHciEvent(const HciPacket& packet) {
- const int HCI_CMD_SET_CIG_PARAMETERS = 0x2062;
- const int HCI_EVT_COMMAND_COMPLETE = 0x0e;
- const int HCI_EVT_NUMBER_OF_COMPLETED_PACKETS = 0x13;
-
- // HCI Event [Core 4.E.5.4.4]
- // | [0] Event Code
- // | [1] Parameter Total Length
- // | [2+] Parameters
-
- if (packet.size() < 2) return;
-
- const uint8_t* payload = packet.data() + 2;
- size_t payload_length = std::min(size_t(packet[1]), packet.size() - 2);
-
- switch (packet[0]) {
- // HCI Command Complete Event [Core 4.E.7.7.14]
- // | [0] Num_HCI_Command_Packets, Ignored
- // | [1..2] Command_Opcode, catch `HCI_LE_Set_CIG_Parameters`
- // | [3+] Return Parameters
-
- case HCI_EVT_COMMAND_COMPLETE: {
- if (payload_length < 3) return;
-
- int cmd_opcode = payload[1] | (payload[2] << 8);
- if (cmd_opcode != HCI_CMD_SET_CIG_PARAMETERS) return;
-
- const uint8_t* parameters = payload + 3;
- size_t parameters_length = payload_length - 3;
-
- // HCI LE Set CIG Parameters return parameters [4.E.7.8.97]
- // | [0] Status, 0 when OK
- // | [1] CIG_ID
- // | [2] CIS_Count
- // | [3..4] Connection_Handle[0]
-
- if (parameters_length < 3) return;
-
- int status = parameters[0];
- int cig_id = parameters[1];
- int cis_count = parameters[2];
-
- if (status != 0) return;
-
- if (cig_id_ >= 0 && cis_handle_ >= 0 && cig_id_ != cig_id) {
- LOG_WARN("Multiple groups not supported");
- return;
- }
-
- cig_id_ = -1;
- cis_handle_ = -1;
-
- if (cis_count > 0 && parameters_length >= 5) {
- cig_id_ = cig_id;
- cis_handle_ = (parameters[3] | (parameters[4] << 8)) & 0xfff;
- }
-
- break;
- }
-
- // HCI Number Of Completed Packets event [Core 4.E.7.7.19]
- // | [0] Num_Handles
- // | FOR each `Num_Handles` connection handles
- // | | [0..1] Connection_Handle, catch the CIS Handle
- // | | [2..3] Num_Completed_Packets
-
- case HCI_EVT_NUMBER_OF_COMPLETED_PACKETS: {
- if (payload_length < 1) return;
-
- int i, num_handles = payload[0];
- const uint8_t* item = payload + 1;
- if (payload_length < size_t(1 + 4 * num_handles)) return;
-
- for (i = 0; i < num_handles && ((item[0] | (item[1] << 8)) & 0xfff) != cis_handle_;
- i++, item += 4)
- ;
- if (i >= num_handles) return;
-
- auto timestamp = std::chrono::system_clock::now().time_since_epoch();
- unsigned timestamp_us =
- std::chrono::duration_cast<std::chrono::microseconds>(timestamp).count();
- int num_of_completed_packets = item[2] | (item[3] << 8);
- (*g_handler).OnEvent(timestamp_us, 0, num_of_completed_packets);
-
- break;
- }
- }
-}
-
-void NocpIsoClocker::Register(NocpIsoHandler* handler) {
- g_handler = handler;
-}
-void NocpIsoClocker::Unregister() {
- g_handler = &g_empty_handler;
-}
-
-const ModuleFactory NocpIsoClocker::Factory = ModuleFactory([]() { return new NocpIsoClocker(); });
-
-} // namespace bluetooth::hal
diff --git a/system/gd/rust/linux/stack/src/bluetooth_adv.rs b/system/gd/rust/linux/stack/src/bluetooth_adv.rs
index 427e362..0c33188 100644
--- a/system/gd/rust/linux/stack/src/bluetooth_adv.rs
+++ b/system/gd/rust/linux/stack/src/bluetooth_adv.rs
@@ -6,11 +6,14 @@
use bt_topshim::profiles::gatt::{AdvertisingStatus, Gatt, GattAdvCallbacks, LePhy};
use itertools::Itertools;
-use log::{debug, error, warn};
+use log::{debug, error, info, warn};
use num_traits::clamp;
-use std::collections::HashMap;
+use std::collections::{HashMap, VecDeque};
use std::sync::{Arc, Mutex};
+use std::time::{Duration, Instant};
use tokio::sync::mpsc::Sender;
+use tokio::task::JoinHandle;
+use tokio::time;
use crate::bluetooth::{Bluetooth, IBluetooth};
use crate::callbacks::Callbacks;
@@ -354,16 +357,9 @@
}
/// Checks if the advertisement can be upgraded to extended.
- pub fn can_upgrade(
- parameters: &mut AdvertisingSetParameters,
- adv_bytes: &Vec<u8>,
- is_le_extended_advertising_supported: bool,
- ) -> bool {
- if parameters.is_legacy
- && is_le_extended_advertising_supported
- && !AdvertiseData::validate_raw_data(true, adv_bytes)
- {
- log::info!("Auto upgrading advertisement to extended");
+ pub fn can_upgrade(parameters: &mut AdvertisingSetParameters, adv_bytes: &Vec<u8>) -> bool {
+ if parameters.is_legacy && !AdvertiseData::validate_raw_data(true, adv_bytes) {
+ info!("Auto upgrading advertisement to extended");
parameters.is_legacy = false;
return true;
}
@@ -546,10 +542,15 @@
is_le_ext_adv_supported: bool,
) {
self.adv_manager_impl = if is_le_ext_adv_supported {
+ info!("AdvertiseManager: Selected extended advertising stack");
Some(Box::new(AdvertiseManagerImpl::new(self.tx.clone(), gatt, adapter)))
} else {
- // TODO: Implement software rotation for legacy controller
- Some(Box::new(AdvertiseManagerImpl::new(self.tx.clone(), gatt, adapter)))
+ info!("AdvertiseManager: Selected software rotation stack");
+ Some(Box::new(SoftwareRotationAdvertiseManagerImpl::new(
+ self.tx.clone(),
+ gatt,
+ adapter,
+ )))
}
}
@@ -699,6 +700,12 @@
}
}
+pub enum AdvertiserActions {
+ /// Triggers the rotation of the advertising set.
+ /// Should only be used in the software rotation stack.
+ RunRotate,
+}
+
/// Defines all required ops for an AdvertiseManager to communicate with the upper/lower layers.
pub(crate) trait AdvertiseManagerOps:
IBluetoothAdvertiseManager + BtifGattAdvCallbacks
@@ -708,6 +715,9 @@
/// Undoes previous suspend preparation
fn exit_suspend(&mut self);
+
+ /// Handles advertise manager actions
+ fn handle_action(&mut self, action: AdvertiserActions);
}
impl AdvertiseManagerOps for AdvertiseManagerImpl {
@@ -748,6 +758,14 @@
self.set_suspend_mode(SuspendMode::Normal);
}
+
+ fn handle_action(&mut self, action: AdvertiserActions) {
+ match action {
+ AdvertiserActions::RunRotate => {
+ error!("Unexpected RunRotate call in hardware offloaded stack");
+ }
+ }
+ }
}
pub trait IBluetoothAdvertiseManager {
@@ -876,15 +894,9 @@
let device_name = self.get_adapter_name();
let adv_bytes = advertise_data.make_with(&device_name);
- let is_le_extended_advertising_supported =
- self.adapter.lock().unwrap().is_le_extended_advertising_supported();
// TODO(b/311417973): Remove this once we have more robust /device/bluetooth APIs to control extended advertising
- let is_legacy = parameters.is_legacy
- && !AdvertiseData::can_upgrade(
- &mut parameters,
- &adv_bytes,
- is_le_extended_advertising_supported,
- );
+ let is_legacy =
+ parameters.is_legacy && !AdvertiseData::can_upgrade(&mut parameters, &adv_bytes);
let params = parameters.into();
if !AdvertiseData::validate_raw_data(is_legacy, &adv_bytes) {
warn!("Failed to start advertising set with invalid advertise data");
@@ -1369,6 +1381,691 @@
}
}
+/// The underlying legacy advertising rotates every SOFTWARE_ROTATION_INTERVAL seconds.
+const SOFTWARE_ROTATION_INTERVAL: Duration = Duration::from_secs(2);
+
+/// The ID of a software rotation advertising.
+///
+/// From DBus API's perspective this is used as both Advertiser ID and Register ID.
+/// Unlike the extended advertising stack we can't propagate the LibBluetooth Advertiser ID to
+/// DBus clients because there can be at most 1 advertiser in LibBluetooth layer at the same time.
+pub type SoftwareRotationAdvertierId = i32;
+
+struct SoftwareRotationAdvertiseInfo {
+ id: SoftwareRotationAdvertierId,
+ callback_id: u32,
+
+ advertising_params: AdvertisingSetParameters,
+ advertising_data: Vec<u8>,
+ scan_response_data: Vec<u8>,
+
+ /// Filled in on the first time the advertiser started.
+ tx_power: Option<i32>,
+
+ /// True if it's advertising (from DBus client's perspective), false otherwise.
+ enabled: bool,
+ duration: i32,
+ /// None means no timeout
+ expire_time: Option<Instant>,
+}
+
+enum SoftwareRotationAdvertiseState {
+ /// No advertiser is running in LibBluetooth.
+ Stopped,
+ /// A StartAdvertisingSet call to LibBluetooth is pending.
+ Pending(SoftwareRotationAdvertierId),
+ /// An advertiser is running in LibBluetooth, i.e., an OnAdvertisingSetStarted is received.
+ /// Parameters: ID, LibBluetooth BLE Advertiser ID, rotation timer handle
+ Advertising(SoftwareRotationAdvertierId, u8, JoinHandle<()>),
+}
+
+struct SoftwareRotationAdvertiseManagerImpl {
+ callbacks: Callbacks<dyn IAdvertisingSetCallback + Send>,
+ suspend_mode: SuspendMode,
+ gatt: Arc<Mutex<Gatt>>,
+ adapter: Arc<Mutex<Box<Bluetooth>>>,
+ tx: Sender<Message>,
+
+ state: SoftwareRotationAdvertiseState,
+ adv_info: HashMap<SoftwareRotationAdvertierId, SoftwareRotationAdvertiseInfo>,
+ /// The enabled advertising sets to be rotate.
+ /// When they are removed from the queue, OnAdvertisingEnabled needs to be sent.
+ /// Note that the current advertiser running in LibBluetooth must *NOT* be in the queue.
+ adv_queue: VecDeque<SoftwareRotationAdvertierId>,
+}
+
+impl SoftwareRotationAdvertiseManagerImpl {
+ fn new(
+ tx: Sender<Message>,
+ gatt: Arc<Mutex<Gatt>>,
+ adapter: Arc<Mutex<Box<Bluetooth>>>,
+ ) -> Self {
+ Self {
+ callbacks: Callbacks::new(tx.clone(), Message::AdvertiserCallbackDisconnected),
+ suspend_mode: SuspendMode::Normal,
+ gatt,
+ adapter,
+ tx,
+ state: SoftwareRotationAdvertiseState::Stopped,
+ adv_info: HashMap::new(),
+ adv_queue: VecDeque::new(),
+ }
+ }
+}
+
+impl SoftwareRotationAdvertiseManagerImpl {
+ /// Updates suspend mode.
+ fn set_suspend_mode(&mut self, suspend_mode: SuspendMode) {
+ if suspend_mode != self.suspend_mode {
+ self.suspend_mode = suspend_mode.clone();
+ self.callbacks.for_all_callbacks(|cb| {
+ cb.on_suspend_mode_change(suspend_mode.clone());
+ });
+ }
+ }
+
+ fn get_adapter_name(&self) -> String {
+ self.adapter.lock().unwrap().get_name()
+ }
+
+ /// Returns the ID of the advertiser running in LibBluetooth.
+ fn current_id(&self) -> Option<SoftwareRotationAdvertierId> {
+ match &self.state {
+ SoftwareRotationAdvertiseState::Pending(id) => Some(*id),
+ SoftwareRotationAdvertiseState::Advertising(id, _, _) => Some(*id),
+ SoftwareRotationAdvertiseState::Stopped => None,
+ }
+ }
+
+ /// Returns the minimum unoccupied ID from 0.
+ fn new_id(&mut self) -> SoftwareRotationAdvertierId {
+ // The advertiser running in LibBluetooth may have been removed in this layer.
+ // Avoid conflicting with it.
+ let current_id = self.current_id();
+ (0..)
+ .find(|id| !self.adv_info.contains_key(id) && Some(*id) != current_id)
+ .expect("There must be an unoccupied register ID")
+ }
+
+ fn is_pending(&self) -> bool {
+ matches!(&self.state, SoftwareRotationAdvertiseState::Pending(_))
+ }
+
+ fn is_stopped(&self) -> bool {
+ matches!(&self.state, SoftwareRotationAdvertiseState::Stopped)
+ }
+
+ /// Clears the removed or disabled advertisers from the queue and invokes callback.
+ fn refresh_queue(&mut self) {
+ let now = Instant::now();
+ let adv_info = &mut self.adv_info;
+ let callbacks = &mut self.callbacks;
+ self.adv_queue.retain(|id| {
+ let Some(info) = adv_info.get_mut(id) else {
+ // This advertiser has been removed.
+ return false;
+ };
+ if info.expire_time.map_or(false, |t| t < now) {
+ // This advertiser has expired.
+ info.enabled = false;
+ callbacks.get_by_id_mut(info.callback_id).map(|cb| {
+ cb.on_advertising_enabled(info.id, false, AdvertisingStatus::Success);
+ });
+ }
+ info.enabled
+ });
+ }
+
+ fn stop_current_advertising(&mut self) {
+ match &self.state {
+ SoftwareRotationAdvertiseState::Advertising(id, adv_id, handle) => {
+ handle.abort();
+ self.gatt.lock().unwrap().advertiser.unregister(*adv_id);
+ self.adv_queue.push_back(*id);
+ self.state = SoftwareRotationAdvertiseState::Stopped;
+ }
+ SoftwareRotationAdvertiseState::Pending(_) => {
+ error!("stop_current_advertising: Unexpected Pending state");
+ }
+ SoftwareRotationAdvertiseState::Stopped => {}
+ };
+ }
+
+ fn start_next_advertising(&mut self) {
+ match &self.state {
+ SoftwareRotationAdvertiseState::Stopped => {
+ self.state = loop {
+ let Some(id) = self.adv_queue.pop_front() else {
+ break SoftwareRotationAdvertiseState::Stopped;
+ };
+ let Some(info) = self.adv_info.get(&id) else {
+ error!("start_next_advertising: Unknown ID, which means queue is not refreshed!");
+ continue;
+ };
+ self.gatt.lock().unwrap().advertiser.start_advertising_set(
+ id,
+ info.advertising_params.clone().into(),
+ info.advertising_data.clone(),
+ info.scan_response_data.clone(),
+ Default::default(), // Unsupported periodic_parameters
+ vec![], // Unsupported periodic_data
+ 0, // Set no timeout. Timeout is controlled in this layer.
+ 0, // Unsupported max_ext_adv_events
+ );
+ break SoftwareRotationAdvertiseState::Pending(id);
+ }
+ }
+ SoftwareRotationAdvertiseState::Pending(_) => {
+ error!("start_next_advertising: Unexpected Pending state");
+ }
+ SoftwareRotationAdvertiseState::Advertising(_, _, _) => {
+ error!("start_next_advertising: Unexpected Advertising state");
+ }
+ };
+ }
+
+ fn run_rotate(&mut self) {
+ if self.is_pending() {
+ return;
+ }
+ let Some(current_id) = self.current_id() else {
+ // State is Stopped. Try to start next one.
+ self.refresh_queue();
+ self.start_next_advertising();
+ return;
+ };
+ // We are Advertising. Checks if the current advertiser is still allowed
+ // to advertise, or if we should schedule the next one in the queue.
+ let current_is_enabled = {
+ let now = Instant::now();
+ if let Some(info) = self.adv_info.get(¤t_id) {
+ if info.enabled {
+ info.expire_time.map_or(true, |t| t >= now)
+ } else {
+ false
+ }
+ } else {
+ false
+ }
+ };
+ if !current_is_enabled {
+ // If current advertiser is not allowed to advertise,
+ // stop it and then let |refresh_queue| handle the callback.
+ self.stop_current_advertising();
+ self.refresh_queue();
+ self.start_next_advertising();
+ } else {
+ // Current advertiser is still enabled, refresh the other advertisers in the queue.
+ self.refresh_queue();
+ if self.adv_queue.is_empty() {
+ // No need to rotate.
+ } else {
+ self.stop_current_advertising();
+ self.start_next_advertising();
+ }
+ }
+ }
+}
+
+impl AdvertiseManagerOps for SoftwareRotationAdvertiseManagerImpl {
+ fn enter_suspend(&mut self) {
+ if self.suspend_mode != SuspendMode::Normal {
+ return;
+ }
+
+ self.set_suspend_mode(SuspendMode::Suspending);
+ if self.is_pending() {
+ // We will unregister it on_advertising_set_started and then set mode to suspended.
+ return;
+ }
+ self.stop_current_advertising();
+ self.set_suspend_mode(SuspendMode::Suspended);
+ }
+
+ fn exit_suspend(&mut self) {
+ if self.suspend_mode != SuspendMode::Suspended {
+ return;
+ }
+ self.refresh_queue();
+ self.start_next_advertising();
+ self.set_suspend_mode(SuspendMode::Normal);
+ }
+
+ fn handle_action(&mut self, action: AdvertiserActions) {
+ match action {
+ AdvertiserActions::RunRotate => {
+ if self.suspend_mode == SuspendMode::Normal {
+ self.run_rotate();
+ }
+ }
+ }
+ }
+}
+
+/// Generates expire time from now per the definition in IBluetoothAdvertiseManager
+///
+/// None means never timeout.
+fn gen_expire_time_from_now(duration: i32) -> Option<Instant> {
+ let duration = clamp(duration, 0, 0xffff) as u64;
+ if duration != 0 {
+ Some(Instant::now() + Duration::from_millis(duration * 10))
+ } else {
+ None
+ }
+}
+
+impl IBluetoothAdvertiseManager for SoftwareRotationAdvertiseManagerImpl {
+ fn register_callback(&mut self, callback: Box<dyn IAdvertisingSetCallback + Send>) -> u32 {
+ self.callbacks.add_callback(callback)
+ }
+
+ fn unregister_callback(&mut self, callback_id: u32) -> bool {
+ self.adv_info.retain(|_, info| info.callback_id != callback_id);
+ let ret = self.callbacks.remove_callback(callback_id);
+ if let Some(current_id) = self.current_id() {
+ if !self.adv_info.contains_key(¤t_id) {
+ self.run_rotate();
+ }
+ }
+ ret
+ }
+
+ fn start_advertising_set(
+ &mut self,
+ advertising_params: AdvertisingSetParameters,
+ advertising_data: AdvertiseData,
+ scan_response_data: Option<AdvertiseData>,
+ periodic_parameters: Option<PeriodicAdvertisingParameters>,
+ periodic_data: Option<AdvertiseData>,
+ duration: i32,
+ max_ext_adv_events: i32,
+ callback_id: u32,
+ ) -> i32 {
+ if self.suspend_mode != SuspendMode::Normal {
+ return INVALID_REG_ID;
+ }
+
+ let is_legacy = advertising_params.is_legacy;
+ let device_name = self.get_adapter_name();
+
+ let advertising_data = advertising_data.make_with(&device_name);
+ if !AdvertiseData::validate_raw_data(is_legacy, &advertising_data) {
+ warn!("Failed to start advertising set with invalid advertising data");
+ return INVALID_REG_ID;
+ }
+
+ let scan_response_data =
+ scan_response_data.map_or(vec![], |data| data.make_with(&device_name));
+ if !AdvertiseData::validate_raw_data(is_legacy, &scan_response_data) {
+ warn!("Failed to start advertising set with invalid scan response data");
+ return INVALID_REG_ID;
+ }
+
+ if periodic_parameters.is_some() {
+ warn!("Periodic parameters is not supported in software rotation stack, ignored");
+ }
+ if periodic_data.is_some() {
+ warn!("Periodic data is not supported in software rotation stack, ignored");
+ }
+ if max_ext_adv_events != 0 {
+ warn!("max_ext_adv_events is not supported in software rotation stack, ignored");
+ }
+
+ let id = self.new_id();
+
+ // expire_time will be determined on this advertiser is started at the first time.
+ self.adv_info.insert(
+ id,
+ SoftwareRotationAdvertiseInfo {
+ id,
+ callback_id,
+ advertising_params,
+ advertising_data,
+ scan_response_data,
+ tx_power: None,
+ enabled: true,
+ duration,
+ expire_time: None,
+ },
+ );
+ // Schedule it as the next one and rotate.
+ self.adv_queue.push_front(id);
+ self.run_rotate();
+
+ id
+ }
+
+ fn stop_advertising_set(&mut self, adv_id: i32) {
+ let current_id = self.current_id();
+ let Some(info) = self.adv_info.remove(&adv_id) else {
+ warn!("stop_advertising_set: Unknown adv_id {}", adv_id);
+ return;
+ };
+ self.callbacks.get_by_id_mut(info.callback_id).map(|cb| {
+ cb.on_advertising_set_stopped(info.id);
+ });
+ if current_id == Some(info.id) {
+ self.run_rotate();
+ }
+ }
+
+ fn get_own_address(&mut self, _adv_id: i32) {
+ error!("get_own_address is not supported in software rotation stack");
+ }
+
+ fn enable_advertising_set(
+ &mut self,
+ adv_id: i32,
+ enable: bool,
+ duration: i32,
+ max_ext_adv_events: i32,
+ ) {
+ if self.suspend_mode != SuspendMode::Normal {
+ return;
+ }
+
+ let current_id = self.current_id();
+ let Some(info) = self.adv_info.get_mut(&adv_id) else {
+ warn!("enable_advertising_set: Unknown adv_id {}", adv_id);
+ return;
+ };
+
+ if max_ext_adv_events != 0 {
+ warn!("max_ext_adv_events is not supported in software rotation stack, ignored");
+ }
+
+ info.enabled = enable;
+ // We won't really call enable() to LibBluetooth so calculate the expire time right now.
+ info.expire_time = gen_expire_time_from_now(duration);
+ // This actually won't be used as the expire_time is already determined.
+ // Still fill it in to keep the data updated.
+ info.duration = duration;
+
+ if enable && !self.adv_queue.contains(&info.id) && current_id != Some(info.id) {
+ // The adv was not enabled and not in the queue. Invoke callback and queue it.
+ self.callbacks.get_by_id_mut(info.callback_id).map(|cb| {
+ cb.on_advertising_enabled(info.id, false, AdvertisingStatus::Success);
+ });
+ self.adv_queue.push_back(info.id);
+ if self.is_stopped() {
+ self.start_next_advertising();
+ }
+ } else if !enable && current_id == Some(info.id) {
+ self.run_rotate();
+ }
+ }
+
+ fn set_advertising_data(&mut self, adv_id: i32, data: AdvertiseData) {
+ if self.suspend_mode != SuspendMode::Normal {
+ return;
+ }
+
+ let current_id = self.current_id();
+ let device_name = self.get_adapter_name();
+ let Some(info) = self.adv_info.get_mut(&adv_id) else {
+ warn!("set_advertising_data: Unknown adv_id {}", adv_id);
+ return;
+ };
+ let data = data.make_with(&device_name);
+ if !AdvertiseData::validate_raw_data(info.advertising_params.is_legacy, &data) {
+ warn!("set_advertising_data {}: invalid advertise data to update", adv_id);
+ return;
+ }
+ info.advertising_data = data;
+ self.callbacks.get_by_id_mut(info.callback_id).map(|cb| {
+ cb.on_advertising_data_set(info.id, AdvertisingStatus::Success);
+ });
+
+ if current_id == Some(info.id) {
+ self.run_rotate();
+ }
+ }
+
+ fn set_raw_adv_data(&mut self, adv_id: i32, data: Vec<u8>) {
+ if self.suspend_mode != SuspendMode::Normal {
+ return;
+ }
+
+ let current_id = self.current_id();
+ let Some(info) = self.adv_info.get_mut(&adv_id) else {
+ warn!("set_raw_adv_data: Unknown adv_id {}", adv_id);
+ return;
+ };
+ if !AdvertiseData::validate_raw_data(info.advertising_params.is_legacy, &data) {
+ warn!("set_raw_adv_data {}: invalid raw advertise data to update", adv_id);
+ return;
+ }
+ info.advertising_data = data;
+ self.callbacks.get_by_id_mut(info.callback_id).map(|cb| {
+ cb.on_advertising_data_set(info.id, AdvertisingStatus::Success);
+ });
+
+ if current_id == Some(info.id) {
+ self.run_rotate();
+ }
+ }
+
+ fn set_scan_response_data(&mut self, adv_id: i32, data: AdvertiseData) {
+ if self.suspend_mode != SuspendMode::Normal {
+ return;
+ }
+
+ let current_id = self.current_id();
+ let device_name = self.get_adapter_name();
+ let Some(info) = self.adv_info.get_mut(&adv_id) else {
+ warn!("set_scan_response_data: Unknown adv_id {}", adv_id);
+ return;
+ };
+ let data = data.make_with(&device_name);
+ if !AdvertiseData::validate_raw_data(info.advertising_params.is_legacy, &data) {
+ warn!("set_scan_response_data {}: invalid scan response to update", adv_id);
+ return;
+ }
+ info.scan_response_data = data;
+ self.callbacks.get_by_id_mut(info.callback_id).map(|cb| {
+ cb.on_scan_response_data_set(info.id, AdvertisingStatus::Success);
+ });
+
+ if current_id == Some(info.id) {
+ self.run_rotate();
+ }
+ }
+
+ fn set_advertising_parameters(&mut self, adv_id: i32, params: AdvertisingSetParameters) {
+ if self.suspend_mode != SuspendMode::Normal {
+ return;
+ }
+
+ let current_id = self.current_id();
+ let Some(info) = self.adv_info.get_mut(&adv_id) else {
+ warn!("set_advertising_parameters: Unknown adv_id {}", adv_id);
+ return;
+ };
+ info.advertising_params = params;
+ let Some(tx_power) = info.tx_power else {
+ error!("set_advertising_parameters: tx_power is None! Is this called before adv has started?");
+ return;
+ };
+ self.callbacks.get_by_id_mut(info.callback_id).map(|cb| {
+ cb.on_advertising_parameters_updated(info.id, tx_power, AdvertisingStatus::Success);
+ });
+
+ if current_id == Some(info.id) {
+ self.run_rotate();
+ }
+ }
+
+ fn set_periodic_advertising_parameters(
+ &mut self,
+ _adv_id: i32,
+ _parameters: PeriodicAdvertisingParameters,
+ ) {
+ error!("set_periodic_advertising_parameters is not supported in software rotation stack");
+ }
+
+ fn set_periodic_advertising_data(&mut self, _adv_id: i32, _data: AdvertiseData) {
+ error!("set_periodic_advertising_data is not supported in software rotation stack");
+ }
+
+ fn set_periodic_advertising_enable(&mut self, _adv_id: i32, _enable: bool, _include_adi: bool) {
+ error!("set_periodic_advertising_enable is not supported in software rotation stack");
+ }
+}
+
+impl BtifGattAdvCallbacks for SoftwareRotationAdvertiseManagerImpl {
+ fn on_advertising_set_started(
+ &mut self,
+ reg_id: i32,
+ adv_id: u8,
+ tx_power: i8,
+ status: AdvertisingStatus,
+ ) {
+ debug!(
+ "on_advertising_set_started(): reg_id = {}, advertiser_id = {}, tx_power = {}, status = {:?}",
+ reg_id, adv_id, tx_power, status
+ );
+
+ // Unregister if it's unexpected.
+ match &self.state {
+ SoftwareRotationAdvertiseState::Pending(pending_id) if pending_id == ®_id => {}
+ _ => {
+ error!(
+ "Unexpected on_advertising_set_started reg_id = {}, adv_id = {}, status = {:?}",
+ reg_id, adv_id, status
+ );
+ if status == AdvertisingStatus::Success {
+ self.gatt.lock().unwrap().advertiser.unregister(adv_id);
+ }
+ return;
+ }
+ }
+ // Switch out from the pending state.
+ self.state = if status != AdvertisingStatus::Success {
+ warn!("on_advertising_set_started failed: reg_id = {}, status = {:?}", reg_id, status);
+ SoftwareRotationAdvertiseState::Stopped
+ } else {
+ let txl = self.tx.clone();
+ SoftwareRotationAdvertiseState::Advertising(
+ reg_id,
+ adv_id,
+ tokio::spawn(async move {
+ loop {
+ time::sleep(SOFTWARE_ROTATION_INTERVAL).await;
+ let _ = txl
+ .send(Message::AdvertiserActions(AdvertiserActions::RunRotate))
+ .await;
+ }
+ }),
+ )
+ };
+
+ // 1. Handle on_advertising_set_started callback if it's the first time it started
+ // 2. Stop advertising if it's removed or disabled
+ // 3. Disable or remove the advertiser if it failed
+ if let Some(info) = self.adv_info.get_mut(®_id) {
+ if info.tx_power.is_none() {
+ // tx_power is none means it's the first time this advertiser started.
+ if status != AdvertisingStatus::Success {
+ self.callbacks.get_by_id_mut(info.callback_id).map(|cb| {
+ cb.on_advertising_set_started(info.id, INVALID_ADV_ID, 0, status);
+ });
+ self.adv_info.remove(®_id);
+ } else {
+ info.tx_power = Some(tx_power.into());
+ info.expire_time = gen_expire_time_from_now(info.duration);
+ self.callbacks.get_by_id_mut(info.callback_id).map(|cb| {
+ cb.on_advertising_set_started(info.id, info.id, tx_power.into(), status);
+ });
+ }
+ } else {
+ // Not the first time. This means we are not able to report the failure through
+ // on_advertising_set_started if it failed. Disable it instead in that case.
+ if status != AdvertisingStatus::Success {
+ info.enabled = false;
+ // Push to the queue and let refresh_queue handle the disabled callback.
+ self.adv_queue.push_back(reg_id);
+ } else {
+ if !info.enabled {
+ self.stop_current_advertising();
+ }
+ }
+ }
+ } else {
+ self.stop_current_advertising();
+ }
+
+ // Rotate again if the next advertiser is new. We need to consume all
+ // "first time" advertiser before suspended to make sure callbacks are sent.
+ if let Some(id) = self.adv_queue.front() {
+ if let Some(info) = self.adv_info.get(id) {
+ if info.tx_power.is_none() {
+ self.run_rotate();
+ return;
+ }
+ }
+ }
+
+ // We're fine to suspend since there is no advertiser pending callback.
+ if self.suspend_mode != SuspendMode::Normal {
+ self.stop_current_advertising();
+ self.set_suspend_mode(SuspendMode::Suspended);
+ return;
+ }
+
+ // If the current advertiser is stopped for some reason, schedule the next one.
+ if self.is_stopped() {
+ self.refresh_queue();
+ self.start_next_advertising();
+ }
+ }
+
+ fn on_advertising_enabled(&mut self, _adv_id: u8, _enabled: bool, _status: AdvertisingStatus) {
+ error!("Unexpected on_advertising_enabled in software rotation stack");
+ }
+
+ fn on_advertising_data_set(&mut self, _adv_id: u8, _status: AdvertisingStatus) {
+ error!("Unexpected on_advertising_data_set in software rotation stack");
+ }
+
+ fn on_scan_response_data_set(&mut self, _adv_id: u8, _status: AdvertisingStatus) {
+ error!("Unexpected on_scan_response_data_set in software rotation stack");
+ }
+
+ fn on_advertising_parameters_updated(
+ &mut self,
+ _adv_id: u8,
+ _tx_power: i8,
+ _status: AdvertisingStatus,
+ ) {
+ error!("Unexpected on_advertising_parameters_updated in software rotation stack");
+ }
+
+ fn on_periodic_advertising_parameters_updated(
+ &mut self,
+ _adv_id: u8,
+ _status: AdvertisingStatus,
+ ) {
+ error!("Unexpected on_periodic_advertising_parameters_updated in software rotation stack");
+ }
+
+ fn on_periodic_advertising_data_set(&mut self, _adv_id: u8, _status: AdvertisingStatus) {
+ error!("Unexpected on_periodic_advertising_data_set in software rotation stack");
+ }
+
+ fn on_periodic_advertising_enabled(
+ &mut self,
+ _adv_id: u8,
+ _enabled: bool,
+ _status: AdvertisingStatus,
+ ) {
+ error!("Unexpected on_periodic_advertising_enabled in software rotation stack");
+ }
+
+ fn on_own_address_read(&mut self, _adv_id: u8, _addr_type: u8, _address: RawAddress) {
+ error!("Unexpected on_own_address_read in software rotation stack");
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/system/gd/rust/linux/stack/src/bluetooth_gatt.rs b/system/gd/rust/linux/stack/src/bluetooth_gatt.rs
index d054af6..4e02cfb 100644
--- a/system/gd/rust/linux/stack/src/bluetooth_gatt.rs
+++ b/system/gd/rust/linux/stack/src/bluetooth_gatt.rs
@@ -20,8 +20,8 @@
use crate::async_helper::{AsyncHelper, CallbackSender};
use crate::bluetooth::{Bluetooth, BluetoothDevice};
use crate::bluetooth_adv::{
- AdvertiseData, AdvertiseManager, AdvertisingSetParameters, BtifGattAdvCallbacks,
- IAdvertisingSetCallback, PeriodicAdvertisingParameters,
+ AdvertiseData, AdvertiseManager, AdvertiserActions, AdvertisingSetParameters,
+ BtifGattAdvCallbacks, IAdvertisingSetCallback, PeriodicAdvertisingParameters,
};
use crate::callbacks::Callbacks;
use crate::uuid::UuidHelper;
@@ -1881,6 +1881,10 @@
}
}
}
+
+ pub fn handle_adv_action(&mut self, action: AdvertiserActions) {
+ self.adv_manager.get_impl().handle_action(action);
+ }
}
#[derive(Debug, FromPrimitive, ToPrimitive)]
diff --git a/system/gd/rust/linux/stack/src/lib.rs b/system/gd/rust/linux/stack/src/lib.rs
index e3fe650..6616b2d 100644
--- a/system/gd/rust/linux/stack/src/lib.rs
+++ b/system/gd/rust/linux/stack/src/lib.rs
@@ -35,7 +35,7 @@
BluetoothDevice, DelayedActions, IBluetooth,
};
use crate::bluetooth_admin::{BluetoothAdmin, IBluetoothAdmin};
-use crate::bluetooth_adv::dispatch_le_adv_callbacks;
+use crate::bluetooth_adv::{dispatch_le_adv_callbacks, AdvertiserActions};
use crate::bluetooth_gatt::{
dispatch_gatt_client_callbacks, dispatch_gatt_server_callbacks, dispatch_le_scanner_callbacks,
dispatch_le_scanner_inband_callbacks, BluetoothGatt, GattActions,
@@ -116,6 +116,7 @@
// Advertising related
AdvertiserCallbackDisconnected(u32),
+ AdvertiserActions(AdvertiserActions),
SocketManagerActions(SocketActions),
SocketManagerCallbackDisconnected(u32),
@@ -367,6 +368,10 @@
bluetooth_gatt.lock().unwrap().remove_adv_callback(id);
}
+ Message::AdvertiserActions(action) => {
+ bluetooth_gatt.lock().unwrap().handle_adv_action(action);
+ }
+
Message::SocketManagerActions(action) => {
bluetooth_socketmgr.lock().unwrap().handle_actions(action);
}
diff --git a/system/include/hardware/bt_hh.h b/system/include/hardware/bt_hh.h
index 1be58aa..3cedd88 100644
--- a/system/include/hardware/bt_hh.h
+++ b/system/include/hardware/bt_hh.h
@@ -224,4 +224,14 @@
} bthh_interface_t;
__END_DECLS
+#if __has_include(<bluetooth/log.h>)
+#include <bluetooth/log.h>
+
+namespace fmt {
+template <> struct formatter<bthh_connection_state_t> :
+enum_formatter<bthh_connection_state_t> {};
+} // namespace fmt
+
+#endif // __has_include(<bluetooth/log.h>)
+
#endif /* ANDROID_INCLUDE_BT_HH_H */
diff --git a/system/main/shim/hci_layer.cc b/system/main/shim/hci_layer.cc
index 9630a70..e14e106 100644
--- a/system/main/shim/hci_layer.cc
+++ b/system/main/shim/hci_layer.cc
@@ -62,11 +62,6 @@
namespace {
bool register_event_code(bluetooth::hci::EventCode event_code) {
switch (event_code) {
- // Inquiry
- case bluetooth::hci::EventCode::INQUIRY_RESULT:
- case bluetooth::hci::EventCode::INQUIRY_RESULT_WITH_RSSI:
- case bluetooth::hci::EventCode::EXTENDED_INQUIRY_RESULT:
-
// SCO
case bluetooth::hci::EventCode::SYNCHRONOUS_CONNECTION_COMPLETE:
case bluetooth::hci::EventCode::SYNCHRONOUS_CONNECTION_CHANGED:
diff --git a/system/stack/btm/btm_inq.cc b/system/stack/btm/btm_inq.cc
index 0b8e5c2..5cb52a7 100644
--- a/system/stack/btm/btm_inq.cc
+++ b/system/stack/btm/btm_inq.cc
@@ -25,8 +25,6 @@
*
******************************************************************************/
-#include "hci_error_code.h"
-#include "neighbor_inquiry.h"
#define LOG_TAG "bluetooth"
#include <base/logging.h>
@@ -49,12 +47,15 @@
#include "include/check.h"
#include "internal_include/bt_target.h"
#include "main/shim/entry.h"
+#include "main/shim/helpers.h"
#include "main/shim/shim.h"
+#include "neighbor_inquiry.h"
#include "os/log.h"
#include "osi/include/allocator.h"
#include "osi/include/osi.h"
#include "osi/include/properties.h"
#include "osi/include/stack_power_telemetry.h"
+#include "packet/bit_inserter.h"
#include "stack/btm/btm_int_types.h"
#include "stack/btm/btm_sec.h"
#include "stack/include/acl_api_types.h"
@@ -65,6 +66,8 @@
#include "stack/include/btm_api.h"
#include "stack/include/btm_ble_api.h"
#include "stack/include/btm_log_history.h"
+#include "stack/include/hci_error_code.h"
+#include "stack/include/hcidefs.h"
#include "stack/include/hcimsgs.h"
#include "stack/include/inq_hci_link_interface.h"
#include "stack/include/main_thread.h"
@@ -689,6 +692,21 @@
get_main_thread()->Bind([](bluetooth::hci::EventView event) {
on_incoming_hci_event(event);
}));
+ bluetooth::shim::GetHciLayer()->RegisterEventHandler(
+ bluetooth::hci::EventCode::INQUIRY_RESULT,
+ get_main_thread()->Bind([](bluetooth::hci::EventView event) {
+ on_incoming_hci_event(event);
+ }));
+ bluetooth::shim::GetHciLayer()->RegisterEventHandler(
+ bluetooth::hci::EventCode::INQUIRY_RESULT_WITH_RSSI,
+ get_main_thread()->Bind([](bluetooth::hci::EventView event) {
+ on_incoming_hci_event(event);
+ }));
+ bluetooth::shim::GetHciLayer()->RegisterEventHandler(
+ bluetooth::hci::EventCode::EXTENDED_INQUIRY_RESULT,
+ get_main_thread()->Bind([](bluetooth::hci::EventView event) {
+ on_incoming_hci_event(event);
+ }));
btm_cb.btm_inq_vars.registered_for_hci_events = true;
}
@@ -1320,9 +1338,7 @@
* Returns void
*
******************************************************************************/
-static void btm_process_inq_results_standard(const uint8_t* p,
- uint8_t hci_evt_len) {
- uint8_t num_resp, xx;
+static void btm_process_inq_results_standard(bluetooth::hci::EventView event) {
RawAddress bda;
tINQ_DB_ENT* p_i;
tBTM_INQ_RESULTS* p_cur = NULL;
@@ -1344,27 +1360,24 @@
return;
}
- STREAM_TO_UINT8(num_resp, p);
+ auto standard_view = bluetooth::hci::InquiryResultView::Create(event);
+ ASSERT(standard_view.IsValid());
+ auto responses = standard_view.GetResponses();
- {
- constexpr uint16_t inquiry_result_size = 14;
- if (hci_evt_len < num_resp * inquiry_result_size) {
- log::error("can't fit {} results in {} bytes", num_resp, hci_evt_len);
- return;
- }
- }
-
- btm_cb.neighbor.classic_inquiry.results += num_resp;
- for (xx = 0; xx < num_resp; xx++) {
+ btm_cb.neighbor.classic_inquiry.results += responses.size();
+ for (const auto& response : responses) {
/* Extract inquiry results */
- STREAM_TO_BDADDR(bda, p);
- STREAM_TO_UINT8(page_scan_rep_mode, p);
- STREAM_TO_UINT8(page_scan_per_mode, p);
+ bda = bluetooth::ToRawAddress(response.bd_addr_);
+ page_scan_rep_mode =
+ static_cast<uint8_t>(response.page_scan_repetition_mode_);
+ page_scan_per_mode = 0; // reserved
+ page_scan_mode = 0; // reserved
- STREAM_TO_UINT8(page_scan_mode, p);
+ dc[0] = response.class_of_device_.cod[2];
+ dc[1] = response.class_of_device_.cod[1];
+ dc[2] = response.class_of_device_.cod[0];
- STREAM_TO_DEVCLASS(dc, p);
- STREAM_TO_UINT16(clock_offset, p);
+ clock_offset = response.clock_offset_;
p_i = btm_inq_db_find(bda);
@@ -1439,17 +1452,10 @@
* from the device. It updates the inquiry database. If the
* inquiry database is full, the oldest entry is discarded.
*
- * Parameters inq_res_mode - BTM_INQ_RESULT_STANDARD
- * BTM_INQ_RESULT_WITH_RSSI
- * BTM_INQ_RESULT_EXTENDED
- *
- *
* Returns void
*
******************************************************************************/
-static void btm_process_inq_results_rssi(const uint8_t* p, uint8_t hci_evt_len,
- uint8_t inq_res_mode) {
- uint8_t num_resp, xx;
+static void btm_process_inq_results_rssi(bluetooth::hci::EventView event) {
RawAddress bda;
tINQ_DB_ENT* p_i;
tBTM_INQ_RESULTS* p_cur = NULL;
@@ -1474,45 +1480,26 @@
return;
}
- STREAM_TO_UINT8(num_resp, p);
+ auto rssi_view = bluetooth::hci::InquiryResultWithRssiView::Create(event);
+ ASSERT(rssi_view.IsValid());
+ auto responses = rssi_view.GetResponses();
- if (inq_res_mode == BTM_INQ_RESULT_EXTENDED) {
- if (num_resp > 1) {
- log::error("extended results ({}) > 1", num_resp);
- return;
- }
-
- constexpr uint16_t extended_inquiry_result_size = 254;
- if (hci_evt_len - 1 != extended_inquiry_result_size) {
- log::error("can't fit {} results in {} bytes", num_resp, hci_evt_len);
- return;
- }
- } else if (inq_res_mode == BTM_INQ_RESULT_STANDARD ||
- inq_res_mode == BTM_INQ_RESULT_WITH_RSSI) {
- constexpr uint16_t inquiry_result_size = 14;
- if (hci_evt_len < num_resp * inquiry_result_size) {
- log::error("can't fit {} results in {} bytes", num_resp, hci_evt_len);
- return;
- }
- }
-
- btm_cb.neighbor.classic_inquiry.results += num_resp;
- for (xx = 0; xx < num_resp; xx++) {
+ btm_cb.neighbor.classic_inquiry.results += responses.size();
+ for (const auto& response : responses) {
update = false;
/* Extract inquiry results */
- STREAM_TO_BDADDR(bda, p);
- STREAM_TO_UINT8(page_scan_rep_mode, p);
- STREAM_TO_UINT8(page_scan_per_mode, p);
+ bda = bluetooth::ToRawAddress(response.address_);
+ page_scan_rep_mode =
+ static_cast<uint8_t>(response.page_scan_repetition_mode_);
+ page_scan_per_mode = 0; // reserved
+ page_scan_mode = 0; // reserved
- if (inq_res_mode == BTM_INQ_RESULT_STANDARD) {
- STREAM_TO_UINT8(page_scan_mode, p);
- }
+ dc[0] = response.class_of_device_.cod[2];
+ dc[1] = response.class_of_device_.cod[1];
+ dc[2] = response.class_of_device_.cod[0];
- STREAM_TO_DEVCLASS(dc, p);
- STREAM_TO_UINT16(clock_offset, p);
- if (inq_res_mode != BTM_INQ_RESULT_STANDARD) {
- STREAM_TO_UINT8(rssi, p);
- }
+ clock_offset = response.clock_offset_;
+ rssi = response.rssi_;
p_i = btm_inq_db_find(bda);
@@ -1533,13 +1520,6 @@
p_cur->rssi = i_rssi;
update = true;
}
- /* If we received a second Extended Inq Event for an already */
- /* discovered device, this is because for the first one EIR was not
- received */
- else if ((inq_res_mode == BTM_INQ_RESULT_EXTENDED) && (p_i)) {
- p_cur = &p_i->inq_info.results;
- update = true;
- }
/* If no update needed continue with next response (if any) */
else
continue;
@@ -1553,20 +1533,15 @@
}
/* If an entry for the device already exists, overwrite it ONLY if it is
- from
- a previous inquiry. (Ignore it if it is a duplicate response from the
- same
- inquiry.
+ from a previous inquiry. (Ignore it if it is a duplicate response from
+ the same inquiry.
*/
else if (p_i->inq_count == btm_cb.btm_inq_vars.inq_counter &&
(p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BREDR))
is_new = false;
/* keep updating RSSI to have latest value */
- if (inq_res_mode != BTM_INQ_RESULT_STANDARD)
- p_i->inq_info.results.rssi = (int8_t)rssi;
- else
- p_i->inq_info.results.rssi = BTM_INQ_RES_IGNORE_RSSI;
+ p_i->inq_info.results.rssi = (int8_t)rssi;
if (is_new) {
/* Save the info */
@@ -1584,17 +1559,7 @@
if (p_i->inq_count != btm_cb.btm_inq_vars.inq_counter) {
/* A new response was found */
btm_cb.btm_inq_vars.inq_cmpl_info.num_resp++;
- switch (static_cast<tBTM_INQ_RESULT>(inq_res_mode)) {
- case BTM_INQ_RESULT_STANDARD:
- case BTM_INQ_RESULT_WITH_RSSI:
- case BTM_INQ_RESULT_EXTENDED:
- btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[inq_res_mode]++;
- break;
- case BTM_INQ_RES_IGNORE_RSSI:
- btm_cb.btm_inq_vars.inq_cmpl_info
- .resp_type[BTM_INQ_RESULT_STANDARD]++;
- break;
- }
+ btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[BTM_INQ_RESULT_WITH_RSSI]++;
}
p_cur->inq_result_type |= BT_DEVICE_TYPE_BREDR;
@@ -1611,14 +1576,7 @@
}
if (is_new || update) {
- if (inq_res_mode == BTM_INQ_RESULT_EXTENDED) {
- memset(p_cur->eir_uuid, 0,
- BTM_EIR_SERVICE_ARRAY_SIZE * (BTM_EIR_ARRAY_BITS / 8));
- /* set bit map of UUID list from received EIR */
- btm_set_eir_uuid(p, p_cur);
- p_eir_data = p;
- } else
- p_eir_data = NULL;
+ p_eir_data = NULL;
/* If a callback is registered, call it with the results */
if (p_inq_results_cb) {
@@ -1639,18 +1597,10 @@
* from the device. It updates the inquiry database. If the
* inquiry database is full, the oldest entry is discarded.
*
- * Parameters inq_res_mode - BTM_INQ_RESULT_STANDARD
- * BTM_INQ_RESULT_WITH_RSSI
- * BTM_INQ_RESULT_EXTENDED
- *
- *
* Returns void
*
******************************************************************************/
-static void btm_process_inq_results_extended(const uint8_t* p,
- uint8_t hci_evt_len,
- uint8_t inq_res_mode) {
- uint8_t num_resp, xx;
+static void btm_process_inq_results_extended(bluetooth::hci::EventView event) {
RawAddress bda;
tINQ_DB_ENT* p_i;
tBTM_INQ_RESULTS* p_cur = NULL;
@@ -1664,7 +1614,6 @@
uint8_t rssi = 0;
DEV_CLASS dc;
uint16_t clock_offset;
- const uint8_t* p_eir_data = NULL;
log::debug("Received inquiry result inq_active:0x{:x} state:{}",
btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state);
@@ -1675,45 +1624,23 @@
return;
}
- STREAM_TO_UINT8(num_resp, p);
+ auto extended_view = bluetooth::hci::ExtendedInquiryResultView::Create(event);
+ ASSERT(extended_view.IsValid());
- if (inq_res_mode == BTM_INQ_RESULT_EXTENDED) {
- if (num_resp > 1) {
- log::error("extended results ({}) > 1", num_resp);
- return;
- }
-
- constexpr uint16_t extended_inquiry_result_size = 254;
- if (hci_evt_len - 1 != extended_inquiry_result_size) {
- log::error("can't fit {} results in {} bytes", num_resp, hci_evt_len);
- return;
- }
- } else if (inq_res_mode == BTM_INQ_RESULT_STANDARD ||
- inq_res_mode == BTM_INQ_RESULT_WITH_RSSI) {
- constexpr uint16_t inquiry_result_size = 14;
- if (hci_evt_len < num_resp * inquiry_result_size) {
- log::error("can't fit {} results in {} bytes", num_resp, hci_evt_len);
- return;
- }
- }
-
- btm_cb.neighbor.classic_inquiry.results += num_resp;
- for (xx = 0; xx < num_resp; xx++) {
+ btm_cb.neighbor.classic_inquiry.results++;
+ {
update = false;
/* Extract inquiry results */
- STREAM_TO_BDADDR(bda, p);
- STREAM_TO_UINT8(page_scan_rep_mode, p);
- STREAM_TO_UINT8(page_scan_per_mode, p);
+ bda = bluetooth::ToRawAddress(extended_view.GetAddress());
+ page_scan_rep_mode =
+ static_cast<uint8_t>(extended_view.GetPageScanRepetitionMode());
+ page_scan_per_mode = 0; // reserved
- if (inq_res_mode == BTM_INQ_RESULT_STANDARD) {
- STREAM_TO_UINT8(page_scan_mode, p);
- }
-
- STREAM_TO_DEVCLASS(dc, p);
- STREAM_TO_UINT16(clock_offset, p);
- if (inq_res_mode != BTM_INQ_RESULT_STANDARD) {
- STREAM_TO_UINT8(rssi, p);
- }
+ dc[0] = extended_view.GetClassOfDevice().cod[2];
+ dc[1] = extended_view.GetClassOfDevice().cod[1];
+ dc[2] = extended_view.GetClassOfDevice().cod[0];
+ clock_offset = extended_view.GetClockOffset();
+ rssi = extended_view.GetRssi();
p_i = btm_inq_db_find(bda);
@@ -1737,13 +1664,13 @@
/* If we received a second Extended Inq Event for an already */
/* discovered device, this is because for the first one EIR was not
received */
- else if ((inq_res_mode == BTM_INQ_RESULT_EXTENDED) && (p_i)) {
+ else if (p_i) {
p_cur = &p_i->inq_info.results;
update = true;
}
/* If no update needed continue with next response (if any) */
else
- continue;
+ return;
}
/* If existing entry, use that, else get a new one (possibly reusing the
@@ -1764,10 +1691,7 @@
is_new = false;
/* keep updating RSSI to have latest value */
- if (inq_res_mode != BTM_INQ_RESULT_STANDARD)
- p_i->inq_info.results.rssi = (int8_t)rssi;
- else
- p_i->inq_info.results.rssi = BTM_INQ_RES_IGNORE_RSSI;
+ p_i->inq_info.results.rssi = (int8_t)rssi;
if (is_new) {
/* Save the info */
@@ -1785,17 +1709,7 @@
if (p_i->inq_count != btm_cb.btm_inq_vars.inq_counter) {
/* A new response was found */
btm_cb.btm_inq_vars.inq_cmpl_info.num_resp++;
- switch (static_cast<tBTM_INQ_RESULT>(inq_res_mode)) {
- case BTM_INQ_RESULT_STANDARD:
- case BTM_INQ_RESULT_WITH_RSSI:
- case BTM_INQ_RESULT_EXTENDED:
- btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[inq_res_mode]++;
- break;
- case BTM_INQ_RES_IGNORE_RSSI:
- btm_cb.btm_inq_vars.inq_cmpl_info
- .resp_type[BTM_INQ_RESULT_STANDARD]++;
- break;
- }
+ btm_cb.btm_inq_vars.inq_cmpl_info.resp_type[BTM_INQ_RESULT_EXTENDED]++;
}
p_cur->inq_result_type |= BT_DEVICE_TYPE_BREDR;
@@ -1812,14 +1726,27 @@
}
if (is_new || update) {
- if (inq_res_mode == BTM_INQ_RESULT_EXTENDED) {
+ // Create a vector of EIR data and pad it with 0
+ auto data = std::vector<uint8_t>();
+ data.reserve(HCI_EXT_INQ_RESPONSE_LEN);
+ bluetooth::packet::BitInserter bi(data);
+ for (const auto& eir : extended_view.GetExtendedInquiryResponse()) {
+ if (eir.data_type_ != static_cast<bluetooth::hci::GapDataType>(0)) {
+ eir.Serialize(bi);
+ }
+ }
+ while (data.size() < HCI_EXT_INQ_RESPONSE_LEN) {
+ data.push_back(0);
+ }
+
+ const uint8_t* p_eir_data = data.data();
+
+ {
memset(p_cur->eir_uuid, 0,
BTM_EIR_SERVICE_ARRAY_SIZE * (BTM_EIR_ARRAY_BITS / 8));
/* set bit map of UUID list from received EIR */
- btm_set_eir_uuid(p, p_cur);
- p_eir_data = p;
- } else
- p_eir_data = NULL;
+ btm_set_eir_uuid(p_eir_data, p_cur);
+ }
/* If a callback is registered, call it with the results */
if (p_inq_results_cb) {
@@ -1834,36 +1761,6 @@
/*******************************************************************************
*
- * Function btm_process_inq_results
- *
- * Description This function is called when inquiry results are received
- * from the device. It updates the inquiry database. If the
- * inquiry database is full, the oldest entry is discarded.
- *
- * Parameters inq_res_mode - BTM_INQ_RESULT_STANDARD
- * BTM_INQ_RESULT_WITH_RSSI
- * BTM_INQ_RESULT_EXTENDED
- *
- * Returns void
- *
- ******************************************************************************/
-void btm_process_inq_results(const uint8_t* p, uint8_t hci_evt_len,
- uint8_t inq_res_mode) {
- switch (inq_res_mode) {
- case BTM_INQ_RESULT_STANDARD:
- btm_process_inq_results_standard(p, hci_evt_len);
- break;
- case BTM_INQ_RESULT_WITH_RSSI:
- btm_process_inq_results_rssi(p, hci_evt_len, BTM_INQ_RESULT_WITH_RSSI);
- break;
- case BTM_INQ_RESULT_EXTENDED:
- btm_process_inq_results_extended(p, hci_evt_len, BTM_INQ_RESULT_EXTENDED);
- break;
- }
-}
-
-/*******************************************************************************
- *
* Function btm_sort_inq_result
*
* Description This function is called when inquiry complete is received
@@ -2610,6 +2507,15 @@
case bluetooth::hci::EventCode::INQUIRY_COMPLETE:
on_inquiry_complete(event);
break;
+ case bluetooth::hci::EventCode::INQUIRY_RESULT:
+ btm_process_inq_results_standard(event);
+ break;
+ case bluetooth::hci::EventCode::INQUIRY_RESULT_WITH_RSSI:
+ btm_process_inq_results_rssi(event);
+ break;
+ case bluetooth::hci::EventCode::EXTENDED_INQUIRY_RESULT:
+ btm_process_inq_results_extended(event);
+ break;
default:
log::warn("Dropping unhandled event: {}",
bluetooth::hci::EventCodeText(event_code));
diff --git a/system/stack/btu/btu_hcif.cc b/system/stack/btu/btu_hcif.cc
index 2201be4..3cc6872 100644
--- a/system/stack/btu/btu_hcif.cc
+++ b/system/stack/btu/btu_hcif.cc
@@ -42,7 +42,6 @@
#include "main/shim/hci_layer.h"
#include "os/log.h"
#include "osi/include/allocator.h"
-#include "stack/btm/neighbor_inquiry.h"
#include "stack/include/acl_hci_link_interface.h"
#include "stack/include/ble_acl_interface.h"
#include "stack/include/ble_hci_link_interface.h"
@@ -232,15 +231,6 @@
btu_hcif_log_event_metrics(hci_evt_code, p);
switch (hci_evt_code) {
- case HCI_INQUIRY_RESULT_EVT:
- btm_process_inq_results(p, hci_evt_len, BTM_INQ_RESULT_STANDARD);
- break;
- case HCI_INQUIRY_RSSI_RESULT_EVT:
- btm_process_inq_results(p, hci_evt_len, BTM_INQ_RESULT_WITH_RSSI);
- break;
- case HCI_EXTENDED_INQUIRY_RESULT_EVT:
- btm_process_inq_results(p, hci_evt_len, BTM_INQ_RESULT_EXTENDED);
- break;
case HCI_AUTHENTICATION_COMP_EVT:
btu_hcif_authentication_comp_evt(p);
break;
diff --git a/system/stack/include/hcidefs.h b/system/stack/include/hcidefs.h
index 270885e..ce79afa 100644
--- a/system/stack/include/hcidefs.h
+++ b/system/stack/include/hcidefs.h
@@ -930,7 +930,7 @@
#define HCI_UNISOC_ACL_HIGH_PRIORITY 0xFF
/* Parameter information for HCI_MTK_SET_ACL_PRIORITY */
-#define HCI_MTK_ACL_PRIORITY_PARAM_SIZE 1
+#define HCI_MTK_ACL_PRIORITY_PARAM_SIZE 4
#define HCI_MTK_SET_ACL_PRIORITY (0xFD95 | HCI_GRP_VENDOR_SPECIFIC)
#define HCI_MTK_ACL_NORMAL_PRIORITY 0x00
#define HCI_MTK_ACL_HIGH_PRIORITY 0x01
diff --git a/system/stack/include/inq_hci_link_interface.h b/system/stack/include/inq_hci_link_interface.h
index 3863889..c48c652 100644
--- a/system/stack/include/inq_hci_link_interface.h
+++ b/system/stack/include/inq_hci_link_interface.h
@@ -26,9 +26,6 @@
void btm_process_remote_name(const RawAddress* bda, const BD_NAME name,
uint16_t evt_len, tHCI_STATUS hci_status);
-void btm_process_inq_results(const uint8_t* p, uint8_t hci_evt_len,
- uint8_t inq_res_mode);
-
void btm_process_inq_complete(tHCI_STATUS status, uint8_t mode);
void btm_acl_process_sca_cmpl_pkt(uint8_t len, uint8_t* data);
diff --git a/system/stack/l2cap/l2c_utils.cc b/system/stack/l2cap/l2c_utils.cc
index f1e845e..0e199f0 100644
--- a/system/stack/l2cap/l2c_utils.cc
+++ b/system/stack/l2cap/l2c_utils.cc
@@ -2342,34 +2342,6 @@
/*******************************************************************************
*
- * Function l2cu_set_acl_priority_latency_mtk
- *
- * Description Sends a VSC to set the ACL priority and recorded latency on
- * Mediatek chip.
- *
- * Returns void
- *
- ******************************************************************************/
-
-static void l2cu_set_acl_priority_latency_mtk(tL2C_LCB* p_lcb,
- tL2CAP_PRIORITY priority) {
- uint8_t vs_param;
- if (priority == L2CAP_PRIORITY_HIGH) {
- // priority to high, if using latency mode check preset latency
- log::info("Set ACL priority: High Priority Mode");
- vs_param = HCI_MTK_ACL_HIGH_PRIORITY;
- } else {
- // priority to normal
- log::info("Set ACL priority: Normal Mode");
- vs_param = HCI_MTK_ACL_NORMAL_PRIORITY;
- }
-
- BTM_VendorSpecificCommand(HCI_MTK_SET_ACL_PRIORITY,
- HCI_MTK_ACL_PRIORITY_PARAM_SIZE, &vs_param, NULL);
-}
-
-/*******************************************************************************
- *
* Function l2cu_set_acl_priority
*
* Description Sets the transmission priority for a channel.
@@ -2413,10 +2385,6 @@
l2cu_set_acl_priority_unisoc(p_lcb, priority);
break;
- case LMP_COMPID_MEDIATEK:
- l2cu_set_acl_priority_latency_mtk(p_lcb, priority);
- break;
-
default:
/* Not supported/required for other vendors */
break;
@@ -2486,6 +2454,34 @@
/*******************************************************************************
*
+ * Function l2cu_set_acl_latency_mtk
+ *
+ * Description Sends a VSC to set the ACL latency on Mediatek chip.
+ *
+ * Returns void
+ *
+ ******************************************************************************/
+
+static void l2cu_set_acl_latency_mtk(tL2CAP_LATENCY latency) {
+ log::info("Set ACL latency: {}",
+ latency == L2CAP_LATENCY_LOW ? "Low Latancy" : "Normal Latency");
+
+ uint8_t command[HCI_MTK_ACL_PRIORITY_PARAM_SIZE];
+ uint8_t* pp = command;
+ uint8_t vs_param = latency == L2CAP_LATENCY_LOW
+ ? HCI_MTK_ACL_HIGH_PRIORITY
+ : HCI_MTK_ACL_NORMAL_PRIORITY;
+ UINT8_TO_STREAM(pp, vs_param);
+ UINT8_TO_STREAM(pp, 0);
+ UINT16_TO_STREAM(pp, 0); //reserved bytes
+
+ BTM_VendorSpecificCommand(HCI_MTK_SET_ACL_PRIORITY,
+ HCI_MTK_ACL_PRIORITY_PARAM_SIZE, command, NULL);
+}
+
+
+/*******************************************************************************
+ *
* Function l2cu_set_acl_latency
*
* Description Sets the transmission latency for a channel.
@@ -2516,6 +2512,10 @@
l2cu_set_acl_latency_syna(p_lcb, latency);
break;
+ case LMP_COMPID_MEDIATEK:
+ l2cu_set_acl_latency_mtk(latency);
+ break;
+
default:
/* Not supported/required for other vendors */
break;
diff --git a/system/test/Android.bp b/system/test/Android.bp
index c1222ef..3116df2 100644
--- a/system/test/Android.bp
+++ b/system/test/Android.bp
@@ -611,12 +611,11 @@
"mts_defaults",
],
shared_libs: [
- "android.hardware.bluetooth.audio@2.0",
- "android.hardware.bluetooth.audio@2.1",
"libbase",
"libbinder",
"libbinder_ndk",
"libchrome",
+ "libcutils",
"libhidlbase",
"liblog",
"libutils",
@@ -624,15 +623,15 @@
include_dirs: ["packages/modules/Bluetooth/system"],
srcs: ["common/hal_version_manager_test.cc"],
static_libs: [
- "android.hardware.bluetooth@1.0",
- "android.hardware.bluetooth@1.1",
+ "android.hardware.audio.common@5.0",
+ "android.hardware.bluetooth.audio@2.0",
+ "android.hardware.bluetooth.audio@2.1",
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
"bluetooth_flags_c_lib",
"libbt-audio-hal-interface",
"libflagtest",
],
- header_libs: ["libbluetooth_headers"],
test_suites: ["general-tests"],
cflags: [
"-Wall",
diff --git a/system/test/mock/mock_stack_btm_inq.cc b/system/test/mock/mock_stack_btm_inq.cc
index 9fc34e8..fbdd941 100644
--- a/system/test/mock/mock_stack_btm_inq.cc
+++ b/system/test/mock/mock_stack_btm_inq.cc
@@ -70,7 +70,6 @@
struct btm_inq_rmt_name_failed_cancelled btm_inq_rmt_name_failed_cancelled;
struct btm_inq_stop_on_ssp btm_inq_stop_on_ssp;
struct btm_process_inq_complete btm_process_inq_complete;
-struct btm_process_inq_results btm_process_inq_results;
struct btm_process_remote_name btm_process_remote_name;
struct btm_set_eir_uuid btm_set_eir_uuid;
struct btm_sort_inq_result btm_sort_inq_result;
@@ -259,12 +258,6 @@
inc_func_call_count(__func__);
test::mock::stack_btm_inq::btm_process_inq_complete(status, mode);
}
-void btm_process_inq_results(const uint8_t* p, uint8_t hci_evt_len,
- uint8_t inq_res_mode) {
- inc_func_call_count(__func__);
- test::mock::stack_btm_inq::btm_process_inq_results(p, hci_evt_len,
- inq_res_mode);
-}
void btm_process_remote_name(const RawAddress* bda, const BD_NAME bdn,
uint16_t evt_len, tHCI_STATUS hci_status) {
inc_func_call_count(__func__);
diff --git a/system/test/mock/mock_stack_btm_inq.h b/system/test/mock/mock_stack_btm_inq.h
index ab805ab..39f62a1 100644
--- a/system/test/mock/mock_stack_btm_inq.h
+++ b/system/test/mock/mock_stack_btm_inq.h
@@ -439,20 +439,6 @@
};
extern struct btm_process_inq_complete btm_process_inq_complete;
-// Name: btm_process_inq_results
-// Params: const uint8_t* p, uint8_t hci_evt_len, uint8_t inq_res_mode
-// Return: void
-struct btm_process_inq_results {
- std::function<void(const uint8_t* p, uint8_t hci_evt_len,
- uint8_t inq_res_mode)>
- body{[](const uint8_t* /* p */, uint8_t /* hci_evt_len */,
- uint8_t /* inq_res_mode */) {}};
- void operator()(const uint8_t* p, uint8_t hci_evt_len, uint8_t inq_res_mode) {
- body(p, hci_evt_len, inq_res_mode);
- };
-};
-extern struct btm_process_inq_results btm_process_inq_results;
-
// Name: btm_process_remote_name
// Params: const RawAddress* bda, const BD_NAME bdn, uint16_t evt_len,
// tHCI_STATUS hci_status Return: void
diff --git a/tools/rootcanal/Android.bp b/tools/rootcanal/Android.bp
index 910ca1b..20447c8 100644
--- a/tools/rootcanal/Android.bp
+++ b/tools/rootcanal/Android.bp
@@ -345,6 +345,7 @@
srcs: [
"test/async_manager_unittest.cc",
"test/h4_parser_unittest.cc",
+ "test/invalid_packet_handler_unittest.cc",
"test/pcap_filter_unittest.cc",
"test/posix_socket_unittest.cc",
],
@@ -356,6 +357,8 @@
],
shared_libs: [
"libbase",
+ "libcrypto",
+ "libprotobuf-cpp-full",
],
static_libs: [
"libbt-rootcanal",
diff --git a/tools/rootcanal/model/controller/dual_mode_controller.cc b/tools/rootcanal/model/controller/dual_mode_controller.cc
index 84d0f94..d7f7dc2 100644
--- a/tools/rootcanal/model/controller/dual_mode_controller.cc
+++ b/tools/rootcanal/model/controller/dual_mode_controller.cc
@@ -52,6 +52,14 @@
constexpr bool kLeApcfTransportDiscoveryDataFilterSupported = true;
constexpr bool kLeApcfAdTypeFilterSupported = true;
+#define CHECK_PACKET_VIEW(view) \
+ do { \
+ if (!CheckPacketView(view, fmt::format("{}:{} - {}() invalid packet", \
+ __FILE__, __LINE__, __func__))) { \
+ return; \
+ } \
+ } while (0)
+
void DualModeController::SetProperties(ControllerProperties properties) {
WARNING(id_, "updating the device properties!");
properties_ = std::move(properties);
@@ -89,6 +97,12 @@
ASSERT(Address::FromString("3C:5A:B4:04:05:06", public_address));
SetAddress(public_address);
+ // Default invalid packet handler will abort the controller
+ // when receiving an invalid packet.
+ invalid_packet_handler_ =
+ [](uint32_t, InvalidPacketReason, std::string message,
+ std::vector<uint8_t> const&) { FATAL("{}", message); };
+
link_layer_controller_.RegisterRemoteChannel(
[this](std::shared_ptr<model::packets::LinkLayerPacketBuilder> packet,
Phy::Type phy_type, int8_t tx_power) {
@@ -109,7 +123,8 @@
void DualModeController::HandleAcl(
std::shared_ptr<std::vector<uint8_t>> packet) {
auto acl_packet = bluetooth::hci::AclView::Create(pdl::packet::slice(packet));
- ASSERT(acl_packet.IsValid());
+ CHECK_PACKET_VIEW(acl_packet);
+
if (loopback_mode_ == LoopbackMode::ENABLE_LOCAL) {
uint16_t handle = acl_packet.GetHandle();
@@ -134,7 +149,8 @@
void DualModeController::HandleSco(
std::shared_ptr<std::vector<uint8_t>> packet) {
auto sco_packet = bluetooth::hci::ScoView::Create(pdl::packet::slice(packet));
- ASSERT(sco_packet.IsValid());
+ CHECK_PACKET_VIEW(sco_packet);
+
if (loopback_mode_ == LoopbackMode::ENABLE_LOCAL) {
uint16_t handle = sco_packet.GetHandle();
@@ -159,7 +175,7 @@
void DualModeController::HandleIso(
std::shared_ptr<std::vector<uint8_t>> packet) {
auto iso = bluetooth::hci::IsoView::Create(pdl::packet::slice(packet));
- ASSERT(iso.IsValid());
+ CHECK_PACKET_VIEW(iso);
link_layer_controller_.HandleIso(iso);
}
@@ -167,7 +183,7 @@
std::shared_ptr<std::vector<uint8_t>> packet) {
auto command_packet =
bluetooth::hci::CommandView::Create(pdl::packet::slice(packet));
- ASSERT(command_packet.IsValid());
+ CHECK_PACKET_VIEW(command_packet);
OpCode op_code = command_packet.GetOpCode();
const bool is_vendor_command = (static_cast<uint16_t>(op_code) >> 10) == 0x3f;
@@ -238,8 +254,8 @@
}
void DualModeController::RegisterInvalidPacketHandler(
- std::function<void(uint32_t, InvalidPacketReason, std::string,
- std::vector<uint8_t> const&)>& handler) {
+ const std::function<void(uint32_t, InvalidPacketReason, std::string,
+ std::vector<uint8_t> const&)>& handler) {
INFO(id_, "updating the invalid packet handler");
invalid_packet_handler_ = handler;
}
@@ -291,7 +307,7 @@
void DualModeController::Reset(CommandView command) {
auto command_view = bluetooth::hci::ResetView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Reset");
@@ -305,7 +321,7 @@
void DualModeController::ReadBufferSize(CommandView command) {
auto command_view = bluetooth::hci::ReadBufferSizeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Buffer Size");
@@ -319,7 +335,7 @@
void DualModeController::ReadFailedContactCounter(CommandView command) {
auto command_view =
bluetooth::hci::ReadFailedContactCounterView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t connection_handle = command_view.GetConnectionHandle();
uint16_t failed_contact_counter = 0;
@@ -337,7 +353,7 @@
void DualModeController::ResetFailedContactCounter(CommandView command) {
auto command_view =
bluetooth::hci::ReadFailedContactCounterView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t connection_handle = command_view.GetConnectionHandle();
DEBUG(id_, "<< Reset Failed Contact Counter");
@@ -353,7 +369,7 @@
void DualModeController::ReadRssi(CommandView command) {
auto command_view = bluetooth::hci::ReadRssiView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t connection_handle = command_view.GetConnectionHandle();
int8_t rssi = 0;
@@ -369,7 +385,7 @@
void DualModeController::ReadEncryptionKeySize(CommandView command) {
auto command_view =
bluetooth::hci::ReadEncryptionKeySizeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Encryption Key Size");
DEBUG(id_, " connection_handle=0x{:x}", command_view.GetConnectionHandle());
@@ -382,7 +398,7 @@
void DualModeController::HostBufferSize(CommandView command) {
auto command_view = bluetooth::hci::HostBufferSizeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Host Buffer Size");
@@ -393,7 +409,7 @@
void DualModeController::ReadLocalVersionInformation(CommandView command) {
auto command_view =
bluetooth::hci::ReadLocalVersionInformationView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Local Version Information");
@@ -412,7 +428,7 @@
void DualModeController::ReadRemoteVersionInformation(CommandView command) {
auto command_view =
bluetooth::hci::ReadRemoteVersionInformationView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Remote Version Information");
DEBUG(id_, " connection_handle=0x{:x}", command_view.GetConnectionHandle());
@@ -427,7 +443,7 @@
void DualModeController::ReadBdAddr(CommandView command) {
auto command_view = bluetooth::hci::ReadBdAddrView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read BD_ADDR");
@@ -438,7 +454,7 @@
void DualModeController::ReadLocalSupportedCommands(CommandView command) {
auto command_view =
bluetooth::hci::ReadLocalSupportedCommandsView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Local Supported Commands");
@@ -449,7 +465,7 @@
void DualModeController::ReadLocalSupportedFeatures(CommandView command) {
auto command_view =
bluetooth::hci::ReadLocalSupportedFeaturesView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Local Supported Features");
@@ -461,7 +477,7 @@
void DualModeController::ReadLocalSupportedCodecsV1(CommandView command) {
auto command_view =
bluetooth::hci::ReadLocalSupportedCodecsV1View::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Local Supported Codecs V1");
@@ -474,7 +490,7 @@
void DualModeController::ReadLocalExtendedFeatures(CommandView command) {
auto command_view =
bluetooth::hci::ReadLocalExtendedFeaturesView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint8_t page_number = command_view.GetPageNumber();
DEBUG(id_, "<< Read Local Extended Features");
@@ -489,7 +505,7 @@
void DualModeController::ReadRemoteExtendedFeatures(CommandView command) {
auto command_view =
bluetooth::hci::ReadRemoteExtendedFeaturesView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Remote Extended Features");
DEBUG(id_, " connection_handle=0x{:x}", command_view.GetConnectionHandle());
@@ -505,7 +521,7 @@
void DualModeController::SwitchRole(CommandView command) {
auto command_view = bluetooth::hci::SwitchRoleView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Switch Role");
DEBUG(id_, " bd_addr={}", command_view.GetBdAddr());
@@ -521,7 +537,7 @@
void DualModeController::ReadRemoteSupportedFeatures(CommandView command) {
auto command_view =
bluetooth::hci::ReadRemoteSupportedFeaturesView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Remote Supported Features");
DEBUG(id_, " connection_handle=0x{:x}", command_view.GetConnectionHandle());
@@ -536,7 +552,7 @@
void DualModeController::ReadClockOffset(CommandView command) {
auto command_view = bluetooth::hci::ReadClockOffsetView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Clock Offset");
DEBUG(id_, " connection_handle=0x{:x}", command_view.GetConnectionHandle());
@@ -554,7 +570,7 @@
// Support is provided to satisfy PTS tester requirements.
void DualModeController::AddScoConnection(CommandView command) {
auto command_view = bluetooth::hci::AddScoConnectionView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Add SCO Connection");
DEBUG(id_, " connection_handle=0x{:x}", command_view.GetConnectionHandle());
@@ -571,7 +587,7 @@
void DualModeController::SetupSynchronousConnection(CommandView command) {
auto command_view =
bluetooth::hci::SetupSynchronousConnectionView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Setup Synchronous Connection");
DEBUG(id_, " connection_handle=0x{:x}", command_view.GetConnectionHandle());
@@ -591,7 +607,7 @@
void DualModeController::AcceptSynchronousConnection(CommandView command) {
auto command_view =
bluetooth::hci::AcceptSynchronousConnectionView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Accept Synchronous Connection");
DEBUG(id_, " bd_addr={}", command_view.GetBdAddr());
@@ -613,7 +629,7 @@
auto command_view =
bluetooth::hci::EnhancedSetupSynchronousConnectionView::Create(command);
auto status = ErrorCode::SUCCESS;
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Enhanced Setup Synchronous Connection");
DEBUG(id_, " connection_handle=0x{:x}", command_view.GetConnectionHandle());
@@ -760,7 +776,7 @@
auto command_view =
bluetooth::hci::EnhancedAcceptSynchronousConnectionView::Create(command);
auto status = ErrorCode::SUCCESS;
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Enhanced Accept Synchronous Connection");
DEBUG(id_, " bd_addr={}", command_view.GetBdAddr());
@@ -904,7 +920,7 @@
void DualModeController::RejectSynchronousConnection(CommandView command) {
auto command_view =
bluetooth::hci::RejectSynchronousConnectionView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Reject Synchronous Connection");
DEBUG(id_, " bd_addr={}", command_view.GetBdAddr());
@@ -923,7 +939,7 @@
auto command_view =
bluetooth::hci::ReadInquiryResponseTransmitPowerLevelView::Create(
command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Inquiry Response Transmit Power Level");
@@ -935,7 +951,7 @@
void DualModeController::EnhancedFlush(CommandView command) {
auto command_view = bluetooth::hci::EnhancedFlushView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Enhanced Flush");
DEBUG(id_, " connection_handle=0x{:x}", command_view.GetConnectionHandle());
@@ -955,7 +971,7 @@
void DualModeController::SetEventMaskPage2(CommandView command) {
auto command_view = bluetooth::hci::SetEventMaskPage2View::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Set Event Mask Page 2");
DEBUG(id_, " event_mask_page_2=0x{:x}", command_view.GetEventMaskPage2());
@@ -985,7 +1001,7 @@
void DualModeController::WriteSimplePairingMode(CommandView command) {
auto command_view =
bluetooth::hci::WriteSimplePairingModeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write Simple Pairing Mode");
DEBUG(id_, " simple_pairing_mode={}",
@@ -1001,7 +1017,7 @@
void DualModeController::ChangeConnectionPacketType(CommandView command) {
auto command_view =
bluetooth::hci::ChangeConnectionPacketTypeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Change Connection Packet Type");
DEBUG(id_, " connection_handle=0x{:x}", command_view.GetConnectionHandle());
@@ -1018,7 +1034,7 @@
void DualModeController::WriteLeHostSupport(CommandView command) {
auto command_view = bluetooth::hci::WriteLeHostSupportView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write LE Host Support");
DEBUG(id_, " le_supported_host={}",
@@ -1035,7 +1051,7 @@
CommandView command) {
auto command_view =
bluetooth::hci::WriteSecureConnectionsHostSupportView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write Secure Connections Host Support");
DEBUG(id_, " secure_connections_host_support={}",
@@ -1052,7 +1068,7 @@
void DualModeController::SetEventMask(CommandView command) {
auto command_view = bluetooth::hci::SetEventMaskView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Set Event Mask");
DEBUG(id_, " event_mask=0x{:x}", command_view.GetEventMask());
@@ -1064,7 +1080,7 @@
void DualModeController::ReadInquiryMode(CommandView command) {
auto command_view = bluetooth::hci::ReadInquiryModeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Inquiry Mode");
@@ -1076,7 +1092,7 @@
void DualModeController::WriteInquiryMode(CommandView command) {
auto command_view = bluetooth::hci::WriteInquiryModeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write Inquiry Mode");
DEBUG(id_, " inquiry_mode={}",
@@ -1090,7 +1106,7 @@
void DualModeController::ReadPageScanType(CommandView command) {
auto command_view = bluetooth::hci::ReadPageScanTypeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Page Scan Type");
@@ -1102,7 +1118,7 @@
void DualModeController::WritePageScanType(CommandView command) {
auto command_view = bluetooth::hci::WritePageScanTypeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write Page Scan Type");
DEBUG(id_, " page_scan_type={}",
@@ -1114,7 +1130,7 @@
void DualModeController::ReadInquiryScanType(CommandView command) {
auto command_view = bluetooth::hci::ReadInquiryScanTypeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Inquiry Scan Type");
@@ -1126,7 +1142,7 @@
void DualModeController::WriteInquiryScanType(CommandView command) {
auto command_view = bluetooth::hci::WriteInquiryScanTypeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write Inquiry Scan Type");
DEBUG(id_, " inquiry_scan_type={}",
@@ -1139,7 +1155,7 @@
void DualModeController::ChangeConnectionLinkKey(CommandView command) {
auto command_view =
bluetooth::hci::ChangeConnectionLinkKeyView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Change Connection Link Key");
DEBUG(id_, " connection_handle=0x{:x}", command_view.GetConnectionHandle());
@@ -1153,7 +1169,7 @@
void DualModeController::CentralLinkKey(CommandView command) {
auto command_view = bluetooth::hci::CentralLinkKeyView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Central Link Key");
DEBUG(id_, " key_flag={}",
@@ -1169,7 +1185,7 @@
void DualModeController::WriteAuthenticationEnable(CommandView command) {
auto command_view =
bluetooth::hci::WriteAuthenticationEnableView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write Authentication Enable");
DEBUG(id_, " authentication_enable={}",
@@ -1185,7 +1201,7 @@
void DualModeController::ReadAuthenticationEnable(CommandView command) {
auto command_view =
bluetooth::hci::ReadAuthenticationEnableView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Authentication Enable");
@@ -1197,7 +1213,7 @@
void DualModeController::ReadClassOfDevice(CommandView command) {
auto command_view = bluetooth::hci::ReadClassOfDeviceView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Class of Device");
@@ -1208,7 +1224,7 @@
void DualModeController::WriteClassOfDevice(CommandView command) {
auto command_view = bluetooth::hci::WriteClassOfDeviceView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write Class of Device");
DEBUG(id_, " class_of_device=0x{:x}", command_view.GetClassOfDevice());
@@ -1220,7 +1236,7 @@
void DualModeController::ReadPageTimeout(CommandView command) {
auto command_view = bluetooth::hci::ReadPageTimeoutView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Page Timeout");
@@ -1231,7 +1247,7 @@
void DualModeController::WritePageTimeout(CommandView command) {
auto command_view = bluetooth::hci::WritePageTimeoutView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write Page Timeout");
DEBUG(id_, " page_timeout={}", command_view.GetPageTimeout());
@@ -1243,7 +1259,7 @@
void DualModeController::HoldMode(CommandView command) {
auto command_view = bluetooth::hci::HoldModeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t handle = command_view.GetConnectionHandle();
uint16_t hold_mode_max_interval = command_view.GetHoldModeMaxInterval();
uint16_t hold_mode_min_interval = command_view.GetHoldModeMinInterval();
@@ -1260,7 +1276,7 @@
void DualModeController::SniffMode(CommandView command) {
auto command_view = bluetooth::hci::SniffModeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t handle = command_view.GetConnectionHandle();
uint16_t sniff_max_interval = command_view.GetSniffMaxInterval();
uint16_t sniff_min_interval = command_view.GetSniffMinInterval();
@@ -1280,7 +1296,7 @@
void DualModeController::ExitSniffMode(CommandView command) {
auto command_view = bluetooth::hci::ExitSniffModeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Exit Sniff Mode");
DEBUG(id_, " connection_handle=0x{:x}", command_view.GetConnectionHandle());
@@ -1294,7 +1310,7 @@
void DualModeController::QosSetup(CommandView command) {
auto command_view = bluetooth::hci::QosSetupView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t handle = command_view.GetConnectionHandle();
uint8_t service_type = static_cast<uint8_t>(command_view.GetServiceType());
uint32_t token_rate = command_view.GetTokenRate();
@@ -1315,7 +1331,7 @@
void DualModeController::RoleDiscovery(CommandView command) {
auto command_view = bluetooth::hci::RoleDiscoveryView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t handle = command_view.GetConnectionHandle();
DEBUG(id_, "<< Role Discovery");
@@ -1331,7 +1347,7 @@
void DualModeController::ReadDefaultLinkPolicySettings(CommandView command) {
auto command_view =
bluetooth::hci::ReadDefaultLinkPolicySettingsView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Default Link Policy Settings");
@@ -1344,7 +1360,7 @@
void DualModeController::WriteDefaultLinkPolicySettings(CommandView command) {
auto command_view =
bluetooth::hci::WriteDefaultLinkPolicySettingsView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write Default Link Policy Settings");
DEBUG(id_, " default_link_policy_settings=0x{:x}",
@@ -1359,7 +1375,7 @@
void DualModeController::SniffSubrating(CommandView command) {
auto command_view = bluetooth::hci::SniffSubratingView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t connection_handle = command_view.GetConnectionHandle();
DEBUG(id_, "<< Sniff Subrating");
@@ -1371,7 +1387,7 @@
void DualModeController::FlowSpecification(CommandView command) {
auto command_view = bluetooth::hci::FlowSpecificationView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t handle = command_view.GetConnectionHandle();
uint8_t flow_direction =
static_cast<uint8_t>(command_view.GetFlowDirection());
@@ -1395,7 +1411,7 @@
void DualModeController::ReadLinkPolicySettings(CommandView command) {
auto command_view =
bluetooth::hci::ReadLinkPolicySettingsView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t handle = command_view.GetConnectionHandle();
DEBUG(id_, "<< Read Link Policy Settings");
@@ -1412,7 +1428,7 @@
void DualModeController::WriteLinkPolicySettings(CommandView command) {
auto command_view =
bluetooth::hci::WriteLinkPolicySettingsView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t handle = command_view.GetConnectionHandle();
uint16_t settings = command_view.GetLinkPolicySettings();
@@ -1430,7 +1446,7 @@
void DualModeController::WriteLinkSupervisionTimeout(CommandView command) {
auto command_view =
bluetooth::hci::WriteLinkSupervisionTimeoutView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t handle = command_view.GetConnectionHandle();
uint16_t timeout = command_view.GetLinkSupervisionTimeout();
@@ -1447,7 +1463,7 @@
void DualModeController::ReadLocalName(CommandView command) {
auto command_view = bluetooth::hci::ReadLocalNameView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Local Name");
@@ -1458,7 +1474,7 @@
void DualModeController::WriteLocalName(CommandView command) {
auto command_view = bluetooth::hci::WriteLocalNameView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write Local Name");
@@ -1470,7 +1486,7 @@
void DualModeController::WriteExtendedInquiryResponse(CommandView command) {
auto command_view =
bluetooth::hci::WriteExtendedInquiryResponseView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write Extended Inquiry Response");
@@ -1483,7 +1499,7 @@
void DualModeController::RefreshEncryptionKey(CommandView command) {
auto command_view = bluetooth::hci::RefreshEncryptionKeyView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t handle = command_view.GetConnectionHandle();
DEBUG(id_, "<< Refresh Encryption Key");
@@ -1498,7 +1514,7 @@
void DualModeController::ReadVoiceSetting(CommandView command) {
auto command_view = bluetooth::hci::ReadVoiceSettingView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Voice Setting");
@@ -1509,7 +1525,7 @@
void DualModeController::WriteVoiceSetting(CommandView command) {
auto command_view = bluetooth::hci::WriteVoiceSettingView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write Voice Setting");
DEBUG(id_, " voice_setting=0x{:x}", command_view.GetVoiceSetting());
@@ -1523,7 +1539,7 @@
void DualModeController::ReadNumberOfSupportedIac(CommandView command) {
auto command_view =
bluetooth::hci::ReadNumberOfSupportedIacView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Number of Supported Iac");
@@ -1533,7 +1549,7 @@
void DualModeController::ReadCurrentIacLap(CommandView command) {
auto command_view = bluetooth::hci::ReadCurrentIacLapView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Current Iac Lap");
@@ -1544,7 +1560,7 @@
void DualModeController::WriteCurrentIacLap(CommandView command) {
auto command_view = bluetooth::hci::WriteCurrentIacLapView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write Current Iac Lap");
@@ -1555,7 +1571,7 @@
void DualModeController::ReadPageScanActivity(CommandView command) {
auto command_view = bluetooth::hci::ReadPageScanActivityView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Page Scan Activity");
@@ -1568,7 +1584,7 @@
void DualModeController::WritePageScanActivity(CommandView command) {
auto command_view =
bluetooth::hci::WritePageScanActivityView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write Page Scan Activity");
@@ -1579,7 +1595,7 @@
void DualModeController::ReadInquiryScanActivity(CommandView command) {
auto command_view =
bluetooth::hci::ReadInquiryScanActivityView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Inquiry Scan Activity");
@@ -1592,7 +1608,7 @@
void DualModeController::WriteInquiryScanActivity(CommandView command) {
auto command_view =
bluetooth::hci::WriteInquiryScanActivityView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write Inquiry Scan Activity");
@@ -1602,7 +1618,7 @@
void DualModeController::ReadScanEnable(CommandView command) {
auto command_view = bluetooth::hci::ReadScanEnableView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Scan Enable");
@@ -1622,7 +1638,7 @@
void DualModeController::WriteScanEnable(CommandView command) {
auto command_view = bluetooth::hci::WriteScanEnableView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
bluetooth::hci::ScanEnable scan_enable = command_view.GetScanEnable();
bool inquiry_scan =
scan_enable == bluetooth::hci::ScanEnable::INQUIRY_AND_PAGE_SCAN ||
@@ -1642,7 +1658,7 @@
void DualModeController::ReadTransmitPowerLevel(CommandView command) {
auto command_view = bluetooth::hci::ReadTransmitPowerLevelView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t connection_handle = command_view.GetConnectionHandle();
DEBUG(id_, "<< Read Transmit Power Level");
@@ -1658,7 +1674,7 @@
void DualModeController::ReadEnhancedTransmitPowerLevel(CommandView command) {
auto command_view = bluetooth::hci::ReadEnhancedTransmitPowerLevelView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t connection_handle = command_view.GetConnectionHandle();
DEBUG(id_, "<< Read Enhanced Transmit Power Level");
@@ -1676,7 +1692,7 @@
void DualModeController::ReadSynchronousFlowControlEnable(CommandView command) {
auto command_view =
bluetooth::hci::ReadSynchronousFlowControlEnableView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Synchronous Flow Control Enable");
@@ -1693,7 +1709,7 @@
CommandView command) {
auto command_view =
bluetooth::hci::WriteSynchronousFlowControlEnableView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
auto enabled = command_view.GetEnable() == bluetooth::hci::Enable::ENABLED;
DEBUG(id_, "<< Write Synchronous Flow Control Enable");
@@ -1707,7 +1723,7 @@
void DualModeController::SetEventFilter(CommandView command) {
auto command_view = bluetooth::hci::SetEventFilterView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Set Event Filter");
DEBUG(id_, " filter_type={}",
@@ -1723,7 +1739,7 @@
void DualModeController::Inquiry(CommandView command) {
auto command_view = bluetooth::hci::InquiryView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
auto max_responses = command_view.GetNumResponses();
auto length = command_view.GetInquiryLength();
@@ -1746,7 +1762,7 @@
void DualModeController::InquiryCancel(CommandView command) {
auto command_view = bluetooth::hci::InquiryCancelView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Inquiry Cancel");
@@ -1758,7 +1774,7 @@
void DualModeController::AcceptConnectionRequest(CommandView command) {
auto command_view =
bluetooth::hci::AcceptConnectionRequestView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
Address bd_addr = command_view.GetBdAddr();
bool try_role_switch =
command_view.GetRole() ==
@@ -1777,7 +1793,7 @@
void DualModeController::RejectConnectionRequest(CommandView command) {
auto command_view =
bluetooth::hci::RejectConnectionRequestView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
Address bd_addr = command_view.GetBdAddr();
auto reason = command_view.GetReason();
@@ -1794,7 +1810,7 @@
void DualModeController::DeleteStoredLinkKey(CommandView command) {
auto command_view = bluetooth::hci::DeleteStoredLinkKeyView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Delete Stored Link Key");
@@ -1804,7 +1820,7 @@
void DualModeController::RemoteNameRequest(CommandView command) {
auto command_view = bluetooth::hci::RemoteNameRequestView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
Address bd_addr = command_view.GetBdAddr();
DEBUG(id_, "<< Remote Name Request");
@@ -1819,7 +1835,7 @@
void DualModeController::LeSetEventMask(CommandView command) {
auto command_view = bluetooth::hci::LeSetEventMaskView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Event Mask");
DEBUG(id_, " le_event_mask=0x{:x}", command_view.GetLeEventMask());
@@ -1831,7 +1847,7 @@
void DualModeController::LeRequestPeerSca(CommandView command) {
auto command_view = bluetooth::hci::LeRequestPeerScaView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t connection_handle = command_view.GetConnectionHandle();
DEBUG(id_, "<< LE Request Peer SCA");
@@ -1863,7 +1879,7 @@
void DualModeController::LeSetHostFeature(CommandView command) {
auto command_view = bluetooth::hci::LeSetHostFeatureView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint8_t bit_number = static_cast<uint8_t>(command_view.GetBitNumber());
uint8_t bit_value = static_cast<uint8_t>(command_view.GetBitValue());
@@ -1879,7 +1895,7 @@
void DualModeController::LeReadBufferSizeV1(CommandView command) {
auto command_view = bluetooth::hci::LeReadBufferSizeV1View::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Read Buffer Size V1");
@@ -1894,7 +1910,7 @@
void DualModeController::LeReadBufferSizeV2(CommandView command) {
auto command_view = bluetooth::hci::LeReadBufferSizeV2View::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Read Buffer Size V2");
@@ -1914,7 +1930,7 @@
void DualModeController::LeSetAddressResolutionEnable(CommandView command) {
auto command_view =
bluetooth::hci::LeSetAddressResolutionEnableView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Address Resolution Enable");
DEBUG(id_, " address_resolution_enable={}",
@@ -1933,7 +1949,7 @@
CommandView command) {
auto command_view =
bluetooth::hci::LeSetResolvablePrivateAddressTimeoutView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Resolvable Private Address Timeout");
@@ -1948,7 +1964,7 @@
void DualModeController::LeReadLocalSupportedFeatures(CommandView command) {
auto command_view =
bluetooth::hci::LeReadLocalSupportedFeaturesView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Read Local Supported Features");
@@ -1960,7 +1976,7 @@
void DualModeController::LeSetRandomAddress(CommandView command) {
auto command_view = bluetooth::hci::LeSetRandomAddressView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Random Address");
DEBUG(id_, " random_address={}", command_view.GetRandomAddress());
@@ -1974,7 +1990,7 @@
void DualModeController::LeSetAdvertisingParameters(CommandView command) {
auto command_view =
bluetooth::hci::LeSetAdvertisingParametersView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Advertising Parameters");
@@ -1994,7 +2010,7 @@
auto command_view =
bluetooth::hci::LeReadAdvertisingPhysicalChannelTxPowerView::Create(
command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Read Physical Channel Tx Power");
@@ -2006,7 +2022,7 @@
void DualModeController::LeSetAdvertisingData(CommandView command) {
auto command_view = bluetooth::hci::LeSetAdvertisingDataView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Advertising Data");
@@ -2019,7 +2035,7 @@
void DualModeController::LeSetScanResponseData(CommandView command) {
auto command_view =
bluetooth::hci::LeSetScanResponseDataView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Scan Response Data");
@@ -2032,7 +2048,7 @@
void DualModeController::LeSetAdvertisingEnable(CommandView command) {
auto command_view =
bluetooth::hci::LeSetAdvertisingEnableView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Advertising Enable");
DEBUG(id_, " advertising_enable={}",
@@ -2046,7 +2062,7 @@
void DualModeController::LeSetScanParameters(CommandView command) {
auto command_view = bluetooth::hci::LeSetScanParametersView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Scan Parameters");
@@ -2060,7 +2076,7 @@
void DualModeController::LeSetScanEnable(CommandView command) {
auto command_view = bluetooth::hci::LeSetScanEnableView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Scan Enable");
DEBUG(id_, " scan_enable={}",
@@ -2075,7 +2091,7 @@
void DualModeController::LeCreateConnection(CommandView command) {
auto command_view = bluetooth::hci::LeCreateConnectionView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Create Connection");
DEBUG(id_, " peer_address={}", command_view.GetPeerAddress());
@@ -2105,7 +2121,7 @@
void DualModeController::LeCreateConnectionCancel(CommandView command) {
auto command_view =
bluetooth::hci::LeCreateConnectionCancelView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Create Connection Cancel");
@@ -2116,7 +2132,7 @@
void DualModeController::LeConnectionUpdate(CommandView command) {
auto command_view = bluetooth::hci::LeConnectionUpdateView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Connection Update");
DEBUG(id_, " connection_handle=0x{:x}", command_view.GetConnectionHandle());
@@ -2133,7 +2149,7 @@
void DualModeController::CreateConnection(CommandView command) {
auto command_view = bluetooth::hci::CreateConnectionView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
Address bd_addr = command_view.GetBdAddr();
uint16_t packet_type = command_view.GetPacketType();
uint8_t page_scan_mode =
@@ -2161,7 +2177,7 @@
void DualModeController::CreateConnectionCancel(CommandView command) {
auto command_view =
bluetooth::hci::CreateConnectionCancelView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
Address address = command_view.GetBdAddr();
DEBUG(id_, "<< Create Connection Cancel");
@@ -2175,7 +2191,7 @@
void DualModeController::Disconnect(CommandView command) {
auto command_view = bluetooth::hci::DisconnectView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t connection_handle = command_view.GetConnectionHandle();
DEBUG(id_, "<< Disconnect");
@@ -2196,7 +2212,7 @@
void DualModeController::LeReadFilterAcceptListSize(CommandView command) {
auto command_view =
bluetooth::hci::LeReadFilterAcceptListSizeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Read Filter Accept List Size");
@@ -2208,7 +2224,7 @@
void DualModeController::LeClearFilterAcceptList(CommandView command) {
auto command_view =
bluetooth::hci::LeClearFilterAcceptListView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Clear Filter Accept List");
@@ -2220,7 +2236,7 @@
void DualModeController::LeAddDeviceToFilterAcceptList(CommandView command) {
auto command_view =
bluetooth::hci::LeAddDeviceToFilterAcceptListView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Add Device To Filter Accept List");
DEBUG(id_, " address={}", command_view.GetAddress());
@@ -2239,7 +2255,7 @@
CommandView command) {
auto command_view =
bluetooth::hci::LeRemoveDeviceFromFilterAcceptListView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Remove Device From Filter Accept List");
DEBUG(id_, " address={}", command_view.GetAddress());
@@ -2256,7 +2272,7 @@
void DualModeController::LeClearResolvingList(CommandView command) {
auto command_view = bluetooth::hci::LeClearResolvingListView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Clear Resolving List");
@@ -2268,7 +2284,7 @@
void DualModeController::LeReadResolvingListSize(CommandView command) {
auto command_view =
bluetooth::hci::LeReadResolvingListSizeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Read Resolving List Size");
@@ -2280,7 +2296,7 @@
void DualModeController::LeReadPeerResolvableAddress(CommandView command) {
auto command_view =
bluetooth::hci::LeReadPeerResolvableAddressView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Read Peer Resolvable Address");
DEBUG(id_, " peer_identity_address={}",
@@ -2301,7 +2317,7 @@
void DualModeController::LeReadLocalResolvableAddress(CommandView command) {
auto command_view =
bluetooth::hci::LeReadLocalResolvableAddressView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Read Local Resolvable Address");
DEBUG(id_, " peer_identity_address={}",
@@ -2322,7 +2338,7 @@
void DualModeController::LeReadMaximumDataLength(CommandView command) {
auto command_view =
bluetooth::hci::LeReadMaximumDataLengthView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Read Maximum Data Length");
@@ -2337,7 +2353,7 @@
void DualModeController::LeReadPhy(CommandView command) {
auto command_view = bluetooth::hci::LeReadPhyView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t connection_handle = command_view.GetConnectionHandle();
DEBUG(id_, "<< LE Read Phy");
@@ -2353,7 +2369,7 @@
void DualModeController::LeSetDefaultPhy(CommandView command) {
auto command_view = bluetooth::hci::LeSetDefaultPhyView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Default Phy");
@@ -2367,7 +2383,7 @@
void DualModeController::LeSetPhy(CommandView command) {
auto command_view = bluetooth::hci::LeSetPhyView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Phy");
DEBUG(id_, " connection_handle=0x{:x}", command_view.GetConnectionHandle());
@@ -2384,7 +2400,7 @@
void DualModeController::LeReadSuggestedDefaultDataLength(CommandView command) {
auto command_view =
bluetooth::hci::LeReadSuggestedDefaultDataLengthView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Read Suggested Default Data Length");
@@ -2399,7 +2415,7 @@
CommandView command) {
auto command_view =
bluetooth::hci::LeWriteSuggestedDefaultDataLengthView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Write Suggested Default Data Length");
@@ -2422,7 +2438,7 @@
void DualModeController::LeAddDeviceToResolvingList(CommandView command) {
auto command_view =
bluetooth::hci::LeAddDeviceToResolvingListView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Add Device to Resolving List");
DEBUG(id_, " peer_identity_address={}",
@@ -2442,7 +2458,7 @@
void DualModeController::LeRemoveDeviceFromResolvingList(CommandView command) {
auto command_view =
bluetooth::hci::LeRemoveDeviceFromResolvingListView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Remove Device from Resolving List");
DEBUG(id_, " peer_identity_address={}",
@@ -2463,7 +2479,7 @@
CommandView command) {
auto command_view =
bluetooth::hci::LeSetPeriodicAdvertisingParametersView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Periodic Advertising Parameters");
DEBUG(id_, " advertising_handle={}", command_view.GetAdvertisingHandle());
@@ -2481,7 +2497,7 @@
void DualModeController::LeSetPeriodicAdvertisingData(CommandView command) {
auto command_view =
bluetooth::hci::LeSetPeriodicAdvertisingDataView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Periodic Advertising Data");
DEBUG(id_, " advertising_handle={}", command_view.GetAdvertisingHandle());
@@ -2497,7 +2513,7 @@
void DualModeController::LeSetPeriodicAdvertisingEnable(CommandView command) {
auto command_view =
bluetooth::hci::LeSetPeriodicAdvertisingEnableView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Periodic Advertising Enable");
DEBUG(id_, " advertising_handle={}", command_view.GetAdvertisingHandle());
@@ -2514,7 +2530,7 @@
void DualModeController::LePeriodicAdvertisingCreateSync(CommandView command) {
auto command_view =
bluetooth::hci::LePeriodicAdvertisingCreateSyncView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Periodic Advertising Create Sync");
DEBUG(id_, " advertiser_address={}", command_view.GetAdvertiserAddress());
@@ -2537,7 +2553,7 @@
auto command_view =
bluetooth::hci::LePeriodicAdvertisingCreateSyncCancelView::Create(
command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Periodic Advertising Create Sync Cancel");
@@ -2552,7 +2568,7 @@
CommandView command) {
auto command_view =
bluetooth::hci::LePeriodicAdvertisingTerminateSyncView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Periodic Advertising Terminate Sync");
DEBUG(id_, " sync_handle=0x{:x}", command_view.GetSyncHandle());
@@ -2568,7 +2584,7 @@
CommandView command) {
auto command_view =
bluetooth::hci::LeAddDeviceToPeriodicAdvertiserListView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Add Device to Periodic Advertiser List");
DEBUG(id_, " advertiser_address={}", command_view.GetAdvertiserAddress());
@@ -2589,7 +2605,7 @@
auto command_view =
bluetooth::hci::LeRemoveDeviceFromPeriodicAdvertiserListView::Create(
command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Remove Device from Periodic Advertiser List");
DEBUG(id_, " advertiser_address={}", command_view.GetAdvertiserAddress());
@@ -2610,7 +2626,7 @@
void DualModeController::LeClearPeriodicAdvertiserList(CommandView command) {
auto command_view =
bluetooth::hci::LeClearPeriodicAdvertiserListView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Clear Periodic Advertiser List");
@@ -2623,7 +2639,7 @@
void DualModeController::LeReadPeriodicAdvertiserListSize(CommandView command) {
auto command_view =
bluetooth::hci::LeReadPeriodicAdvertiserListSizeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Read Periodic Advertiser List Size");
@@ -2636,7 +2652,7 @@
void DualModeController::LeSetExtendedScanParameters(CommandView command) {
auto command_view =
bluetooth::hci::LeSetExtendedScanParametersView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Extended Scan Parameters");
@@ -2651,7 +2667,7 @@
void DualModeController::LeSetExtendedScanEnable(CommandView command) {
auto command_view =
bluetooth::hci::LeSetExtendedScanEnableView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Extended Scan Enable");
DEBUG(id_, " enable={}",
@@ -2668,7 +2684,7 @@
void DualModeController::LeExtendedCreateConnection(CommandView command) {
auto command_view =
bluetooth::hci::LeExtendedCreateConnectionView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Extended Create Connection");
DEBUG(id_, " peer_address={}", command_view.GetPeerAddress());
@@ -2703,7 +2719,7 @@
void DualModeController::LeSetPrivacyMode(CommandView command) {
auto command_view = bluetooth::hci::LeSetPrivacyModeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Privacy Mode");
DEBUG(id_, " peer_identity_address={}",
@@ -2723,7 +2739,7 @@
void DualModeController::LeReadRemoteFeatures(CommandView command) {
auto command_view = bluetooth::hci::LeReadRemoteFeaturesView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t handle = command_view.GetConnectionHandle();
DEBUG(id_, "<< LE Read Remote Features");
@@ -2738,7 +2754,7 @@
void DualModeController::LeEncrypt(CommandView command) {
auto command_view = bluetooth::hci::LeEncryptView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Encrypt");
@@ -2751,7 +2767,7 @@
void DualModeController::LeRand(CommandView command) {
auto command_view = bluetooth::hci::LeRandView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Rand");
@@ -2762,7 +2778,7 @@
void DualModeController::LeReadSupportedStates(CommandView command) {
auto command_view =
bluetooth::hci::LeReadSupportedStatesView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Read Supported States");
@@ -2775,7 +2791,7 @@
auto command_view =
bluetooth::hci::LeRemoteConnectionParameterRequestReplyView::Create(
command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Remote Connection Parameters Request Reply");
DEBUG(id_, " connection_handle=0x{:x}", command_view.GetConnectionHandle());
@@ -2795,7 +2811,7 @@
CommandView command) {
auto command_view = bluetooth::hci::
LeRemoteConnectionParameterRequestNegativeReplyView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Remote Connection Parameters Request Negative Reply");
DEBUG(id_, " connection_handle=0x{:x}", command_view.GetConnectionHandle());
@@ -2813,7 +2829,7 @@
void DualModeController::LeGetVendorCapabilities(CommandView command) {
auto command_view =
bluetooth::hci::LeGetVendorCapabilitiesView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
if (!properties_.supports_le_get_vendor_capabilities_command) {
SendCommandCompleteUnknownOpCodeEvent(OpCode::LE_GET_VENDOR_CAPABILITIES);
@@ -2843,13 +2859,13 @@
void DualModeController::LeBatchScan(CommandView command) {
auto command_view = bluetooth::hci::LeBatchScanView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
SendCommandCompleteUnknownOpCodeEvent(OpCode::LE_BATCH_SCAN);
}
void DualModeController::LeApcf(CommandView command) {
auto command_view = bluetooth::hci::LeApcfView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
if (!properties_.supports_le_apcf_vendor_command) {
SendCommandCompleteUnknownOpCodeEvent(OpCode::LE_APCF);
@@ -2860,7 +2876,7 @@
case bluetooth::hci::ApcfOpcode::ENABLE: {
auto subcommand_view =
bluetooth::hci::LeApcfEnableView::Create(command_view);
- ASSERT(subcommand_view.IsValid());
+ CHECK_PACKET_VIEW(subcommand_view);
DEBUG(id_, "<< LE APCF Enable");
DEBUG(id_, " enable={}",
@@ -2876,7 +2892,7 @@
auto subcommand_view =
bluetooth::hci::LeApcfSetFilteringParametersView::Create(
command_view);
- ASSERT(subcommand_view.IsValid());
+ CHECK_PACKET_VIEW(subcommand_view);
DEBUG(id_, "<< LE APCF Set Filtering Parameters");
DEBUG(id_, " action={}",
@@ -2890,7 +2906,7 @@
auto subsubcommand_view =
bluetooth::hci::LeApcfAddFilteringParametersView::Create(
subcommand_view);
- ASSERT(subsubcommand_view.IsValid());
+ CHECK_PACKET_VIEW(subcommand_view);
status = link_layer_controller_.LeApcfAddFilteringParameters(
subsubcommand_view.GetApcfFilterIndex(),
subsubcommand_view.GetApcfFeatureSelection(),
@@ -2910,7 +2926,7 @@
auto subsubcommand_view =
bluetooth::hci::LeApcfDeleteFilteringParametersView::Create(
subcommand_view);
- ASSERT(subsubcommand_view.IsValid());
+ CHECK_PACKET_VIEW(subcommand_view);
status = link_layer_controller_.LeApcfDeleteFilteringParameters(
subsubcommand_view.GetApcfFilterIndex(), &apcf_available_spaces);
break;
@@ -2919,7 +2935,7 @@
auto subsubcommand_view =
bluetooth::hci::LeApcfClearFilteringParametersView::Create(
subcommand_view);
- ASSERT(subsubcommand_view.IsValid());
+ CHECK_PACKET_VIEW(subcommand_view);
status = link_layer_controller_.LeApcfClearFilteringParameters(
&apcf_available_spaces);
break;
@@ -2939,7 +2955,7 @@
case bluetooth::hci::ApcfOpcode::BROADCASTER_ADDRESS: {
auto subcommand_view =
bluetooth::hci::LeApcfBroadcasterAddressView::Create(command_view);
- ASSERT(subcommand_view.IsValid());
+ CHECK_PACKET_VIEW(subcommand_view);
DEBUG(id_, "<< LE APCF Broadcaster Address");
DEBUG(id_, " action={}",
@@ -2953,7 +2969,7 @@
auto subsubcommand_view =
bluetooth::hci::LeApcfAddBroadcasterAddressView::Create(
subcommand_view);
- ASSERT(subsubcommand_view.IsValid());
+ CHECK_PACKET_VIEW(subcommand_view);
status = link_layer_controller_.LeApcfBroadcasterAddress(
bluetooth::hci::ApcfAction::ADD,
subsubcommand_view.GetApcfFilterIndex(),
@@ -2966,7 +2982,7 @@
auto subsubcommand_view =
bluetooth::hci::LeApcfDeleteBroadcasterAddressView::Create(
subcommand_view);
- ASSERT(subsubcommand_view.IsValid());
+ CHECK_PACKET_VIEW(subcommand_view);
status = link_layer_controller_.LeApcfBroadcasterAddress(
bluetooth::hci::ApcfAction::DELETE,
subsubcommand_view.GetApcfFilterIndex(),
@@ -2979,7 +2995,7 @@
auto subsubcommand_view =
bluetooth::hci::LeApcfClearBroadcasterAddressView::Create(
subcommand_view);
- ASSERT(subsubcommand_view.IsValid());
+ CHECK_PACKET_VIEW(subcommand_view);
status = link_layer_controller_.LeApcfBroadcasterAddress(
bluetooth::hci::ApcfAction::CLEAR,
subsubcommand_view.GetApcfFilterIndex(), Address(),
@@ -3002,7 +3018,7 @@
case bluetooth::hci::ApcfOpcode::SERVICE_UUID: {
auto subcommand_view =
bluetooth::hci::LeApcfServiceUuidView::Create(command_view);
- ASSERT(subcommand_view.IsValid());
+ CHECK_PACKET_VIEW(subcommand_view);
DEBUG(id_, "<< LE APCF Service UUID");
DEBUG(id_, " action={}",
@@ -3021,7 +3037,7 @@
auto subcommand_view =
bluetooth::hci::LeApcfServiceSolicitationUuidView::Create(
command_view);
- ASSERT(subcommand_view.IsValid());
+ CHECK_PACKET_VIEW(subcommand_view);
DEBUG(id_, "<< LE APCF Service Solicitation UUID");
DEBUG(id_, " action={}",
@@ -3040,7 +3056,7 @@
case bluetooth::hci::ApcfOpcode::LOCAL_NAME: {
auto subcommand_view =
bluetooth::hci::LeApcfLocalNameView::Create(command_view);
- ASSERT(subcommand_view.IsValid());
+ CHECK_PACKET_VIEW(subcommand_view);
DEBUG(id_, "<< LE APCF Local Name");
DEBUG(id_, " action={}",
@@ -3058,7 +3074,7 @@
case bluetooth::hci::ApcfOpcode::MANUFACTURER_DATA: {
auto subcommand_view =
bluetooth::hci::LeApcfManufacturerDataView::Create(command_view);
- ASSERT(subcommand_view.IsValid());
+ CHECK_PACKET_VIEW(subcommand_view);
DEBUG(id_, "<< LE APCF Manufacturer Data");
DEBUG(id_, " action={}",
@@ -3076,7 +3092,7 @@
case bluetooth::hci::ApcfOpcode::SERVICE_DATA: {
auto subcommand_view =
bluetooth::hci::LeApcfServiceDataView::Create(command_view);
- ASSERT(subcommand_view.IsValid());
+ CHECK_PACKET_VIEW(subcommand_view);
DEBUG(id_, "<< LE APCF Service Data");
DEBUG(id_, " action={}",
@@ -3094,7 +3110,7 @@
case bluetooth::hci::ApcfOpcode::AD_TYPE_FILTER: {
auto subcommand_view =
bluetooth::hci::LeApcfAdTypeFilterView::Create(command_view);
- ASSERT(subcommand_view.IsValid());
+ CHECK_PACKET_VIEW(subcommand_view);
DEBUG(id_, "<< LE APCF AD Type Filter");
DEBUG(id_, " action={}",
@@ -3113,7 +3129,7 @@
case bluetooth::hci::ApcfOpcode::READ_EXTENDED_FEATURES: {
auto subcommand_view =
bluetooth::hci::LeApcfReadExtendedFeaturesView::Create(command_view);
- ASSERT(subcommand_view.IsValid());
+ CHECK_PACKET_VIEW(subcommand_view);
DEBUG(id_, "<< LE APCF Read Extended Features");
@@ -3134,7 +3150,7 @@
CommandView command) {
auto command_view =
bluetooth::hci::LeGetControllerActivityEnergyInfoView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
SendCommandCompleteUnknownOpCodeEvent(
OpCode::LE_GET_CONTROLLER_ACTIVITY_ENERGY_INFO);
}
@@ -3142,14 +3158,14 @@
void DualModeController::LeExSetScanParameters(CommandView command) {
auto command_view =
bluetooth::hci::LeExSetScanParametersView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
SendCommandCompleteUnknownOpCodeEvent(OpCode::LE_EX_SET_SCAN_PARAMETERS);
}
void DualModeController::GetControllerDebugInfo(CommandView command) {
auto command_view =
bluetooth::hci::GetControllerDebugInfoView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Get Controller Debug Info");
@@ -3338,7 +3354,7 @@
void DualModeController::LeSetAdvertisingSetRandomAddress(CommandView command) {
auto command_view =
bluetooth::hci::LeSetAdvertisingSetRandomAddressView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Advertising Set Random Address");
DEBUG(id_, " advertising_handle={}", command_view.GetAdvertisingHandle());
@@ -3355,7 +3371,7 @@
CommandView command) {
auto command_view =
bluetooth::hci::LeSetExtendedAdvertisingParametersView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Extended Advertising Parameters");
DEBUG(id_, " advertising_handle={}", command_view.GetAdvertisingHandle());
@@ -3384,7 +3400,7 @@
void DualModeController::LeSetExtendedAdvertisingData(CommandView command) {
auto command_view =
bluetooth::hci::LeSetExtendedAdvertisingDataView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Extended Advertising Data");
DEBUG(id_, " advertising_handle={}", command_view.GetAdvertisingHandle());
@@ -3400,7 +3416,7 @@
void DualModeController::LeSetExtendedScanResponseData(CommandView command) {
auto command_view =
bluetooth::hci::LeSetExtendedScanResponseDataView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Extended Scan Response Data");
DEBUG(id_, " advertising_handle={}", command_view.GetAdvertisingHandle());
@@ -3416,7 +3432,7 @@
void DualModeController::LeSetExtendedAdvertisingEnable(CommandView command) {
auto command_view =
bluetooth::hci::LeSetExtendedAdvertisingEnableView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Set Extended Advertising Enable");
DEBUG(id_, " enable={}",
@@ -3437,7 +3453,7 @@
CommandView command) {
auto command_view =
bluetooth::hci::LeReadMaximumAdvertisingDataLengthView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Read Maximum Advertising Data Length");
@@ -3452,7 +3468,7 @@
auto command_view =
bluetooth::hci::LeReadNumberOfSupportedAdvertisingSetsView::Create(
command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Read Number of Supported Advertising Sets");
@@ -3465,7 +3481,7 @@
void DualModeController::LeRemoveAdvertisingSet(CommandView command) {
auto command_view =
bluetooth::hci::LeRemoveAdvertisingSetView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Remove Advertising Set");
DEBUG(id_, " advertising_handle={}", command_view.GetAdvertisingHandle());
@@ -3479,7 +3495,7 @@
void DualModeController::LeClearAdvertisingSets(CommandView command) {
auto command_view =
bluetooth::hci::LeClearAdvertisingSetsView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Clear Advertising Sets");
@@ -3490,7 +3506,7 @@
void DualModeController::LeStartEncryption(CommandView command) {
auto command_view = bluetooth::hci::LeStartEncryptionView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< LE Start Encryption");
DEBUG(id_, " connection_handle=0x{:x}", command_view.GetConnectionHandle());
@@ -3506,7 +3522,7 @@
void DualModeController::LeLongTermKeyRequestReply(CommandView command) {
auto command_view =
bluetooth::hci::LeLongTermKeyRequestReplyView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t handle = command_view.GetConnectionHandle();
DEBUG(id_, "<< LE Long Term Key Request Reply");
@@ -3523,7 +3539,7 @@
CommandView command) {
auto command_view =
bluetooth::hci::LeLongTermKeyRequestNegativeReplyView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
uint16_t handle = command_view.GetConnectionHandle();
DEBUG(id_, "<< LE Long Term Key Request Negative Reply");
@@ -3540,7 +3556,7 @@
void DualModeController::ReadConnectionAcceptTimeout(CommandView command) {
auto command_view =
bluetooth::hci::ReadConnectionAcceptTimeoutView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Connection Accept Timeout");
@@ -3553,7 +3569,7 @@
void DualModeController::WriteConnectionAcceptTimeout(CommandView command) {
auto command_view =
bluetooth::hci::WriteConnectionAcceptTimeoutView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write Connection Accept Timeout");
@@ -3567,7 +3583,7 @@
void DualModeController::ReadLoopbackMode(CommandView command) {
auto command_view = bluetooth::hci::ReadLoopbackModeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Read Loopback Mode");
@@ -3577,7 +3593,7 @@
void DualModeController::WriteLoopbackMode(CommandView command) {
auto command_view = bluetooth::hci::WriteLoopbackModeView::Create(command);
- ASSERT(command_view.IsValid());
+ CHECK_PACKET_VIEW(command_view);
DEBUG(id_, "<< Write Loopback Mode");
DEBUG(id_, " loopback_mode={}",
diff --git a/tools/rootcanal/model/controller/dual_mode_controller.h b/tools/rootcanal/model/controller/dual_mode_controller.h
index b2e9b17..f3b0ce1 100644
--- a/tools/rootcanal/model/controller/dual_mode_controller.h
+++ b/tools/rootcanal/model/controller/dual_mode_controller.h
@@ -89,8 +89,8 @@
/// to an external tracker. Packets are rejected if they failed to
/// be parsed, or run into an unimplemented part of the controller.
void RegisterInvalidPacketHandler(
- std::function<void(uint32_t, InvalidPacketReason, std::string,
- std::vector<uint8_t> const&)>& handler);
+ const std::function<void(uint32_t, InvalidPacketReason, std::string,
+ std::vector<uint8_t> const&)>& handler);
// Set the callbacks for sending packets to the HCI.
void RegisterEventChannel(
@@ -553,6 +553,24 @@
void SendCommandCompleteUnknownOpCodeEvent(
bluetooth::hci::OpCode op_code) const;
+ // Validate that a received packet is correctly formatted.
+ // If the packet failed to be parsed, the function sends a
+ // HCI Hardware Error event to the host and logs the packet to
+ // the configured handler.
+ template <typename T>
+ bool CheckPacketView(T const& view, std::string reason) {
+ if (view.IsValid()) {
+ return true;
+ }
+
+ // Send a hardware error to reset the host, and report the packet
+ // for tracing.
+ send_event_(bluetooth::hci::HardwareErrorBuilder::Create(0x43));
+ invalid_packet_handler_(id_, InvalidPacketReason::kParseError, reason,
+ view.bytes().bytes());
+ return false;
+ }
+
// Callbacks to send packets back to the HCI.
std::function<void(std::shared_ptr<bluetooth::hci::AclBuilder>)> send_acl_;
std::function<void(std::shared_ptr<bluetooth::hci::EventBuilder>)>
diff --git a/tools/rootcanal/model/controller/link_layer_controller.cc b/tools/rootcanal/model/controller/link_layer_controller.cc
index 71d950d..d0754bd 100644
--- a/tools/rootcanal/model/controller/link_layer_controller.cc
+++ b/tools/rootcanal/model/controller/link_layer_controller.cc
@@ -3165,6 +3165,7 @@
// Save the original advertising type to report if the advertising
// is connectable in the scan response report.
scanner_.connectable_scan_response = connectable_advertising;
+ scanner_.extended_scan_response = false;
scanner_.pending_scan_request = advertising_address;
scanner_.pending_scan_request_timeout =
std::chrono::steady_clock::now() + kScanRequestTimeout;
@@ -3588,6 +3589,7 @@
// Save the original advertising type to report if the advertising
// is connectable in the scan response report.
scanner_.connectable_scan_response = connectable_advertising;
+ scanner_.extended_scan_response = true;
scanner_.pending_scan_request = advertising_address;
INFO(id_,
@@ -4963,15 +4965,36 @@
resolved_advertising_address.GetAddressType());
response.connectable_ = scanner_.connectable_scan_response;
response.scannable_ = true;
- response.legacy_ = true;
+ response.legacy_ = !scanner_.extended_scan_response;
response.scan_response_ = true;
response.primary_phy_ = bluetooth::hci::PrimaryPhyType::LE_1M;
+ // TODO: SID should be set in scan response PDU
response.advertising_sid_ = 0xFF;
response.tx_power_ = 0x7F;
- response.advertising_data_ = scan_response.GetScanResponseData();
response.rssi_ = rssi;
- send_event_(
- bluetooth::hci::LeExtendedAdvertisingReportBuilder::Create({response}));
+ response.direct_address_type_ =
+ bluetooth::hci::DirectAdvertisingAddressType::NO_ADDRESS_PROVIDED;
+
+ // Each extended advertising report can only pass 229 bytes of
+ // advertising data (255 - size of report fields).
+ // RootCanal must fragment the report as necessary.
+ const size_t max_fragment_size = 229;
+ size_t offset = 0;
+ std::vector<uint8_t> advertising_data = scan_response.GetScanResponseData();
+
+ do {
+ size_t remaining_size = advertising_data.size() - offset;
+ size_t fragment_size = std::min(max_fragment_size, remaining_size);
+ response.data_status_ = remaining_size <= max_fragment_size
+ ? bluetooth::hci::DataStatus::COMPLETE
+ : bluetooth::hci::DataStatus::CONTINUING;
+ response.advertising_data_ =
+ std::vector(advertising_data.begin() + offset,
+ advertising_data.begin() + offset + fragment_size);
+ offset += fragment_size;
+ send_event_(bluetooth::hci::LeExtendedAdvertisingReportBuilder::Create(
+ {response}));
+ } while (offset < advertising_data.size());
}
}
diff --git a/tools/rootcanal/model/controller/link_layer_controller.h b/tools/rootcanal/model/controller/link_layer_controller.h
index b7af7a3..e9645b8 100644
--- a/tools/rootcanal/model/controller/link_layer_controller.h
+++ b/tools/rootcanal/model/controller/link_layer_controller.h
@@ -1070,6 +1070,7 @@
// Save information about the advertising PDU being scanned.
bool connectable_scan_response;
+ bool extended_scan_response;
std::optional<AddressWithType> pending_scan_request{};
std::optional<std::chrono::steady_clock::time_point>
pending_scan_request_timeout{};
diff --git a/tools/rootcanal/test/LL/DDI/SCN/BV_20_C.py b/tools/rootcanal/test/LL/DDI/SCN/BV_20_C.py
new file mode 100644
index 0000000..726e35a
--- /dev/null
+++ b/tools/rootcanal/test/LL/DDI/SCN/BV_20_C.py
@@ -0,0 +1,264 @@
+# Copyright 2024 Google LLC
+#
+# 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
+#
+# https://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.
+
+import hci_packets as hci
+import link_layer_packets as ll
+import math
+import random
+from dataclasses import dataclass
+from hci_packets import ErrorCode
+from py.bluetooth import Address
+from py.controller import ControllerTest
+from typing import Optional
+
+ADV_IND = 0x13
+ADV_DIRECT_IND = 0x15
+ADV_SCAN_IND = 0x12
+ADV_EXT_IND = 0x02
+
+
+@dataclass
+class TestRound:
+ advertising_event_properties: int
+ target_address: Optional[Address]
+ scan_data_length: int
+
+
+class Test(ControllerTest):
+
+ # LL/DDI/SCN/BV-20-C [Extended Scanning, Active – LE 1M PHY, Core 5.0]
+ #
+ # Verify that a scanner IUT detects and requests additional information from
+ # advertisements received and reports the results from the Controller. The
+ # Lower Tester advertises using scannable extended advertising events on one
+ # channel at a time and expects the IUT to report the advertising to the
+ # Upper Tester. Both directed and undirected advertising events are tested.
+ async def test(self):
+ # Test rounds.
+ # Note: some tests are skipped as no distinction is made between
+ # ADV_EXT_IND, AUX_ADV_IND, AUX_CHAIN_IND.
+ controller = self.controller
+ invalid_address = Address("11:22:33:44:55:66")
+ test_rounds = [
+ TestRound(ADV_IND, None, 0),
+ TestRound(ADV_IND, None, 31),
+ TestRound(ADV_SCAN_IND, None, 0),
+ TestRound(ADV_SCAN_IND, None, 31),
+ TestRound(ADV_EXT_IND, None, 1),
+ TestRound(ADV_EXT_IND, controller.address, 1),
+ TestRound(ADV_EXT_IND, invalid_address, 1),
+ TestRound(ADV_EXT_IND, None, 191),
+ TestRound(ADV_EXT_IND, None, 382),
+ TestRound(ADV_EXT_IND, None, 1647),
+ ]
+
+ # 1. For each round as specified in Table 4.2-35 based on Table 4.2-36, if ScanData Length is less
+ # than or equal to the “Scan Max Data” then perform steps 2–8 and otherwise omit this round.
+ for test_round in test_rounds:
+ await self.steps_2_8(**vars(test_round))
+
+ async def steps_2_8(self, advertising_event_properties: int, target_address: Optional[Address],
+ scan_data_length: int):
+
+ controller = self.controller
+ lower_tester_address = Address("ca:fe:ca:fe:00:01")
+
+ # 2. The Upper Tester sends an HCI_LE_Set_Extended_Scan_Parameters command to the IUT. The
+ # Scanning_PHYs parameter is set as specified in Table 4.2-35, Scan_Type[0] set to 0x01 (Active
+ # Scanning), Scan_Interval[0] set to 0x0010, and Scan_Window[0] set to 0x0010.
+ # Own_Address_Type is set to 0x00 (Public Device Address), and Scanning_Filter_Policy is set to
+ # 0x00 (Accept All) and receives a successful HCI_Command_Complete.
+ controller.send_cmd(
+ hci.LeSetExtendedScanParameters(own_address_type=hci.OwnAddressType.PUBLIC_DEVICE_ADDRESS,
+ scanning_filter_policy=hci.LeScanningFilterPolicy.ACCEPT_ALL,
+ scanning_phys=0x1,
+ scanning_phy_parameters=[
+ hci.ScanningPhyParameters(le_scan_type=hci.LeScanType.ACTIVE,
+ le_scan_interval=0x0010,
+ le_scan_window=0x0010)
+ ]))
+
+ await self.expect_evt(
+ hci.LeSetExtendedScanParametersComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1))
+
+ # 3. The Upper Tester sends an HCI_LE_Set_Extended_Scan_Enable command to the IUT to enable
+ # scanning. Filter_Duplicates, Duration, and Period are all set to zero and receive a successful
+ # HCI_Command_Complete.
+ controller.send_cmd(
+ hci.LeSetExtendedScanEnable(enable=hci.Enable.ENABLED,
+ filter_duplicates=hci.Enable.DISABLED,
+ duration=0,
+ period=0))
+
+ await self.expect_evt(hci.LeSetExtendedScanEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1))
+
+ # 4. The Lower Tester begins advertising on the channel as specified in Table 4.2-35 using the PDU
+ # Type specified in Table 4.2-36 for this round. If AUX_ADV_IND is included in the round, the
+ # ADV_EXT_IND includes an AuxPtr that refers to the AUX_ADV_IND on the PHY as specified in
+ # Table 4.2-35, and all fields specified should be included with the AUX_ADV_IND only. If AdvA is
+ # specified, the appropriate PDU includes the field, where “LT” equals the Lower Tester address. If
+ # TargetA is specified, the appropriate PDU includes the field, where “IUT” equals the IUT address
+ # and “Not IUT” equals a random address other than the IUT address. Repeat for at least 20
+ # advertising intervals or until step 5 occurs.
+ connectable = (advertising_event_properties & 0x1) != 0
+ scannable = (advertising_event_properties & 0x2) != 0
+ directed = (advertising_event_properties & 0x4) != 0
+ high_duty_cycle = (advertising_event_properties & 0x8) != 0
+ legacy = (advertising_event_properties & 0x10) != 0
+
+ if legacy:
+ if advertising_event_properties == ADV_IND:
+ advertising_type = ll.LegacyAdvertisingType.ADV_IND
+ elif advertising_event_properties == ADV_DIRECT_IND:
+ advertising_type = ll.LegacyAdvertisingType.ADV_DIRECT_IND
+ elif advertising_event_properties == ADV_SCAN_IND:
+ advertising_type = ll.LegacyAdvertisingType.ADV_SCAN_IND
+ elif advertising_event_properties == ADV_NONCONN_IND:
+ advertising_type = ll.LegacyAdvertisingType.ADV_NONCONN_IND
+ pdu = ll.LeLegacyAdvertisingPdu(source_address=lower_tester_address,
+ destination_address=target_address or Address(),
+ advertising_address_type=ll.AddressType.PUBLIC,
+ target_address_type=ll.AddressType.PUBLIC,
+ advertising_type=advertising_type,
+ advertising_data=[])
+ else:
+ pdu = ll.LeExtendedAdvertisingPdu(source_address=lower_tester_address,
+ destination_address=target_address or Address(),
+ advertising_address_type=ll.AddressType.PUBLIC,
+ target_address_type=ll.AddressType.PUBLIC,
+ connectable=connectable,
+ scannable=scannable,
+ directed=not target_address is None,
+ sid=0,
+ tx_power=0x7f,
+ primary_phy=ll.PrimaryPhyType.LE_1M,
+ secondary_phy=ll.SecondaryPhyType.NO_PACKETS,
+ advertising_data=[])
+
+ # 5. For undirected advertisements or advertisements directed at the IUT, the Lower Tester receives
+ # either a SCAN_REQ (if advertising with legacy PDUs) or an AUX_SCAN_REQ (if advertising with
+ # extended PDUs) on the appropriate advertising channel. The ScanA field is set to the IUT’s
+ # address, and the AdvA address is set to the Lower Tester’s address. The Upper Tester receives
+ # an HCI_LE_Extended_Advertising_Report event from the IUT with an Event_Type where bit 3
+ # (Scan response) is not set, the Data Status in the Event_Type field is set to Complete (0b00),
+ # Periodic_Advertising_Interval is set to 0, and no advertising data. If the advertisements were
+ # directed but TargetA is not the IUT, skip to step 8.
+ for n in range(3):
+ if not legacy:
+ sid = random.randint(0, 15)
+ pdu.sid = sid
+ else:
+ sid = 0xff
+
+ controller.send_ll(pdu, rssi=0)
+
+ if target_address and target_address != controller.address:
+ # If the controller still emits an event, the error
+ # will appear in the subsequent rounds.
+ continue
+
+ await self.expect_evt(
+ hci.LeExtendedAdvertisingReport(responses=[
+ hci.LeExtendedAdvertisingResponse(
+ connectable=connectable,
+ scannable=scannable,
+ directed=not target_address is None,
+ scan_response=False,
+ legacy=legacy,
+ data_status=hci.DataStatus.COMPLETE,
+ address_type=hci.AddressType.PUBLIC_DEVICE_ADDRESS,
+ address=lower_tester_address,
+ primary_phy=hci.PrimaryPhyType.LE_1M,
+ secondary_phy=hci.SecondaryPhyType.NO_PACKETS,
+ advertising_sid=sid,
+ tx_power=0x7f,
+ rssi=0,
+ periodic_advertising_interval=0,
+ direct_address_type=hci.DirectAdvertisingAddressType.NO_ADDRESS_PROVIDED
+ if not target_address else hci.DirectAdvertisingAddressType.PUBLIC_DEVICE_ADDRESS,
+ direct_address=target_address or Address(),
+ advertising_data=[])
+ ]))
+
+ await self.expect_ll(
+ ll.LeScan(source_address=controller.address,
+ destination_address=lower_tester_address,
+ scanning_address_type=ll.AddressType.PUBLIC,
+ advertising_address_type=ll.AddressType.PUBLIC))
+
+ advertising_data = [random.randint(1, 254) for n in range(scan_data_length)]
+
+ # 6. Perform step 6A or 6B depending on the PDU sent by the IUT in step 5.
+ # Alternative 6A (The IUT sent a SCAN_REQ in step 5):
+ # 6A.1 The Lower Tester responds with a SCAN_RSP packet to the IUT T_IFS after the end
+ # of the SCAN_REQ PDU. If ScanData is specified, the SCAN_RSP PDU includes the
+ # field populated with random octets from 1 to 254 of the specified count.
+ # Alternative 6B (The IUT sent an AUX_SCAN_REQ in step 5):
+ # 6B.1 The Lower Tester responds with an AUX_SCAN_RSP packet to the IUT T_IFS after
+ # the end of the AUX_SCAN_REQ PDU with an AdvMode of 0b00. If ScanData is
+ # specified, the AUX_SCAN_RSP PDU includes the AdvData field populated with
+ # random octets from 1 to 254 of the specified count. If the ScanData is greater in
+ # length than will fit in one PDU, the Lower Tester includes an AuxPtr field and sends
+ # one or more AUX_CHAIN_IND PDUs containing the remaining data. Each PDU
+ # except the last contains as much AdvData as can fit.
+ controller.send_ll(ll.LeScanResponse(source_address=lower_tester_address,
+ destination_address=controller.address,
+ advertising_address_type=ll.AddressType.PUBLIC,
+ scan_response_data=advertising_data),
+ rssi=0)
+
+ # 7. If the Lower Tester sent a scan response in step 6, the Upper Tester receives one or more
+ # HCI_LE_Extended_Advertising_Report events from the IUT with an Event_Type where bit 3
+ # (Scan response) is set, and Periodic_Advertising_Interval is set to 0. If ScanData was included in
+ # the response, the Upper Tester receives the data included in one of the advertising packets. If
+ # ScanData is sent to the Upper Tester in multiple reports, the Data Status in the Event_Type field
+ # for each report except the last is set to “Incomplete, more data to come”, 0b01. The Event_Type
+ # field for the last report sent with advertisement data is set to “Complete”, 0b00.
+ offset = 0
+ max_fragment_length = 229
+ num_fragments = math.ceil(scan_data_length / max_fragment_length) or 1
+
+ for n in range(num_fragments):
+ remaining_length = scan_data_length - offset
+ fragment_length = min(max_fragment_length, remaining_length)
+ data_status = hci.DataStatus.CONTINUING if remaining_length > max_fragment_length else hci.DataStatus.COMPLETE
+ await self.expect_evt(
+ hci.LeExtendedAdvertisingReport(responses=[
+ hci.LeExtendedAdvertisingResponse(
+ connectable=connectable,
+ scannable=scannable,
+ directed=False,
+ scan_response=True,
+ legacy=legacy,
+ data_status=data_status,
+ address_type=hci.AddressType.PUBLIC_DEVICE_ADDRESS,
+ address=lower_tester_address,
+ primary_phy=hci.PrimaryPhyType.LE_1M,
+ secondary_phy=hci.SecondaryPhyType.NO_PACKETS,
+ # TODO SID should be set in scan response PDU
+ advertising_sid=0xff,
+ tx_power=0x7f,
+ rssi=0,
+ periodic_advertising_interval=0,
+ direct_address_type=hci.DirectAdvertisingAddressType.NO_ADDRESS_PROVIDED,
+ direct_address=Address(),
+ advertising_data=advertising_data[offset:offset + fragment_length])
+ ]))
+ offset += fragment_length
+
+ # 8. The Upper Tester sends an HCI_LE_Set_Scan_Enable to the IUT to disable scanning and
+ # receives an HCI_Command_Complete event in response.
+ controller.send_cmd(hci.LeSetExtendedScanEnable(enable=hci.Enable.DISABLED))
+
+ await self.expect_evt(hci.LeSetExtendedScanEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1))
diff --git a/tools/rootcanal/test/invalid_packet_handler_unittest.cc b/tools/rootcanal/test/invalid_packet_handler_unittest.cc
new file mode 100644
index 0000000..803124b
--- /dev/null
+++ b/tools/rootcanal/test/invalid_packet_handler_unittest.cc
@@ -0,0 +1,82 @@
+/*
+ * Copyright 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include "log.h"
+#include "model/controller/dual_mode_controller.h"
+
+namespace rootcanal {
+
+using namespace bluetooth::hci;
+
+class InvalidPacketHandlerTest : public ::testing::Test {
+ public:
+ InvalidPacketHandlerTest() = default;
+ ~InvalidPacketHandlerTest() override = default;
+
+ protected:
+ DualModeController controller_;
+};
+
+// Set Event Mask command with missing parameters.
+const std::vector<uint8_t> kInvalidCommandPacket = {0x01, 0x0C, 0x03,
+ 0xff, 0xff, 0xff};
+
+// Hardware Error event with code 0x43.
+const std::vector<uint8_t> kHardwareErrorEvent = {0x10, 0x01, 0x43};
+
+TEST_F(InvalidPacketHandlerTest, DefaultHandler) {
+ // Validate that the default invalid packet handler causes
+ // an abort when an invalid packet is received.
+ ASSERT_DEATH(controller_.HandleCommand(std::make_shared<std::vector<uint8_t>>(
+ kInvalidCommandPacket)),
+ "");
+}
+
+TEST_F(InvalidPacketHandlerTest, RegisteredHandler) {
+ static struct {
+ uint32_t id;
+ InvalidPacketReason reason;
+ std::vector<uint8_t> bytes;
+ } invalid_packet;
+
+ static std::vector<uint8_t> hci_event;
+
+ // Validate that the registered invalid packet handler is correctly
+ // invoked when an invalid packet is received.
+ controller_.RegisterInvalidPacketHandler(
+ [&](uint32_t id, InvalidPacketReason reason, std::string,
+ std::vector<uint8_t> const& bytes) {
+ invalid_packet.id = id;
+ invalid_packet.reason = reason;
+ invalid_packet.bytes = bytes;
+ });
+
+ controller_.RegisterEventChannel(
+ [&](std::shared_ptr<std::vector<uint8_t>> packet) {
+ hci_event = std::vector<uint8_t>(*packet);
+ });
+
+ controller_.HandleCommand(
+ std::make_shared<std::vector<uint8_t>>(kInvalidCommandPacket));
+ ASSERT_EQ(invalid_packet.id, controller_.id_);
+ ASSERT_EQ(invalid_packet.reason, InvalidPacketReason::kParseError);
+ ASSERT_EQ(invalid_packet.bytes, kInvalidCommandPacket);
+ ASSERT_EQ(hci_event, kHardwareErrorEvent);
+}
+
+} // namespace rootcanal
diff --git a/tools/rootcanal/test/main.py b/tools/rootcanal/test/main.py
index ecf8609..b61a5b8 100644
--- a/tools/rootcanal/test/main.py
+++ b/tools/rootcanal/test/main.py
@@ -58,6 +58,7 @@
'LL.DDI.SCN.BV_14_C',
'LL.DDI.SCN.BV_18_C',
'LL.DDI.SCN.BV_19_C',
+ 'LL.DDI.SCN.BV_20_C',
'LL.DDI.SCN.BV_79_C',
'LL.SEC.ADV.BV_11_C',
'LMP.LIH.BV_01_C',