diff options
516 files changed, 12591 insertions, 15772 deletions
@@ -1,12 +1,4 @@ # Project owners -cmanton@google.com -cncn@google.com -hsz@google.com -jpawlowski@google.com -mylesgw@google.com -optedoblivion@google.com -qasimj@google.com -rahulsabnis@google.com sattiraju@google.com siyuanh@google.com zachoverflow@google.com diff --git a/android/app/OWNERS b/android/app/OWNERS index cc15db5d23..f758f97703 100644 --- a/android/app/OWNERS +++ b/android/app/OWNERS @@ -1 +1,13 @@ -include platform/packages/modules/Bluetooth:/OWNERS +# Reviewers for /android/app + +cmanton@google.com +cncn@google.com +hsz@google.com +jpawlowski@google.com +mylesgw@google.com +optedoblivion@google.com +qasimj@google.com +rahulsabnis@google.com +sattiraju@google.com +siyuanh@google.com +zachoverflow@google.com
\ No newline at end of file diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp index db1f299f3f..05d1944d48 100644 --- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp @@ -599,31 +599,15 @@ static void link_quality_report_callback( (jint)negative_acknowledgement_count); } -static void switch_buffer_size_callback(RawAddress* bd_addr, - bool is_low_latency_buffer_size) { - - if (!bd_addr) { - ALOGE("Address is null in %s", __func__); - return; - } +static void switch_buffer_size_callback(bool is_low_latency_buffer_size) { CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid()) return; - ScopedLocalRef<jbyteArray> addr( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); - if (!addr.get()) { - ALOGE("Error while allocating in: %s", __func__); - return; - } - - sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), - (jbyte*)bd_addr); - ALOGV("%s: SwitchBufferSizeCallback: %s", __func__, is_low_latency_buffer_size ? "true" : "false"); sCallbackEnv->CallVoidMethod( - sJniCallbacksObj, method_switchBufferSizeCallback, addr.get(), + sJniCallbacksObj, method_switchBufferSizeCallback, (jboolean)is_low_latency_buffer_size); } @@ -924,7 +908,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) { jniCallbackClass, "linkQualityReportCallback", "(JIIIIII)V"); method_switchBufferSizeCallback = - env->GetMethodID(jniCallbackClass, "switchBufferSizeCallback", "([BZ)V"); + env->GetMethodID(jniCallbackClass, "switchBufferSizeCallback", "(Z)V"); method_setWakeAlarm = env->GetMethodID(clazz, "setWakeAlarm", "(JZ)Z"); method_acquireWakeLock = diff --git a/android/app/jni/com_android_bluetooth_vc.cpp b/android/app/jni/com_android_bluetooth_vc.cpp index ce760c2206..5bb744db7a 100644 --- a/android/app/jni/com_android_bluetooth_vc.cpp +++ b/android/app/jni/com_android_bluetooth_vc.cpp @@ -66,7 +66,7 @@ class VolumeControlCallbacksImpl : public VolumeControlCallbacks { } void OnVolumeStateChanged(const RawAddress& bd_addr, uint8_t volume, - bool mute) override { + bool mute, bool isAutonomous) override { LOG(INFO) << __func__; std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); @@ -83,11 +83,11 @@ class VolumeControlCallbacksImpl : public VolumeControlCallbacks { sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)&bd_addr); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVolumeStateChanged, - (jint)volume, (jboolean)mute, addr.get()); + (jint)volume, (jboolean)mute, addr.get(), (jboolean)isAutonomous); } void OnGroupVolumeStateChanged(int group_id, uint8_t volume, - bool mute) override { + bool mute, bool isAutonomous) override { LOG(INFO) << __func__; std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); @@ -96,7 +96,7 @@ class VolumeControlCallbacksImpl : public VolumeControlCallbacks { sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onGroupVolumeStateChanged, (jint)volume, - (jboolean)mute, group_id); + (jboolean)mute, group_id, (jboolean)isAutonomous); } }; @@ -107,10 +107,10 @@ static void classInitNative(JNIEnv* env, jclass clazz) { env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V"); method_onVolumeStateChanged = - env->GetMethodID(clazz, "onVolumeStateChanged", "(IZ[B)V"); + env->GetMethodID(clazz, "onVolumeStateChanged", "(IZ[BZ)V"); method_onGroupVolumeStateChanged = - env->GetMethodID(clazz, "onGroupVolumeStateChanged", "(IZI)V"); + env->GetMethodID(clazz, "onGroupVolumeStateChanged", "(IZIZ)V"); LOG(INFO) << __func__ << ": succeeds"; } diff --git a/android/app/res/values/config.xml b/android/app/res/values/config.xml index 005d7bd60f..3a709770c1 100644 --- a/android/app/res/values/config.xml +++ b/android/app/res/values/config.xml @@ -33,6 +33,7 @@ <bool name="profile_supported_mapmce">false</bool> <bool name="profile_supported_hid_device">true</bool> <bool name="profile_supported_le_audio">true</bool> + <bool name="profile_supported_le_audio_broadcast">false</bool> <bool name="profile_supported_vc">true</bool> <bool name="profile_supported_mcp_server">true</bool> <bool name="profile_supported_csip_set_coordinator">true</bool> diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpService.java b/android/app/src/com/android/bluetooth/a2dp/A2dpService.java index 7a3b7df82b..a987758aff 100644 --- a/android/app/src/com/android/bluetooth/a2dp/A2dpService.java +++ b/android/app/src/com/android/bluetooth/a2dp/A2dpService.java @@ -88,6 +88,9 @@ public class A2dpService extends ProfileService { // Protect setActiveDevice() so all invoked is handled squentially private final Object mActiveSwitchingGuard = new Object(); + // Timeout for state machine thread join, to prevent potential ANR. + private static final int SM_THREAD_JOIN_TIMEOUT_MS = 1000; + // Upper limit of all A2DP devices: Bonded or Connected private static final int MAX_A2DP_STATE_MACHINES = 50; // Upper limit of all A2DP devices that are Connected or Connecting @@ -216,8 +219,13 @@ public class A2dpService extends ProfileService { } if (mStateMachinesThread != null) { - mStateMachinesThread.quitSafely(); - mStateMachinesThread = null; + try { + mStateMachinesThread.quitSafely(); + mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS); + mStateMachinesThread = null; + } catch (InterruptedException e) { + // Do not rethrow as we are shutting down anyway + } } // Step 2: Reset maximum number of connected audio devices mMaxConnectedAudioDevices = 1; diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java index 743b85a92e..e05dedc210 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java @@ -1114,11 +1114,21 @@ class AdapterProperties { writer.println(" " + "DiscoveryEndMs: " + mDiscoveryEndMs); writer.println(" " + "Bonded devices:"); + StringBuilder sb = new StringBuilder(); for (BluetoothDevice device : mBondedDevices) { - writer.println( - " " + device.getAddress() + " [" + dumpDeviceType(device.getType()) + "] " + String address = device.getAddress(); + String identityAddress = mService.getIdentityAddress(address); + if (identityAddress.equals(address)) { + writer.println(" " + address + + " [" + dumpDeviceType(device.getType()) + "] " + Utils.getName(device)); + } else { + sb.append(" " + address + " => " + identityAddress + + " [" + dumpDeviceType(device.getType()) + "] " + + Utils.getName(device) + "\n"); + } } + writer.println(sb.toString()); } private String dumpDeviceType(int deviceType) { diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index dd06cd3855..82d1f8d51f 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -824,15 +824,21 @@ public class AdapterService extends Service { } } - void switchBufferSizeCallback(byte[] address, boolean isLowLatencyBufferSize) { - BluetoothDevice device = getDeviceFromByte(address); + void switchBufferSizeCallback(boolean isLowLatencyBufferSize) { + List<BluetoothDevice> activeDevices = getActiveDevices(BluetoothProfile.A2DP); + if (activeDevices.size() != 1) { + errorLog( + "Cannot switch buffer size. The number of A2DP active devices is " + + activeDevices.size()); + } + // Send intent to fastpair Intent switchBufferSizeIntent = new Intent(BluetoothDevice.ACTION_SWITCH_BUFFER_SIZE); switchBufferSizeIntent.setClassName( getString(com.android.bluetooth.R.string.peripheral_link_package), getString(com.android.bluetooth.R.string.peripheral_link_package) + getString(com.android.bluetooth.R.string.peripheral_link_service)); - switchBufferSizeIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); + switchBufferSizeIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, activeDevices.get(0)); switchBufferSizeIntent.putExtra( BluetoothDevice.EXTRA_LOW_LATENCY_BUFFER_SIZE, isLowLatencyBufferSize); sendBroadcast(switchBufferSizeIntent); @@ -1084,7 +1090,7 @@ public class AdapterService extends Service { * @return true if any profile is enabled, false otherwise */ @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) - private boolean isAnyProfileEnabled(BluetoothDevice device) { + boolean isAnyProfileEnabled(BluetoothDevice device) { if (mA2dpService != null && mA2dpService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { @@ -4556,8 +4562,8 @@ public class AdapterService extends Service { * @return true, if the LE audio broadcast source is supported */ public boolean isLeAudioBroadcastSourceSupported() { - //TODO: check the profile support status as well after we have the implementation - return mAdapterProperties.isLePeriodicAdvertisingSupported() + return getResources().getBoolean(R.bool.profile_supported_le_audio_broadcast) + && mAdapterProperties.isLePeriodicAdvertisingSupported() && mAdapterProperties.isLeExtendedAdvertisingSupported() && mAdapterProperties.isLeIsochronousBroadcasterSupported(); } diff --git a/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java b/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java index 5d7b49d109..cc0c6a09d4 100644 --- a/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java +++ b/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java @@ -106,8 +106,8 @@ final class JniCallbacks { packets_not_receive_count, negative_acknowledgement_count); } - void switchBufferSizeCallback(byte[] mac_address, boolean is_low_latency_buffer_size) { - mAdapterService.switchBufferSizeCallback(mac_address, is_low_latency_buffer_size); + void switchBufferSizeCallback(boolean is_low_latency_buffer_size) { + mAdapterService.switchBufferSizeCallback(is_low_latency_buffer_size); } } diff --git a/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java b/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java index 50aff4ae61..f1cef7af66 100644 --- a/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java +++ b/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java @@ -43,6 +43,7 @@ import com.android.bluetooth.Utils; import com.android.bluetooth.a2dp.A2dpService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.csip.CsipSetCoordinatorService; +import com.android.bluetooth.hap.HapClientService; import com.android.bluetooth.hearingaid.HearingAidService; import com.android.bluetooth.hfp.HeadsetService; import com.android.bluetooth.hid.HidHostService; @@ -296,6 +297,7 @@ class PhonePolicy { mFactory.getCsipSetCoordinatorService(); VolumeControlService volumeControlService = mFactory.getVolumeControlService(); + HapClientService hapClientService = mFactory.getHapClientService(); // Set profile priorities only for the profiles discovered on the remote device. // This avoids needless auto-connect attempts to profiles non-existent on the remote device @@ -364,6 +366,14 @@ class PhonePolicy { mAdapterService.getDatabase().setProfileConnectionPolicy(device, BluetoothProfile.VOLUME_CONTROL, BluetoothProfile.CONNECTION_POLICY_ALLOWED); } + + if ((hapClientService != null) && Utils.arrayContains(uuids, + BluetoothUuid.HAS) && (hapClientService.getConnectionPolicy(device) + == BluetoothProfile.CONNECTION_POLICY_UNKNOWN)) { + debugLog("setting hearing access profile priority for device " + device); + mAdapterService.getDatabase().setProfileConnectionPolicy(device, + BluetoothProfile.HAP_CLIENT, BluetoothProfile.CONNECTION_POLICY_ALLOWED); + } } @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) diff --git a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java index 540f971679..2d8915388d 100644 --- a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +++ b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java @@ -24,6 +24,7 @@ import android.bluetooth.BluetoothAssignedNumbers; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; +import android.bluetooth.BluetoothHeadsetClient; import android.bluetooth.BluetoothProfile; import android.bluetooth.IBluetoothConnectionCallback; import android.content.BroadcastReceiver; @@ -71,6 +72,24 @@ final class RemoteDevices { private final HashMap<String, String> mDualDevicesMap; private Queue<String> mDeviceQueue; + /** + * Bluetooth HFP v1.8 specifies the Battery Charge indicator of AG can take values from + * {@code 0} to {@code 5}, but it does not specify how to map the values back to percentages. + * The following mapping is used: + * - Level 0: 0% + * - Level 1: midpoint of 1-25% + * - Level 2: midpoint of 26-50% + * - Level 3: midpoint of 51-75% + * - Level 4: midpoint of 76-99% + * - Level 5: 100% + */ + private static final int HFP_BATTERY_CHARGE_INDICATOR_0 = 0; + private static final int HFP_BATTERY_CHARGE_INDICATOR_1 = 13; + private static final int HFP_BATTERY_CHARGE_INDICATOR_2 = 38; + private static final int HFP_BATTERY_CHARGE_INDICATOR_3 = 63; + private static final int HFP_BATTERY_CHARGE_INDICATOR_4 = 88; + private static final int HFP_BATTERY_CHARGE_INDICATOR_5 = 100; + private final Handler mHandler; private class RemoteDevicesHandler extends Handler { @@ -110,6 +129,12 @@ final class RemoteDevices { case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED: onHeadsetConnectionStateChanged(intent); break; + case BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED: + onHeadsetClientConnectionStateChanged(intent); + break; + case BluetoothHeadsetClient.ACTION_AG_EVENT: + onAgIndicatorValueChanged(intent); + break; default: Log.w(TAG, "Unhandled intent: " + intent); break; @@ -157,6 +182,8 @@ final class RemoteDevices { filter.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY + "." + BluetoothAssignedNumbers.APPLE); filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothHeadsetClient.ACTION_AG_EVENT); sAdapterService.registerReceiver(mReceiver, filter); } @@ -565,6 +592,38 @@ final class RemoteDevices { Utils.getTempAllowlistBroadcastOptions()); } + /** + * Converts HFP's Battery Charge indicator values of {@code 0 -- 5} to an integer percentage. + */ + @VisibleForTesting + static int batteryChargeIndicatorToPercentge(int indicator) { + int percent; + switch (indicator) { + case 5: + percent = HFP_BATTERY_CHARGE_INDICATOR_5; + break; + case 4: + percent = HFP_BATTERY_CHARGE_INDICATOR_4; + break; + case 3: + percent = HFP_BATTERY_CHARGE_INDICATOR_3; + break; + case 2: + percent = HFP_BATTERY_CHARGE_INDICATOR_2; + break; + case 1: + percent = HFP_BATTERY_CHARGE_INDICATOR_1; + break; + case 0: + percent = HFP_BATTERY_CHARGE_INDICATOR_0; + break; + default: + percent = BluetoothDevice.BATTERY_LEVEL_UNKNOWN; + } + Log.d(TAG, "Battery charge indicator: " + indicator + "; converted to: " + percent + "%"); + return percent; + } + private static boolean areUuidsEqual(ParcelUuid[] uuids1, ParcelUuid[] uuids2) { final int length1 = uuids1 == null ? 0 : uuids1.length; final int length2 = uuids2 == null ? 0 : uuids2.length; @@ -663,6 +722,9 @@ final class RemoteDevices { } break; case AbstractionLayer.BT_PROPERTY_TYPE_OF_DEVICE: + if (device.isConsolidated()) { + return; + } // The device type from hal layer, defined in bluetooth.h, // matches the type defined in BluetoothDevice.java device.mDeviceType = Utils.byteArrayToInt(val); @@ -737,6 +799,7 @@ final class RemoteDevices { DeviceProperties deviceProperties = getDeviceProperties(device); deviceProperties.mIsConsolidated = true; + deviceProperties.mDeviceType = BluetoothDevice.DEVICE_TYPE_DUAL; deviceProperties.mIdentityAddress = Utils.getAddressStringFromByte(secondaryAddress); mDualDevicesMap.put(deviceProperties.getIdentityAddress(), Utils.getAddressStringFromByte(mainAddress)); } @@ -784,6 +847,12 @@ final class RemoteDevices { if (sAdapterService.getConnectionState(device) == 0) { resetBatteryLevel(device); } + if (!sAdapterService.isAnyProfileEnabled(device)) { + DeviceProperties deviceProp = getDeviceProperties(device); + if (deviceProp != null) { + deviceProp.setBondingInitiatedLocally(false); + } + } debugLog( "aclStateChangeCallback: Adapter State: " + BluetoothAdapter.nameForState(state) + " Disconnected: " + device @@ -1038,6 +1107,38 @@ final class RemoteDevices { return batteryLevel * 100 / (numberOfLevels - 1); } + /** + * Handles headset client connection state change event + * @param intent must be {@link BluetoothHeadsetClient#ACTION_CONNECTION_STATE_CHANGED} intent + */ + @VisibleForTesting + void onHeadsetClientConnectionStateChanged(Intent intent) { + BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + if (device == null) { + Log.e(TAG, "onHeadsetClientConnectionStateChanged() remote device is null"); + return; + } + if (intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED) + == BluetoothProfile.STATE_DISCONNECTED) { + // TODO: Rework this when non-HFP sources of battery level indication is added + resetBatteryLevel(device); + } + } + + @VisibleForTesting + void onAgIndicatorValueChanged(Intent intent) { + BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + if (device == null) { + Log.e(TAG, "onAgIndicatorValueChanged() remote device is null"); + return; + } + + if (intent.hasExtra(BluetoothHeadsetClient.EXTRA_BATTERY_LEVEL)) { + int batteryLevel = intent.getIntExtra(BluetoothHeadsetClient.EXTRA_BATTERY_LEVEL, -1); + updateBatteryLevel(device, batteryChargeIndicatorToPercentge(batteryLevel)); + } + } + private static void errorLog(String msg) { Log.e(TAG, msg); } diff --git a/android/app/src/com/android/bluetooth/btservice/ServiceFactory.java b/android/app/src/com/android/bluetooth/btservice/ServiceFactory.java index 6842dc0de5..f9256ad2a1 100644 --- a/android/app/src/com/android/bluetooth/btservice/ServiceFactory.java +++ b/android/app/src/com/android/bluetooth/btservice/ServiceFactory.java @@ -19,6 +19,7 @@ package com.android.bluetooth.btservice; import com.android.bluetooth.a2dp.A2dpService; import com.android.bluetooth.avrcp.AvrcpTargetService; import com.android.bluetooth.csip.CsipSetCoordinatorService; +import com.android.bluetooth.hap.HapClientService; import com.android.bluetooth.hearingaid.HearingAidService; import com.android.bluetooth.hfp.HeadsetService; import com.android.bluetooth.hid.HidDeviceService; @@ -73,4 +74,8 @@ public class ServiceFactory { public VolumeControlService getVolumeControlService() { return VolumeControlService.getVolumeControlService(); } + + public HapClientService getHapClientService() { + return HapClientService.getHapClientService(); + } } diff --git a/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java b/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java index dec6db2e4b..b127534ff7 100644 --- a/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java +++ b/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java @@ -67,6 +67,9 @@ public class CsipSetCoordinatorService extends ProfileService { private static final boolean DBG = false; private static final String TAG = "CsipSetCoordinatorService"; + // Timeout for state machine thread join, to prevent potential ANR. + private static final int SM_THREAD_JOIN_TIMEOUT_MS = 1000; + // Upper limit of all CSIP devices: Bonded or Connected private static final int MAX_CSIS_STATE_MACHINES = 10; private static CsipSetCoordinatorService sCsipSetCoordinatorService; @@ -182,8 +185,13 @@ public class CsipSetCoordinatorService extends ProfileService { } if (mStateMachinesThread != null) { - mStateMachinesThread.quitSafely(); - mStateMachinesThread = null; + try { + mStateMachinesThread.quitSafely(); + mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS); + mStateMachinesThread = null; + } catch (InterruptedException e) { + // Do not rethrow as we are shutting down anyway + } } mDeviceGroupIdMap.clear(); diff --git a/android/app/src/com/android/bluetooth/gatt/AppScanStats.java b/android/app/src/com/android/bluetooth/gatt/AppScanStats.java index a6c2bb94e6..cdd11f3c91 100644 --- a/android/app/src/com/android/bluetooth/gatt/AppScanStats.java +++ b/android/app/src/com/android/bluetooth/gatt/AppScanStats.java @@ -60,11 +60,13 @@ import java.util.Objects; ContextMap mContextMap; // GattService is needed to add scan event protos to be dumped later - GattService mGattService; + final GattService mGattService; // Battery stats is used to keep track of scans and result stats BatteryStatsManager mBatteryStatsManager; + private final AdapterService mAdapterService; + class LastScan { public long duration; public long suspendDuration; @@ -164,6 +166,7 @@ import java.util.Objects; } mWorkSource = source; mWorkSourceUtil = new WorkSourceUtil(source); + mAdapterService = Objects.requireNonNull(AdapterService.getAdapterService()); } synchronized void addResult(int scannerId) { @@ -272,7 +275,7 @@ import java.util.Objects; mTotalSuspendTime += suspendDuration; } mOngoingScans.remove(scannerId); - if (mLastScans.size() >= getNumScanDurationsKept()) { + if (mLastScans.size() >= mAdapterService.getScanQuotaCount()) { mLastScans.remove(0); } mLastScans.add(scan); @@ -355,19 +358,20 @@ import java.util.Objects; } synchronized boolean isScanningTooFrequently() { - if (mLastScans.size() < getNumScanDurationsKept()) { + if (mLastScans.size() < mAdapterService.getScanQuotaCount()) { return false; } return (SystemClock.elapsedRealtime() - mLastScans.get(0).timestamp) - < getExcessiveScanningPeriodMillis(); + < mAdapterService.getScanQuotaWindowMillis(); } synchronized boolean isScanningTooLong() { if (!isScanning()) { return false; } - return (SystemClock.elapsedRealtime() - mScanStartTime) > getScanTimeoutMillis(); + return (SystemClock.elapsedRealtime() - mScanStartTime) + > mAdapterService.getScanTimeoutMillis(); } synchronized boolean hasRecentScan() { diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java index 2c360f574d..a8a4db2ad2 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattService.java +++ b/android/app/src/com/android/bluetooth/gatt/GattService.java @@ -167,8 +167,7 @@ public class GattService extends ProfileService { UUID.fromString("00001850-0000-1000-8000-00805F9B34FB"), // PACS UUID.fromString("0000184E-0000-1000-8000-00805F9B34FB"), // ASCS UUID.fromString("0000184F-0000-1000-8000-00805F9B34FB"), // BASS - /* FIXME: Not known yet, using a placeholder instead. */ - UUID.fromString("EEEEEEEE-EEEE-EEEE-EEEE-EEEEEEEEEEEE"), // HAP + UUID.fromString("00001854-0000-1000-8000-00805F9B34FB"), // HAP }; /** @@ -315,7 +314,7 @@ public class GattService extends ProfileService { mAdvertiseManager = new AdvertiseManager(this, mAdapterService); mAdvertiseManager.start(); - mScanManager = new ScanManager(this); + mScanManager = new ScanManager(this, mAdapterService); mScanManager.start(); mPeriodicScanManager = new PeriodicScanManager(mAdapterService); @@ -3454,7 +3453,7 @@ public class GattService extends ProfileService { return new ArrayList<>(0); } List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); - for (HandleMap.Entry entry : mHandleMap.mEntries) { + for (HandleMap.Entry entry : mHandleMap.getEntries()) { serviceUuids.add(new ParcelUuid(entry.uuid)); } return serviceUuids; diff --git a/android/app/src/com/android/bluetooth/gatt/HandleMap.java b/android/app/src/com/android/bluetooth/gatt/HandleMap.java index 2b662d6011..2d8d9369e1 100644 --- a/android/app/src/com/android/bluetooth/gatt/HandleMap.java +++ b/android/app/src/com/android/bluetooth/gatt/HandleMap.java @@ -17,12 +17,11 @@ package com.android.bluetooth.gatt; import android.util.Log; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; class HandleMap { private static final boolean DBG = GattServiceConfig.DBG; @@ -88,8 +87,8 @@ class HandleMap { int mLastCharacteristic = 0; HandleMap() { - mEntries = new ArrayList<Entry>(); - mRequestMap = new HashMap<Integer, Integer>(); + mEntries = new CopyOnWriteArrayList<Entry>(); + mRequestMap = new ConcurrentHashMap<Integer, Integer>(); } void clear() { @@ -144,16 +143,8 @@ class HandleMap { } void deleteService(int serverIf, int serviceHandle) { - for (Iterator<Entry> it = mEntries.iterator(); it.hasNext(); ) { - Entry entry = it.next(); - if (entry.serverIf != serverIf) { - continue; - } - - if (entry.handle == serviceHandle || entry.serviceHandle == serviceHandle) { - it.remove(); - } - } + mEntries.removeIf(entry -> ((entry.serverIf == serverIf) + && (entry.handle == serviceHandle || entry.serviceHandle == serviceHandle))); } List<Entry> getEntries() { diff --git a/android/app/src/com/android/bluetooth/gatt/ScanManager.java b/android/app/src/com/android/bluetooth/gatt/ScanManager.java index 2aee8637bf..6494a6f448 100644 --- a/android/app/src/com/android/bluetooth/gatt/ScanManager.java +++ b/android/app/src/com/android/bluetooth/gatt/ScanManager.java @@ -95,7 +95,8 @@ public class ScanManager { private BatchScanParams mBatchScanParms; private Integer mCurUsedTrackableAdvertisements; - private GattService mService; + private final GattService mService; + private final AdapterService mAdapterService; private BroadcastReceiver mBatchAlarmReceiver; private boolean mBatchAlarmReceiverRegistered; private ScanNative mScanNative; @@ -129,7 +130,7 @@ public class ScanManager { } } - ScanManager(GattService service) { + ScanManager(GattService service, AdapterService adapterService) { mRegularScanClients = Collections.newSetFromMap(new ConcurrentHashMap<ScanClient, Boolean>()); mBatchClients = Collections.newSetFromMap(new ConcurrentHashMap<ScanClient, Boolean>()); @@ -141,6 +142,7 @@ public class ScanManager { mDm = mService.getSystemService(DisplayManager.class); mActivityManager = mService.getSystemService(ActivityManager.class); mLocationManager = mService.getSystemService(LocationManager.class); + mAdapterService = adapterService; mPriorityMap.put(ScanSettings.SCAN_MODE_OPPORTUNISTIC, 0); mPriorityMap.put(ScanSettings.SCAN_MODE_SCREEN_OFF, 1); @@ -383,7 +385,7 @@ public class ScanManager { Message msg = obtainMessage(MSG_SCAN_TIMEOUT); msg.obj = client; // Only one timeout message should exist at any time - sendMessageDelayed(msg, AppScanStats.getScanTimeoutMillis()); + sendMessageDelayed(msg, mAdapterService.getScanTimeoutMillis()); } } } @@ -547,7 +549,7 @@ public class ScanManager { } private boolean upgradeScanModeBeforeStart(ScanClient client) { - if (client.started || AppScanStats.getScanUpgradeDurationMillis() == 0) { + if (client.started || mAdapterService.getScanUpgradeDurationMillis() == 0) { return false; } if (client.stats == null || client.stats.hasRecentScan()) { @@ -563,7 +565,7 @@ public class ScanManager { if (DBG) { Log.d(TAG, "scanMode is upgraded for " + client); } - sendMessageDelayed(msg, AppScanStats.getScanUpgradeDurationMillis()); + sendMessageDelayed(msg, mAdapterService.getScanUpgradeDurationMillis()); return true; } return false; diff --git a/android/app/src/com/android/bluetooth/hap/HapClientService.java b/android/app/src/com/android/bluetooth/hap/HapClientService.java index 852bf67ea2..4a44daf8b7 100644 --- a/android/app/src/com/android/bluetooth/hap/HapClientService.java +++ b/android/app/src/com/android/bluetooth/hap/HapClientService.java @@ -20,14 +20,18 @@ package com.android.bluetooth.hap; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission; + import android.bluetooth.BluetoothCsipSetCoordinator; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHapClient; import android.bluetooth.BluetoothHapPresetInfo; import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothProfile; +import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothUuid; import android.bluetooth.IBluetoothHapClient; +import android.bluetooth.IBluetoothHapClientCallback; import android.content.AttributionSource; import android.content.BroadcastReceiver; import android.content.Context; @@ -35,6 +39,8 @@ import android.content.Intent; import android.content.IntentFilter; import android.os.HandlerThread; import android.os.ParcelUuid; +import android.os.RemoteCallbackList; +import android.os.RemoteException; import android.util.Log; import com.android.bluetooth.Utils; @@ -48,6 +54,7 @@ import com.android.modules.utils.SynchronousResultReceiver; import java.math.BigInteger; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.ListIterator; @@ -64,6 +71,7 @@ public class HapClientService extends ProfileService { // Upper limit of all HearingAccess devices: Bonded or Connected private static final int MAX_HEARING_ACCESS_STATE_MACHINES = 10; + private static final int SM_THREAD_JOIN_TIMEOUT_MS = 1000; private static HapClientService sHapClient; private final Map<BluetoothDevice, HapClientStateMachine> mStateMachines = new HashMap<>(); @@ -76,10 +84,13 @@ public class HapClientService extends ProfileService { private final Map<BluetoothDevice, Integer> mDeviceCurrentPresetMap = new HashMap<>(); private final Map<BluetoothDevice, Integer> mDeviceFeaturesMap = new HashMap<>(); - private final Map<BluetoothDevice, ArrayList<BluetoothHapPresetInfo>> mPresetsMap = + private final Map<BluetoothDevice, List<BluetoothHapPresetInfo>> mPresetsMap = new HashMap<>(); @VisibleForTesting + RemoteCallbackList<IBluetoothHapClientCallback> mCallbacks; + + @VisibleForTesting ServiceFactory mFactory = new ServiceFactory(); private static synchronized void setHapClient(HapClientService instance) { @@ -148,10 +159,6 @@ public class HapClientService extends ProfileService { mStateMachinesThread = new HandlerThread("HapClientService.StateMachines"); mStateMachinesThread.start(); - mDeviceCurrentPresetMap.clear(); - mDeviceFeaturesMap.clear(); - mPresetsMap.clear(); - // Setup broadcast receivers IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); @@ -162,12 +169,14 @@ public class HapClientService extends ProfileService { mConnectionStateChangedReceiver = new ConnectionStateChangedReceiver(); registerReceiver(mConnectionStateChangedReceiver, filter, Context.RECEIVER_NOT_EXPORTED); - // Mark service as started - setHapClient(this); + mCallbacks = new RemoteCallbackList<IBluetoothHapClientCallback>(); // Initialize native interface mHapClientNativeInterface.init(); + // Mark service as started + setHapClient(this); + return true; } @@ -181,10 +190,6 @@ public class HapClientService extends ProfileService { return true; } - // Cleanup GATT interface - mHapClientNativeInterface.cleanup(); - mHapClientNativeInterface = null; - // Marks service as stopped setHapClient(null); @@ -203,13 +208,27 @@ public class HapClientService extends ProfileService { mStateMachines.clear(); } + if (mStateMachinesThread != null) { + try { + mStateMachinesThread.quitSafely(); + mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS); + mStateMachinesThread = null; + } catch (InterruptedException e) { + // Do not rethrow as we are shutting down anyway + } + } + + // Cleanup GATT interface + mHapClientNativeInterface.cleanup(); + mHapClientNativeInterface = null; + + // Cleanup the internals mDeviceCurrentPresetMap.clear(); mDeviceFeaturesMap.clear(); mPresetsMap.clear(); - if (mStateMachinesThread != null) { - mStateMachinesThread.quitSafely(); - mStateMachinesThread = null; + if (mCallbacks != null) { + mCallbacks.kill(); } // Clear AdapterService @@ -340,8 +359,7 @@ public class HapClientService extends ProfileService { * @return true on success, otherwise false */ public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) { - enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, - "Need BLUETOOTH_PRIVILEGED permission"); + enforceBluetoothPrivilegedPermission(this); if (DBG) { Log.d(TAG, "Saved connectionPolicy " + device + " = " + connectionPolicy); } @@ -432,8 +450,7 @@ public class HapClientService extends ProfileService { * @return true if hearing access service client successfully connected, false otherwise */ public boolean connect(BluetoothDevice device) { - enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, - "Need BLUETOOTH_PRIVILEGED permission"); + enforceBluetoothPrivilegedPermission(this); if (DBG) { Log.d(TAG, "connect(): " + device); } @@ -469,8 +486,7 @@ public class HapClientService extends ProfileService { * @return true if hearing access service client successfully disconnected, false otherwise */ public boolean disconnect(BluetoothDevice device) { - enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, - "Need BLUETOOTH_PRIVILEGED permission"); + enforceBluetoothPrivilegedPermission(this); if (DBG) { Log.d(TAG, "disconnect(): " + device); } @@ -537,12 +553,33 @@ public class HapClientService extends ProfileService { * Gets the currently active preset index for a HA device * * @param device is the device for which we want to get the currently active preset - * @return true if valid request was sent, false otherwise + * @return active preset index */ - public boolean getActivePresetIndex(BluetoothDevice device) { - notifyActivePresetIndex(device, mDeviceCurrentPresetMap.getOrDefault(device, - BluetoothHapClient.PRESET_INDEX_UNAVAILABLE)); - return true; + public int getActivePresetIndex(BluetoothDevice device) { + return mDeviceCurrentPresetMap.getOrDefault(device, + BluetoothHapClient.PRESET_INDEX_UNAVAILABLE); + } + + /** + * Gets the currently active preset info for a HA device + * + * @param device is the device for which we want to get the currently active preset info + * @return active preset info + */ + public BluetoothHapPresetInfo getActivePresetInfo(BluetoothDevice device) { + int index = getActivePresetIndex(device); + if (index == BluetoothHapClient.PRESET_INDEX_UNAVAILABLE) return null; + + List<BluetoothHapPresetInfo> current_presets = mPresetsMap.get(device); + if (current_presets != null) { + for (BluetoothHapPresetInfo preset : current_presets) { + if (preset.getIndex() == index) { + return preset; + } + } + } + + return null; } /** @@ -550,12 +587,25 @@ public class HapClientService extends ProfileService { * * @param device is the device for which we want to set the active preset * @param presetIndex is an index of one of the available presets - * @return true if valid request was sent, false otherwise */ - public boolean selectActivePreset(BluetoothDevice device, int presetIndex) { - if (presetIndex == BluetoothHapClient.PRESET_INDEX_UNAVAILABLE) return false; + public void selectPreset(BluetoothDevice device, int presetIndex) { + if (presetIndex == BluetoothHapClient.PRESET_INDEX_UNAVAILABLE) { + if (mCallbacks != null) { + int n = mCallbacks.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onSelectActivePresetFailed(device, + BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX); + } catch (RemoteException e) { + continue; + } + } + mCallbacks.finishBroadcast(); + } + return; + } + mHapClientNativeInterface.selectActivePreset(device, presetIndex); - return true; } /** @@ -563,64 +613,70 @@ public class HapClientService extends ProfileService { * * @param groupId is the device group identifier for which want to set the active preset * @param presetIndex is an index of one of the available presets - * @return true if valid group request was sent, false otherwise */ - public boolean groupSelectActivePreset(int groupId, int presetIndex) { - if (presetIndex == BluetoothHapClient.PRESET_INDEX_UNAVAILABLE - || groupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) { - return false; + public void selectPresetForGroup(int groupId, int presetIndex) { + int status = BluetoothStatusCodes.ERROR_UNKNOWN; + + if ((presetIndex == BluetoothHapClient.PRESET_INDEX_UNAVAILABLE) + || (groupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID)) { + if (presetIndex == BluetoothHapClient.PRESET_INDEX_UNAVAILABLE) { + status = BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX; + } else { + status = BluetoothStatusCodes.ERROR_CSIP_INVALID_GROUP_ID; + } + + if (mCallbacks != null) { + int n = mCallbacks.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onSelectActivePresetForGroupFailed(groupId, + BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX); + } catch (RemoteException e) { + continue; + } + } + mCallbacks.finishBroadcast(); + } + return; } mHapClientNativeInterface.groupSelectActivePreset(groupId, presetIndex); - return true; } /** * Sets the next preset as a currently active preset for a HA device * * @param device is the device for which we want to set the active preset - * @return true if valid request was sent, false otherwise */ - public boolean nextActivePreset(BluetoothDevice device) { + public void switchToNextPreset(BluetoothDevice device) { mHapClientNativeInterface.nextActivePreset(device); - return true; } /** * Sets the next preset as a currently active preset for a HA device group * * @param groupId is the device group identifier for which want to set the active preset - * @return true if valid group request was sent, false otherwise */ - public boolean groupNextActivePreset(int groupId) { - if (groupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) return false; - + public void switchToNextPresetForGroup(int groupId) { mHapClientNativeInterface.groupNextActivePreset(groupId); - return true; } /** * Sets the previous preset as a currently active preset for a HA device * * @param device is the device for which we want to set the active preset - * @return true if valid request was sent, false otherwise */ - public boolean previousActivePreset(BluetoothDevice device) { + public void switchToPreviousPreset(BluetoothDevice device) { mHapClientNativeInterface.previousActivePreset(device); - return true; } /** * Sets the previous preset as a currently active preset for a HA device group * * @param groupId is the device group identifier for which want to set the active preset - * @return true if valid group request was sent, false otherwise */ - public boolean groupPreviousActivePreset(int groupId) { - if (groupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) return false; - + public void switchToPreviousPresetForGroup(int groupId) { mHapClientNativeInterface.groupPreviousActivePreset(groupId); - return true; } /** @@ -628,78 +684,241 @@ public class HapClientService extends ProfileService { * * @param device is the device for which we want to get the preset name * @param presetIndex is an index of one of the available presets - * @return true if valid request was sent, false otherwise + * @return a preset Info corresponding to the requested preset index */ - public boolean getPresetInfo(BluetoothDevice device, int presetIndex) { - if (presetIndex == BluetoothHapClient.PRESET_INDEX_UNAVAILABLE) return false; - mHapClientNativeInterface.getPresetInfo(device, presetIndex); - return true; + public BluetoothHapPresetInfo getPresetInfo(BluetoothDevice device, int presetIndex) { + BluetoothHapPresetInfo defaultValue = new BluetoothHapPresetInfo.Builder().build(); + + if (presetIndex == BluetoothHapClient.PRESET_INDEX_UNAVAILABLE) return defaultValue; + + List<BluetoothHapPresetInfo> current_presets = mPresetsMap.get(device); + if (current_presets != null) { + for (BluetoothHapPresetInfo preset : current_presets) { + if (preset.getIndex() == presetIndex) { + return preset; + } + } + } + + return defaultValue; } /** * Requests all presets info * * @param device is the device for which we want to get all presets info - * @return true if request was processed, false otherwise + * @return a list of all presets Info */ - public boolean getAllPresetsInfo(BluetoothDevice device) { + public List<BluetoothHapPresetInfo> getAllPresetInfo(BluetoothDevice device) { if (mPresetsMap.containsKey(device)) { - notifyPresets(device, BluetoothHapClient.PRESET_INFO_REASON_ALL_PRESET_INFO, - mPresetsMap.get(device)); - return true; + return mPresetsMap.get(device); } - return false; + return Collections.emptyList(); } /** * Requests features * * @param device is the device for which we want to get features - * @return true if request was processed, false otherwise + * @return integer with feature bits set */ - public boolean getFeatures(BluetoothDevice device) { + public int getFeatures(BluetoothDevice device) { if (mDeviceFeaturesMap.containsKey(device)) { - notifyFeatures(device, mDeviceFeaturesMap.get(device)); - return true; + return mDeviceFeaturesMap.get(device); } - return false; + return 0x00; } - private void notifyPresets(BluetoothDevice device, int infoReason, - ArrayList<BluetoothHapPresetInfo> presets) { - Intent intent = null; + private int stackEventPresetInfoReasonToProfileStatus(int statusCode) { + switch (statusCode) { + case HapClientStackEvent.PRESET_INFO_REASON_ALL_PRESET_INFO: + return BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST; + case HapClientStackEvent.PRESET_INFO_REASON_PRESET_INFO_UPDATE: + return BluetoothStatusCodes.REASON_REMOTE_REQUEST; + case HapClientStackEvent.PRESET_INFO_REASON_PRESET_DELETED: + return BluetoothStatusCodes.REASON_REMOTE_REQUEST; + case HapClientStackEvent.PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED: + return BluetoothStatusCodes.REASON_REMOTE_REQUEST; + case HapClientStackEvent.PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE: + return BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST; + default: + return BluetoothStatusCodes.ERROR_UNKNOWN; + } + } - intent = new Intent(BluetoothHapClient.ACTION_HAP_ON_PRESET_INFO); - if (intent != null) { - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - intent.putExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INFO_REASON, infoReason); - intent.putParcelableArrayListExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INFO, presets); - sendBroadcast(intent, BLUETOOTH_PRIVILEGED); + private void notifyPresetInfoChanged(BluetoothDevice device, int infoReason) { + List current_presets = mPresetsMap.get(device); + if (current_presets == null) return; + + if (mCallbacks != null) { + int n = mCallbacks.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onPresetInfoChanged(device, current_presets, + stackEventPresetInfoReasonToProfileStatus(infoReason)); + } catch (RemoteException e) { + continue; + } + } + mCallbacks.finishBroadcast(); } } - private void notifyPresets(int groupId, int infoReason, - ArrayList<BluetoothHapPresetInfo> presets) { - Intent intent = null; + private void notifyPresetInfoForGroupChanged(int groupId, int infoReason) { + List<BluetoothDevice> all_group_devices = getGroupDevices(groupId); + for (BluetoothDevice dev : all_group_devices) { + notifyPresetInfoChanged(dev, infoReason); + } + } - intent = new Intent(BluetoothHapClient.ACTION_HAP_ON_PRESET_INFO); - if (intent != null) { - intent.putExtra(BluetoothHapClient.EXTRA_HAP_GROUP_ID, groupId); - intent.putExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INFO_REASON, infoReason); - intent.putParcelableArrayListExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INFO, presets); - sendBroadcast(intent, BLUETOOTH_PRIVILEGED); + private void notifyFeaturesAvailable(BluetoothDevice device, int features) { + if (mCallbacks != null) { + int n = mCallbacks.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onHapFeaturesAvailable(device, features); + } catch (RemoteException e) { + continue; + } + } + mCallbacks.finishBroadcast(); } } - private void notifyFeatures(BluetoothDevice device, int features) { - Intent intent = null; + private void notifyActivePresetChanged(BluetoothDevice device, int presetIndex) { + if (mCallbacks != null) { + int n = mCallbacks.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onActivePresetChanged(device, presetIndex); + } catch (RemoteException e) { + continue; + } + } + mCallbacks.finishBroadcast(); + } + } - intent = new Intent(BluetoothHapClient.ACTION_HAP_ON_DEVICE_FEATURES); - if (intent != null) { - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - intent.putExtra(BluetoothHapClient.EXTRA_HAP_FEATURES, features); - sendBroadcast(intent, BLUETOOTH_PRIVILEGED); + private void notifyActivePresetChangedForGroup(int groupId, int presetIndex) { + List<BluetoothDevice> all_group_devices = getGroupDevices(groupId); + for (BluetoothDevice dev : all_group_devices) { + notifyActivePresetChanged(dev, presetIndex); + } + } + + private int stackEventStatusToProfileStatus(int statusCode) { + switch (statusCode) { + case HapClientStackEvent.STATUS_SET_NAME_NOT_ALLOWED: + return BluetoothStatusCodes.ERROR_REMOTE_OPERATION_REJECTED; + case HapClientStackEvent.STATUS_OPERATION_NOT_SUPPORTED: + return BluetoothStatusCodes.ERROR_REMOTE_OPERATION_NOT_SUPPORTED; + case HapClientStackEvent.STATUS_OPERATION_NOT_POSSIBLE: + return BluetoothStatusCodes.ERROR_REMOTE_OPERATION_REJECTED; + case HapClientStackEvent.STATUS_INVALID_PRESET_NAME_LENGTH: + return BluetoothStatusCodes.ERROR_HAP_PRESET_NAME_TOO_LONG; + case HapClientStackEvent.STATUS_INVALID_PRESET_INDEX: + return BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX; + case HapClientStackEvent.STATUS_GROUP_OPERATION_NOT_SUPPORTED: + return BluetoothStatusCodes.ERROR_REMOTE_OPERATION_NOT_SUPPORTED; + case HapClientStackEvent.STATUS_PROCEDURE_ALREADY_IN_PROGRESS: + return BluetoothStatusCodes.ERROR_UNKNOWN; + default: + return BluetoothStatusCodes.ERROR_UNKNOWN; + } + } + + private void notifySelectActivePresetFailed(BluetoothDevice device, int statusCode) { + if (mCallbacks != null) { + int n = mCallbacks.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onSelectActivePresetFailed(device, + stackEventStatusToProfileStatus(statusCode)); + } catch (RemoteException e) { + continue; + } + } + mCallbacks.finishBroadcast(); + } + } + + private void notifySelectActivePresetForGroupFailed(int groupId, int statusCode) { + if (mCallbacks != null) { + int n = mCallbacks.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onSelectActivePresetForGroupFailed(groupId, + stackEventStatusToProfileStatus(statusCode)); + } catch (RemoteException e) { + continue; + } + } + mCallbacks.finishBroadcast(); + } + } + + private void notifySetPresetNameFailed(BluetoothDevice device, int statusCode) { + if (mCallbacks != null) { + int n = mCallbacks.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onSetPresetNameFailed(device, + stackEventStatusToProfileStatus(statusCode)); + } catch (RemoteException e) { + continue; + } + } + mCallbacks.finishBroadcast(); + } + } + + private void notifySetPresetNameForGroupFailed(int groupId, int statusCode) { + if (mCallbacks != null) { + int n = mCallbacks.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onSetPresetNameForGroupFailed(groupId, + stackEventStatusToProfileStatus(statusCode)); + } catch (RemoteException e) { + continue; + } + } + mCallbacks.finishBroadcast(); + } + } + + private boolean isPresetIndexValid(BluetoothDevice device, int presetIndex) { + if (presetIndex == BluetoothHapClient.PRESET_INDEX_UNAVAILABLE) return false; + + List<BluetoothHapPresetInfo> device_presets = mPresetsMap.get(device); + if (device_presets != null) { + for (BluetoothHapPresetInfo preset : device_presets) { + if (preset.getIndex() == presetIndex) { + return true; + } + } + } + return false; + } + + private boolean isPresetIndexValid(int groupId, int presetIndex) { + List<BluetoothDevice> all_group_devices = getGroupDevices(groupId); + for (BluetoothDevice device : all_group_devices) { + if (!isPresetIndexValid(device, presetIndex)) return false; } + return true; + } + + + private boolean isGroupIdValid(int groupId) { + if (groupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) return false; + + CsipSetCoordinatorService csipClient = mFactory.getCsipSetCoordinatorService(); + if (csipClient != null) { + List<Integer> groups = csipClient.getAllGroupIds(BluetoothUuid.CAP); + return groups.contains(groupId); + } + return true; } /** @@ -708,12 +927,27 @@ public class HapClientService extends ProfileService { * @param device is the device for which we want to get the preset name * @param presetIndex is an index of one of the available presets * @param name is a new name for a preset - * @return true if valid request was sent, false otherwise */ - public boolean setPresetName(BluetoothDevice device, int presetIndex, String name) { - if (presetIndex == BluetoothHapClient.PRESET_INDEX_UNAVAILABLE) return false; + public void setPresetName(BluetoothDevice device, int presetIndex, String name) { + if (!isPresetIndexValid(device, presetIndex)) { + if (mCallbacks != null) { + int n = mCallbacks.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onSetPresetNameFailed(device, + BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX); + } catch (RemoteException e) { + continue; + } + } + mCallbacks.finishBroadcast(); + } + return; + } + // WARNING: We should check cache if preset exists and is writable, but then we would still + // need a way to trigger this action with an invalid index or on a non-writable + // preset for tests purpose. mHapClientNativeInterface.setPresetName(device, presetIndex, name); - return true; } /** @@ -722,13 +956,33 @@ public class HapClientService extends ProfileService { * @param groupId is the device group identifier * @param presetIndex is an index of one of the available presets * @param name is a new name for a preset - * @return true if valid request was sent, false otherwise */ - public boolean groupSetPresetName(int groupId, int presetIndex, String name) { - if (groupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) return false; - if (presetIndex == BluetoothHapClient.PRESET_INDEX_UNAVAILABLE) return false; + public void setPresetNameForGroup(int groupId, int presetIndex, String name) { + int status = BluetoothStatusCodes.SUCCESS; + + if (!isGroupIdValid(groupId)) { + status = BluetoothStatusCodes.ERROR_CSIP_INVALID_GROUP_ID; + } + if (!isPresetIndexValid(groupId, presetIndex)) { + status = BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX; + } + if (status != BluetoothStatusCodes.SUCCESS) { + if (mCallbacks != null) { + int n = mCallbacks.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onSetPresetNameForGroupFailed(groupId, + status); + } catch (RemoteException e) { + continue; + } + } + mCallbacks.finishBroadcast(); + } + return; + } + mHapClientNativeInterface.groupSetPresetName(groupId, presetIndex, name); - return true; } @Override @@ -745,30 +999,16 @@ public class HapClientService extends ProfileService { HapClientStackEvent.FEATURE_BIT_NUM_SYNCHRONIZATED_PRESETS); } - void notifyActivePresetIndex(BluetoothDevice device, int presetIndex) { - Intent intent = new Intent(BluetoothHapClient.ACTION_HAP_ON_ACTIVE_PRESET); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - intent.putExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INDEX, presetIndex); - sendBroadcast(intent, BLUETOOTH_PRIVILEGED); - } - - void notifyActivePresetIndex(int groupId, int presetIndex) { - Intent intent = new Intent(BluetoothHapClient.ACTION_HAP_ON_ACTIVE_PRESET); - intent.putExtra(BluetoothHapClient.EXTRA_HAP_GROUP_ID, groupId); - intent.putExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INDEX, presetIndex); - sendBroadcast(intent, BLUETOOTH_PRIVILEGED); - } - void updateDevicePresetsCache(BluetoothDevice device, int infoReason, - ArrayList<BluetoothHapPresetInfo> presets) { + List<BluetoothHapPresetInfo> presets) { switch (infoReason) { - case BluetoothHapClient.PRESET_INFO_REASON_ALL_PRESET_INFO: + case HapClientStackEvent.PRESET_INFO_REASON_ALL_PRESET_INFO: mPresetsMap.put(device, presets); break; - case BluetoothHapClient.PRESET_INFO_REASON_PRESET_INFO_UPDATE: - case BluetoothHapClient.PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED: - case BluetoothHapClient.PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE: { - ArrayList current_presets = mPresetsMap.get(device); + case HapClientStackEvent.PRESET_INFO_REASON_PRESET_INFO_UPDATE: + case HapClientStackEvent.PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED: + case HapClientStackEvent.PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE: { + List current_presets = mPresetsMap.get(device); if (current_presets != null) { ListIterator<BluetoothHapPresetInfo> iter = current_presets.listIterator(); for (BluetoothHapPresetInfo new_preset : presets) { @@ -786,8 +1026,8 @@ public class HapClientService extends ProfileService { } break; - case BluetoothHapClient.PRESET_INFO_REASON_PRESET_DELETED: { - ArrayList current_presets = mPresetsMap.get(device); + case HapClientStackEvent.PRESET_INFO_REASON_PRESET_DELETED: { + List current_presets = mPresetsMap.get(device); if (current_presets != null) { ListIterator<BluetoothHapPresetInfo> iter = current_presets.listIterator(); for (BluetoothHapPresetInfo new_preset : presets) { @@ -807,6 +1047,19 @@ public class HapClientService extends ProfileService { } } + private List<BluetoothDevice> getGroupDevices(int groupId) { + List<BluetoothDevice> devices = new ArrayList<>(); + + // TODO: Fix missing CSIS service API to decouple from LeAudioService + LeAudioService le_audio_service = mFactory.getLeAudioService(); + if (le_audio_service != null) { + if (groupId != BluetoothLeAudio.GROUP_ID_INVALID) { + devices = le_audio_service.getGroupDevices(groupId); + } + } + return devices; + } + /** * Handle messages from native (JNI) to Java * @@ -840,7 +1093,7 @@ public class HapClientService extends ProfileService { if (device != null) { mDeviceFeaturesMap.put(device, features); - notifyFeatures(device, features); + notifyFeaturesAvailable(device, features); } } return; @@ -850,36 +1103,25 @@ public class HapClientService extends ProfileService { if (device != null) { mDeviceCurrentPresetMap.put(device, currentPresetIndex); - notifyActivePresetIndex(device, currentPresetIndex); + notifyActivePresetChanged(device, currentPresetIndex); } else if (groupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) { - // TODO: Fix missing CSIS service API to decouple from LeAudioService - LeAudioService le_audio_service = mFactory.getLeAudioService(); - if (le_audio_service != null) { - int group_id = le_audio_service.getGroupId(device); - if (group_id != BluetoothLeAudio.GROUP_ID_INVALID) { - List<BluetoothDevice> all_group_devices = - le_audio_service.getGroupDevices(group_id); - for (BluetoothDevice dev : all_group_devices) { - mDeviceCurrentPresetMap.put(dev, currentPresetIndex); - } - } + List<BluetoothDevice> all_group_devices = getGroupDevices(groupId); + for (BluetoothDevice dev : all_group_devices) { + mDeviceCurrentPresetMap.put(dev, currentPresetIndex); } - notifyActivePresetIndex(groupId, currentPresetIndex); + notifyActivePresetChangedForGroup(groupId, currentPresetIndex); } } return; case (HapClientStackEvent.EVENT_TYPE_ON_ACTIVE_PRESET_SELECT_ERROR): { - int statusCode = stackEvent.valueInt1; int groupId = stackEvent.valueInt2; - - intent = new Intent(BluetoothHapClient.ACTION_HAP_ON_ACTIVE_PRESET_SELECT_ERROR); - intent.putExtra(BluetoothHapClient.EXTRA_HAP_STATUS_CODE, statusCode); + int statusCode = stackEvent.valueInt1; if (device != null) { - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); + notifySelectActivePresetFailed(device, statusCode); } else if (groupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) { - intent.putExtra(BluetoothHapClient.EXTRA_HAP_GROUP_ID, groupId); + notifySelectActivePresetForGroupFailed(groupId, statusCode); } } break; @@ -891,22 +1133,14 @@ public class HapClientService extends ProfileService { if (device != null) { updateDevicePresetsCache(device, infoReason, presets); - notifyPresets(device, infoReason, presets); + notifyPresetInfoChanged(device, infoReason); } else if (groupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) { - // TODO: Fix missing CSIS service API to decouple from LeAudioService - LeAudioService le_audio_service = mFactory.getLeAudioService(); - if (le_audio_service != null) { - int group_id = le_audio_service.getGroupId(device); - if (group_id != BluetoothLeAudio.GROUP_ID_INVALID) { - List<BluetoothDevice> all_group_devices = - le_audio_service.getGroupDevices(group_id); - for (BluetoothDevice dev : all_group_devices) { - updateDevicePresetsCache(dev, infoReason, presets); - } - } + List<BluetoothDevice> all_group_devices = getGroupDevices(groupId); + for (BluetoothDevice dev : all_group_devices) { + updateDevicePresetsCache(dev, infoReason, presets); } - notifyPresets(groupId, infoReason, presets); + notifyPresetInfoForGroupChanged(groupId, infoReason); } } return; @@ -914,33 +1148,18 @@ public class HapClientService extends ProfileService { case (HapClientStackEvent.EVENT_TYPE_ON_PRESET_NAME_SET_ERROR): { int statusCode = stackEvent.valueInt1; int presetIndex = stackEvent.valueInt2; - - intent = new Intent(BluetoothHapClient.ACTION_HAP_ON_PRESET_NAME_SET_ERROR); - intent.putExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INDEX, presetIndex); - intent.putExtra(BluetoothHapClient.EXTRA_HAP_STATUS_CODE, statusCode); + int groupId = stackEvent.valueInt3; if (device != null) { - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - } else { - int groupId = stackEvent.valueInt3; - intent.putExtra(BluetoothHapClient.EXTRA_HAP_GROUP_ID, groupId); + notifySetPresetNameFailed(device, statusCode); + } else if (groupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) { + notifySetPresetNameForGroupFailed(groupId, statusCode); } } break; case (HapClientStackEvent.EVENT_TYPE_ON_PRESET_INFO_ERROR): { - int statusCode = stackEvent.valueInt1; - int presetIndex = stackEvent.valueInt2; - - intent = new Intent(BluetoothHapClient.ACTION_HAP_ON_PRESET_INFO_GET_ERROR); - intent.putExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INDEX, presetIndex); - intent.putExtra(BluetoothHapClient.EXTRA_HAP_STATUS_CODE, statusCode); - - if (device != null) { - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - } else { - int groupId = stackEvent.valueInt3; - intent.putExtra(BluetoothHapClient.EXTRA_HAP_GROUP_ID, groupId); - } + // Used only to report back on hidden API calls used for testing. + Log.d(TAG, stackEvent.toString()); } break; default: @@ -1009,36 +1228,6 @@ public class HapClientService extends ProfileService { } @Override - public void connect(BluetoothDevice device, AttributionSource source, - SynchronousResultReceiver receiver) { - try { - boolean defaultValue = false; - HapClientService service = getService(source); - if (service != null) { - defaultValue = service.connect(device); - } - receiver.send(defaultValue); - } catch (RuntimeException e) { - receiver.propagateException(e); - } - } - - @Override - public void disconnect(BluetoothDevice device, AttributionSource source, - SynchronousResultReceiver receiver) { - try { - boolean defaultValue = false; - HapClientService service = getService(source); - if (service != null) { - defaultValue = service.disconnect(device); - } - receiver.send(defaultValue); - } catch (RuntimeException e) { - receiver.propagateException(e); - } - } - - @Override public void getConnectedDevices(AttributionSource source, SynchronousResultReceiver receiver) { try { @@ -1117,7 +1306,7 @@ public class HapClientService extends ProfileService { public void getActivePresetIndex(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver) { try { - boolean defaultValue = false; + int defaultValue = BluetoothHapClient.PRESET_INDEX_UNAVAILABLE; HapClientService service = getService(source); if (service != null) { defaultValue = service.getActivePresetIndex(device); @@ -1129,13 +1318,13 @@ public class HapClientService extends ProfileService { } @Override - public void getHapGroup(BluetoothDevice device, AttributionSource source, - SynchronousResultReceiver receiver) { + public void getActivePresetInfo(BluetoothDevice device, + AttributionSource source, SynchronousResultReceiver receiver) { try { - int defaultValue = BluetoothCsipSetCoordinator.GROUP_ID_INVALID; + BluetoothHapPresetInfo defaultValue = null; HapClientService service = getService(source); if (service != null) { - defaultValue = service.getHapGroup(device); + defaultValue = service.getActivePresetInfo(device); } receiver.send(defaultValue); } catch (RuntimeException e) { @@ -1144,13 +1333,13 @@ public class HapClientService extends ProfileService { } @Override - public void selectActivePreset(BluetoothDevice device, int presetIndex, - AttributionSource source, SynchronousResultReceiver receiver) { + public void getHapGroup(BluetoothDevice device, AttributionSource source, + SynchronousResultReceiver receiver) { try { - boolean defaultValue = false; + int defaultValue = BluetoothCsipSetCoordinator.GROUP_ID_INVALID; HapClientService service = getService(source); if (service != null) { - defaultValue = service.selectActivePreset(device, presetIndex); + defaultValue = service.getHapGroup(device); } receiver.send(defaultValue); } catch (RuntimeException e) { @@ -1159,76 +1348,51 @@ public class HapClientService extends ProfileService { } @Override - public void groupSelectActivePreset(int groupId, int presetIndex, - AttributionSource source, SynchronousResultReceiver receiver) { - try { - boolean defaultValue = false; - HapClientService service = getService(source); - if (service != null) { - defaultValue = service.groupSelectActivePreset(groupId, presetIndex); - } - receiver.send(defaultValue); - } catch (RuntimeException e) { - receiver.propagateException(e); + public void selectPreset(BluetoothDevice device, int presetIndex, + AttributionSource source) { + HapClientService service = getService(source); + if (service != null) { + service.selectPreset(device, presetIndex); } } @Override - public void nextActivePreset(BluetoothDevice device, AttributionSource source, - SynchronousResultReceiver receiver) { - try { - boolean defaultValue = false; - HapClientService service = getService(source); - if (service != null) { - defaultValue = service.nextActivePreset(device); - } - receiver.send(defaultValue); - } catch (RuntimeException e) { - receiver.propagateException(e); + public void selectPresetForGroup(int groupId, int presetIndex, AttributionSource source) { + HapClientService service = getService(source); + if (service != null) { + service.selectPresetForGroup(groupId, presetIndex); } } @Override - public void groupNextActivePreset(int groupId, AttributionSource source, - SynchronousResultReceiver receiver) { - try { - boolean defaultValue = false; - HapClientService service = getService(source); - if (service != null) { - defaultValue = service.groupNextActivePreset(groupId); - } - receiver.send(defaultValue); - } catch (RuntimeException e) { - receiver.propagateException(e); + public void switchToNextPreset(BluetoothDevice device, AttributionSource source) { + HapClientService service = getService(source); + if (service != null) { + service.switchToNextPreset(device); } } @Override - public void previousActivePreset(BluetoothDevice device, AttributionSource source, - SynchronousResultReceiver receiver) { - try { - boolean defaultValue = false; - HapClientService service = getService(source); - if (service != null) { - defaultValue = service.previousActivePreset(device); - } - receiver.send(defaultValue); - } catch (RuntimeException e) { - receiver.propagateException(e); + public void switchToNextPresetForGroup(int groupId, AttributionSource source) { + HapClientService service = getService(source); + if (service != null) { + service.switchToNextPresetForGroup(groupId); } } @Override - public void groupPreviousActivePreset(int groupId, AttributionSource source, SynchronousResultReceiver receiver) { - try { - boolean defaultValue = false; - HapClientService service = getService(source); - if (service != null) { - defaultValue = service.groupPreviousActivePreset(groupId); - } - receiver.send(defaultValue); - } catch (RuntimeException e) { - receiver.propagateException(e); + public void switchToPreviousPreset(BluetoothDevice device, AttributionSource source) { + HapClientService service = getService(source); + if (service != null) { + service.switchToPreviousPreset(device); + } + } + + @Override + public void switchToPreviousPresetForGroup(int groupId, AttributionSource source) { + HapClientService service = getService(source); + if (service != null) { + service.switchToPreviousPresetForGroup(groupId); } } @@ -1236,7 +1400,7 @@ public class HapClientService extends ProfileService { public void getPresetInfo(BluetoothDevice device, int presetIndex, AttributionSource source, SynchronousResultReceiver receiver) { try { - boolean defaultValue = false; + BluetoothHapPresetInfo defaultValue = new BluetoothHapPresetInfo.Builder().build(); HapClientService service = getService(source); if (service != null) { defaultValue = service.getPresetInfo(device, presetIndex); @@ -1248,12 +1412,13 @@ public class HapClientService extends ProfileService { } @Override - public void getAllPresetsInfo(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver) { + public void getAllPresetInfo(BluetoothDevice device, AttributionSource source, + SynchronousResultReceiver receiver) { try { - boolean defaultValue = false; + List<BluetoothHapPresetInfo> defaultValue = new ArrayList<>(); HapClientService service = getService(source); if (service != null) { - defaultValue = service.getAllPresetsInfo(device); + defaultValue = service.getAllPresetInfo(device); } receiver.send(defaultValue); } catch (RuntimeException e) { @@ -1262,9 +1427,10 @@ public class HapClientService extends ProfileService { } @Override - public void getFeatures(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver) { + public void getFeatures(BluetoothDevice device, AttributionSource source, + SynchronousResultReceiver receiver) { try { - boolean defaultValue = false; + int defaultValue = 0x00; HapClientService service = getService(source); if (service != null) { defaultValue = service.getFeatures(device); @@ -1277,29 +1443,51 @@ public class HapClientService extends ProfileService { @Override public void setPresetName(BluetoothDevice device, int presetIndex, String name, + AttributionSource source) { + HapClientService service = getService(source); + if (service != null) { + service.setPresetName(device, presetIndex, name); + } + } + + @Override + public void setPresetNameForGroup(int groupId, int presetIndex, String name, + AttributionSource source) { + HapClientService service = getService(source); + if (service != null) { + service.setPresetNameForGroup(groupId, presetIndex, name); + } + } + + @Override + public void registerCallback(IBluetoothHapClientCallback callback, AttributionSource source, SynchronousResultReceiver receiver) { + HapClientService service = getService(source); + if (service == null) { + throw new IllegalStateException("Service is unavailable"); + } + + enforceBluetoothPrivilegedPermission(service); try { - boolean defaultValue = false; - HapClientService service = getService(source); - if (service != null) { - defaultValue = service.setPresetName(device, presetIndex, name); - } - receiver.send(defaultValue); + service.mCallbacks.register(callback); + receiver.send(null); } catch (RuntimeException e) { receiver.propagateException(e); } } @Override - public void groupSetPresetName(int groupId, int presetIndex, String name, + public void unregisterCallback(IBluetoothHapClientCallback callback, AttributionSource source, SynchronousResultReceiver receiver) { + HapClientService service = getService(source); + if (service == null) { + throw new IllegalStateException("Service is unavailable"); + } + + enforceBluetoothPrivilegedPermission(service); try { - boolean defaultValue = false; - HapClientService service = getService(source); - if (service != null) { - defaultValue = service.groupSetPresetName(groupId, presetIndex, name); - } - receiver.send(defaultValue); + service.mCallbacks.unregister(callback); + receiver.send(null); } catch (RuntimeException e) { receiver.propagateException(e); } diff --git a/android/app/src/com/android/bluetooth/hap/HapClientStackEvent.java b/android/app/src/com/android/bluetooth/hap/HapClientStackEvent.java index 278bb1a06f..e322f505f0 100644 --- a/android/app/src/com/android/bluetooth/hap/HapClientStackEvent.java +++ b/android/app/src/com/android/bluetooth/hap/HapClientStackEvent.java @@ -47,20 +47,15 @@ public class HapClientStackEvent { static final int CONNECTION_STATE_DISCONNECTING = 3; // Possible operation results - static final int STATUS_SET_NAME_NOT_ALLOWED = - IBluetoothHapClient.STATUS_SET_NAME_NOT_ALLOWED; - static final int STATUS_OPERATION_NOT_SUPPORTED = - IBluetoothHapClient.STATUS_OPERATION_NOT_SUPPORTED; - static final int STATUS_OPERATION_NOT_POSSIBLE = - IBluetoothHapClient.STATUS_OPERATION_NOT_POSSIBLE; - static final int STATUS_INVALID_PRESET_NAME_LENGTH = - IBluetoothHapClient.STATUS_INVALID_PRESET_NAME_LENGTH; - static final int STATUS_INVALID_PRESET_INDEX = - IBluetoothHapClient.STATUS_INVALID_PRESET_INDEX; - static final int STATUS_GROUP_OPERATION_NOT_SUPPORTED = - IBluetoothHapClient.STATUS_GROUP_OPERATION_NOT_SUPPORTED; - static final int STATUS_PROCEDURE_ALREADY_IN_PROGRESS = - IBluetoothHapClient.STATUS_PROCEDURE_ALREADY_IN_PROGRESS; + /* WARNING: Matches status codes defined in bta_has.h */ + static final int STATUS_NO_ERROR = 0; + static final int STATUS_SET_NAME_NOT_ALLOWED = 1; + static final int STATUS_OPERATION_NOT_SUPPORTED = 2; + static final int STATUS_OPERATION_NOT_POSSIBLE = 3; + static final int STATUS_INVALID_PRESET_NAME_LENGTH = 4; + static final int STATUS_INVALID_PRESET_INDEX = 5; + static final int STATUS_GROUP_OPERATION_NOT_SUPPORTED = 6; + static final int STATUS_PROCEDURE_ALREADY_IN_PROGRESS = 7; // Supported features public static final int FEATURE_BIT_NUM_TYPE_MONAURAL = @@ -77,16 +72,12 @@ public class HapClientStackEvent { IBluetoothHapClient.FEATURE_BIT_NUM_WRITABLE_PRESETS; // Preset Info notification reason - public static final int PRESET_INFO_REASON_ALL_PRESET_INFO = - IBluetoothHapClient.PRESET_INFO_REASON_ALL_PRESET_INFO; - public static final int PRESET_INFO_REASON_PRESET_INFO_UPDATE = - IBluetoothHapClient.PRESET_INFO_REASON_PRESET_INFO_UPDATE; - public static final int PRESET_INFO_REASON_PRESET_DELETED = - IBluetoothHapClient.PRESET_INFO_REASON_PRESET_DELETED; - public static final int PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED = - IBluetoothHapClient.PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED; - public static final int PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE = - IBluetoothHapClient.PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE; + /* WARNING: Matches status codes defined in bta_has.h */ + public static final int PRESET_INFO_REASON_ALL_PRESET_INFO = 0; + public static final int PRESET_INFO_REASON_PRESET_INFO_UPDATE = 1; + public static final int PRESET_INFO_REASON_PRESET_DELETED = 2; + public static final int PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED = 3; + public static final int PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE = 4; public int type; public BluetoothDevice device; @@ -207,6 +198,8 @@ public class HapClientStackEvent { private String statusCodeValueToString(int value) { switch (value) { + case STATUS_NO_ERROR: + return "STATUS_NO_ERROR"; case STATUS_SET_NAME_NOT_ALLOWED: return "STATUS_SET_NAME_NOT_ALLOWED"; case STATUS_OPERATION_NOT_SUPPORTED: @@ -222,7 +215,7 @@ public class HapClientStackEvent { case STATUS_PROCEDURE_ALREADY_IN_PROGRESS: return "STATUS_PROCEDURE_ALREADY_IN_PROGRESS"; default: - return "UNKNOWN_STATUS_CODE"; + return "ERROR_UNKNOWN"; } } diff --git a/android/app/src/com/android/bluetooth/hap/HapClientStateMachine.java b/android/app/src/com/android/bluetooth/hap/HapClientStateMachine.java index 7f10decb19..62c9dd2d14 100644 --- a/android/app/src/com/android/bluetooth/hap/HapClientStateMachine.java +++ b/android/app/src/com/android/bluetooth/hap/HapClientStateMachine.java @@ -238,7 +238,7 @@ final class HapClientStateMachine extends StateMachine { @Override public boolean processMessage(Message message) { - log("Disconnected process message(" + mDevice + "): " + messageWhatToString( + log("Disconnected: process message(" + mDevice + "): " + messageWhatToString( message.what)); switch (message.what) { @@ -343,7 +343,7 @@ final class HapClientStateMachine extends StateMachine { @Override public boolean processMessage(Message message) { - log("Connecting process message(" + mDevice + "): " + log("Connecting: process message(" + mDevice + "): " + messageWhatToString(message.what)); switch (message.what) { @@ -430,7 +430,7 @@ final class HapClientStateMachine extends StateMachine { @Override public boolean processMessage(Message message) { - log("Disconnecting process message(" + mDevice + "): " + log("Disconnecting: process message(" + mDevice + "): " + messageWhatToString(message.what)); switch (message.what) { @@ -530,7 +530,7 @@ final class HapClientStateMachine extends StateMachine { @Override public boolean processMessage(Message message) { - log("Connected process message(" + mDevice + "): " + log("Connected: process message(" + mDevice + "): " + messageWhatToString(message.what)); switch (message.what) { diff --git a/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java b/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java index 4f4a45ad6b..8d4b6d32c9 100644 --- a/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java +++ b/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java @@ -61,6 +61,9 @@ public class HearingAidService extends ProfileService { private static final boolean DBG = true; private static final String TAG = "HearingAidService"; + // Timeout for state machine thread join, to prevent potential ANR. + private static final int SM_THREAD_JOIN_TIMEOUT_MS = 1000; + // Upper limit of all HearingAid devices: Bonded or Connected private static final int MAX_HEARING_AID_STATE_MACHINES = 10; private static HearingAidService sHearingAidService; @@ -189,8 +192,13 @@ public class HearingAidService extends ProfileService { mHiSyncIdConnectedMap.clear(); if (mStateMachinesThread != null) { - mStateMachinesThread.quitSafely(); - mStateMachinesThread = null; + try { + mStateMachinesThread.quitSafely(); + mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS); + mStateMachinesThread = null; + } catch (InterruptedException e) { + // Do not rethrow as we are shutting down anyway + } } // Clear AdapterService, HearingAidNativeInterface @@ -531,7 +539,10 @@ public class HearingAidService extends ProfileService { .getProfileConnectionPolicy(device, BluetoothProfile.HEARING_AID); } + @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) void setVolume(int volume) { + enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, + "Need BLUETOOTH_PRIVILEGED permission"); mHearingAidNativeInterface.setVolume(volume); } diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java index a1af96c9c8..01702c9ea4 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java @@ -100,6 +100,9 @@ public class HeadsetService extends ProfileService { {BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_CONNECTED}; private static final int DIALING_OUT_TIMEOUT_MS = 10000; + // Timeout for state machine thread join, to prevent potential ANR. + private static final int SM_THREAD_JOIN_TIMEOUT_MS = 1000; + private int mMaxHeadsetConnections = 1; private BluetoothDevice mActiveDevice; private AdapterService mAdapterService; @@ -237,8 +240,14 @@ public class HeadsetService extends ProfileService { // Step 3: Destroy system interface mSystemInterface.stop(); // Step 2: Stop handler thread - mStateMachinesThread.quitSafely(); - mStateMachinesThread = null; + try { + mStateMachinesThread.quitSafely(); + mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS); + mStateMachinesThread = null; + } catch (InterruptedException e) { + // Do not rethrow as we are shutting down anyway + } + mStateMachinesThreadHandler = null; // Step 1: Clear synchronized (mStateMachines) { diff --git a/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java b/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java index 7b63700f47..4026b3913b 100644 --- a/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java +++ b/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java @@ -39,6 +39,7 @@ import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadsetClient; +import android.bluetooth.BluetoothHeadsetClient.NetworkServiceState; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothUuid; import android.bluetooth.hfp.BluetoothHfpProtoEnums; @@ -359,6 +360,27 @@ public class HeadsetClientStateMachine extends StateMachine { HfpClientConnectionService.onCallChanged(c.getDevice(), c); } + private void sendNetworkStateChangedIntent(BluetoothDevice device) { + if (device == null) { + return; + } + NetworkServiceState networkServiceState = new NetworkServiceState( + device, + mIndicatorNetworkState == HeadsetClientHalConstants.NETWORK_STATE_AVAILABLE, + mOperatorName, + mIndicatorNetworkSignal, + mIndicatorNetworkType == HeadsetClientHalConstants.SERVICE_TYPE_ROAMING); + + Intent intent = + new Intent(BluetoothHeadsetClient.ACTION_NETWORK_SERVICE_STATE_CHANGED); + intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); + intent.putExtra(BluetoothHeadsetClient.EXTRA_NETWORK_SERVICE_STATE, networkServiceState); + + mService.sendBroadcastMultiplePermissions(intent, + new String[] {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}, + Utils.getTempBroadcastOptions()); + } + private boolean queryCallsStart() { logD("queryCallsStart"); clearPendingAction(); @@ -1429,6 +1451,7 @@ public class HeadsetClientStateMachine extends StateMachine { intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device); mService.sendBroadcast(intent, BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions()); + sendNetworkStateChangedIntent(event.device); if (mIndicatorNetworkState == HeadsetClientHalConstants.NETWORK_STATE_AVAILABLE) { @@ -1448,6 +1471,7 @@ public class HeadsetClientStateMachine extends StateMachine { intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device); mService.sendBroadcast(intent, BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions()); + sendNetworkStateChangedIntent(event.device); break; case StackEvent.EVENT_TYPE_NETWORK_SIGNAL: mIndicatorNetworkSignal = event.valueInt; @@ -1458,6 +1482,7 @@ public class HeadsetClientStateMachine extends StateMachine { intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device); mService.sendBroadcast(intent, BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions()); + sendNetworkStateChangedIntent(event.device); break; case StackEvent.EVENT_TYPE_BATTERY_LEVEL: mIndicatorBatteryLevel = event.valueInt; @@ -1478,6 +1503,7 @@ public class HeadsetClientStateMachine extends StateMachine { intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device); mService.sendBroadcast(intent, BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions()); + sendNetworkStateChangedIntent(event.device); break; case StackEvent.EVENT_TYPE_VR_STATE_CHANGED: int oldState = mVoiceRecognitionActive; 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 a94a5687c1..6ac0a88ea8 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -66,6 +66,9 @@ public class LeAudioService extends ProfileService { private static final boolean DBG = true; private static final String TAG = "LeAudioService"; + // Timeout for state machine thread join, to prevent potential ANR. + private static final int SM_THREAD_JOIN_TIMEOUT_MS = 1000; + // Upper limit of all LeAudio devices: Bonded or Connected private static final int MAX_LE_AUDIO_STATE_MACHINES = 10; private static LeAudioService sLeAudioService; @@ -260,8 +263,13 @@ public class LeAudioService extends ProfileService { } if (mStateMachinesThread != null) { - mStateMachinesThread.quitSafely(); - mStateMachinesThread = null; + try { + mStateMachinesThread.quitSafely(); + mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS); + mStateMachinesThread = null; + } catch (InterruptedException e) { + // Do not rethrow as we are shutting down anyway + } } mAudioManager = null; @@ -650,6 +658,14 @@ public class LeAudioService extends ProfileService { boolean newSupportedByDeviceInput = (newSupportedAudioDirections & AUDIO_DIRECTION_INPUT_BIT) != 0; + /* + * Do not update input if neither previous nor current device support input + */ + if (!oldSupportedByDeviceInput && !newSupportedByDeviceInput) { + Log.d(TAG, "updateActiveInDevice: Device does not support input."); + return false; + } + if (device != null && mActiveAudioInDevice != null) { int previousGroupId = getGroupId(mActiveAudioInDevice); if (previousGroupId == groupId) { @@ -660,20 +676,16 @@ public class LeAudioService extends ProfileService { if (mActiveAudioInDevice.isConnected()) { device = mActiveAudioInDevice; } + } else { + /* Mark old group as no active */ + LeAudioGroupDescriptor descriptor = mGroupDescriptors.get(previousGroupId); + descriptor.mIsActive = false; } } BluetoothDevice previousInDevice = mActiveAudioInDevice; /* - * Do not update input if neither previous nor current device support input - */ - if (!oldSupportedByDeviceInput && !newSupportedByDeviceInput) { - Log.d(TAG, "updateActiveInDevice: Device does not support input."); - return false; - } - - /* * Update input if: * - Device changed * OR @@ -709,6 +721,14 @@ public class LeAudioService extends ProfileService { boolean newSupportedByDeviceOutput = (newSupportedAudioDirections & AUDIO_DIRECTION_OUTPUT_BIT) != 0; + /* + * Do not update output if neither previous nor current device support output + */ + if (!oldSupportedByDeviceOutput && !newSupportedByDeviceOutput) { + Log.d(TAG, "updateActiveOutDevice: Device does not support output."); + return false; + } + if (device != null && mActiveAudioOutDevice != null) { int previousGroupId = getGroupId(mActiveAudioOutDevice); if (previousGroupId == groupId) { @@ -719,20 +739,17 @@ public class LeAudioService extends ProfileService { if (mActiveAudioOutDevice.isConnected()) { device = mActiveAudioOutDevice; } + } else { + Log.i(TAG, " Switching active group from " + previousGroupId + " to " + groupId); + /* Mark old group as no active */ + LeAudioGroupDescriptor descriptor = mGroupDescriptors.get(previousGroupId); + descriptor.mIsActive = false; } } BluetoothDevice previousOutDevice = mActiveAudioOutDevice; /* - * Do not update output if neither previous nor current device support output - */ - if (!oldSupportedByDeviceOutput && !newSupportedByDeviceOutput) { - Log.d(TAG, "updateActiveOutDevice: Device does not support output."); - return false; - } - - /* * Update output if: * - Device changed * OR @@ -762,14 +779,16 @@ public class LeAudioService extends ProfileService { * Report the active devices change to the active device manager and the media framework. * @param groupId id of group which devices should be updated * @param newActiveContexts new active contexts for group of devices + * @param oldActiveContexts old active contexts for group of devices + * @param isActive if there is new active group */ private void updateActiveDevices(Integer groupId, Integer oldActiveContexts, Integer newActiveContexts, boolean isActive) { - BluetoothDevice device = null; - if (isActive) + if (isActive) { device = getFirstDeviceFromGroup(groupId); + } boolean outReplaced = updateActiveOutDevice(device, groupId, oldActiveContexts, newActiveContexts); diff --git a/android/app/src/com/android/bluetooth/mcp/McpService.java b/android/app/src/com/android/bluetooth/mcp/McpService.java index 1da7da7858..2508b2f38f 100644 --- a/android/app/src/com/android/bluetooth/mcp/McpService.java +++ b/android/app/src/com/android/bluetooth/mcp/McpService.java @@ -26,6 +26,7 @@ import android.util.Log; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.ProfileService; +import com.android.internal.annotations.VisibleForTesting; import java.util.HashMap; import java.util.Map; @@ -41,7 +42,7 @@ public class McpService extends ProfileService { private static McpService sMcpService; - private static MediaControlProfile mGmcs; + private static MediaControlProfile sGmcs; private Map<BluetoothDevice, Integer> mDeviceAuthorizations = new HashMap<>(); private Handler mHandler = new Handler(Looper.getMainLooper()); @@ -65,8 +66,13 @@ public class McpService extends ProfileService { return sMcpService; } + @VisibleForTesting + public static MediaControlProfile getMediaControlProfile() { + return sGmcs; + } + public static void setMediaControlProfileForTesting(MediaControlProfile mediaControlProfile) { - mGmcs = mediaControlProfile; + sGmcs = mediaControlProfile; } @Override @@ -94,11 +100,11 @@ public class McpService extends ProfileService { // Mark service as started setMcpService(this); - if (mGmcs == null) { + if (sGmcs == null) { // Initialize the Media Control Service Server - mGmcs = new MediaControlProfile(this); + sGmcs = new MediaControlProfile(this); // Requires this service to be already started thus we have to make it an async call - mHandler.post(() -> mGmcs.init()); + mHandler.post(() -> sGmcs.init()); } return true; @@ -115,8 +121,9 @@ public class McpService extends ProfileService { return true; } - if (mGmcs != null) { - mGmcs.cleanup(); + if (sGmcs != null) { + sGmcs.cleanup(); + sGmcs = null; } // Mark service as stopped @@ -141,7 +148,7 @@ public class McpService extends ProfileService { : BluetoothDevice.ACCESS_REJECTED; mDeviceAuthorizations.put(device, authorization); - mGmcs.onDeviceAuthorizationSet(device); + sGmcs.onDeviceAuthorizationSet(device); } public int getDeviceAuthorization(BluetoothDevice device) { @@ -192,6 +199,6 @@ public class McpService extends ProfileService { @Override public void dump(StringBuilder sb) { super.dump(sb); - mGmcs.dump(sb); + sGmcs.dump(sb); } } diff --git a/android/app/src/com/android/bluetooth/sap/SapServer.java b/android/app/src/com/android/bluetooth/sap/SapServer.java index c838fa37dc..2514863434 100644 --- a/android/app/src/com/android/bluetooth/sap/SapServer.java +++ b/android/app/src/com/android/bluetooth/sap/SapServer.java @@ -93,6 +93,9 @@ public class SapServer extends Thread implements Callback { private PendingIntent mPendingDiscIntent = null; // Holds a reference to disconnect timeout intents + /* Timeout for the message handler thread join, to prevent potential ANR. */ + private static final int HANDLER_THREAD_JOIN_TIMEOUT_MS = 1000; + /* We store the mMaxMessageSize, as we need a copy of it when the init. sequence completes */ private int mMaxMsgSize = 0; /* keep track of the current RIL test mode */ @@ -498,7 +501,7 @@ public class SapServer extends Thread implements Callback { if (mHandlerThread != null) { try { mHandlerThread.quitSafely(); - mHandlerThread.join(); + mHandlerThread.join(HANDLER_THREAD_JOIN_TIMEOUT_MS); mHandlerThread = null; } catch (InterruptedException e) { } diff --git a/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java b/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java index a590a51916..cc974cf5f8 100644 --- a/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java +++ b/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java @@ -18,15 +18,14 @@ package com.android.bluetooth.tbs; import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCharacteristic; -import android.bluetooth.BluetoothGattDescriptor; -import android.bluetooth.BluetoothGattServerCallback; -import android.bluetooth.BluetoothGattService; -import android.bluetooth.BluetoothLeCallControl; import android.bluetooth.BluetoothLeCall; +import android.bluetooth.BluetoothLeCallControl; import android.bluetooth.IBluetoothLeCallControlCallback; +import android.content.BroadcastReceiver; +import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; +import android.media.AudioManager; import android.net.Uri; import android.os.ParcelUuid; import android.os.RemoteException; @@ -115,6 +114,28 @@ public class TbsGeneric { private Bearer mForegroundBearer = null; private int mLastRequestIdAssigned = 0; private List<String> mUriSchemes = new ArrayList<>(Arrays.asList("tel")); + private Receiver mReceiver = null; + private int mStoredRingerMode = -1; + + private final class Receiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { + int ringerMode = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1); + + if (ringerMode < 0 || ringerMode == mStoredRingerMode) return; + + mStoredRingerMode = ringerMode; + + if (isSilentModeEnabled()) { + mTbsGatt.setSilentModeFlag(); + } else { + mTbsGatt.clearSilentModeFlag(); + } + } + } + }; public boolean init(TbsGatt tbsGatt) { if (DBG) { @@ -128,8 +149,32 @@ public class TbsGeneric { return false; } - return mTbsGatt.init(ccid, UCI, mUriSchemes, true, true, DEFAULT_PROVIDER_NAME, - DEFAULT_BEARER_TECHNOLOGY, mTbsGattCallback); + if (!mTbsGatt.init(ccid, UCI, mUriSchemes, true, true, DEFAULT_PROVIDER_NAME, + DEFAULT_BEARER_TECHNOLOGY, mTbsGattCallback)) { + Log.e(TAG, " TbsGatt init failed"); + return false; + } + + AudioManager mAudioManager = mTbsGatt.getContext() + .getSystemService(AudioManager.class); + if (mAudioManager == null) { + Log.w(TAG, " AudioManager is not available"); + return true; + } + + // read initial value of ringer mode + mStoredRingerMode = mAudioManager.getRingerMode(); + + if (isSilentModeEnabled()) { + mTbsGatt.setSilentModeFlag(); + } else { + mTbsGatt.clearSilentModeFlag(); + } + + mReceiver = new Receiver(); + mTbsGatt.getContext().registerReceiver(mReceiver, + new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION)); + return true; } public void cleanup() { @@ -138,11 +183,18 @@ public class TbsGeneric { } if (mTbsGatt != null) { + if (mReceiver != null) { + mTbsGatt.getContext().unregisterReceiver(mReceiver); + } mTbsGatt.cleanup(); mTbsGatt = null; } } + private boolean isSilentModeEnabled() { + return mStoredRingerMode != AudioManager.RINGER_MODE_NORMAL; + } + private Bearer getBearerByToken(String token) { synchronized (mBearerList) { for (Bearer bearer : mBearerList) { diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java index ee6fd37b26..0d2b0ec0af 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java @@ -154,7 +154,8 @@ public class VolumeControlNativeInterface { sendMessageToService(event); } - private void onVolumeStateChanged(int volume, boolean mute, byte[] address) { + private void onVolumeStateChanged(int volume, boolean mute, byte[] address, + boolean isAutonomous) { VolumeControlStackEvent event = new VolumeControlStackEvent( VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED); @@ -162,6 +163,7 @@ public class VolumeControlNativeInterface { event.valueInt1 = -1; event.valueInt2 = volume; event.valueBool1 = mute; + event.valueBool2 = isAutonomous; if (DBG) { Log.d(TAG, "onVolumeStateChanged: " + event); @@ -169,7 +171,8 @@ public class VolumeControlNativeInterface { sendMessageToService(event); } - private void onGroupVolumeStateChanged(int volume, boolean mute, int groupId) { + private void onGroupVolumeStateChanged(int volume, boolean mute, int groupId, + boolean isAutonomous) { VolumeControlStackEvent event = new VolumeControlStackEvent( VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED); @@ -177,6 +180,7 @@ public class VolumeControlNativeInterface { event.valueInt1 = groupId; event.valueInt2 = volume; event.valueBool1 = mute; + event.valueBool2 = isAutonomous; if (DBG) { Log.d(TAG, "onGroupVolumeStateChanged: " + event); diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index d15a956211..f6a8e037dc 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -32,6 +32,8 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.media.AudioDeviceAttributes; +import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.os.HandlerThread; import android.os.ParcelUuid; @@ -54,14 +56,25 @@ public class VolumeControlService extends ProfileService { private static final boolean DBG = false; private static final String TAG = "VolumeControlService"; + // Timeout for state machine thread join, to prevent potential ANR. + private static final int SM_THREAD_JOIN_TIMEOUT_MS = 1000; + // Upper limit of all VolumeControl devices: Bonded or Connected private static final int MAX_VC_STATE_MACHINES = 10; + private static final int LE_AUDIO_MAX_VOL = 255; + private static final int LE_AUDIO_MIN_VOL = 0; + private static VolumeControlService sVolumeControlService; private AdapterService mAdapterService; private HandlerThread mStateMachinesThread; private BluetoothDevice mPreviousAudioDevice; + private int mMusicMaxVolume = 0; + private int mMusicMinVolume = 0; + private int mVoiceCallMaxVolume = 0; + private int mVoiceCallMinVolume = 0; + @VisibleForTesting VolumeControlNativeInterface mVolumeControlNativeInterface; @VisibleForTesting @@ -106,6 +119,11 @@ public class VolumeControlService extends ProfileService { Objects.requireNonNull(mAudioManager, "AudioManager cannot be null when VolumeControlService starts"); + mMusicMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + mMusicMinVolume = mAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC); + mVoiceCallMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL); + mVoiceCallMinVolume = mAudioManager.getStreamMinVolume(AudioManager.STREAM_VOICE_CALL); + // Start handler thread for state machines mStateMachines.clear(); mStateMachinesThread = new HandlerThread("VolumeControlService.StateMachines"); @@ -164,8 +182,13 @@ public class VolumeControlService extends ProfileService { if (mStateMachinesThread != null) { - mStateMachinesThread.quitSafely(); - mStateMachinesThread = null; + try { + mStateMachinesThread.quitSafely(); + mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS); + mStateMachinesThread = null; + } catch (InterruptedException e) { + // Do not rethrow as we are shutting down anyway + } } // Clear AdapterService, VolumeControlNativeInterface @@ -422,18 +445,51 @@ public class VolumeControlService extends ProfileService { } void handleVolumeControlChanged(BluetoothDevice device, int groupId, - int volume, boolean mute) { - /* TODO handle volume change for group in case of unicast le audio - * or per device in case of broadcast or simple remote controller. - * Note: minimum volume is 0 and maximum 255. - */ + int volume, boolean mute, boolean isAutonomous) { + if (!isAutonomous) { + // If the change is triggered by Android device, the stream is already changed. + return; + } + // TODO: Handle the other arguments: device, groupId, mute. + + int streamType = getBluetoothContextualVolumeStream(); + mAudioManager.setStreamVolume(streamType, getDeviceVolume(streamType, volume), + AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_BLUETOOTH_ABS_VOLUME); + } + + int getDeviceVolume(int streamType, int bleVolume) { + int bleMaxVolume = 255; // min volume is zero + int deviceMaxVolume = (streamType == AudioManager.STREAM_VOICE_CALL) + ? mVoiceCallMaxVolume : mMusicMaxVolume; + int deviceMinVolume = (streamType == AudioManager.STREAM_VOICE_CALL) + ? mVoiceCallMinVolume : mMusicMinVolume; + + // TODO: Investigate what happens in classic BT when BT volume is changed to zero. + return (int) Math.floor( + (double) bleVolume * (deviceMaxVolume - deviceMinVolume) / bleMaxVolume); + } + + // Copied from AudioService.getBluetoothContextualVolumeStream() and modified it. + int getBluetoothContextualVolumeStream() { + int mode = mAudioManager.getMode(); + switch (mode) { + case AudioManager.MODE_IN_COMMUNICATION: + case AudioManager.MODE_IN_CALL: + return AudioManager.STREAM_VOICE_CALL; + case AudioManager.MODE_NORMAL: + default: + // other conditions will influence the stream type choice, read on... + break; + } + return AudioManager.STREAM_MUSIC; } void messageFromNative(VolumeControlStackEvent stackEvent) { if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED) { handleVolumeControlChanged(stackEvent.device, stackEvent.valueInt1, - stackEvent.valueInt2, stackEvent.valueBool1); + stackEvent.valueInt2, stackEvent.valueBool1, + stackEvent.valueBool2); return; } @@ -495,6 +551,14 @@ public class VolumeControlService extends ProfileService { sm = VolumeControlStateMachine.make(device, this, mVolumeControlNativeInterface, mStateMachinesThread.getLooper()); mStateMachines.put(device, sm); + + mAudioManager.setDeviceVolumeBehavior( + new AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, + // Currently, TYPE_BLUETOOTH_A2DP is the only thing that works. + AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, + ""), + AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE); return sm; } } diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java index c5d4aa336b..2750c7e694 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java @@ -37,6 +37,7 @@ public class VolumeControlStackEvent { public int valueInt1; public int valueInt2; public boolean valueBool1; + public boolean valueBool2; /* Might need more for other callbacks*/ VolumeControlStackEvent(int type) { @@ -52,6 +53,7 @@ public class VolumeControlStackEvent { result.append(", valueInt1:" + eventTypeValue1ToString(type, valueInt1)); result.append(", valueInt2:" + eventTypeValue2ToString(type, valueInt2)); result.append(", valueBool1:" + eventTypeValueBool1ToString(type, valueBool1)); + result.append(", valueBool2:" + eventTypeValueBool2ToString(type, valueBool2)); result.append("}"); return result.toString(); } @@ -124,4 +126,14 @@ public class VolumeControlStackEvent { } return Boolean.toString(value); } + + private static String eventTypeValueBool2ToString(int type, boolean value) { + switch (type) { + case EVENT_TYPE_VOLUME_STATE_CHANGED: + return "{isAutonomous:" + value + "}"; + default: + break; + } + return Boolean.toString(value); + } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java index b38c8423c2..1a78d7c67c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java @@ -122,6 +122,7 @@ public class A2dpStateMachineTest { } mA2dpStateMachine.doQuit(); mHandlerThread.quit(); + mHandlerThread.join(TIMEOUT_MS); TestUtils.clearAdapterService(mAdapterService); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java index db3ae79763..42e93e5bd8 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java @@ -8,6 +8,7 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAssignedNumbers; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; +import android.bluetooth.BluetoothHeadsetClient; import android.bluetooth.BluetoothProfile; import android.content.Intent; import android.os.Bundle; @@ -437,6 +438,85 @@ public class RemoteDevicesTest { new Object[]{1, "WRONG", "WRONG"})); } + @Test + public void testResetBatteryLevelOnHeadsetClientStateChange() { + int batteryLevel = 10; + + // Verify that device property is null initially + Assert.assertNull(mRemoteDevices.getDeviceProperties(mDevice1)); + + // Verify that updating battery level triggers ACTION_BATTERY_LEVEL_CHANGED intent + mRemoteDevices.updateBatteryLevel(mDevice1, batteryLevel); + verify(mAdapterService).sendBroadcast(mIntentArgument.capture(), mStringArgument.capture(), + any(Bundle.class)); + verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument); + Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + + // Verify that user can get battery level after the update + Assert.assertNotNull(mRemoteDevices.getDeviceProperties(mDevice1)); + Assert.assertEquals(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel(), + batteryLevel); + + // Verify that resetting battery level changes it back to BluetoothDevice + // .BATTERY_LEVEL_UNKNOWN + mRemoteDevices.onHeadsetClientConnectionStateChanged( + getHeadsetClientConnectionStateChangedIntent(mDevice1, + BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_DISCONNECTED)); + + // Verify BATTERY_LEVEL_CHANGED intent is sent after first reset + verify(mAdapterService, times(2)).sendBroadcast(mIntentArgument.capture(), + mStringArgument.capture(), any(Bundle.class)); + verifyBatteryLevelChangedIntent(mDevice1, BluetoothDevice.BATTERY_LEVEL_UNKNOWN, + mIntentArgument); + Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + + // Verify value is reset in properties + Assert.assertNotNull(mRemoteDevices.getDeviceProperties(mDevice1)); + Assert.assertEquals(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel(), + BluetoothDevice.BATTERY_LEVEL_UNKNOWN); + + // Verify that updating battery level triggers ACTION_BATTERY_LEVEL_CHANGED intent again + mRemoteDevices.updateBatteryLevel(mDevice1, batteryLevel); + verify(mAdapterService, times(3)).sendBroadcast(mIntentArgument.capture(), + mStringArgument.capture(), any(Bundle.class)); + verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument); + Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + + verifyNoMoreInteractions(mAdapterService); + } + + @Test + public void testAGIndicatorParser_testCorrectValue() { + int batteryLevel = 3; + + // Verify that device property is null initially + Assert.assertNull(mRemoteDevices.getDeviceProperties(mDevice1)); + + // Verify that ACTION_AG_EVENT intent updates battery level + mRemoteDevices.onAgIndicatorValueChanged( + getAgIndicatorIntent(mDevice1, null, null, null, new Integer(batteryLevel), null)); + verify(mAdapterService).sendBroadcast(mIntentArgument.capture(), mStringArgument.capture(), + any(Bundle.class)); + verifyBatteryLevelChangedIntent(mDevice1, + RemoteDevices.batteryChargeIndicatorToPercentge(batteryLevel), mIntentArgument); + Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + } + + @Test + public void testAgIndicatorParser_testWrongIndicatorId() { + int batteryLevel = 10; + + // Verify that device property is null initially + Assert.assertNull(mRemoteDevices.getDeviceProperties(mDevice1)); + + // Verify that ACTION_AG_EVENT intent updates battery level + mRemoteDevices.onAgIndicatorValueChanged( + getAgIndicatorIntent(mDevice1, new Integer(1), null, null, null, null)); + verify(mAdapterService, never()).sendBroadcast(any(), anyString()); + // Verify that device property is still null after invalid update + Assert.assertNull(mRemoteDevices.getDeviceProperties(mDevice1)); + } + private static void verifyBatteryLevelChangedIntent(BluetoothDevice device, int batteryLevel, ArgumentCaptor<Intent> intentArgument) { verifyBatteryLevelChangedIntent(device, batteryLevel, intentArgument.getValue()); @@ -492,4 +572,38 @@ public class RemoteDevicesTest { list.add(0); return list.toArray(); } + + private static Intent getHeadsetClientConnectionStateChangedIntent(BluetoothDevice device, + int oldState, int newState) { + Intent intent = new Intent(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED); + intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); + intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, oldState); + intent.putExtra(BluetoothProfile.EXTRA_STATE, newState); + return intent; + } + + private static Intent getAgIndicatorIntent(BluetoothDevice device, Integer networkStatus, + Integer networkStrength, Integer roaming, Integer batteryLevel, String operatorName) { + Intent intent = new Intent(BluetoothHeadsetClient.ACTION_AG_EVENT); + intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); + + if (networkStatus != null) { + intent.putExtra(BluetoothHeadsetClient.EXTRA_NETWORK_STATUS, networkStatus.intValue()); + } + if (networkStrength != null) { + intent.putExtra(BluetoothHeadsetClient.EXTRA_NETWORK_SIGNAL_STRENGTH, + networkStrength.intValue()); + } + if (roaming != null) { + intent.putExtra(BluetoothHeadsetClient.EXTRA_NETWORK_ROAMING, roaming.intValue()); + } + if (batteryLevel != null) { + intent.putExtra(BluetoothHeadsetClient.EXTRA_BATTERY_LEVEL, batteryLevel.intValue()); + } + if (operatorName != null) { + intent.putExtra(BluetoothHeadsetClient.EXTRA_OPERATOR_NAME, operatorName); + } + + return intent; + } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientTest.java b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientTest.java index 7589ff24ae..6d2f61b240 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientTest.java @@ -24,8 +24,11 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.os.Binder; import android.os.Looper; import android.os.ParcelUuid; +import android.os.RemoteException; +import android.util.Log; import androidx.test.InstrumentationRegistry; import androidx.test.filters.MediumTest; @@ -39,6 +42,7 @@ import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.ServiceFactory; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.csip.CsipSetCoordinatorService; +import com.android.bluetooth.le_audio.LeAudioService; import org.junit.After; import org.junit.Assert; @@ -47,13 +51,16 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeoutException; @@ -69,9 +76,9 @@ public class HapClientTest { private BluetoothDevice mDevice3; private Context mTargetContext; private HapClientService mService; - private IBluetoothHapClient.Stub mServiceBinder; private HasIntentReceiver mHasIntentReceiver; private HashMap<BluetoothDevice, LinkedBlockingQueue<Intent>> mIntentQueue; + @Mock private AdapterService mAdapterService; @Mock @@ -82,6 +89,12 @@ public class HapClientTest { private ServiceFactory mServiceFactory; @Mock private CsipSetCoordinatorService mCsipService; + @Mock + private LeAudioService mLeAudioService; + @Mock + private IBluetoothHapClientCallback mCallback; + @Mock + private Binder mBinder; @Before public void setUp() throws Exception { @@ -96,6 +109,8 @@ public class HapClientTest { Looper.prepare(); } + HapClientStateMachine.sConnectTimeoutMs = TIMEOUT_MS; + TestUtils.setAdapterService(mAdapterService); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); doReturn(true, false).when(mAdapterService).isStartedProfile(anyString()); @@ -106,18 +121,15 @@ public class HapClientTest { mService.mHapClientNativeInterface = mNativeInterface; mService.mFactory = mServiceFactory; doReturn(mCsipService).when(mServiceFactory).getCsipSetCoordinatorService(); - mServiceBinder = (IBluetoothHapClient.Stub) mService.initBinder(); - Assert.assertNotNull(mServiceBinder); + doReturn(mLeAudioService).when(mServiceFactory).getLeAudioService(); // Set up the State Changed receiver IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHapClient.ACTION_HAP_DEVICE_AVAILABLE); - filter.addAction(BluetoothHapClient.ACTION_HAP_ON_ACTIVE_PRESET); - filter.addAction(BluetoothHapClient.ACTION_HAP_ON_ACTIVE_PRESET_SELECT_ERROR); - filter.addAction(BluetoothHapClient.ACTION_HAP_ON_PRESET_INFO); - filter.addAction(BluetoothHapClient.ACTION_HAP_ON_PRESET_NAME_SET_ERROR); - filter.addAction(BluetoothHapClient.ACTION_HAP_ON_PRESET_INFO_GET_ERROR); + + when(mCallback.asBinder()).thenReturn(mBinder); + mService.mCallbacks.register(mCallback); mHasIntentReceiver = new HasIntentReceiver(); mTargetContext.registerReceiver(mHasIntentReceiver, filter); @@ -129,6 +141,27 @@ public class HapClientTest { mDevice3 = TestUtils.getTestDevice(mAdapter, 2); when(mNativeInterface.getDevice(getByteAddress(mDevice3))).thenReturn(mDevice3); + /* Prepare CAS groups */ + doReturn(Arrays.asList(0x02, 0x03)).when(mCsipService).getAllGroupIds(BluetoothUuid.CAP); + + int groupId2 = 0x02; + Map groups2 = new HashMap<Integer, ParcelUuid>(); + groups2.put(groupId2, ParcelUuid.fromString("00001853-0000-1000-8000-00805F9B34FB")); + + int groupId3 = 0x03; + Map groups3 = new HashMap<Integer, ParcelUuid>(); + groups3.put(groupId3, + ParcelUuid.fromString("00001853-0000-1000-8000-00805F9B34FB")); + + doReturn(Arrays.asList(mDevice, mDevice2)).when(mLeAudioService).getGroupDevices(groupId2); + doReturn(groups2).when(mCsipService).getGroupUuidMapByDevice(mDevice); + doReturn(groups2).when(mCsipService).getGroupUuidMapByDevice(mDevice2); + + doReturn(Arrays.asList(mDevice3)).when(mLeAudioService).getGroupDevices(0x03); + doReturn(groups3).when(mCsipService).getGroupUuidMapByDevice(mDevice3); + + doReturn(Arrays.asList(mDevice)).when(mLeAudioService).getGroupDevices(0x01); + doReturn(BluetoothDevice.BOND_BONDED).when(mAdapterService) .getBondState(any(BluetoothDevice.class)); doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService) @@ -147,8 +180,12 @@ public class HapClientTest { R.bool.profile_supported_hap_client)) { return; } + mService.mCallbacks.unregister(mCallback); + stopService(); mTargetContext.unregisterReceiver(mHasIntentReceiver); + + mAdapter = null; TestUtils.clearAdapterService(mAdapterService); mIntentQueue.clear(); } @@ -169,7 +206,7 @@ public class HapClientTest { * Test getting HA Service Client */ @Test - public void testGetHearingAidService() { + public void testGetHapService() { Assert.assertEquals(mService, HapClientService.getHapClientService()); } @@ -177,7 +214,7 @@ public class HapClientTest { * Test stop HA Service Client */ @Test - public void testStopHearingAidService() { + public void testStopHapService() { Assert.assertEquals(mService, HapClientService.getHapClientService()); InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { @@ -371,14 +408,8 @@ public class HapClientTest { */ @Test public void testCallsForNotConnectedDevice() { - Assert.assertEquals(true, mService.getActivePresetIndex(mDevice)); - - Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(mDevice)); - Assert.assertNotNull(intent); - Assert.assertEquals(BluetoothHapClient.ACTION_HAP_ON_ACTIVE_PRESET, intent.getAction()); - Assert.assertEquals(mDevice, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); Assert.assertEquals(BluetoothHapClient.PRESET_INDEX_UNAVAILABLE, - intent.getIntExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INDEX, -1)); + mService.getActivePresetIndex(mDevice)); } /** @@ -395,51 +426,45 @@ public class HapClientTest { int flags = 0x04; mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice), flags); - int flags2 = 0x04; - mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice2), flags); + int flags3 = 0x04; + mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice3), flags); /* This one has no coordinated operation support but is part of a coordinated set with * mDevice, which supports it, thus mDevice will forward the operation to mDevice2. * This device should also be rocognised as grouped one. */ - int flags3 = 0; - mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice3), flags3); + int flags2 = 0; + mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice2), flags2); - /* Prepare CAS groups */ - int base_group_id = 0x03; - Map groups = new HashMap<Integer, ParcelUuid>(); - groups.put(base_group_id, ParcelUuid.fromString("00001853-0000-1000-8000-00805F9B34FB")); - - Map groups2 = new HashMap<Integer, ParcelUuid>(); - groups2.put(base_group_id + 1, - ParcelUuid.fromString("00001853-0000-1000-8000-00805F9B34FB")); - - doReturn(groups).when(mCsipService).getGroupUuidMapByDevice(mDevice); - doReturn(groups).when(mCsipService).getGroupUuidMapByDevice(mDevice3); - doReturn(groups2).when(mCsipService).getGroupUuidMapByDevice(mDevice2); - - /* Two devices support coordinated operations thus shell report valid group ID */ - Assert.assertEquals(base_group_id, mService.getHapGroup(mDevice)); - Assert.assertEquals(base_group_id + 1, mService.getHapGroup(mDevice2)); + /* Two devices support coordinated operations thus shall report valid group ID */ + Assert.assertEquals(2, mService.getHapGroup(mDevice)); + Assert.assertEquals(3, mService.getHapGroup(mDevice3)); /* Third one has no coordinated operations support but is part of the group */ - Assert.assertEquals(base_group_id, mService.getHapGroup(mDevice3)); + Assert.assertEquals(2, mService.getHapGroup(mDevice2)); } /** - * Test that selectActivePreset properly calls the native method. + * Test that selectPreset properly calls the native method. */ @Test - public void testSelectActivePresetNative() { + public void testSelectPresetNative() { doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService) .getRemoteUuids(any(BluetoothDevice.class)); testConnectingDevice(mDevice); // Verify Native Interface call - Assert.assertFalse(mService.selectActivePreset(mDevice, 0x00)); + mService.selectPreset(mDevice, 0x00); verify(mNativeInterface, times(0)) .selectActivePreset(eq(mDevice), eq(0x00)); - Assert.assertTrue(mService.selectActivePreset(mDevice, 0x01)); + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onSelectActivePresetFailed(eq(mDevice), + eq(BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + mService.selectPreset(mDevice, 0x01); verify(mNativeInterface, times(1)) .selectActivePreset(eq(mDevice), eq(0x01)); } @@ -455,8 +480,15 @@ public class HapClientTest { mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice), flags); // Verify Native Interface call - Assert.assertFalse(mService.groupSelectActivePreset(0x03, 0x00)); - Assert.assertTrue(mService.groupSelectActivePreset(0x03, 0x01)); + mService.selectPresetForGroup(0x03, 0x00); + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onSelectActivePresetForGroupFailed( + eq(0x03), eq(BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + mService.selectPresetForGroup(0x03, 0x01); verify(mNativeInterface, times(1)) .groupSelectActivePreset(eq(0x03), eq(0x01)); } @@ -465,13 +497,13 @@ public class HapClientTest { * Test that nextActivePreset properly calls the native method. */ @Test - public void testNextActivePresetNative() { + public void testSwitchToNextPreset() { doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService) .getRemoteUuids(any(BluetoothDevice.class)); testConnectingDevice(mDevice); // Verify Native Interface call - Assert.assertTrue(mService.nextActivePreset(mDevice)); + mService.switchToNextPreset(mDevice); verify(mNativeInterface, times(1)) .nextActivePreset(eq(mDevice)); } @@ -480,14 +512,14 @@ public class HapClientTest { * Test that groupNextActivePreset properly calls the native method. */ @Test - public void testGroupNextActivePresetNative() { + public void testSwitchToNextPresetForGroup() { doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService) .getRemoteUuids(any(BluetoothDevice.class)); int flags = 0x01; mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice), flags); // Verify Native Interface call - Assert.assertTrue(mService.groupNextActivePreset(0x03)); + mService.switchToNextPresetForGroup(0x03); verify(mNativeInterface, times(1)).groupNextActivePreset(eq(0x03)); } @@ -495,13 +527,13 @@ public class HapClientTest { * Test that previousActivePreset properly calls the native method. */ @Test - public void testPreviousActivePresetNative() { + public void testSwitchToPreviousPreset() { doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService) .getRemoteUuids(any(BluetoothDevice.class)); testConnectingDevice(mDevice); // Verify Native Interface call - Assert.assertTrue(mService.previousActivePreset(mDevice)); + mService.switchToPreviousPreset(mDevice); verify(mNativeInterface, times(1)) .previousActivePreset(eq(mDevice)); } @@ -510,7 +542,7 @@ public class HapClientTest { * Test that groupPreviousActivePreset properly calls the native method. */ @Test - public void testGroupPreviousActivePresetNative() { + public void testSwitchToPreviousPresetForGroup() { doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService) .getRemoteUuids(any(BluetoothDevice.class)); testConnectingDevice(mDevice); @@ -520,7 +552,7 @@ public class HapClientTest { mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice), flags); // Verify Native Interface call - Assert.assertTrue(mService.groupPreviousActivePreset(0x03)); + mService.switchToPreviousPresetForGroup(0x03); verify(mNativeInterface, times(1)).groupPreviousActivePreset(eq(0x03)); } @@ -532,39 +564,38 @@ public class HapClientTest { doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService) .getRemoteUuids(any(BluetoothDevice.class)); testConnectingDevice(mDevice); - testOnActivePresetSelected(mDevice, 0x01); + testOnActivePresetChanged(mDevice, 0x01); // Verify cached value - Assert.assertEquals(true, mService.getActivePresetIndex(mDevice)); - - Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(mDevice)); - Assert.assertNotNull(intent); - Assert.assertEquals(BluetoothHapClient.ACTION_HAP_ON_ACTIVE_PRESET, intent.getAction()); - Assert.assertEquals(mDevice, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals(0x01, - intent.getIntExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INDEX, -1)); + Assert.assertEquals(0x01, mService.getActivePresetIndex(mDevice)); } /** - * Test that getPresetInfo properly calls the native method. + * Test that getActivePresetInfo returns cached value for valid parameters. */ @Test - public void testGetPresetInfoNative() { + public void testGetActivePresetInfo() { doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService) .getRemoteUuids(any(BluetoothDevice.class)); - testConnectingDevice(mDevice); + testConnectingDevice(mDevice2); - // Verify Native Interface call - Assert.assertFalse(mService.getPresetInfo(mDevice, 0x00)); - verify(mNativeInterface, times(0)) - .getPresetInfo(eq(mDevice), eq(0x00)); - Assert.assertTrue(mService.getPresetInfo(mDevice, 0x01)); - verify(mNativeInterface, times(1)) - .getPresetInfo(eq(mDevice), eq(0x01)); + // Check when active preset is not known yet + Assert.assertEquals(BluetoothHapClient.PRESET_INDEX_UNAVAILABLE, + mService.getActivePresetIndex(mDevice2)); + Assert.assertEquals(null, mService.getActivePresetInfo(mDevice2)); + + // Inject active preset change event + testOnActivePresetChanged(mDevice2, 0x01); + + // Check when active preset is known + Assert.assertEquals(0x01, mService.getActivePresetIndex(mDevice2)); + BluetoothHapPresetInfo info = mService.getActivePresetInfo(mDevice2); + Assert.assertNotNull(info); + Assert.assertEquals(0x01, info.getIndex()); } /** - * Test that setPresetName properly calls the native method. + * Test that setPresetName properly calls the native method for the valid parameters. */ @Test public void testSetPresetNameNative() { @@ -572,31 +603,57 @@ public class HapClientTest { .getRemoteUuids(any(BluetoothDevice.class)); testConnectingDevice(mDevice); - // Verify Native Interface call - Assert.assertFalse(mService.setPresetName(mDevice, 0x00, "ExamplePresetName")); + mService.setPresetName(mDevice, 0x00, "ExamplePresetName"); verify(mNativeInterface, times(0)) .setPresetName(eq(mDevice), eq(0x00), eq("ExamplePresetName")); - Assert.assertTrue(mService.setPresetName(mDevice, 0x01, "ExamplePresetName")); + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onSetPresetNameFailed(eq(mDevice), + eq(BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + // Verify Native Interface call + mService.setPresetName(mDevice, 0x01, "ExamplePresetName"); verify(mNativeInterface, times(1)) .setPresetName(eq(mDevice), eq(0x01), eq("ExamplePresetName")); } /** - * Test that groupSetPresetName properly calls the native method. + * Test that setPresetNameForGroup properly calls the native method for the valid parameters. */ @Test - public void testGroupSetPresetName() { + public void testSetPresetNameForGroup() { doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService) .getRemoteUuids(any(BluetoothDevice.class)); + int test_group = 0x02; + for (BluetoothDevice device : mLeAudioService.getGroupDevices(test_group)) { + testConnectingDevice(device); + } + int flags = 0x21; mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice), flags); + mService.setPresetNameForGroup(test_group, 0x00, "ExamplePresetName"); + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onSetPresetNameForGroupFailed(eq(test_group), + eq(BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + mService.setPresetNameForGroup(-1, 0x01, "ExamplePresetName"); + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onSetPresetNameForGroupFailed(eq(-1), + eq(BluetoothStatusCodes.ERROR_CSIP_INVALID_GROUP_ID)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + // Verify Native Interface call - Assert.assertFalse(mService.groupSetPresetName(0x03, 0x00, "ExamplePresetName")); - Assert.assertFalse(mService.groupSetPresetName(-1, 0x01, "ExamplePresetName")); - Assert.assertTrue(mService.groupSetPresetName(0x03, 0x01, "ExamplePresetName")); + mService.setPresetNameForGroup(test_group, 0x01, "ExamplePresetName"); verify(mNativeInterface, times(1)) - .groupSetPresetName(eq(0x03), eq(0x01), eq("ExamplePresetName")); + .groupSetPresetName(eq(test_group), eq(0x01), eq("ExamplePresetName")); } /** @@ -607,153 +664,233 @@ public class HapClientTest { doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService) .getRemoteUuids(any(BluetoothDevice.class)); - // Verify getting current preset return an invalid value when there is no such device - // available - Assert.assertEquals(true, mService.getActivePresetIndex(mDevice)); - - Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(mDevice)); - Assert.assertNotNull(intent); - Assert.assertEquals(BluetoothHapClient.ACTION_HAP_ON_ACTIVE_PRESET, intent.getAction()); - Assert.assertEquals(mDevice, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals(BluetoothHapClient.PRESET_INDEX_UNAVAILABLE, - intent.getIntExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INDEX, -1)); - mNativeInterface.onDeviceAvailable(getByteAddress(mDevice), 0x03); - intent = TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(mDevice)); + Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(mDevice)); Assert.assertNotNull(intent); Assert.assertEquals(BluetoothHapClient.ACTION_HAP_DEVICE_AVAILABLE, intent.getAction()); Assert.assertEquals(mDevice, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); Assert.assertEquals(0x03, - intent.getIntExtra(BluetoothHapClient.EXTRA_HAP_FEATURES, 0x03)); + intent.getIntExtra(BluetoothHapClient.EXTRA_HAP_FEATURES, 0x00)); } /** - * Test that native callback generates proper intent. + * Test that native callback generates proper callback call. */ @Test - public void testStackEventOnActivePresetSelected() { + public void testStackEventOnFeaturesUpdate() { + doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService) + .getRemoteUuids(any(BluetoothDevice.class)); + + mNativeInterface.onDeviceAvailable(getByteAddress(mDevice), 0x00); + mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice), 0x03); + + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onHapFeaturesAvailable(eq(mDevice), + eq(0x03)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Test that native callback generates proper callback call. + */ + @Test + public void testStackEventOnActivePresetChanged() { doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService) .getRemoteUuids(any(BluetoothDevice.class)); mNativeInterface.onActivePresetSelected(getByteAddress(mDevice), 0x01); - Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(mDevice)); - Assert.assertNotNull(intent); - Assert.assertEquals(BluetoothHapClient.ACTION_HAP_ON_ACTIVE_PRESET, intent.getAction()); - Assert.assertEquals(mDevice, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals(0x01, - intent.getIntExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INDEX, -1)); + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onActivePresetChanged(eq(mDevice), + eq(0x01)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } // Verify that getting current preset returns a proper value now - Assert.assertEquals(true, mService.getActivePresetIndex(mDevice)); - - intent = TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(mDevice)); - Assert.assertNotNull(intent); - Assert.assertEquals(BluetoothHapClient.ACTION_HAP_ON_ACTIVE_PRESET, intent.getAction()); - Assert.assertEquals(mDevice, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals(0x01, - intent.getIntExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INDEX, -1)); + Assert.assertEquals(0x01, mService.getActivePresetIndex(mDevice)); } /** - * Test that native callback generates proper intent. + * Test that native callback generates proper callback call. */ @Test - public void testStackEventOnCurrentPresetSelectError() { + public void testStackEventOnActivePresetSelectError() { doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService) .getRemoteUuids(any(BluetoothDevice.class)); - mNativeInterface.onActivePresetSelectError(getByteAddress(mDevice), - BluetoothHapClient.STATUS_INVALID_PRESET_INDEX); + /* Send INVALID_PRESET_INDEX error */ + mNativeInterface.onActivePresetSelectError(getByteAddress(mDevice), 0x05); - Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(mDevice)); - Assert.assertNotNull(intent); - Assert.assertEquals(BluetoothHapClient.ACTION_HAP_ON_ACTIVE_PRESET_SELECT_ERROR, - intent.getAction()); - Assert.assertEquals(mDevice, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals(BluetoothHapClient.STATUS_INVALID_PRESET_INDEX, - intent.getIntExtra(BluetoothHapClient.EXTRA_HAP_STATUS_CODE, -1)); + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onSelectActivePresetFailed(eq(mDevice), + eq(BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** - * Test that native callback generates proper intent. + * Test that native callback generates proper callback call. */ @Test public void testStackEventOnPresetInfo() { doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService) .getRemoteUuids(any(BluetoothDevice.class)); - int info_reason = BluetoothHapClient.PRESET_INFO_REASON_PRESET_INFO_UPDATE; + // Connect and inject initial presets + testConnectingDevice(mDevice); + + int info_reason = HapClientStackEvent.PRESET_INFO_REASON_PRESET_INFO_UPDATE; BluetoothHapPresetInfo[] info = {new BluetoothHapPresetInfo.Builder() .setIndex(0x01) - .setName("PresetName") + .setName("OneChangedToUnavailable") .setWritable(true) - .setAvailable(true) + .setAvailable(false) .build()}; mNativeInterface.onPresetInfo(getByteAddress(mDevice), info_reason, info); - Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(mDevice)); - Assert.assertNotNull(intent); - Assert.assertEquals(BluetoothHapClient.ACTION_HAP_ON_PRESET_INFO, intent.getAction()); - Assert.assertEquals(mDevice, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals(info_reason, - intent.getIntExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INFO_REASON, -1)); + ArgumentCaptor<List<BluetoothHapPresetInfo>> presetsCaptor = + ArgumentCaptor.forClass(List.class); + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onPresetInfoChanged(eq(mDevice), + presetsCaptor.capture(), eq(BluetoothStatusCodes.REASON_REMOTE_REQUEST)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } - ArrayList presets = - intent.getParcelableArrayListExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INFO); - Assert.assertNotNull(presets); + List<BluetoothHapPresetInfo> presets = presetsCaptor.getValue(); + Assert.assertEquals(3, presets.size()); - BluetoothHapPresetInfo preset = (BluetoothHapPresetInfo) presets.get(0); - Assert.assertEquals(preset.getIndex(), info[0].getIndex()); - Assert.assertEquals(preset.getName(), info[0].getName()); - Assert.assertEquals(preset.isWritable(), info[0].isWritable()); - Assert.assertEquals(preset.isAvailable(), info[0].isAvailable()); + Optional<BluetoothHapPresetInfo> preset = presetsCaptor.getValue() + .stream() + .filter(p -> 0x01 == p.getIndex()) + .findFirst(); + Assert.assertEquals("OneChangedToUnavailable", preset.get().getName()); + Assert.assertFalse(preset.get().isAvailable()); + Assert.assertTrue(preset.get().isWritable()); } /** - * Test that native callback generates proper intent. + * Test that native callback generates proper callback call. */ @Test public void testStackEventOnPresetNameSetError() { doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService) .getRemoteUuids(any(BluetoothDevice.class)); + /* Not a valid name length */ mNativeInterface.onPresetNameSetError(getByteAddress(mDevice), 0x01, - BluetoothHapClient.STATUS_SET_NAME_NOT_ALLOWED); + HapClientStackEvent.STATUS_INVALID_PRESET_NAME_LENGTH); + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onSetPresetNameFailed(eq(mDevice), + eq(BluetoothStatusCodes.ERROR_HAP_PRESET_NAME_TOO_LONG)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } - Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(mDevice)); - Assert.assertNotNull(intent); - Assert.assertEquals(BluetoothHapClient.ACTION_HAP_ON_PRESET_NAME_SET_ERROR, - intent.getAction()); - Assert.assertEquals(0x01, - intent.getIntExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INDEX, -1)); - Assert.assertEquals(mDevice, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals(BluetoothHapClient.STATUS_SET_NAME_NOT_ALLOWED, - intent.getIntExtra(BluetoothHapClient.EXTRA_HAP_STATUS_CODE, -1)); + /* Invalid preset index provided */ + mNativeInterface.onPresetNameSetError(getByteAddress(mDevice), 0x01, + HapClientStackEvent.STATUS_INVALID_PRESET_INDEX); + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onSetPresetNameFailed(eq(mDevice), + eq(BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + /* Not allowed on this particular preset */ + mNativeInterface.onPresetNameSetError(getByteAddress(mDevice), 0x01, + HapClientStackEvent.STATUS_SET_NAME_NOT_ALLOWED); + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onSetPresetNameFailed(eq(mDevice), + eq(BluetoothStatusCodes.ERROR_REMOTE_OPERATION_REJECTED)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + /* Not allowed on this particular preset at this time, might be possible later on */ + mNativeInterface.onPresetNameSetError(getByteAddress(mDevice), 0x01, + HapClientStackEvent.STATUS_OPERATION_NOT_POSSIBLE); + try { + verify(mCallback, after(TIMEOUT_MS).times(2)).onSetPresetNameFailed(eq(mDevice), + eq(BluetoothStatusCodes.ERROR_REMOTE_OPERATION_REJECTED)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + /* Not allowed on all presets - for example missing characteristic */ + mNativeInterface.onPresetNameSetError(getByteAddress(mDevice), 0x01, + HapClientStackEvent.STATUS_OPERATION_NOT_SUPPORTED); + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onSetPresetNameFailed(eq(mDevice), + eq(BluetoothStatusCodes.ERROR_REMOTE_OPERATION_NOT_SUPPORTED)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** - * Test that native callback generates proper intent. + * Test that native callback generates proper callback call. */ @Test - public void testStackEventOnPresetInfoError() { + public void testStackEventOnGroupPresetNameSetError() { doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService) .getRemoteUuids(any(BluetoothDevice.class)); - mNativeInterface.onPresetInfoError(getByteAddress(mDevice), 0x01, - BluetoothHapClient.STATUS_INVALID_PRESET_INDEX); + /* Not a valid name length */ + mNativeInterface.onGroupPresetNameSetError(0x01, 0x01, + HapClientStackEvent.STATUS_INVALID_PRESET_NAME_LENGTH); + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onSetPresetNameForGroupFailed(0x01, + BluetoothStatusCodes.ERROR_HAP_PRESET_NAME_TOO_LONG); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } - Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(mDevice)); - Assert.assertNotNull(intent); - Assert.assertEquals(BluetoothHapClient.ACTION_HAP_ON_PRESET_INFO_GET_ERROR, - intent.getAction()); - Assert.assertEquals(0x01, - intent.getIntExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INDEX, -1)); - Assert.assertEquals(mDevice, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals(BluetoothHapClient.STATUS_INVALID_PRESET_INDEX, - intent.getIntExtra(BluetoothHapClient.EXTRA_HAP_STATUS_CODE, -1)); + /* Invalid preset index provided */ + mNativeInterface.onGroupPresetNameSetError(0x01, 0x01, + HapClientStackEvent.STATUS_INVALID_PRESET_INDEX); + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onSetPresetNameForGroupFailed(0x01, + BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + /* Not allowed on this particular preset */ + mNativeInterface.onGroupPresetNameSetError(0x01, 0x01, + HapClientStackEvent.STATUS_SET_NAME_NOT_ALLOWED); + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onSetPresetNameForGroupFailed(0x01, + BluetoothStatusCodes.ERROR_REMOTE_OPERATION_REJECTED); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + /* Not allowed on this particular preset at this time, might be possible later on */ + mNativeInterface.onGroupPresetNameSetError(0x01, 0x01, + HapClientStackEvent.STATUS_OPERATION_NOT_POSSIBLE); + try { + verify(mCallback, after(TIMEOUT_MS).times(2)).onSetPresetNameForGroupFailed(0x01, + BluetoothStatusCodes.ERROR_REMOTE_OPERATION_REJECTED); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + /* Not allowed on all presets - for example if peer is missing optional CP characteristic */ + mNativeInterface.onGroupPresetNameSetError(0x01, 0x01, + HapClientStackEvent.STATUS_OPERATION_NOT_SUPPORTED); + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onSetPresetNameForGroupFailed(0x01, + BluetoothStatusCodes.ERROR_REMOTE_OPERATION_NOT_SUPPORTED); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** @@ -812,21 +949,57 @@ public class HapClientTest { Assert.assertEquals(device, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); Assert.assertEquals(evt.valueInt1, intent.getIntExtra(BluetoothHapClient.EXTRA_HAP_FEATURES, -1)); + + evt = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_DEVICE_FEATURES); + evt.device = device; + evt.valueInt1 = 0x01; // features + mService.messageFromNative(evt); + + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onHapFeaturesAvailable(eq(device), + eq(evt.valueInt1)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + // Inject some initial presets + List<BluetoothHapPresetInfo> presets = + new ArrayList<BluetoothHapPresetInfo>(Arrays.asList( + new BluetoothHapPresetInfo.Builder() + .setIndex(0x01) + .setName("One") + .setAvailable(true) + .setWritable(false) + .build(), + new BluetoothHapPresetInfo.Builder() + .setIndex(0x02) + .setName("Two") + .setAvailable(true) + .setWritable(true) + .build(), + new BluetoothHapPresetInfo.Builder() + .setIndex(0x03) + .setName("Three") + .setAvailable(false) + .setWritable(false) + .build())); + mService.updateDevicePresetsCache(device, + HapClientStackEvent.PRESET_INFO_REASON_ALL_PRESET_INFO, presets); } - private void testOnActivePresetSelected(BluetoothDevice device, int index) { + private void testOnActivePresetChanged(BluetoothDevice device, int index) { HapClientStackEvent evt = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_ON_ACTIVE_PRESET_SELECTED); evt.device = device; evt.valueInt1 = index; mService.messageFromNative(evt); - Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mIntentQueue.get(device)); - Assert.assertNotNull(intent); - Assert.assertEquals(BluetoothHapClient.ACTION_HAP_ON_ACTIVE_PRESET, intent.getAction()); - Assert.assertEquals(device, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals(index, - intent.getIntExtra(BluetoothHapClient.EXTRA_HAP_PRESET_INDEX, -1)); + try { + verify(mCallback, after(TIMEOUT_MS).times(1)).onActivePresetChanged(eq(device), + eq(evt.valueInt1)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** diff --git a/android/app/tests/unit/src/com/android/bluetooth/mcp/McpServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/mcp/McpServiceTest.java index 5bb690ddb6..b467f04fd2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mcp/McpServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mcp/McpServiceTest.java @@ -50,11 +50,15 @@ public class McpServiceTest { private McpService mMcpService; private Context mTargetContext; - @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); + @Rule + public final ServiceTestRule mServiceRule = new ServiceTestRule(); - @Mock private AdapterService mAdapterService; - @Mock private MediaControlGattService mMockMcpService; - @Mock private MediaControlProfile mMediaControlProfile; + @Mock + private AdapterService mAdapterService; + @Mock + private MediaControlGattService mMockMcpService; + @Mock + private MediaControlProfile mMediaControlProfile; @Before public void setUp() throws Exception { @@ -115,4 +119,23 @@ public class McpServiceTest { Assert.assertEquals(BluetoothDevice.ACCESS_REJECTED, mMcpService.getDeviceAuthorization(device1)); } + + @Test + public void testStopMcpService() { + InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { + public void run() { + Assert.assertTrue(mMcpService.stop()); + } + }); + Assert.assertNull(McpService.getMcpService()); + Assert.assertNull(McpService.getMediaControlProfile()); + + McpService.setMediaControlProfileForTesting(mMediaControlProfile); + // Try to restart the service. Note: must be done on the main thread + InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { + public void run() { + Assert.assertTrue(mMcpService.start()); + } + }); + } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGenericTest.java b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGenericTest.java index 4a79b3904a..eae7e099f2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGenericTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGenericTest.java @@ -31,6 +31,7 @@ import androidx.test.InstrumentationRegistry; import androidx.test.filters.MediumTest; import androidx.test.rule.ServiceTestRule; import androidx.test.runner.AndroidJUnit4; +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; @@ -71,12 +72,14 @@ public class TbsGenericTest { private @Captor ArgumentCaptor<Integer> mDefaultGtbsTechnologyCaptor; private @Captor ArgumentCaptor<TbsGatt.Callback> mTbsGattCallback; + private static Context mContext; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mAdapter = BluetoothAdapter.getDefaultAdapter(); + mContext = getInstrumentation().getTargetContext(); // Default TbsGatt mock behavior doReturn(true).when(mTbsGatt).init(mGtbsCcidCaptor.capture(), mGtbsUciCaptor.capture(), @@ -97,6 +100,7 @@ public class TbsGenericTest { doReturn(true).when(mTbsGatt).clearIncomingCall(); doReturn(true).when(mTbsGatt).setCallFriendlyName(anyInt(), anyString()); doReturn(true).when(mTbsGatt).clearFriendlyName(); + doReturn(mContext).when(mTbsGatt).getContext(); mTbsGeneric = new TbsGeneric(); mTbsGeneric.init(mTbsGatt); diff --git a/android/blueberry/OWNERS b/android/blueberry/OWNERS new file mode 100644 index 0000000000..610b34604a --- /dev/null +++ b/android/blueberry/OWNERS @@ -0,0 +1,5 @@ +# Project owners +girardier@google.com +licorne@google.com +uael@google.com +charliebout@google.com diff --git a/android/blueberry/server/Android.bp b/android/blueberry/server/Android.bp new file mode 100644 index 0000000000..705ffa6c7e --- /dev/null +++ b/android/blueberry/server/Android.bp @@ -0,0 +1,25 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +android_test { + name: "BlueberryServer", + srcs: ["src/**/*.kt"], + certificate: "platform", + + static_libs: [ + "androidx.test.runner", + "androidx.test.core", + "grpc-java-netty-shaded-test", + "grpc-java-lite", + "guava", + "opencensus-java-api", + ], + + dex_preopt: { + enabled: false, + }, + optimize: { + enabled: false, + }, +} diff --git a/android/blueberry/server/AndroidManifest.xml b/android/blueberry/server/AndroidManifest.xml new file mode 100644 index 0000000000..16a47bfc83 --- /dev/null +++ b/android/blueberry/server/AndroidManifest.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.blueberry"> + + <application> + <uses-library android:name="android.test.runner" /> + </application> + + <uses-permission android:name="android.permission.INTERNET" /> + + <instrumentation android:name="com.android.blueberry.Server" + android:targetPackage="com.android.blueberry" + android:label="Blueberry Android Server" /> +</manifest> diff --git a/android/blueberry/server/README.md b/android/blueberry/server/README.md new file mode 100644 index 0000000000..ebeea949a1 --- /dev/null +++ b/android/blueberry/server/README.md @@ -0,0 +1,117 @@ +# Blueberry Android server + +The Blueberry Android server exposes the [Blueberry test interfaces]( +go/blueberry-doc) over gRPC implemented on top of the Android Bluetooth SDK. + +## Getting started + +Using Blueberry Android server requires to: + +* Build AOSP for your DUT, which can be either a physical device or an Android + Virtual Device (AVD). +* [Only for virtual tests] Build Rootcanal, the Android + virtual Bluetooth Controller. +* Setup your test environment. +* Build, install, and run Blueberry server. +* Run your tests. + +### 1. Build and run AOSP code + +Refer to the AOSP documentation to [initialize and sync]( +https://g3doc.corp.google.com/company/teams/android/developing/init-sync.md) +AOSP code, and [build]( +https://g3doc.corp.google.com/company/teams/android/developing/build-flash.md) +it for your DUT (`aosp_cf_x86_64_phone-userdebug` for the emulator). + +**If your DUT is a physical device**, flash the built image on it. You may +need to use [Remote Device Proxy]( +https://g3doc.corp.google.com/company/teams/android/wfh/adb/remote_device_proxy.md) +if you are using a remote instance to build. If you are also using `adb` on +your local machine, you may need to force kill the local `adb` server (`adb +kill-server` before using Remote Device Proxy. + +**If your DUT is a Cuttlefish virtual device**, then proceed with the following steps: + +* Connect to your [Chrome Remote Desktop]( + https://remotedesktop.corp.google.com/access/). +* Create a local Cuttlefish instance using your locally built image with the command + `acloud create --local-instance --local-image` (see [documentation]( + go/acloud-manual#local-instance-using-a-locally-built-image)) + +### 2. Build Rootcanal [only for virtual tests on a physical device] + +Rootcanal is a virtual Bluetooth Controller that allows emulating Bluetooth +communications. It is used by default within Cuttlefish when running it using the [acloud](go/acloud) command (and thus this step is not +needed) and is required for all virtual tests. However, it does not come +preinstalled on a build for a physical device. + +Proceed with the [following instructions]( +https://docs.google.com/document/d/1-qoK1HtdOKK6sTIKAToFf7nu9ybxs8FQWU09idZijyc/edit#heading=h.x9snb54sjlu9) +to build and install Rootcanal on your DUT. + +### 3. Setup your test environment + +Each time when starting a new ADB server to communicate with your DUT, proceed +with the following steps to setup the test environment: + +* If running virtual tests (such as PTS-bot) on a physical device: + * Run Rootcanal: + `adb root` then + `adb shell ./vendor/bin/hw/android.hardware.bluetooth@1.1-service.sim &` + * Forward Rootcanal port through ADB: + `adb forward tcp:<rootcanal-port> tcp:<rootcanal-port>`. + Rootcanal port number may differ depending on its configuration. It is + 7200 for the AVD, and generally 6211 for physical devices. +* Forward Blueberry Android server port through ADB: + `adb forward tcp:8999 tcp:8999`. + +The above steps can be done by executing the `setup.sh` helper script (the +`-rootcanal` option must be used for virtual tests on a physical device). + +Finally, you must also make sure that the machine on which tests are executed +can access the ports of the Blueberry Android server, Rootcanal (if required), +and ADB (if required). + +You can also check the usage examples provided below. + +### 4. Build, install, and run Blueberry Android server + +* `m BlueberryServer` +* `adb install -r -g out/target/product/<device>/testcases/Blueberry/arm64/Blueberry.apk` + +* Start the instrumented app: +* `adb shell am instrument -w -e Debug false com.android.blueberry/.Server` + +### 5. Run your tests + +You should now be fully set up to run your tests! + +### Usage examples + +Here are some usage examples: + +* **DUT**: physical + **Test type**: virtual + **Test executer**: remote instance (for instance a Cloudtop) accessed via SSH + **Blueberry Android server repository location**: local machine (typically + using Android Studio) + + * On your local machine: `./setup.sh --rootcanal`. + * On your local machine: build and install the app on your DUT. + * Log on your remote instance, and forward Rootcanal port (6211, may change + depending on your build) and Blueberry Android server (8999) port: + `ssh -R 6211:localhost:6211 -R 8999:localhost:8999 <remote-instance>`. + Optionnally, you can also share ADB port to your remote instance (if + needed) by adding `-R 5037:localhost:5037` to the command. + * On your remote instance: execute your tests. + +* **DUT**: virtual (running in remote instance) + **Test type**: virtual + **Test executer**: remote instance + **Blueberry Android server repository location**: remote instance + + On your remote instance: + * `./setup.sh`. + * Build and install the app on the AVD. + * Execute your tests. + diff --git a/android/blueberry/server/scripts/setup.sh b/android/blueberry/server/scripts/setup.sh new file mode 100755 index 0000000000..1ade4f5159 --- /dev/null +++ b/android/blueberry/server/scripts/setup.sh @@ -0,0 +1,12 @@ +#!/bin/env bash + +# Run Rootcanal and forward port +if [ "$1" == "--rootcanal" ] +then + adb root + adb shell ./vendor/bin/hw/android.hardware.bluetooth@1.1-service.sim & + adb forward tcp:6211 tcp:6211 +fi + +# Forward Blueberry server port +adb forward tcp:8999 tcp:8999 diff --git a/android/blueberry/server/src/com/android/blueberry/Server.kt b/android/blueberry/server/src/com/android/blueberry/Server.kt new file mode 100644 index 0000000000..cbfff9084d --- /dev/null +++ b/android/blueberry/server/src/com/android/blueberry/Server.kt @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.blueberry + +import android.os.Bundle +import android.os.Debug +import android.util.Log +import androidx.test.runner.MonitoringInstrumentation +import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder + +class Server : MonitoringInstrumentation() { + + private val TAG = "BlueberryServer" + private val GRPC_PORT = 8999 + + override fun onCreate(arguments: Bundle) { + super.onCreate(arguments) + + // Activate debugger + if (arguments.getString("debug").toBoolean()) { + Log.i(TAG, "Waiting for debugger to connect...") + Debug.waitForDebugger() + Log.i(TAG, "Debugger connected") + } + + // Start instrumentation thread + start() + } + + override fun onStart() { + super.onStart() + + NettyServerBuilder.forPort(GRPC_PORT).build().start() + Log.d(TAG, "Blueberry Server started at $GRPC_PORT") + } +} @@ -59,13 +59,14 @@ USE_DEFAULTS = { } VALID_TARGETS = [ + 'all', # All targets except test and clean + 'clean', # Clean up output directory + 'docs', # Build Rust docs + 'main', # Build the main C++ codebase 'prepare', # Prepare the output directory (gn gen + rust setup) - 'tools', # Build the host tools (i.e. packetgen) 'rust', # Build only the rust components + copy artifacts to output dir - 'main', # Build the main C++ codebase 'test', # Run the unit tests - 'clean', # Clean up output directory - 'all', # All targets except test and clean + 'tools', # Build the host tools (i.e. packetgen) ] # TODO(b/190750167) - Host tests are disabled until we are full bazel build @@ -98,19 +99,24 @@ REQUIRED_APT_PACKAGES = [ 'generate-ninja', 'gnupg', 'gperf', + 'libc++abi-dev', 'libc++-dev', 'libdbus-1-dev', + 'libdouble-conversion-dev', 'libevent-dev', 'libevent-dev', 'libflatbuffers-dev', 'libflatbuffers1', 'libgl1-mesa-dev', 'libglib2.0-dev', + 'libgtest-dev', + 'libgmock-dev', 'liblz4-tool', 'libncurses5', 'libnss3-dev', 'libprotobuf-dev', 'libre2-9', + 'libre2-dev', 'libssl-dev', 'libtinyxml2-dev', 'libx11-dev', @@ -327,7 +333,7 @@ class HostBuild(): 'libbase_ver': self._get_basever(), 'enable_exceptions': os.environ.get('CXXEXCEPTIONS', 0) == '1', 'external_cflags': [], - 'external_cxxflags': [], + 'external_cxxflags': ["-DNDEBUG"], 'enable_werror': False, } @@ -413,6 +419,10 @@ class HostBuild(): shutil.copy( os.path.join(self._gn_default_output(), 'bluetooth_packetgen'), os.path.join(self.env['CARGO_HOME'], 'bin')) + def _target_docs(self): + """Build the Rust docs.""" + self.run_command('docs', ['cargo', 'doc'], cwd=os.path.join(self.platform_dir, 'bt'), env=self.env) + def _target_rust(self): """ Build rust artifacts in an already prepared environment. """ @@ -427,7 +437,11 @@ class HostBuild(): """ Runs the host tests. """ # Rust tests first - self.run_command('test', ['cargo', 'test'], cwd=os.path.join(self.platform_dir, 'bt'), env=self.env) + rust_test_cmd = ['cargo', 'test'] + if self.args.test_name: + rust_test_cmd = rust_test_cmd + [self.args.test_name] + + self.run_command('test', rust_test_cmd, cwd=os.path.join(self.platform_dir, 'bt'), env=self.env) # Host tests second based on host test list for t in HOST_TESTS: @@ -502,7 +516,7 @@ class HostBuild(): pass def _target_all(self): - """ Build all common targets (skipping test and clean). + """ Build all common targets (skipping doc, test, and clean). """ self._target_prepare() self._target_tools() @@ -514,12 +528,19 @@ class HostBuild(): """ print('Building target ', self.target) + # Validate that the target is valid + if self.target not in VALID_TARGETS: + print('Target {} is not valid. Must be in {}', self.target, VALID_TARGETS) + return + if self.target == 'prepare': self._target_prepare() elif self.target == 'tools': self._target_tools() elif self.target == 'rust': self._target_rust() + elif self.target == 'docs': + self._target_docs() elif self.target == 'main': self._target_main() elif self.target == 'test': @@ -594,7 +615,10 @@ class Bootstrap(): # Create symlinks for pairs in symlinks: (src, dst) = pairs - os.unlink(dst) + try: + os.unlink(dst) + except Exception as e: + print(e) os.symlink(src, dst) # Write to setup complete file so we don't repeat this step @@ -759,7 +783,8 @@ if __name__ == '__main__': parser.add_argument( '--no-strip', help='Skip stripping binaries during install.', default=False, action='store_true') parser.add_argument('--use', help='Set a specific use flag.') - parser.add_argument('--notest', help="Don't compile test code.", default=False, action='store_true') + parser.add_argument('--notest', help='Don\'t compile test code.', default=False, action='store_true') + parser.add_argument('--test-name', help='Run test with this string in the name.', default=None) parser.add_argument('--target', help='Run specific build target') parser.add_argument('--sysroot', help='Set a specific sysroot path', default='/') parser.add_argument('--libdir', help='Libdir - default = usr/lib', default='usr/lib') diff --git a/floss/OWNERS b/floss/OWNERS new file mode 100644 index 0000000000..45bfdd2be4 --- /dev/null +++ b/floss/OWNERS @@ -0,0 +1 @@ +include platform/packages/modules/Bluetooth:/OWNERS_chromeos diff --git a/floss/build/Dockerfile b/floss/build/Dockerfile new file mode 100644 index 0000000000..7e938f9a10 --- /dev/null +++ b/floss/build/Dockerfile @@ -0,0 +1,76 @@ +# Build environment for Floss +# +# This dockerfile generates the build environment required to build Floss, which +# is the Linux build for the Fluoride Bluetooth stack. + +# Inherit from a recent Debian version. The slim version is a smaller variant +# meant for containers. +FROM debian:bookworm-slim + +# First install all required apt packages. +RUN apt-get update && \ + apt-get install -y \ + bison \ + build-essential \ + clang \ + cmake \ + curl \ + debmake \ + flatbuffers-compiler \ + flex \ + g++-multilib \ + gcc-multilib \ + generate-ninja \ + gnupg \ + gperf \ + libabsl-dev \ + libc++abi-dev \ + libc++-dev \ + libdbus-1-dev \ + libdouble-conversion-dev \ + libevent-dev \ + libflatbuffers-dev \ + libflatbuffers1 \ + libgl1-mesa-dev \ + libglib2.0-dev \ + libgtest-dev \ + libgmock-dev \ + liblz4-tool \ + libncurses5 \ + libnss3-dev \ + libprotobuf-dev \ + libre2-9 \ + libre2-dev \ + libssl-dev \ + libtinyxml2-dev \ + libx11-dev \ + libxml2-utils \ + ninja-build \ + openssl \ + protobuf-compiler \ + python3 \ + unzip \ + x11proto-core-dev \ + xsltproc \ + zip \ + zlib1g-dev \ + ; + +# Next install the Rust toolchain. +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + +# Add .cargo/bin to $PATH +ENV PATH="/root/.cargo/bin:${PATH}" + +# Install cargo packages required on build image. +RUN cargo install cxxbridge-cmd --version 1.0.42 + +# Rename llvm packages. By default, they are named 11vm-ar-13, etc. which won't +# work properly with the build. +ADD llvm-rename.sh /tmp +RUN /tmp/llvm-rename.sh 13 + +# At this point, the base container is ready. Now we need to build and install +# both libchrome and modp-b64. If you ran this via `docker-build-image.py`, this +# will be done after the image is created and tagged. Otherwise, you need to +# manually mount the source and run the dpkg builders in `system/build/dpkg`. diff --git a/floss/build/README.md b/floss/build/README.md new file mode 100644 index 0000000000..ac58410fb1 --- /dev/null +++ b/floss/build/README.md @@ -0,0 +1,23 @@ +# Docker build for Floss + +This repo contains the Docker image build rule, used to generate the docker +image necessary to build Floss. If building a new docker image, run +`docker-build-image.py` with the tag `floss:latest`. + +## Using the docker image to build + +Once the Docker image is built (and assuming it's tagged as `floss:latest`), you +should use the `build-in-docker.py` script to build the current repo. + +This script will use the local `floss:latest` (or pull it from the registry), +mount (or create) the `floss-out` volume to `/root/.floss` and the current +source to `/root/src` before running these commands in the container: + +* `cd /root/src` +* `./build.py --run-bootstrap` +* `./build.py --libdir=/usr/lib/x86-64_linux_gnu/` + +If you want to run the build more quickly (or pass other commands), run +`build-in-docker.py --only-start`. This will only start the container for you +(doing the correct mounts) and will print the commands it would have run via +docker exec normally. diff --git a/floss/build/build-in-docker.py b/floss/build/build-in-docker.py new file mode 100755 index 0000000000..a84d2dd7c9 --- /dev/null +++ b/floss/build/build-in-docker.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 + +import argparse +import os +import subprocess +import sys + + +class FlossDockerRunner: + """Runs Floss build inside docker container.""" + + # Commands to run for build + BUILD_COMMANDS = [ + # First run bootstrap to get latest code + create symlinks + ['/root/src/build.py', '--run-bootstrap'], + + # Clean up any previous artifacts inside the volume + ['/root/src/build.py', '--target', 'clean'], + + # Run normal code builder + ['/root/src/build.py', '--target', 'all'], + + # Run tests + ['/root/src/build.py', '--target', 'test'], + ] + + def __init__(self, workdir, rootdir, image_tag, volume_tag): + """ Constructor. + + Args: + workdir: Current working directory (should be the script path). + rootdir: Root directory for Bluetooth. + build_tag: Tag for docker image used for building. + """ + self.workdir = workdir + self.rootdir = rootdir + self.image_tag = image_tag + self.env = os.environ.copy() + + # Name of running container + self.container_name = 'floss-docker-runner' + + # Name of volume where we'll send build output + self.volume_name = volume_tag + + def run_command(self, target, args, cwd=None, env=None, ignore_rc=False): + """ Run command and stream the output. + """ + # Set some defaults + if not cwd: + cwd = self.workdir + if not env: + env = self.env + + rc = 0 + process = subprocess.Popen(args, cwd=cwd, env=env, stdout=subprocess.PIPE) + while True: + line = process.stdout.readline() + print(line.decode('utf-8'), end="") + if not line: + rc = process.poll() + if rc is not None: + break + + time.sleep(0.1) + + if rc != 0 and not ignore_rc: + raise Exception("{} failed. Return code is {}".format(target, rc)) + + def _create_volume_if_needed(self): + # Check if the volume exists. Otherwise create it. + try: + subprocess.check_output(['docker', 'volume', 'inspect', self.volume_name]) + finally: + self.run_command('docker volume create', ['docker', 'volume', 'create', self.volume_name]) + + def start_container(self): + """Starts the docker container with correct mounts.""" + # Stop any previously started container. + self.stop_container(ignore_error=True) + + # Create volume and create mount string + self._create_volume_if_needed() + mount_output_volume = 'type=volume,src={},dst=/root/.floss'.format(self.volume_name) + + # Mount the source directory + mount_src_dir = 'type=bind,src={},dst=/root/src'.format(self.rootdir) + + # Run the docker image. It will run `tail` indefinitely so the container + # doesn't close and we can run `docker exec` on it. + self.run_command('docker run', [ + 'docker', 'run', '--name', self.container_name, '--mount', mount_output_volume, '--mount', mount_src_dir, + '-d', self.image_tag, 'tail', '-f', '/dev/null' + ]) + + def stop_container(self, ignore_error=False): + """Stops the docker container for build.""" + self.run_command('docker stop', ['docker', 'stop', '-t', '1', self.container_name], ignore_rc=ignore_error) + self.run_command('docker rm', ['docker', 'rm', self.container_name], ignore_rc=ignore_error) + + def do_build(self): + """Runs the basic build commands.""" + # Start container before building + self.start_container() + + # Run all commands + for i, cmd in enumerate(self.BUILD_COMMANDS): + self.run_command('docker exec #{}'.format(i), ['docker', 'exec', '-it', self.container_name] + cmd) + + # Stop container before exiting + self.stop_container() + + def print_do_build(self): + """Prints the commands for building.""" + docker_exec = ['docker', 'exec', '-it', self.container_name] + print('Normally, build would run the following commands: \n') + for cmd in self.BUILD_COMMANDS: + print(' '.join(docker_exec + cmd)) + + def check_docker_runnable(self): + try: + subprocess.check_output(['docker', 'ps'], stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as err: + if 'denied' in err.output.decode('utf-8'): + print('Run script as sudo') + else: + print('Unexpected error: {}'.format(err.output.decode('utf-8'))) + + return False + + # No exception means docker is ok + return True + + +if __name__ == "__main__": + parser = argparse.ArgumentParser('Builder Floss inside docker image.') + parser.add_argument( + '--only-start', + action='store_true', + default=False, + help='Only start the container. Prints the commands it would have ran.') + parser.add_argument('--only-stop', action='store_true', default=False, help='Only stop the container and exit.') + parser.add_argument('--image-tag', default='floss:latest', help='Docker image to use to build.') + parser.add_argument('--volume-tag', default='floss-out', help='Name of volume to use.') + args = parser.parse_args() + + # cwd should be set to same directory as this script (that's where Dockerfile + # is kept). + workdir = os.path.dirname(os.path.abspath(sys.argv[0])) + rootdir = os.path.abspath(os.path.join(workdir, '../..')) + + fdr = FlossDockerRunner(workdir, rootdir, args.image_tag, args.volume_tag) + + # Make sure docker is runnable before continuing + if fdr.check_docker_runnable(): + # Handle some flags + if args.only_start: + fdr.start_container() + fdr.print_do_build() + elif args.only_stop: + fdr.stop_container() + else: + fdr.do_build() diff --git a/floss/build/docker-build-image.py b/floss/build/docker-build-image.py new file mode 100755 index 0000000000..81b622b87b --- /dev/null +++ b/floss/build/docker-build-image.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 + +import argparse +import os +import sys +import subprocess + +SRC_MOUNT = "/root/src" + + +class DockerImageBuilder: + """Builds the docker image for Floss build environment.""" + + def __init__(self, workdir, rootdir, tag): + """ Constructor. + + Args: + workdir: Working directory for this script. Dockerfile should exist here. + rootdir: Root directory for Bluetooth. + tag: Label in format |name:version|. + """ + self.workdir = workdir + self.rootdir = rootdir + (self.name, self.version) = tag.split(':') + self.build_tag = '{}:{}'.format(self.name, 'buildtemp') + self.container_name = 'floss-buildtemp' + self.final_tag = tag + self.env = os.environ.copy() + + # Mark dpkg builders for docker + self.env['LIBCHROME_DOCKER'] = '1' + self.env['MODP_DOCKER'] = '1' + + def run_command(self, target, args, cwd=None, env=None, ignore_rc=False): + """ Run command and stream the output. + """ + # Set some defaults + if not cwd: + cwd = self.workdir + if not env: + env = self.env + + rc = 0 + process = subprocess.Popen(args, cwd=cwd, env=env, stdout=subprocess.PIPE) + while True: + line = process.stdout.readline() + print(line.decode('utf-8'), end="") + if not line: + rc = process.poll() + if rc is not None: + break + + time.sleep(0.1) + + if rc != 0 and not ignore_rc: + raise Exception("{} failed. Return code is {}".format(target, rc)) + + def _docker_build(self): + self.run_command('docker build', ['docker', 'build', '-t', self.build_tag, '.']) + + def _build_dpkg_and_commit(self): + # Try to remove any previous instance of the container that may be + # running if this script didn't complete cleanly last time. + self.run_command('docker stop', ['docker', 'stop', '-t', '1', self.container_name], ignore_rc=True) + self.run_command('docker rm', ['docker', 'rm', self.container_name], ignore_rc=True) + + # Runs never terminating application on the newly built image in detached mode + mount_str = 'type=bind,src={},dst={},readonly'.format(self.rootdir, SRC_MOUNT) + self.run_command('docker run', [ + 'docker', 'run', '--name', self.container_name, '--mount', mount_str, '-d', self.build_tag, 'tail', '-f', + '/dev/null' + ]) + + commands = [ + # Create the output directories + ['mkdir', '-p', '/tmp/libchrome', '/tmp/modpb64'], + + # Run the dpkg builder for modp_b64 + ['/root/src/system/build/dpkg/modp_b64/gen-src-pkg.sh', '/tmp/modpb64'], + + # Install modp_b64 since libchrome depends on it + ['find', '/tmp/modpb64', '-name', 'modp*.deb', '-exec', 'dpkg', '-i', '{}', '+'], + + # Run the dpkg builder for libchrome + ['/root/src/system/build/dpkg/libchrome/gen-src-pkg.sh', '/tmp/libchrome'], + + # Install libchrome. + ['find', '/tmp/libchrome', '-name', 'libchrome_*.deb', '-exec', 'dpkg', '-i', '{}', '+'], + + # Delete intermediate files + ['rm', '-rf', '/tmp/libchrome', '/tmp/modpb64'], + ] + + # Run commands in container first to install everything. + for i, cmd in enumerate(commands): + self.run_command('docker exec #{}'.format(i), ['docker', 'exec', '-it', self.container_name] + cmd) + + # Commit changes into the final tag name + self.run_command('docker commit', ['docker', 'commit', self.container_name, self.final_tag]) + + # Stop running the container and remove it + self.run_command('docker stop', ['docker', 'stop', '-t', '1', self.container_name]) + self.run_command('docker rm', ['docker', 'rm', self.container_name]) + + def _check_docker_runnable(self): + try: + subprocess.check_output(['docker', 'ps'], stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as err: + if 'denied' in err.output.decode('utf-8'): + print('Run script as sudo') + else: + print('Unexpected error: {}'.format(err.output.decode('utf-8'))) + + return False + + # No exception means docker is ok + return True + + def build(self): + if not self._check_docker_runnable(): + return + + # First build the docker image + self._docker_build() + + # Then build libchrome and modp-b64 inside the docker image and install + # them. Commit those changes to the final label. + self._build_dpkg_and_commit() + + +def main(): + parser = argparse.ArgumentParser(description='Build docker image for Floss build environment.') + parser.add_argument('--tag', required=True, help='Tag for docker image. i.e. floss:latest') + args = parser.parse_args() + + # cwd should be set to same directory as this script (that's where Dockerfile + # is kept). + workdir = os.path.dirname(os.path.abspath(sys.argv[0])) + rootdir = os.path.abspath(os.path.join(workdir, '../..')) + + # Build the docker image + dib = DockerImageBuilder(workdir, rootdir, args.tag) + dib.build() + + +if __name__ == '__main__': + main() diff --git a/floss/build/llvm-rename.sh b/floss/build/llvm-rename.sh new file mode 100755 index 0000000000..454d19bf99 --- /dev/null +++ b/floss/build/llvm-rename.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +# Rename all llvm binaries using update-alternatives +# Without this, the llvm binaries must have the version appended at the end +# instead of just using the base name +function rename_llvm_binaries { + version=$1 + priority=100 + + update-alternatives \ + --install /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-${version} ${priority} \ + --slave /usr/bin/llvm-ar llvm-ar /usr/bin/llvm-ar-${version} \ + --slave /usr/bin/llvm-as llvm-as /usr/bin/llvm-as-${version} \ + --slave /usr/bin/llvm-bcanalyzer llvm-bcanalyzer /usr/bin/llvm-bcanalyzer-${version} \ + --slave /usr/bin/llvm-cov llvm-cov /usr/bin/llvm-cov-${version} \ + --slave /usr/bin/llvm-diff llvm-diff /usr/bin/llvm-diff-${version} \ + --slave /usr/bin/llvm-dis llvm-dis /usr/bin/llvm-dis-${version} \ + --slave /usr/bin/llvm-dwarfdump llvm-dwarfdump /usr/bin/llvm-dwarfdump-${version} \ + --slave /usr/bin/llvm-extract llvm-extract /usr/bin/llvm-extract-${version} \ + --slave /usr/bin/llvm-link llvm-link /usr/bin/llvm-link-${version} \ + --slave /usr/bin/llvm-mc llvm-mc /usr/bin/llvm-mc-${version} \ + --slave /usr/bin/llvm-mcmarkup llvm-mcmarkup /usr/bin/llvm-mcmarkup-${version} \ + --slave /usr/bin/llvm-nm llvm-nm /usr/bin/llvm-nm-${version} \ + --slave /usr/bin/llvm-objdump llvm-objdump /usr/bin/llvm-objdump-${version} \ + --slave /usr/bin/llvm-ranlib llvm-ranlib /usr/bin/llvm-ranlib-${version} \ + --slave /usr/bin/llvm-readobj llvm-readobj /usr/bin/llvm-readobj-${version} \ + --slave /usr/bin/llvm-rtdyld llvm-rtdyld /usr/bin/llvm-rtdyld-${version} \ + --slave /usr/bin/llvm-size llvm-size /usr/bin/llvm-size-${version} \ + --slave /usr/bin/llvm-stress llvm-stress /usr/bin/llvm-stress-${version} \ + --slave /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-${version} \ + --slave /usr/bin/llvm-tblgen llvm-tblgen /usr/bin/llvm-tblgen-${version} + + update-alternatives \ + --install /usr/bin/clang clang /usr/bin/clang-${version} ${priority} \ + --slave /usr/bin/clang++ clang++ /usr/bin/clang++-${version} \ + --slave /usr/bin/asan_symbolize asan_symbolize /usr/bin/asan_symbolize-${version} \ + --slave /usr/bin/c-index-test c-index-test /usr/bin/c-index-test-${version} \ + --slave /usr/bin/clang-check clang-check /usr/bin/clang-check-${version} \ + --slave /usr/bin/clang-cl clang-cl /usr/bin/clang-cl-${version} \ + --slave /usr/bin/clang-cpp clang-cpp /usr/bin/clang-cpp-${version} \ + --slave /usr/bin/clang-format clang-format /usr/bin/clang-format-${version} \ + --slave /usr/bin/clang-format-diff clang-format-diff /usr/bin/clang-format-diff-${version} \ + --slave /usr/bin/clang-import-test clang-import-test /usr/bin/clang-import-test-${version} \ + --slave /usr/bin/clang-include-fixer clang-include-fixer /usr/bin/clang-include-fixer-${version} \ + --slave /usr/bin/clang-offload-bundler clang-offload-bundler /usr/bin/clang-offload-bundler-${version} \ + --slave /usr/bin/clang-query clang-query /usr/bin/clang-query-${version} \ + --slave /usr/bin/clang-rename clang-rename /usr/bin/clang-rename-${version} \ + --slave /usr/bin/clang-reorder-fields clang-reorder-fields /usr/bin/clang-reorder-fields-${version} \ + --slave /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-${version} \ + --slave /usr/bin/lldb lldb /usr/bin/lldb-${version} \ + --slave /usr/bin/lldb-server lldb-server /usr/bin/lldb-server-${version} + + # Use clang instead of cc by default + update-alternatives --install /usr/bin/cc cc /usr/bin/clang $priority +} + +rename_llvm_binaries $@ diff --git a/framework/Android.bp b/framework/Android.bp index 5601d9db57..a3bacd226b 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -82,10 +82,10 @@ java_sdk_library { }, } -// defaults for CTS tests that need to build against framework-bluetooths's @hide APIs +// defaults for tests that need to build against framework-bluetooths's @hide APIs java_defaults { - name: "framework-bluetooth-cts-defaults", - sdk_version: "core_current", + name: "framework-bluetooth-tests-defaults", + sdk_version: "core_platform", libs: [ // order matters: classes in framework-bluetooth are resolved before framework, meaning // @hide APIs in framework-bluetooth are resolved before @SystemApi stubs in framework diff --git a/framework/java/android/bluetooth/OWNERS b/framework/OWNERS index bf15cf08bd..fbee577731 100644 --- a/framework/java/android/bluetooth/OWNERS +++ b/framework/OWNERS @@ -1,5 +1,3 @@ -set noparent - # Bug component: 27441 rahulsabnis@google.com diff --git a/framework/api/current.txt b/framework/api/current.txt index bb9e85e11c..659323fe54 100644 --- a/framework/api/current.txt +++ b/framework/api/current.txt @@ -17,8 +17,8 @@ package android.bluetooth { method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean cancelDiscovery(); method public static boolean checkBluetoothAddress(String); method public void closeProfileProxy(int, android.bluetooth.BluetoothProfile); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disable(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enable(); + method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disable(); + method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enable(); method public String getAddress(); method public android.bluetooth.le.BluetoothLeAdvertiser getBluetoothLeAdvertiser(); method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner(); diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 43e1792c26..a47cc0a506 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -54,7 +54,6 @@ package android.bluetooth { public final class BluetoothAdapter { method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean addOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int closeRfcommServer(@NonNull java.util.UUID); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean disable(boolean); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disableBLE(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enableBLE(); @@ -80,6 +79,7 @@ package android.bluetooth { method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int setDiscoverableTimeout(@NonNull java.time.Duration); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int setScanMode(int); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int startRfcommServer(@NonNull String, @NonNull java.util.UUID, @NonNull android.app.PendingIntent); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int stopRfcommServer(@NonNull java.util.UUID); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean unregisterBluetoothConnectionCallback(@NonNull android.bluetooth.BluetoothAdapter.BluetoothConnectionCallback); method public void unregisterServiceLifecycleCallback(@NonNull android.bluetooth.BluetoothAdapter.ServiceLifecycleCallback); field public static final String ACTION_BLE_STATE_CHANGED = "android.bluetooth.adapter.action.BLE_STATE_CHANGED"; @@ -88,6 +88,7 @@ package android.bluetooth { field public static final int ACTIVE_DEVICE_ALL = 2; // 0x2 field public static final int ACTIVE_DEVICE_AUDIO = 0; // 0x0 field public static final int ACTIVE_DEVICE_PHONE_CALL = 1; // 0x1 + field public static final String EXTRA_RFCOMM_LISTENER_ID = "android.bluetooth.adapter.extra.RFCOMM_LISTENER_ID"; field public static final int STATE_BLE_ON = 15; // 0xf } @@ -151,7 +152,6 @@ package android.bluetooth { public final class BluetoothDevice implements android.os.Parcelable { method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean canBondWithoutDialog(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean cancelBondProcess(); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean cancelPairing(); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public int connect(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBond(int); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBondOutOfBand(int, @Nullable android.bluetooth.OobData, @Nullable android.bluetooth.OobData); @@ -301,10 +301,10 @@ package android.bluetooth { public static final class BluetoothHapPresetInfo.Builder { ctor public BluetoothHapPresetInfo.Builder(); method @NonNull public android.bluetooth.BluetoothHapPresetInfo build(); - method @NonNull public android.bluetooth.BluetoothHapPresetInfo.Builder setAvailable(@NonNull boolean); + method @NonNull public android.bluetooth.BluetoothHapPresetInfo.Builder setAvailable(boolean); method @NonNull public android.bluetooth.BluetoothHapPresetInfo.Builder setIndex(int); method @NonNull public android.bluetooth.BluetoothHapPresetInfo.Builder setName(@NonNull String); - method @NonNull public android.bluetooth.BluetoothHapPresetInfo.Builder setWritable(@NonNull boolean); + method @NonNull public android.bluetooth.BluetoothHapPresetInfo.Builder setWritable(boolean); } public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile { @@ -328,14 +328,26 @@ package android.bluetooth { method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice); method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]); + method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public android.bluetooth.BluetoothHeadsetClient.NetworkServiceState getNetworkServiceState(@NonNull android.bluetooth.BluetoothDevice); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_AUDIO_STATE_CHANGED = "android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED"; field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED"; + field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_NETWORK_SERVICE_STATE_CHANGED = "android.bluetooth.headsetclient.profile.action.NETWORK_SERVICE_STATE_CHANGED"; + field public static final String EXTRA_NETWORK_SERVICE_STATE = "android.bluetooth.headsetclient.extra.EXTRA_NETWORK_SERVICE_STATE"; field public static final int STATE_AUDIO_CONNECTED = 2; // 0x2 field public static final int STATE_AUDIO_CONNECTING = 1; // 0x1 field public static final int STATE_AUDIO_DISCONNECTED = 0; // 0x0 } + public static final class BluetoothHeadsetClient.NetworkServiceState implements android.os.Parcelable { + method @NonNull public android.bluetooth.BluetoothDevice getDevice(); + method @Nullable public String getOperatorName(); + method public int getSignalStrength(); + method public boolean isRoaming(); + method public boolean isServiceAvailable(); + field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHeadsetClient.NetworkServiceState> CREATOR; + } + public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile { method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public long getHiSyncId(@NonNull android.bluetooth.BluetoothDevice); @@ -604,8 +616,8 @@ package android.bluetooth { } public interface BluetoothProfile { - method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static String getConnectionStateName(int); - method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static String getProfileName(int); + method @NonNull public static String getConnectionStateName(int); + method @NonNull public static String getProfileName(int); field public static final int A2DP_SINK = 11; // 0xb field public static final int AVRCP_CONTROLLER = 12; // 0xc field public static final int CONNECTION_POLICY_ALLOWED = 100; // 0x64 @@ -660,7 +672,7 @@ package android.bluetooth { field public static final int ERROR_PROFILE_NOT_CONNECTED = 14; // 0xe field public static final int ERROR_REMOTE_LINK_ERROR = 25; // 0x19 field public static final int ERROR_REMOTE_NOT_ENOUGH_RESOURCES = 23; // 0x17 - field public static final int ERROR_REMOTE_OPERATION_NOT_SUPPORTED = 24; // 0x18 + field public static final int ERROR_REMOTE_OPERATION_NOT_SUPPORTED = 27; // 0x1b field public static final int ERROR_REMOTE_OPERATION_REJECTED = 24; // 0x18 field public static final int ERROR_TIMEOUT = 15; // 0xf field public static final int NOT_ALLOWED = 401; // 0x191 @@ -685,6 +697,7 @@ package android.bluetooth { field @NonNull public static final android.os.ParcelUuid AVRCP_CONTROLLER; field @NonNull public static final android.os.ParcelUuid AVRCP_TARGET; field @NonNull public static final android.os.ParcelUuid BASE_UUID; + field @NonNull public static final android.os.ParcelUuid BASS; field @NonNull public static final android.os.ParcelUuid BNEP; field @NonNull public static final android.os.ParcelUuid CAP; field @NonNull public static final android.os.ParcelUuid COORDINATED_SET; diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index 05c67f360a..dc7ffa6fd2 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -251,6 +251,8 @@ public final class BluetoothAdapter { * * @hide */ + @SystemApi + @SuppressLint("ActionValue") public static final String EXTRA_RFCOMM_LISTENER_ID = "android.bluetooth.adapter.extra.RFCOMM_LISTENER_ID"; @@ -1137,9 +1139,7 @@ public final class BluetoothAdapter { try { final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); - if (mService != null) { - mService.getState(recv); - } + mService.getState(recv); return recv.awaitResultNoInterrupt(getSyncTimeout()) .getValue(BluetoothAdapter.STATE_OFF); } catch (TimeoutException e) { @@ -1183,11 +1183,8 @@ public final class BluetoothAdapter { mService.getState(recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(state); } - } catch (TimeoutException e) { + } catch (RemoteException | TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } catch (RemoteException e) { - Log.e(TAG, "", e); - e.rethrowFromSystemServer(); } finally { mServiceLock.readLock().unlock(); } @@ -1289,7 +1286,20 @@ public final class BluetoothAdapter { * such as Airplane mode, or the adapter is already turned on. * * @return true to indicate adapter startup has begun, or false on immediate error + * + * @deprecated Starting with {@link android.os.Build.VERSION_CODES#TIRAMISU}, applications + * are not allowed to enable/disable Bluetooth. + * <b>Compatibility Note:</b> For applications targeting + * {@link android.os.Build.VERSION_CODES#TIRAMISU} or above, this API will always fail and return + * {@code false}. If apps are targeting an older SDK ({@link android.os.Build.VERSION_CODES#S} + * or below), they can continue to use this API. + * <p> + * Deprecation Exemptions: + * <ul> + * <li>Device Owner (DO), Profile Owner (PO) and system apps. + * </ul> */ + @Deprecated @RequiresLegacyBluetoothAdminPermission @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) @@ -1329,7 +1339,20 @@ public final class BluetoothAdapter { * such as the adapter already being turned off. * * @return true to indicate adapter shutdown has begun, or false on immediate error + * + * @deprecated Starting with {@link android.os.Build.VERSION_CODES#TIRAMISU}, applications + * are not allowed to enable/disable Bluetooth. + * <b>Compatibility Note:</b> For applications targeting + * {@link android.os.Build.VERSION_CODES#TIRAMISU} or above, this API will always fail and return + * {@code false}. If apps are targeting an older SDK ({@link android.os.Build.VERSION_CODES#S} + * or below), they can continue to use this API. + * <p> + * Deprecation Exemptions: + * <ul> + * <li>Device Owner (DO), Profile Owner (PO) and system apps. + * </ul> */ + @Deprecated @RequiresLegacyBluetoothAdminPermission @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) @@ -3139,7 +3162,7 @@ public final class BluetoothAdapter { android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) @RfcommListenerResult - public int closeRfcommServer(@NonNull UUID uuid) { + public int stopRfcommServer(@NonNull UUID uuid) { try { final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); mService.stopRfcommListener(new ParcelUuid(uuid), mAttributionSource, recv); diff --git a/framework/java/android/bluetooth/BluetoothClass.java b/framework/java/android/bluetooth/BluetoothClass.java index 699c80e5b6..fb13be4672 100755 --- a/framework/java/android/bluetooth/BluetoothClass.java +++ b/framework/java/android/bluetooth/BluetoothClass.java @@ -18,7 +18,6 @@ package android.bluetooth; import android.annotation.Nullable; import android.annotation.SystemApi; -import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; @@ -307,7 +306,6 @@ public final class BluetoothClass implements Parcelable { * * @hide */ - @TestApi public int getClassOfDevice() { return mClass; } diff --git a/framework/java/android/bluetooth/BluetoothDevice.java b/framework/java/android/bluetooth/BluetoothDevice.java index 2b335abc84..9caed4ccac 100644 --- a/framework/java/android/bluetooth/BluetoothDevice.java +++ b/framework/java/android/bluetooth/BluetoothDevice.java @@ -2545,39 +2545,6 @@ public final class BluetoothDevice implements Parcelable, Attributable { return defaultValue; } - /** - * Cancels pairing to this device - * - * @return true if pairing cancelled successfully, false otherwise - * - * @hide - */ - @SystemApi - @RequiresLegacyBluetoothAdminPermission - @RequiresBluetoothConnectPermission - @RequiresPermission(allOf = { - android.Manifest.permission.BLUETOOTH_CONNECT, - android.Manifest.permission.BLUETOOTH_PRIVILEGED, - }) - public boolean cancelPairing() { - if (DBG) log("cancelPairing()"); - final IBluetooth service = sService; - final boolean defaultValue = false; - if (service == null) { - Log.e(TAG, "BT not enabled. Cannot cancel pairing"); - if (DBG) log(Log.getStackTraceString(new Throwable())); - } else { - try { - final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); - service.cancelBondProcess(this, mAttributionSource, recv); - return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - } catch (RemoteException | TimeoutException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } - } - return defaultValue; - } - boolean isBluetoothEnabled() { boolean ret = false; BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); diff --git a/framework/java/android/bluetooth/BluetoothHapClient.java b/framework/java/android/bluetooth/BluetoothHapClient.java index 2b245bcb41..fd769d412b 100644 --- a/framework/java/android/bluetooth/BluetoothHapClient.java +++ b/framework/java/android/bluetooth/BluetoothHapClient.java @@ -25,6 +25,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.content.AttributionSource; @@ -39,7 +40,9 @@ import com.android.modules.utils.SynchronousResultReceiver; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.TimeoutException; @@ -58,6 +61,8 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable private static final boolean DBG = false; private static final boolean VDBG = false; + private final Map<Callback, Executor> mCallbackExecutorMap = new HashMap<>(); + private CloseGuard mCloseGuard; /** @@ -83,17 +88,6 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable }) @interface Status {} - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(value = { - PRESET_INFO_REASON_ALL_PRESET_INFO, - PRESET_INFO_REASON_PRESET_INFO_UPDATE, - PRESET_INFO_REASON_PRESET_DELETED, - PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED, - PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE, - }) - @interface PresetInfoReason {} - /** * Invoked to inform about HA device's currently active preset. * @@ -180,6 +174,87 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable void onSetPresetNameForGroupFailed(int hapGroupId, @Status int status); } + @SuppressLint("AndroidFrameworkBluetoothPermission") + private final IBluetoothHapClientCallback mCallback = new IBluetoothHapClientCallback.Stub() { + @Override + public void onActivePresetChanged(@NonNull BluetoothDevice device, int presetIndex) { + Attributable.setAttributionSource(device, mAttributionSource); + for (Map.Entry<BluetoothHapClient.Callback, Executor> callbackExecutorEntry: + mCallbackExecutorMap.entrySet()) { + BluetoothHapClient.Callback callback = callbackExecutorEntry.getKey(); + Executor executor = callbackExecutorEntry.getValue(); + executor.execute(() -> callback.onActivePresetChanged(device, presetIndex)); + } + } + + @Override + public void onSelectActivePresetFailed(@NonNull BluetoothDevice device, int status) { + Attributable.setAttributionSource(device, mAttributionSource); + for (Map.Entry<BluetoothHapClient.Callback, Executor> callbackExecutorEntry: + mCallbackExecutorMap.entrySet()) { + BluetoothHapClient.Callback callback = callbackExecutorEntry.getKey(); + Executor executor = callbackExecutorEntry.getValue(); + executor.execute(() -> callback.onSelectActivePresetFailed(device, status)); + } + } + + @Override + public void onSelectActivePresetForGroupFailed(int hapGroupId, int statusCode) { + for (Map.Entry<BluetoothHapClient.Callback, Executor> callbackExecutorEntry: + mCallbackExecutorMap.entrySet()) { + BluetoothHapClient.Callback callback = callbackExecutorEntry.getKey(); + Executor executor = callbackExecutorEntry.getValue(); + executor.execute( + () -> callback.onSelectActivePresetForGroupFailed(hapGroupId, statusCode)); + } + } + + @Override + public void onPresetInfoChanged(@NonNull BluetoothDevice device, + @NonNull List<BluetoothHapPresetInfo> presetInfoList, int statusCode) { + Attributable.setAttributionSource(device, mAttributionSource); + for (Map.Entry<BluetoothHapClient.Callback, Executor> callbackExecutorEntry: + mCallbackExecutorMap.entrySet()) { + BluetoothHapClient.Callback callback = callbackExecutorEntry.getKey(); + Executor executor = callbackExecutorEntry.getValue(); + executor.execute( + () -> callback.onPresetInfoChanged(device, presetInfoList, statusCode)); + } + } + + @Override + public void onHapFeaturesAvailable(@NonNull BluetoothDevice device, int hapFeatures) { + Attributable.setAttributionSource(device, mAttributionSource); + for (Map.Entry<BluetoothHapClient.Callback, Executor> callbackExecutorEntry: + mCallbackExecutorMap.entrySet()) { + BluetoothHapClient.Callback callback = callbackExecutorEntry.getKey(); + Executor executor = callbackExecutorEntry.getValue(); + executor.execute(() -> callback.onHapFeaturesAvailable(device, hapFeatures)); + } + } + + @Override + public void onSetPresetNameFailed(@NonNull BluetoothDevice device, int status) { + Attributable.setAttributionSource(device, mAttributionSource); + for (Map.Entry<BluetoothHapClient.Callback, Executor> callbackExecutorEntry: + mCallbackExecutorMap.entrySet()) { + BluetoothHapClient.Callback callback = callbackExecutorEntry.getKey(); + Executor executor = callbackExecutorEntry.getValue(); + executor.execute(() -> callback.onSetPresetNameFailed(device, status)); + } + } + + @Override + public void onSetPresetNameForGroupFailed(int hapGroupId, int status) { + for (Map.Entry<BluetoothHapClient.Callback, Executor> callbackExecutorEntry: + mCallbackExecutorMap.entrySet()) { + BluetoothHapClient.Callback callback = callbackExecutorEntry.getKey(); + Executor executor = callbackExecutorEntry.getValue(); + executor.execute(() -> callback.onSetPresetNameForGroupFailed(hapGroupId, status)); + } + } + }; + /** * Intent used to broadcast the change in connection state of the Hearing Access Profile Client * service. Please note that in the binaural case, there will be two different LE devices for @@ -229,235 +304,12 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable "android.bluetooth.action.HAP_DEVICE_AVAILABLE"; /** - * Intent used to broadcast HA device's feature set. - * - * <p>This intent will have 2 extras: - * <ul> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> - * <li> {@link #EXTRA_HAP_FEATURES}- The feature set integer with these possible bit numbers - * set: {@link #FEATURE_BIT_NUM_TYPE_MONAURAL}, {@link #FEATURE_BIT_NUM_TYPE_BANDED}, - * {@link #FEATURE_BIT_NUM_SYNCHRONIZATED_PRESETS}, - * {@link #FEATURE_BIT_NUM_INDEPENDENT_PRESETS}, {@link #FEATURE_BIT_NUM_DYNAMIC_PRESETS}, - * {@link #FEATURE_BIT_NUM_WRITABLE_PRESETS}.</li> - * </ul> - * - * @hide - */ - @RequiresPermission(allOf = { - android.Manifest.permission.BLUETOOTH_CONNECT, - android.Manifest.permission.BLUETOOTH_PRIVILEGED, - }) - @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_HAP_ON_DEVICE_FEATURES = - "android.bluetooth.action.HAP_ON_DEVICE_FEATURES"; - - /** - * Intent used to broadcast the change of a HA device's active preset. - * - * <p>This intent will have 2 extras: - * <ul> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> - * <li> {@link #EXTRA_HAP_PRESET_INDEX}- The currently active preset.</li> - * </ul> - * - * @hide - */ - @RequiresPermission(allOf = { - android.Manifest.permission.BLUETOOTH_CONNECT, - android.Manifest.permission.BLUETOOTH_PRIVILEGED, - }) - @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_HAP_ON_ACTIVE_PRESET = - "android.bluetooth.action.HAP_ON_ACTIVE_PRESET"; - - /** - * Intent used to broadcast the result of a failed preset change attempt. - * - * <p>This intent will have 2 extras: - * <ul> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> - * <li> {@link #EXTRA_HAP_STATUS_CODE}- Failure reason.</li> - * </ul> - * - * <p>{@link #EXTRA_HAP_STATUS_CODE} can be any of {@link #STATUS_INVALID_PRESET_INDEX}, - * {@link #STATUS_OPERATION_NOT_POSSIBLE},{@link #STATUS_OPERATION_NOT_SUPPORTED}. - * - * @hide - */ - @RequiresPermission(allOf = { - android.Manifest.permission.BLUETOOTH_CONNECT, - android.Manifest.permission.BLUETOOTH_PRIVILEGED, - }) - @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_HAP_ON_ACTIVE_PRESET_SELECT_ERROR = - "android.bluetooth.action.HAP_ON_ACTIVE_PRESET_SELECT_ERROR"; - - /** - * Intent used to broadcast preset name change. - * - * <p>This intent will have 4 extras: - * <ul> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> - * <li> {@link #EXTRA_HAP_PRESET_INFO}- List of preset informations </li> - * <li> {@link #EXTRA_HAP_PRESET_INFO_REASON}- Why this preset info notification was sent </li> - * notifications or the user should expect more to come. </li> - * </ul> - * - * @hide - */ - @RequiresPermission(allOf = { - android.Manifest.permission.BLUETOOTH_CONNECT, - android.Manifest.permission.BLUETOOTH_PRIVILEGED, - }) - @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_HAP_ON_PRESET_INFO = - "android.bluetooth.action.HAP_ON_PRESET_INFO"; - - /** - * Intent used to broadcast result of a failed rename attempt. - * - * <p>This intent will have 3 extras: - * <ul> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> - * <li> {@link #EXTRA_HAP_PRESET_INDEX}- The currently active preset.</li> - * <li> {@link #EXTRA_HAP_STATUS_CODE}- Failure reason code.</li> - * </ul> - * - * <p>{@link #EXTRA_HAP_STATUS_CODE} can be any of {@link #STATUS_SET_NAME_NOT_ALLOWED}, - * {@link #STATUS_INVALID_PRESET_INDEX}, {@link #STATUS_INVALID_PRESET_NAME_LENGTH}. - * - * @hide - */ - @RequiresPermission(allOf = { - android.Manifest.permission.BLUETOOTH_CONNECT, - android.Manifest.permission.BLUETOOTH_PRIVILEGED, - }) - @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_HAP_ON_PRESET_NAME_SET_ERROR = - "android.bluetooth.action.HAP_ON_PRESET_NAME_SET_ERROR"; - - /** - * Intent used to broadcast the result of a failed name get attempt. - * - * <p>This intent will have 3 extras: - * <ul> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> - * <li> {@link #EXTRA_HAP_PRESET_INDEX}- The currently active preset.</li> - * <li> {@link #EXTRA_HAP_STATUS_CODE}- Failure reason code.</li> - * </ul> - * - * <p>{@link #EXTRA_HAP_STATUS_CODE} can be any of {@link #STATUS_INVALID_PRESET_INDEX}, - * {@link #STATUS_OPERATION_NOT_POSSIBLE}. - * - * @hide - */ - @RequiresPermission(allOf = { - android.Manifest.permission.BLUETOOTH_CONNECT, - android.Manifest.permission.BLUETOOTH_PRIVILEGED, - }) - @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_HAP_ON_PRESET_INFO_GET_ERROR = - "android.bluetooth.action.HAP_ON_PRESET_INFO_GET_ERROR"; - - /** * Contains a list of all available presets * @hide */ public static final String EXTRA_HAP_FEATURES = "android.bluetooth.extra.HAP_FEATURES"; /** - * Contains a preset identifier - * @hide - */ - public static final String EXTRA_HAP_PRESET_INDEX = "android.bluetooth.extra.HAP_PRESET_INDEX"; - - /** - * Used to report failure reasons. - * @hide - */ - public static final String EXTRA_HAP_STATUS_CODE = "android.bluetooth.extra.HAP_STATUS_CODE"; - - /** - * Used by group events. - * @hide - */ - public static final String EXTRA_HAP_GROUP_ID = "android.bluetooth.extra.HAP_GROUP_ID"; - - /** - * Preset Info reason. - * Possible values: - * {@link #PRESET_INFO_REASON_ALL_PRESET_INFO} or - * {@link #PRESET_INFO_REASON_PRESET_INFO_UPDATE} or - * {@link #PRESET_INFO_REASON_PRESET_DELETED} or - * {@link #PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED} or - * {@link #PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE} - * @hide - */ - public static final String EXTRA_HAP_PRESET_INFO_REASON = - "android.bluetooth.extra.HAP_PRESET_INFO_REASON"; - - /** - * Preset Info. - * @hide - */ - public static final String EXTRA_HAP_PRESET_INFO = "android.bluetooth.extra.HAP_PRESET_INFO"; - - /** - * Preset name change failure due to preset being read-only. - * @hide - */ - public static final int STATUS_SET_NAME_NOT_ALLOWED = - IBluetoothHapClient.STATUS_SET_NAME_NOT_ALLOWED; - - /** - * Means that the requested operation is not supported by the HA device. - * - * <p> It could mean that the requested name change is not supported on - * a given preset or the device does not support presets at all. - * @hide - */ - public static final int STATUS_OPERATION_NOT_SUPPORTED = - IBluetoothHapClient.STATUS_OPERATION_NOT_SUPPORTED; - - /** - * Usually means a temporary denial of certain operation. Peer device may report this - * status due to various implementation specific reasons. It's different than - * the {@link #STATUS_OPERATION_NOT_SUPPORTED} which represents more of a - * permanent inability to perform some of the operations. - * @hide - */ - public static final int STATUS_OPERATION_NOT_POSSIBLE = - IBluetoothHapClient.STATUS_OPERATION_NOT_POSSIBLE; - - /** - * Used when preset name change failed due to the passed name parameter being to long. - * @hide - */ - public static final int STATUS_INVALID_PRESET_NAME_LENGTH = - IBluetoothHapClient.STATUS_INVALID_PRESET_NAME_LENGTH; - - /** - * Group operations are not supported. - * @hide - */ - public static final int STATUS_GROUP_OPERATION_NOT_SUPPORTED = - IBluetoothHapClient.STATUS_GROUP_OPERATION_NOT_SUPPORTED; - - /** - * Procedure is already in progress. - * @hide - */ - public static final int STATUS_PROCEDURE_ALREADY_IN_PROGRESS = - IBluetoothHapClient.STATUS_PROCEDURE_ALREADY_IN_PROGRESS; - - /** - * Invalid preset index input parameter used in one of the API calls. - * @hide - */ - public static final int STATUS_INVALID_PRESET_INDEX = - IBluetoothHapClient.STATUS_INVALID_PRESET_INDEX; - - /** * Represets an invalid index value. This is usually value returned in a currently * active preset request for a device which is not connected. This value shouldn't be used * in the API calls. @@ -507,48 +359,6 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable public static final int FEATURE_BIT_NUM_WRITABLE_PRESETS = IBluetoothHapClient.FEATURE_BIT_NUM_WRITABLE_PRESETS; - /** - * Preset Info notification reason. - * @hide - */ - public static final int PRESET_INFO_REASON_ALL_PRESET_INFO = - IBluetoothHapClient.PRESET_INFO_REASON_ALL_PRESET_INFO; - - /** - * Preset Info notification reason. - * @hide - */ - public static final int PRESET_INFO_REASON_PRESET_INFO_UPDATE = - IBluetoothHapClient.PRESET_INFO_REASON_PRESET_INFO_UPDATE; - - /** - * Preset Info notification reason. - * @hide - */ - public static final int PRESET_INFO_REASON_PRESET_DELETED = - IBluetoothHapClient.PRESET_INFO_REASON_PRESET_DELETED; - - /** - * Preset Info notification reason. - * @hide - */ - public static final int PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED = - IBluetoothHapClient.PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED; - - /** - * Preset Info notification reason. - * @hide - */ - public static final int PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE = - IBluetoothHapClient.PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE; - - /** - * Represents invalid group identifier. It's returned when user requests a group identifier - * for a device which is not part of any group. This value shouldn't be used in the API calls. - * @hide - */ - public static final int HAP_GROUP_UNAVAILABLE = IBluetoothHapClient.GROUP_ID_UNAVAILABLE; - private final BluetoothAdapter mAdapter; private final AttributionSource mAttributionSource; private final BluetoothProfileConnector<IBluetoothHapClient> mProfileConnector = @@ -560,6 +370,35 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable } }; + @SuppressLint("AndroidFrameworkBluetoothPermission") + private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { + public void onBluetoothStateChange(boolean up) { + if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); + if (up) { + // re-register the service-to-app callback + synchronized (mCallbackExecutorMap) { + if (mCallbackExecutorMap.isEmpty()) return; + + try { + final IBluetoothHapClient service = getService(); + if (service != null) { + final SynchronousResultReceiver<Integer> recv = + new SynchronousResultReceiver(); + service.registerCallback(mCallback, mAttributionSource, recv); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); + } + } catch (TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + + Log.getStackTraceString(new Throwable())); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + } + }; + /** * Create a BluetoothHapClient proxy object for interacting with the local * Bluetooth Hearing Access Profile (HAP) client. @@ -568,6 +407,16 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable mAdapter = BluetoothAdapter.getDefaultAdapter(); mAttributionSource = mAdapter.getAttributionSource(); mProfileConnector.connect(context, listener); + + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + mCloseGuard = new CloseGuard(); mCloseGuard.open("close"); } @@ -586,6 +435,17 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable * @hide */ public void close() { + if (VDBG) log("close()"); + + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + } + mProfileConnector.disconnect(); } @@ -621,8 +481,36 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable if (callback == null) { throw new IllegalArgumentException("callback cannot be null"); } + if (!isEnabled()) { + throw new IllegalStateException("service not enabled"); + } + if (DBG) log("registerCallback"); - throw new UnsupportedOperationException("Not Implemented"); + + synchronized (mCallbackExecutorMap) { + // If the callback map is empty, we register the service-to-app callback + if (mCallbackExecutorMap.isEmpty()) { + try { + final IBluetoothHapClient service = getService(); + if (service != null) { + final SynchronousResultReceiver<Integer> recv = + new SynchronousResultReceiver(); + service.registerCallback(mCallback, mAttributionSource, recv); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); + } + } catch (IllegalStateException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + // Adds the passed in callback to our map of callbacks to executors + if (mCallbackExecutorMap.containsKey(callback)) { + throw new IllegalArgumentException("This callback has already been registered"); + } + mCallbackExecutorMap.put(callback, executor); + } } /** @@ -646,8 +534,30 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable if (callback == null) { throw new IllegalArgumentException("callback cannot be null"); } + if (DBG) log("unregisterCallback"); - throw new UnsupportedOperationException("Not Implemented"); + + synchronized (mCallbackExecutorMap) { + if (mCallbackExecutorMap.remove(callback) != null) { + throw new IllegalArgumentException("This callback has not been registered"); + } + } + + // If the callback map is empty, we unregister the service-to-app callback + if (mCallbackExecutorMap.isEmpty()) { + try { + final IBluetoothHapClient service = getService(); + if (service != null) { + final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); + service.unregisterCallback(mCallback, mAttributionSource, recv); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); + } + } catch (TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } /** @@ -683,8 +593,10 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - } catch (RemoteException | TimeoutException e) { + } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } return defaultValue; @@ -719,8 +631,10 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); service.getConnectionPolicy(device, mAttributionSource, recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - } catch (RemoteException | TimeoutException e) { + } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } return defaultValue; @@ -748,9 +662,13 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable try { final SynchronousResultReceiver<List> recv = new SynchronousResultReceiver(); service.getConnectedDevices(mAttributionSource, recv); - return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - } catch (RemoteException | TimeoutException e) { + return Attributable.setAttributionSource( + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } return defaultValue; @@ -779,9 +697,13 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable try { final SynchronousResultReceiver<List> recv = new SynchronousResultReceiver(); service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv); - return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - } catch (RemoteException | TimeoutException e) { + return Attributable.setAttributionSource( + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } return defaultValue; @@ -811,8 +733,10 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); service.getConnectionState(device, mAttributionSource, recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - } catch (RemoteException | TimeoutException e) { + } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } return defaultValue; @@ -828,12 +752,11 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable * require individual device calls. * * <p>Note that some binaural HA devices may not support group operations, - * therefore are not considered a valid HAP group. In such case the - * {@link #HAP_GROUP_UNAVAILABLE} is returned even when such - * device is a valid Le Audio Coordinated Set member. + * therefore are not considered a valid HAP group. In such case -1 is returned + * even if such device is a valid Le Audio Coordinated Set member. * * @param device - * @return valid group identifier or {@link #HAP_GROUP_UNAVAILABLE} + * @return valid group identifier or -1 * @hide */ @RequiresBluetoothConnectPermission @@ -843,7 +766,7 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable }) public int getHapGroup(@NonNull BluetoothDevice device) { final IBluetoothHapClient service = getService(); - final int defaultValue = HAP_GROUP_UNAVAILABLE; + final int defaultValue = BluetoothCsipSetCoordinator.GROUP_ID_INVALID; if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); @@ -852,8 +775,10 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); service.getHapGroup(device, mAttributionSource, recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - } catch (RemoteException | TimeoutException e) { + } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } return defaultValue; @@ -878,14 +803,15 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled() && isValidDevice(device)) { - // TODO(b/216639668) - // try { - // final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); - // service.getActivePresetIndex(device, mAttributionSource, recv); - // return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - // } catch (RemoteException | TimeoutException e) { - // Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - // } + try { + final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); + service.getActivePresetIndex(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } return defaultValue; } @@ -905,8 +831,25 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable android.Manifest.permission.BLUETOOTH_PRIVILEGED }) public @Nullable BluetoothHapPresetInfo getActivePresetInfo(@NonNull BluetoothDevice device) { - // TODO(b/216639668) - return null; + final IBluetoothHapClient service = getService(); + final BluetoothHapPresetInfo defaultValue = null; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver<BluetoothHapPresetInfo> recv = + new SynchronousResultReceiver(); + service.getActivePresetInfo(device, mAttributionSource, recv); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + return defaultValue; } /** @@ -928,18 +871,14 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable }) public void selectPreset(@NonNull BluetoothDevice device, int presetIndex) { final IBluetoothHapClient service = getService(); - final boolean defaultValue = false; if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled() && isValidDevice(device)) { try { - // TODO(b/216639668) - final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); - service.selectActivePreset(device, presetIndex, mAttributionSource, recv); - recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - } catch (RemoteException | TimeoutException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + service.selectPreset(device, presetIndex, mAttributionSource); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } } @@ -968,18 +907,14 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable }) public void selectPresetForGroup(int groupId, int presetIndex) { final IBluetoothHapClient service = getService(); - final boolean defaultValue = false; if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled()) { try { - // TODO(b/216639668) - final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); - service.groupSelectActivePreset(groupId, presetIndex, mAttributionSource, recv); - recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - } catch (RemoteException | TimeoutException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + service.selectPresetForGroup(groupId, presetIndex, mAttributionSource); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } } @@ -1000,18 +935,14 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable }) public void switchToNextPreset(@NonNull BluetoothDevice device) { final IBluetoothHapClient service = getService(); - final boolean defaultValue = false; if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled() && isValidDevice(device)) { try { - // TODO(b/216639668) - final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); - service.nextActivePreset(device, mAttributionSource, recv); - recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - } catch (RemoteException | TimeoutException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + service.switchToNextPreset(device, mAttributionSource); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } } @@ -1034,18 +965,14 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable }) public void switchToNextPresetForGroup(int groupId) { final IBluetoothHapClient service = getService(); - final boolean defaultValue = false; if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled()) { try { - // TODO(b/216639668) - final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); - service.groupNextActivePreset(groupId, mAttributionSource, recv); - recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - } catch (RemoteException | TimeoutException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + service.switchToNextPresetForGroup(groupId, mAttributionSource); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } } @@ -1066,18 +993,14 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable }) public void switchToPreviousPreset(@NonNull BluetoothDevice device) { final IBluetoothHapClient service = getService(); - final boolean defaultValue = false; if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled() && isValidDevice(device)) { try { - // TODO(b/216639668) - final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); - service.previousActivePreset(device, mAttributionSource, recv); - recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - } catch (RemoteException | TimeoutException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + service.switchToPreviousPreset(device, mAttributionSource); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } } @@ -1100,18 +1023,14 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable }) public void switchToPreviousPresetForGroup(int groupId) { final IBluetoothHapClient service = getService(); - final boolean defaultValue = false; if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled()) { try { - // TODO(b/216639668) - final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); - service.groupPreviousActivePreset(groupId, mAttributionSource, recv); - recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - } catch (RemoteException | TimeoutException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + service.switchToPreviousPresetForGroup(groupId, mAttributionSource); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } } @@ -1129,24 +1048,26 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED }) - public @NonNull BluetoothHapPresetInfo getPresetInfo(@NonNull BluetoothDevice device, + public @Nullable BluetoothHapPresetInfo getPresetInfo(@NonNull BluetoothDevice device, int presetIndex) { final IBluetoothHapClient service = getService(); - final BluetoothHapPresetInfo.Builder builder = new BluetoothHapPresetInfo.Builder(); + final BluetoothHapPresetInfo defaultValue = null; if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled() && isValidDevice(device)) { - // TODO(b/216639668) - // try { - // final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); - // service.getPresetInfo(device, presetIndex, mAttributionSource, recv); - // return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(builder); - // } catch (RemoteException | TimeoutException e) { - // Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - // } + try { + final SynchronousResultReceiver<BluetoothHapPresetInfo> recv = + new SynchronousResultReceiver(); + service.getPresetInfo(device, presetIndex, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } - return builder.build(); + return defaultValue; } /** @@ -1169,14 +1090,16 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled() && isValidDevice(device)) { - // TODO(b/216639668) - // try { - // final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); - // service.getAllPresetsInfo(device, mAttributionSource, recv); - // return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - // } catch (RemoteException | TimeoutException e) { - // Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - // } + try { + final SynchronousResultReceiver<List<BluetoothHapPresetInfo>> recv = + new SynchronousResultReceiver(); + service.getAllPresetInfo(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } return defaultValue; } @@ -1193,19 +1116,21 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED }) - public boolean getFeatures(@NonNull BluetoothDevice device) { + public int getFeatures(@NonNull BluetoothDevice device) { final IBluetoothHapClient service = getService(); - final boolean defaultValue = false; + final int defaultValue = 0x00; if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled() && isValidDevice(device)) { try { - final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); + final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); service.getFeatures(device, mAttributionSource, recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - } catch (RemoteException | TimeoutException e) { + } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } return defaultValue; @@ -1235,18 +1160,14 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable public void setPresetName(@NonNull BluetoothDevice device, int presetIndex, @NonNull String name) { final IBluetoothHapClient service = getService(); - final boolean defaultValue = false; if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled() && isValidDevice(device)) { try { - // TODO(b/216639668) - final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); - service.setPresetName(device, presetIndex, name, mAttributionSource, recv); - recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - } catch (RemoteException | TimeoutException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + service.setPresetName(device, presetIndex, name, mAttributionSource); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } } @@ -1274,18 +1195,14 @@ public final class BluetoothHapClient implements BluetoothProfile, AutoCloseable }) public void setPresetNameForGroup(int groupId, int presetIndex, @NonNull String name) { final IBluetoothHapClient service = getService(); - final boolean defaultValue = false; if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (isEnabled()) { try { - // TODO(b/216639668) - final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); - service.groupSetPresetName(groupId, presetIndex, name, mAttributionSource, recv); - recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); - } catch (RemoteException | TimeoutException e) { - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + service.setPresetNameForGroup(groupId, presetIndex, name, mAttributionSource); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } } diff --git a/framework/java/android/bluetooth/BluetoothHapPresetInfo.java b/framework/java/android/bluetooth/BluetoothHapPresetInfo.java index b8c09ccbb7..70fb54a3bb 100644 --- a/framework/java/android/bluetooth/BluetoothHapPresetInfo.java +++ b/framework/java/android/bluetooth/BluetoothHapPresetInfo.java @@ -29,7 +29,7 @@ import android.os.Parcelable; @SystemApi public final class BluetoothHapPresetInfo implements Parcelable { private int mPresetIndex; - private String mPresetName; + private String mPresetName = ""; private boolean mIsWritable; private boolean mIsAvailable; @@ -165,7 +165,7 @@ public final class BluetoothHapPresetInfo implements Parcelable { * @param isWritable whether preset is writable * @return the same Builder instance */ - public @NonNull Builder setWritable(@NonNull boolean isWritable) { + public @NonNull Builder setWritable(boolean isWritable) { mIsWritable = isWritable; return this; } @@ -176,7 +176,7 @@ public final class BluetoothHapPresetInfo implements Parcelable { * @param isAvailable whether preset is currently available to select * @return the same Builder instance */ - public @NonNull Builder setAvailable(@NonNull boolean isAvailable) { + public @NonNull Builder setAvailable(boolean isAvailable) { mIsAvailable = isAvailable; return this; } diff --git a/framework/java/android/bluetooth/BluetoothHeadset.java b/framework/java/android/bluetooth/BluetoothHeadset.java index 8a037a97c0..4ff224d21a 100644 --- a/framework/java/android/bluetooth/BluetoothHeadset.java +++ b/framework/java/android/bluetooth/BluetoothHeadset.java @@ -1005,10 +1005,21 @@ public final class BluetoothHeadset implements BluetoothProfile { BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED, BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND, BluetoothStatusCodes.ERROR_TIMEOUT, + BluetoothStatusCodes.ERROR_UNKNOWN, + }) + public @interface SetAudioRouteAllowedReturnValues {} + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { BluetoothStatusCodes.ALLOWED, BluetoothStatusCodes.NOT_ALLOWED, + BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED, + BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND, + BluetoothStatusCodes.ERROR_TIMEOUT, + BluetoothStatusCodes.ERROR_UNKNOWN, }) - public @interface AudioRouteAllowedReturnValues {} + public @interface GetAudioRouteAllowedReturnValues {} /** * Sets whether audio routing is allowed. When set to {@code false}, the AG @@ -1029,7 +1040,7 @@ public final class BluetoothHeadset implements BluetoothProfile { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) - public @AudioRouteAllowedReturnValues int setAudioRouteAllowed(boolean allowed) { + public @SetAudioRouteAllowedReturnValues int setAudioRouteAllowed(boolean allowed) { if (VDBG) log("setAudioRouteAllowed"); final IBluetoothHeadset service = mService; if (service == null) { @@ -1068,7 +1079,7 @@ public final class BluetoothHeadset implements BluetoothProfile { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) - public @AudioRouteAllowedReturnValues int getAudioRouteAllowed() { + public @GetAudioRouteAllowedReturnValues int getAudioRouteAllowed() { if (VDBG) log("getAudioRouteAllowed"); final IBluetoothHeadset service = mService; if (service == null) { diff --git a/framework/java/android/bluetooth/BluetoothHeadsetClient.java b/framework/java/android/bluetooth/BluetoothHeadsetClient.java index 87bd76114b..f1402d485d 100644 --- a/framework/java/android/bluetooth/BluetoothHeadsetClient.java +++ b/framework/java/android/bluetooth/BluetoothHeadsetClient.java @@ -18,6 +18,7 @@ package android.bluetooth; import static android.bluetooth.BluetoothUtils.getSyncTimeout; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; @@ -31,6 +32,8 @@ import android.content.Context; import android.os.Build; import android.os.Bundle; import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; import android.os.RemoteException; import android.util.CloseGuard; import android.util.Log; @@ -1615,6 +1618,218 @@ public final class BluetoothHeadsetClient implements BluetoothProfile, AutoClose } return defaultValue; } + + /** + * A class that contains the network service info provided by the HFP Client profile + * + * @hide + */ + @SystemApi + public static final class NetworkServiceState implements Parcelable { + /** The device associated with this service state */ + private final BluetoothDevice mDevice; + + /** True if there is service available, False otherwise */ + private final boolean mIsServiceAvailable; + + /** The name of the operator associated with the remote device's current network */ + private final String mOperatorName; + + /** + * The general signal strength + * (0 - Unknown, 1 - Poor, 2 - Fair, 3 - Good, 4 - Great, 5 - Excellent) + */ + private final int mSignalStrength; + + /** True if we are network roaming, False otherwise */ + private final boolean mIsRoaming; + + /** + * Create a NetworkServiceState Object + * + * @param device The device associated with this network signal state + * @param isServiceAvailable True if there is service available, False otherwise + * @param operatorName The name of the operator associated with the remote device's current + * network. Use Null if the value is unknown + * @param signalStrength The general signal strength + * @param isRoaming True if we are network roaming, False otherwise + * + * @hide + */ + public NetworkServiceState(BluetoothDevice device, boolean isServiceAvailable, + String operatorName, int signalStrength, boolean isRoaming) { + mDevice = device; + mIsServiceAvailable = isServiceAvailable; + mOperatorName = operatorName; + mSignalStrength = signalStrength; + mIsRoaming = isRoaming; + } + + /** + * Get the device associated with this network service state + * + * @return a BluetoothDevice associated with this state + * + * @hide + */ + @SystemApi + public @NonNull BluetoothDevice getDevice() { + return mDevice; + } + + /** + * Get the network service availablility state + * + * @return True if there is service available, False otherwise + * + * @hide + */ + @SystemApi + public boolean isServiceAvailable() { + return mIsServiceAvailable; + } + + /** + * Get the network operator name + * + * @return A string representing the name of the operator the remote device is on, or null + * if unknown. + * + * @hide + */ + @SystemApi + public @Nullable String getOperatorName() { + return mOperatorName; + } + + /** + * Get the network's general signal strength + * + * @return The general signal strength (0 - None, 1 - Poor, 2 - Fair, 3 - Good, + * 4 - Great, 5 - Excellent) + * + * @hide + */ + @SystemApi + public int getSignalStrength() { + return mSignalStrength; + } + + /** + * Get the network service roaming status + * + * * @return True if we are network roaming, False otherwise + * + * @hide + */ + @SystemApi + public boolean isRoaming() { + return mIsRoaming; + } + + /** + * {@link Parcelable.Creator} interface implementation. + */ + public static final @NonNull Parcelable.Creator<NetworkServiceState> CREATOR = + new Parcelable.Creator<NetworkServiceState>() { + public NetworkServiceState createFromParcel(Parcel in) { + return new NetworkServiceState((BluetoothDevice) in.readParcelable(null), + in.readInt() == 1, in.readString(), in.readInt(), in.readInt() == 1); + } + + public @NonNull NetworkServiceState[] newArray(int size) { + return new NetworkServiceState[size]; + } + }; + + /** + * @hide + */ + @Override + public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeParcelable(mDevice, 0); + out.writeInt(mIsServiceAvailable ? 1 : 0); + out.writeString(mOperatorName); + out.writeInt(mSignalStrength); + out.writeInt(mIsRoaming ? 1 : 0); + } + + /** + * @hide + */ + @Override + public int describeContents() { + return 0; + } + } + + /** + * Intent used to broadcast the change in network service state of an HFP Client device + * + * <p>This intent will have 2 extras: + * <ul> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * <li> {@link EXTRA_NETWORK_SERVICE_STATE} - A {@link NetworkServiceState} object. </li> + * </ul> + * + * @hide + */ + @SuppressLint("ActionValue") + @SystemApi + @RequiresBluetoothConnectPermission + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_NETWORK_SERVICE_STATE_CHANGED = + "android.bluetooth.headsetclient.profile.action.NETWORK_SERVICE_STATE_CHANGED"; + + /** + * Extra for the network service state changed intent. + * + * This extra represents the current network service state of a connected Bluetooth device. + * + * @hide + */ + @SuppressLint("ActionValue") + @SystemApi + public static final String EXTRA_NETWORK_SERVICE_STATE = + "android.bluetooth.headsetclient.extra.EXTRA_NETWORK_SERVICE_STATE"; + + /** + * Get the network service state for a device + * + * @param device The {@link BluetoothDevice} you want the network service state for + * @return A {@link NetworkServiceState} representing the network service state of the device, + * or null if the device is not connected + * @hide + */ + @SystemApi + @RequiresBluetoothConnectPermission + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) + public @Nullable NetworkServiceState getNetworkServiceState(@NonNull BluetoothDevice device) { + if (device == null) { + return null; + } + + Bundle agEvents = getCurrentAgEvents(device); + if (agEvents == null) { + return null; + } + + boolean isServiceAvailable = (agEvents.getInt(EXTRA_NETWORK_STATUS, 0) == 1); + int signalStrength = agEvents.getInt(EXTRA_NETWORK_SIGNAL_STRENGTH, 0); + String operatorName = agEvents.getString(EXTRA_OPERATOR_NAME, null); + boolean isRoaming = (agEvents.getInt(EXTRA_NETWORK_ROAMING, 0) == 1); + + return new NetworkServiceState(device, isServiceAvailable, operatorName, signalStrength, + isRoaming); + } + private boolean isEnabled() { return mAdapter.getState() == BluetoothAdapter.STATE_ON; } diff --git a/framework/java/android/bluetooth/BluetoothLeAudioCodecConfig.java b/framework/java/android/bluetooth/BluetoothLeAudioCodecConfig.java index e3f691a66a..8377c2c7d2 100644 --- a/framework/java/android/bluetooth/BluetoothLeAudioCodecConfig.java +++ b/framework/java/android/bluetooth/BluetoothLeAudioCodecConfig.java @@ -336,14 +336,14 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { /** * Returns the frame duration. */ - public @ChannelMode int getFrameDuration() { + public @FrameDuration int getFrameDuration() { return mFrameDuration; } /** * Returns the octets per frame */ - public @ChannelMode int getOctetsPerFrame() { + public int getOctetsPerFrame() { return mOctetsPerFrame; } diff --git a/framework/java/android/bluetooth/BluetoothProfile.java b/framework/java/android/bluetooth/BluetoothProfile.java index 86606d2077..ff95269c30 100644 --- a/framework/java/android/bluetooth/BluetoothProfile.java +++ b/framework/java/android/bluetooth/BluetoothProfile.java @@ -19,7 +19,6 @@ package android.bluetooth; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresNoPermission; -import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; @@ -457,7 +456,7 @@ public interface BluetoothProfile { */ @SystemApi @NonNull - @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) + @RequiresNoPermission static String getConnectionStateName(int connectionState) { switch (connectionState) { case STATE_DISCONNECTED: @@ -482,7 +481,7 @@ public interface BluetoothProfile { */ @SystemApi @NonNull - @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) + @RequiresNoPermission static String getProfileName(int profile) { switch(profile) { case HEADSET: diff --git a/framework/java/android/bluetooth/BluetoothStatusCodes.java b/framework/java/android/bluetooth/BluetoothStatusCodes.java index 8825c3e71b..ebaace621b 100644 --- a/framework/java/android/bluetooth/BluetoothStatusCodes.java +++ b/framework/java/android/bluetooth/BluetoothStatusCodes.java @@ -227,7 +227,7 @@ public final class BluetoothStatusCodes { * @hide */ @SystemApi - public static final int ERROR_REMOTE_OPERATION_NOT_SUPPORTED = 24; + public static final int ERROR_REMOTE_OPERATION_NOT_SUPPORTED = 27; /** * A GATT writeCharacteristic request is not permitted on the remote device. diff --git a/framework/java/android/bluetooth/BluetoothUuid.java b/framework/java/android/bluetooth/BluetoothUuid.java index 7c9a076270..85c16f1288 100644 --- a/framework/java/android/bluetooth/BluetoothUuid.java +++ b/framework/java/android/bluetooth/BluetoothUuid.java @@ -158,9 +158,8 @@ public final class BluetoothUuid { /** @hide */ @NonNull @SystemApi - /* FIXME: Not known yet, using a placeholder instead. */ public static final ParcelUuid HAS = - ParcelUuid.fromString("EEEEEEEE-EEEE-EEEE-EEEE-EEEEEEEEEEEE"); + ParcelUuid.fromString("00001854-0000-1000-8000-00805F9B34FB"); /** @hide */ @NonNull @SystemApi @@ -199,6 +198,11 @@ public final class BluetoothUuid { /** @hide */ @NonNull @SystemApi + public static final ParcelUuid BASS = + ParcelUuid.fromString("0000184F-0000-1000-8000-00805F9B34FB"); + /** @hide */ + @NonNull + @SystemApi public static final ParcelUuid BASE_UUID = ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB"); diff --git a/framework/tests/Android.bp b/framework/tests/Android.bp index a6a2fe5115..efec1dd521 100644 --- a/framework/tests/Android.bp +++ b/framework/tests/Android.bp @@ -4,8 +4,18 @@ package { android_test { name: "BluetoothTests", + + defaults: ["framework-bluetooth-tests-defaults"], + + min_sdk_version: "current", + target_sdk_version: "current", + // Include all test java files. srcs: ["src/**/*.java"], + jacoco: { + include_filter: ["android.bluetooth.*"], + exclude_filter: [], + }, libs: [ "android.test.runner", "android.test.base", @@ -14,6 +24,8 @@ android_test { "junit", "modules-utils-bytesmatcher", ], - platform_apis: true, - certificate: "platform", + test_suites: [ + "general-tests", + "mts-bluetooth", + ], } diff --git a/service/Android.bp b/service/Android.bp index a0f6ec6dc8..b115b6953c 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -61,10 +61,12 @@ java_library { libs: [ "framework-annotations-lib", "framework-bluetooth-pre-jarjar", + "app-compat-annotations", ], static_libs: [ "androidx.annotation_annotation", + "androidx.appcompat_appcompat", ], apex_available: [ @@ -78,22 +80,24 @@ java_library { name: "service-bluetooth", defaults: ["service-bluetooth-common-defaults"], installable: true, - static_libs: ["service-bluetooth-pre-jarjar"], + static_libs: [ + "service-bluetooth-pre-jarjar", + "androidx.appcompat_appcompat", + ], libs: [ "framework-bluetooth.impl", + "app-compat-annotations", ], sdk_version: "system_server_current", + jarjar_rules: ":bluetooth-jarjar-rules", + optimize: { enabled: true, shrink: true, proguard_flags_files: ["proguard.flags"], }, - dex_preopt: { - enabled: false, - app_image: false, - }, visibility: [ "//packages/modules/Bluetooth/apex", ], diff --git a/service/OWNERS b/service/OWNERS new file mode 100644 index 0000000000..ffb8a05845 --- /dev/null +++ b/service/OWNERS @@ -0,0 +1,6 @@ +# Reviewers for /service + +rahulsabnis@google.com +sattiraju@google.com +siyuanh@google.com +zachoverflow@google.com
\ No newline at end of file diff --git a/service/java/com/android/server/bluetooth/BluetoothAirplaneModeListener.java b/service/java/com/android/server/bluetooth/BluetoothAirplaneModeListener.java index 380b1f37b9..d4aad1c642 100644 --- a/service/java/com/android/server/bluetooth/BluetoothAirplaneModeListener.java +++ b/service/java/com/android/server/bluetooth/BluetoothAirplaneModeListener.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.bluetooth; import android.annotation.RequiresPermission; import android.content.Context; @@ -37,7 +37,7 @@ import com.android.internal.annotations.VisibleForTesting; * 2. Bluetooth Hearing Aid profile is connected. * 3. Bluetooth LE Audio is connected */ -class BluetoothAirplaneModeListener { +public class BluetoothAirplaneModeListener { private static final String TAG = "BluetoothAirplaneModeListener"; @VisibleForTesting static final String TOAST_COUNT = "bluetooth_airplane_toast_count"; diff --git a/service/java/com/android/server/bluetooth/BluetoothDeviceConfigListener.java b/service/java/com/android/server/bluetooth/BluetoothDeviceConfigListener.java index 49779c0a0c..62860a5f02 100644 --- a/service/java/com/android/server/bluetooth/BluetoothDeviceConfigListener.java +++ b/service/java/com/android/server/bluetooth/BluetoothDeviceConfigListener.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.bluetooth; import android.provider.DeviceConfig; import android.util.Log; @@ -30,7 +30,7 @@ import java.util.ArrayList; * 1. Bluetooth A2DP is connected. * 2. Bluetooth Hearing Aid profile is connected. */ -class BluetoothDeviceConfigListener { +public class BluetoothDeviceConfigListener { private static final String TAG = "BluetoothDeviceConfigListener"; private final BluetoothManagerService mService; diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 366104a326..f6201a7b3f 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.bluetooth; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; @@ -28,6 +28,8 @@ import android.annotation.SuppressLint; import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.BroadcastOptions; +import android.app.admin.DevicePolicyManager; +import android.app.compat.CompatChanges; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothHearingAid; @@ -43,7 +45,8 @@ import android.bluetooth.IBluetoothManager; import android.bluetooth.IBluetoothManagerCallback; import android.bluetooth.IBluetoothProfileServiceConnection; import android.bluetooth.IBluetoothStateChangeCallback; -import android.content.ActivityNotFoundException; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledSince; import android.content.AttributionSource; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -79,11 +82,13 @@ import android.provider.Settings.SettingNotFoundException; import android.sysprop.BluetoothProperties; import android.text.TextUtils; import android.util.Log; +import android.util.Pair; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.SynchronousResultReceiver; +import com.android.server.BluetoothManagerServiceDumpProto; import java.io.FileDescriptor; import java.io.FileOutputStream; @@ -100,7 +105,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeoutException; import java.util.concurrent.locks.ReentrantReadWriteLock; -class BluetoothManagerService extends IBluetoothManager.Stub { +public class BluetoothManagerService extends IBluetoothManager.Stub { private static final String TAG = "BluetoothManagerService"; private static final boolean DBG = true; @@ -178,6 +183,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int SERVICE_IBLUETOOTH = 1; private static final int SERVICE_IBLUETOOTHGATT = 2; + private static final int FLAGS_SYSTEM_APP = + ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; + + /** + * Starting with {@link android.os.Build.VERSION_CODES#TIRAMISU}, applications are + * not allowed to enable/disable Bluetooth. + */ + @ChangeId + @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.TIRAMISU) + static final long RESTRICT_ENABLE_DISABLE = 218493289L; + private final Context mContext; private final UserManager mUserManager; @@ -275,8 +291,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // bluetooth profile services private final Map<Integer, ProfileServiceConnections> mProfileServices = new HashMap<>(); - private final boolean mWirelessConsentRequired; - private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { @Override public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { @@ -488,10 +502,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext = context; - mWirelessConsentRequired = context.getResources() - .getBoolean(Resources.getSystem().getIdentifier( - "config_wirelessConsentRequired", "bool", "android")); - mCrashes = 0; mBluetooth = null; mBluetoothBinder = null; @@ -1282,10 +1292,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } final int callingUid = Binder.getCallingUid(); - final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - if (!callerSystem && !isEnabled() && mWirelessConsentRequired - && startConsentUiIfNeeded(packageName, - callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) { + final int callingPid = Binder.getCallingPid(); + if (!isPrivileged(callingPid, callingUid) && !isDeviceOwner(callingUid, packageName) + && CompatChanges.isChangeEnabled(RESTRICT_ENABLE_DISABLE, callingUid) + && !isSystem(packageName, callingUid)) { return false; } @@ -1324,10 +1334,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } final int callingUid = Binder.getCallingUid(); - final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - if (!callerSystem && isEnabled() && mWirelessConsentRequired - && startConsentUiIfNeeded(packageName, - callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) { + final int callingPid = Binder.getCallingPid(); + if (!isPrivileged(callingPid, callingUid) && !isDeviceOwner(callingUid, packageName) + && CompatChanges.isChangeEnabled(RESTRICT_ENABLE_DISABLE, callingUid) + && !isSystem(packageName, callingUid)) { return false; } @@ -1374,39 +1384,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } - private boolean startConsentUiIfNeeded(String packageName, - int callingUid, String intentAction) throws RemoteException { - if (checkBluetoothPermissionWhenWirelessConsentRequired()) { - return false; - } - try { - // Validate the package only if we are going to use it - ApplicationInfo applicationInfo = mContext.getPackageManager() - .getApplicationInfoAsUser(packageName, - PackageManager.MATCH_DIRECT_BOOT_AUTO, - UserHandle.getUserHandleForUid(callingUid)); - if (applicationInfo.uid != callingUid) { - throw new SecurityException("Package " + packageName - + " not in uid " + callingUid); - } - - Intent intent = new Intent(intentAction); - intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); - intent.setFlags( - Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); - try { - mContext.startActivity(intent); - } catch (ActivityNotFoundException e) { - // Shouldn't happen - Log.e(TAG, "Intent to handle action " + intentAction + " missing"); - return false; - } - return true; - } catch (PackageManager.NameNotFoundException e) { - throw new RemoteException(e.getMessage()); - } - } - /** * Check if AppOpsManager is available and the packageName belongs to uid * @@ -3528,4 +3505,60 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } return comp; } + + private boolean isPrivileged(int pid, int uid) { + return (mContext.checkPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED, pid, uid) + == PackageManager.PERMISSION_GRANTED) + || (mContext.checkPermission(android.Manifest.permission.NETWORK_SETTINGS, pid, uid) + == PackageManager.PERMISSION_GRANTED) + || (mContext.getPackageManager().checkSignatures(uid, Process.SYSTEM_UID) + == PackageManager.SIGNATURE_MATCH); + } + + private Pair<UserHandle, ComponentName> getDeviceOwner() { + DevicePolicyManager devicePolicyManager = + mContext.getSystemService(DevicePolicyManager.class); + if (devicePolicyManager == null) return null; + long ident = Binder.clearCallingIdentity(); + UserHandle deviceOwnerUser = null; + ComponentName deviceOwnerComponent = null; + try { + deviceOwnerUser = devicePolicyManager.getDeviceOwnerUser(); + deviceOwnerComponent = devicePolicyManager.getDeviceOwnerComponentOnAnyUser(); + } finally { + Binder.restoreCallingIdentity(ident); + } + if (deviceOwnerUser == null || deviceOwnerComponent == null + || deviceOwnerComponent.getPackageName() == null) { + return null; + } + return new Pair<>(deviceOwnerUser, deviceOwnerComponent); + } + + private boolean isDeviceOwner(int uid, String packageName) { + if (packageName == null) { + Log.e(TAG, "isDeviceOwner: packageName is null, returning false"); + return false; + } + Pair<UserHandle, ComponentName> deviceOwner = getDeviceOwner(); + + // no device owner + if (deviceOwner == null) return false; + + return deviceOwner.first.equals(UserHandle.getUserHandleForUid(uid)) + && deviceOwner.second.getPackageName().equals(packageName); + } + + public boolean isSystem(String packageName, int uid) { + long ident = Binder.clearCallingIdentity(); + try { + ApplicationInfo info = mContext.getPackageManager().getApplicationInfoAsUser( + packageName, 0, UserHandle.getUserHandleForUid(uid)); + return (info.flags & FLAGS_SYSTEM_APP) != 0; + } catch (PackageManager.NameNotFoundException e) { + return false; + } finally { + Binder.restoreCallingIdentity(ident); + } + } } diff --git a/service/java/com/android/server/bluetooth/BluetoothModeChangeHelper.java b/service/java/com/android/server/bluetooth/BluetoothModeChangeHelper.java index fd728ad494..dbdc466ad9 100644 --- a/service/java/com/android/server/bluetooth/BluetoothModeChangeHelper.java +++ b/service/java/com/android/server/bluetooth/BluetoothModeChangeHelper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.bluetooth; import android.annotation.RequiresPermission; import android.bluetooth.BluetoothA2dp; diff --git a/service/java/com/android/server/bluetooth/BluetoothService.java b/service/java/com/android/server/bluetooth/BluetoothService.java index f5e100b338..ff6938e5f6 100644 --- a/service/java/com/android/server/bluetooth/BluetoothService.java +++ b/service/java/com/android/server/bluetooth/BluetoothService.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.bluetooth; import android.annotation.NonNull; import android.annotation.Nullable; @@ -22,9 +22,10 @@ import android.bluetooth.BluetoothAdapter; import android.content.Context; import android.os.UserManager; +import com.android.server.SystemService; import com.android.server.SystemService.TargetUser; -class BluetoothService extends SystemService { +public class BluetoothService extends SystemService { private BluetoothManagerService mBluetoothManagerService; private boolean mInitialized = false; diff --git a/service/tests/Android.bp b/service/tests/Android.bp index 6cfa7ecb63..2f889aa797 100644 --- a/service/tests/Android.bp +++ b/service/tests/Android.bp @@ -28,3 +28,54 @@ filegroup { "//frameworks/base/services/tests/servicestests", ], } + +android_test { + name: "ServiceBluetoothTests", + + srcs: [ + "src/**/*.java", + ], + + dxflags: ["--multi-dex"], + + java_version: "1.9", + + static_libs: [ + "androidx.test.rules", + "collector-device-lib", + "hamcrest-library", + "mockito-target-extended-minus-junit4", + "platform-test-annotations", + "frameworks-base-testutils", + "truth-prebuilt", + + // Statically link service-bluetooth-pre-jarjar since we want to test the working copy of + // service-uwb, not the on-device copy. + // Use pre-jarjar version so that we can reference symbols before they are renamed. + // Then, the jarjar_rules here will perform the rename for the entire APK + // i.e. service-bluetooth + test code + "service-bluetooth-pre-jarjar", + ], + + jarjar_rules: ":bluetooth-jarjar-rules", + + libs: [ + "android.test.runner", + "android.test.base", + "android.test.mock", + "framework-bluetooth-pre-jarjar", + ], + + jni_libs: [ + // these are needed for Extended Mockito + "//packages/modules/Bluetooth/android/app:libbluetooth_jni", + ], + compile_multilib: "both", + + min_sdk_version: "current", + + test_suites: [ + "general-tests", + "mts-bluetooth", + ], +} diff --git a/service/tests/AndroidManifest.xml b/service/tests/AndroidManifest.xml new file mode 100644 index 0000000000..afecc067ed --- /dev/null +++ b/service/tests/AndroidManifest.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2015 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 + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.server.bluetooth.test"> + + <application android:debuggable="true" + android:largeHeap="true"> + <uses-library android:name="android.test.runner"/> + <activity android:label="BluetoothTestDummyLabel" + android:name="BluetoothTestDummyName" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.LAUNCHER"/> + </intent-filter> + </activity> + </application> + + <instrumentation android:name="com.android.server.bluetooth.CustomTestRunner" + android:targetPackage="com.android.server.bluetooth.test" + android:label="Service Bluetooth Tests"> + </instrumentation> + + <uses-permission android:name="android.permission.READ_PHONE_STATE"/> + <uses-permission android:name="android.permission.INTERNET"/> + +</manifest> diff --git a/service/tests/AndroidTest.xml b/service/tests/AndroidTest.xml new file mode 100644 index 0000000000..c31c6cb068 --- /dev/null +++ b/service/tests/AndroidTest.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 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. +--> +<configuration description="Runs Service Bluetooth Tests."> + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> + <option name="test-file-name" value="ServiceBluetoothTests.apk" /> + </target_preparer> + + <option name="test-suite-tag" value="apct" /> + <option name="test-tag" value="ServiceBluetoothTests" /> + <option name="config-descriptor:metadata" key="mainline-param" + value="com.google.android.bluetooth.apex" /> + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="com.android.server.bluetooth.test" /> + <option name="runner" value="com.android.server.bluetooth.CustomTestRunner" /> + <option name="hidden-api-checks" value="false"/> + </test> + + <!-- Only run ServiceBluetoothTests in MTS if the Bluetooth Mainline module is installed. --> + <object type="module_controller" + class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> + <option name="mainline-module-package-name" value="com.google.android.bluetooth" /> + </object> +</configuration> diff --git a/service/tests/src/com/android/server/BluetoothAirplaneModeListenerTest.java b/service/tests/src/com/android/server/BluetoothAirplaneModeListenerTest.java index a1d4c203de..fb067800a1 100644 --- a/service/tests/src/com/android/server/BluetoothAirplaneModeListenerTest.java +++ b/service/tests/src/com/android/server/BluetoothAirplaneModeListenerTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.bluetooth; import static org.mockito.Mockito.*; diff --git a/system/Android.bp b/system/Android.bp index 6b06881f7b..f3bbab694e 100644 --- a/system/Android.bp +++ b/system/Android.bp @@ -1,3 +1,15 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_bt_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-BSD + // SPDX-license-identifier-MIT + // legacy_unencumbered + default_applicable_licenses: ["system_bt_license"], +} + filegroup { name: "BlueberryFacadeProto", srcs: [ @@ -164,10 +176,10 @@ genrule { "protoc-gen-grpc-python-plugin", "soong_zip", ], - cmd: "$(location aprotoc) --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-python-plugin) -Ipackages/modules/Bluetooth/system $(in) --grpc_out=$(genDir) --python_out=$(genDir)", + cmd: "$(location aprotoc) --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-python-plugin) -Iexternal/protobuf/src -Ipackages/modules/Bluetooth/system $(in) --grpc_out=$(genDir) --python_out=$(genDir)", srcs: ["blueberry/facade/topshim/facade.proto"], out: [ "blueberry/facade/topshim/facade_pb2.py", "blueberry/facade/topshim/facade_pb2_grpc.py" ], -}
\ No newline at end of file +} diff --git a/system/OWNERS b/system/OWNERS new file mode 100644 index 0000000000..ab51efd928 --- /dev/null +++ b/system/OWNERS @@ -0,0 +1,13 @@ +# Reviewers for /system + +cmanton@google.com +cncn@google.com +hsz@google.com +jpawlowski@google.com +mylesgw@google.com +optedoblivion@google.com +qasimj@google.com +rahulsabnis@google.com +sattiraju@google.com +siyuanh@google.com +zachoverflow@google.com diff --git a/system/audio_bluetooth_hw/Android.bp b/system/audio_bluetooth_hw/Android.bp index 08496c22a1..25e1f8c141 100644 --- a/system/audio_bluetooth_hw/Android.bp +++ b/system/audio_bluetooth_hw/Android.bp @@ -17,21 +17,25 @@ cc_library_shared { "audio_bluetooth_hw.cc", "stream_apis.cc", "device_port_proxy.cc", + "device_port_proxy_hidl.cc", "utils.cc", ], header_libs: ["libhardware_headers"], shared_libs: [ - "android.hardware.bluetooth.audio@2.0", - "android.hardware.bluetooth.audio@2.1", - "android.hardware.bluetooth.audio@2.2", + "android.hardware.bluetooth.audio-V1-ndk", + "libbluetooth_audio_session_aidl", "libaudioutils", "libbase", - "libbluetooth_audio_session", + "libbinder_ndk", "libcutils", "libfmq", - "libhidlbase", "liblog", "libutils", + // HIDL dependencies + "android.hardware.bluetooth.audio@2.0", + "android.hardware.bluetooth.audio@2.1", + "libbluetooth_audio_session", + "libhidlbase", ], cflags: [ "-Wall", diff --git a/system/audio_bluetooth_hw/device_port_proxy.cc b/system/audio_bluetooth_hw/device_port_proxy.cc index ed9f0952ba..b9be63de36 100644 --- a/system/audio_bluetooth_hw/device_port_proxy.cc +++ b/system/audio_bluetooth_hw/device_port_proxy.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,9 @@ * limitations under the License. */ -#define LOG_TAG "BTAudioHalDeviceProxy" +#define LOG_TAG "BTAudioHalDeviceProxyAIDL" + +#include "device_port_proxy.h" #include <android-base/logging.h> #include <android-base/stringprintf.h> @@ -23,56 +25,29 @@ #include <log/log.h> #include <stdlib.h> -#include "BluetoothAudioSessionControl_2_2.h" -#include "device_port_proxy.h" +#include "BluetoothAudioSessionControl.h" #include "stream_apis.h" #include "utils.h" namespace android { namespace bluetooth { namespace audio { +namespace aidl { + +using ::aidl::android::hardware::bluetooth::audio::AudioConfiguration; +using ::aidl::android::hardware::bluetooth::audio::BluetoothAudioSessionControl; +using ::aidl::android::hardware::bluetooth::audio::ChannelMode; +using ::aidl::android::hardware::bluetooth::audio::PcmConfiguration; +using ::aidl::android::hardware::bluetooth::audio::PortStatusCallbacks; +using ::aidl::android::hardware::bluetooth::audio::PresentationPosition; using ::android::base::StringPrintf; -using ::android::bluetooth::audio::BluetoothAudioSessionControl_2_2; -using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample; -using ::android::hardware::bluetooth::audio::V2_0::ChannelMode; -using ::android::hardware::bluetooth::audio::V2_0::PcmParameters; -using SampleRate = ::android::hardware::bluetooth::audio::V2_0::SampleRate; -using SampleRate_2_1 = ::android::hardware::bluetooth::audio::V2_1::SampleRate; -using BluetoothAudioStatus = - ::android::hardware::bluetooth::audio::V2_0::Status; using ControlResultCallback = std::function<void( uint16_t cookie, bool start_resp, const BluetoothAudioStatus& status)>; using SessionChangedCallback = std::function<void(uint16_t cookie)>; namespace { -unsigned int SampleRateToAudioFormat(SampleRate_2_1 sample_rate) { - switch (sample_rate) { - case SampleRate_2_1::RATE_8000: - return 8000; - case SampleRate_2_1::RATE_16000: - return 16000; - case SampleRate_2_1::RATE_24000: - return 24000; - case SampleRate_2_1::RATE_32000: - return 32000; - case SampleRate_2_1::RATE_44100: - return 44100; - case SampleRate_2_1::RATE_48000: - return 48000; - case SampleRate_2_1::RATE_88200: - return 88200; - case SampleRate_2_1::RATE_96000: - return 96000; - case SampleRate_2_1::RATE_176400: - return 176400; - case SampleRate_2_1::RATE_192000: - return 192000; - default: - return kBluetoothDefaultSampleRate; - } -} audio_channel_mask_t OutputChannelModeToAudioFormat(ChannelMode channel_mode) { switch (channel_mode) { case ChannelMode::MONO: @@ -95,13 +70,13 @@ audio_channel_mask_t InputChannelModeToAudioFormat(ChannelMode channel_mode) { } } -audio_format_t BitsPerSampleToAudioFormat(BitsPerSample bits_per_sample) { +audio_format_t BitsPerSampleToAudioFormat(uint8_t bits_per_sample) { switch (bits_per_sample) { - case BitsPerSample::BITS_16: + case 16: return AUDIO_FORMAT_PCM_16_BIT; - case BitsPerSample::BITS_24: + case 24: return AUDIO_FORMAT_PCM_24_BIT_PACKED; - case BitsPerSample::BITS_32: + case 32: return AUDIO_FORMAT_PCM_32_BIT; default: return kBluetoothDefaultAudioFormatBitsPerSample; @@ -113,12 +88,21 @@ constexpr unsigned int kMaxWaitingTimeMs = 4500; } // namespace -BluetoothAudioPort::BluetoothAudioPort() - : cookie_(android::bluetooth::audio::kObserversCookieUndefined), +BluetoothAudioPortAidl::BluetoothAudioPortAidl() + : cookie_(::aidl::android::hardware::bluetooth::audio:: + kObserversCookieUndefined), state_(BluetoothStreamState::DISABLED), - session_type_(SessionType_2_1::UNKNOWN) {} + session_type_(SessionType::UNKNOWN) {} -bool BluetoothAudioPort::SetUp(audio_devices_t devices) { +BluetoothAudioPortAidlOut::~BluetoothAudioPortAidlOut() { + if (in_use()) TearDown(); +} + +BluetoothAudioPortAidlIn::~BluetoothAudioPortAidlIn() { + if (in_use()) TearDown(); +} + +bool BluetoothAudioPortAidl::SetUp(audio_devices_t devices) { if (!init_session_type(devices)) return false; state_ = BluetoothStreamState::STANDBY; @@ -126,106 +110,120 @@ bool BluetoothAudioPort::SetUp(audio_devices_t devices) { auto control_result_cb = [port = this](uint16_t cookie, bool start_resp, const BluetoothAudioStatus& status) { if (!port->in_use()) { - LOG(ERROR) << "control_result_cb: BluetoothAudioPort is not in use"; + LOG(ERROR) << "control_result_cb: BluetoothAudioPortAidl is not in use"; return; } if (port->cookie_ != cookie) { - LOG(ERROR) << "control_result_cb: proxy of device port (cookie=" << StringPrintf("%#hx", cookie) - << ") is corrupted"; + LOG(ERROR) << "control_result_cb: proxy of device port (cookie=" + << StringPrintf("%#hx", cookie) << ") is corrupted"; return; } port->ControlResultHandler(status); }; auto session_changed_cb = [port = this](uint16_t cookie) { if (!port->in_use()) { - LOG(ERROR) << "session_changed_cb: BluetoothAudioPort is not in use"; + LOG(ERROR) << "session_changed_cb: BluetoothAudioPortAidl is not in use"; return; } if (port->cookie_ != cookie) { - LOG(ERROR) << "session_changed_cb: proxy of device port (cookie=" << StringPrintf("%#hx", cookie) - << ") is corrupted"; + LOG(ERROR) << "session_changed_cb: proxy of device port (cookie=" + << StringPrintf("%#hx", cookie) << ") is corrupted"; return; } port->SessionChangedHandler(); }; - ::android::bluetooth::audio::PortStatusCallbacks cbacks = { + // TODO: Add audio_config_changed_cb + PortStatusCallbacks cbacks = { .control_result_cb_ = control_result_cb, - .session_changed_cb_ = session_changed_cb}; - cookie_ = BluetoothAudioSessionControl_2_2::RegisterControlResultCback( + .session_changed_cb_ = session_changed_cb, + }; + cookie_ = BluetoothAudioSessionControl::RegisterControlResultCback( session_type_, cbacks); - LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_); + LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) + << ", cookie=" << StringPrintf("%#hx", cookie_); - return (cookie_ != android::bluetooth::audio::kObserversCookieUndefined); + return ( + cookie_ != + ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined); } -bool BluetoothAudioPort::init_session_type(audio_devices_t device) { +bool BluetoothAudioPortAidl::init_session_type(audio_devices_t device) { switch (device) { case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP: case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES: case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER: - LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) (" - << StringPrintf("%#x", device) << ")"; - session_type_ = SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH; + LOG(VERBOSE) + << __func__ + << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) (" + << StringPrintf("%#x", device) << ")"; + session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH; break; case AUDIO_DEVICE_OUT_HEARING_AID: - LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) (" << StringPrintf("%#x", device) - << ")"; - session_type_ = SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH; + LOG(VERBOSE) << __func__ + << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) (" + << StringPrintf("%#x", device) << ")"; + session_type_ = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH; break; case AUDIO_DEVICE_OUT_BLE_HEADSET: LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_HEADSET (MEDIA/VOICE) (" << StringPrintf("%#x", device) << ")"; - session_type_ = SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH; + session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH; break; case AUDIO_DEVICE_OUT_BLE_SPEAKER: LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLE_SPEAKER (MEDIA) (" << StringPrintf("%#x", device) << ")"; - session_type_ = SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH; + session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH; break; case AUDIO_DEVICE_IN_BLE_HEADSET: LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_IN_BLE_HEADSET (VOICE) (" << StringPrintf("%#x", device) << ")"; - session_type_ = SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH; + session_type_ = SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH; break; default: - LOG(ERROR) << __func__ << ": unknown device=" << StringPrintf("%#x", device); + LOG(ERROR) << __func__ + << ": unknown device=" << StringPrintf("%#x", device); return false; } - if (!BluetoothAudioSessionControl_2_2::IsSessionReady(session_type_)) { - LOG(ERROR) << __func__ << ": device=" << StringPrintf("%#x", device) << ", session_type=" << toString(session_type_) + if (!BluetoothAudioSessionControl::IsSessionReady(session_type_)) { + LOG(ERROR) << __func__ << ": device=" << StringPrintf("%#x", device) + << ", session_type=" << toString(session_type_) << " is not ready"; return false; } return true; } -void BluetoothAudioPort::TearDown() { +void BluetoothAudioPortAidl::TearDown() { if (!in_use()) { LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_) - << ", cookie=" << StringPrintf("%#hx", cookie_) << " unknown monitor"; + << ", cookie=" << StringPrintf("%#hx", cookie_) + << " unknown monitor"; return; } - LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_); - BluetoothAudioSessionControl_2_2::UnregisterControlResultCback(session_type_, - cookie_); - cookie_ = android::bluetooth::audio::kObserversCookieUndefined; + LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) + << ", cookie=" << StringPrintf("%#hx", cookie_); + BluetoothAudioSessionControl::UnregisterControlResultCback(session_type_, + cookie_); + cookie_ = + ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined; } -void BluetoothAudioPort::ControlResultHandler( +void BluetoothAudioPortAidl::ControlResultHandler( const BluetoothAudioStatus& status) { if (!in_use()) { - LOG(ERROR) << __func__ << ": BluetoothAudioPortis not in use"; + LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlis not in use"; return; } std::unique_lock<std::mutex> port_lock(cv_mutex_); BluetoothStreamState previous_state = state_; LOG(INFO) << "control_result_cb: session_type=" << toString(session_type_) - << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", previous_state=" << previous_state << ", status=" << toString(status); switch (previous_state) { @@ -236,7 +234,8 @@ void BluetoothAudioPort::ControlResultHandler( // Set to standby since the stack may be busy switching between outputs LOG(WARNING) << "control_result_cb: status=" << toString(status) << " failure for session_type=" << toString(session_type_) - << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state; + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", previous_state=" << previous_state; state_ = BluetoothStreamState::STANDBY; } break; @@ -248,13 +247,15 @@ void BluetoothAudioPort::ControlResultHandler( // to wait for re-init again LOG(WARNING) << "control_result_cb: status=" << toString(status) << " failure for session_type=" << toString(session_type_) - << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state; + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", previous_state=" << previous_state; state_ = BluetoothStreamState::DISABLED; } break; default: LOG(ERROR) << "control_result_cb: unexpected status=" << toString(status) - << " for session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_) + << " for session_type=" << toString(session_type_) + << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state; return; } @@ -262,75 +263,73 @@ void BluetoothAudioPort::ControlResultHandler( internal_cv_.notify_all(); } -void BluetoothAudioPort::SessionChangedHandler() { +void BluetoothAudioPortAidl::SessionChangedHandler() { if (!in_use()) { - LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use"; + LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use"; return; } std::unique_lock<std::mutex> port_lock(cv_mutex_); BluetoothStreamState previous_state = state_; LOG(INFO) << "session_changed_cb: session_type=" << toString(session_type_) - << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state; + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", previous_state=" << previous_state; state_ = BluetoothStreamState::DISABLED; port_lock.unlock(); internal_cv_.notify_all(); } -bool BluetoothAudioPort::in_use() const { - return (cookie_ != android::bluetooth::audio::kObserversCookieUndefined); +bool BluetoothAudioPortAidl::in_use() const { + return ( + cookie_ != + ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined); } -bool BluetoothAudioPort::GetPreferredDataIntervalUs(size_t* interval_us) const { +bool BluetoothAudioPortAidl::GetPreferredDataIntervalUs( + size_t* interval_us) const { if (!in_use()) { return false; } - const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration& - hal_audio_cfg = - BluetoothAudioSessionControl_2_2::GetAudioConfig(session_type_); - if (hal_audio_cfg.getDiscriminator() != - ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration:: - hidl_discriminator::pcmConfig) { + const AudioConfiguration& hal_audio_cfg = + BluetoothAudioSessionControl::GetAudioConfig(session_type_); + if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) { return false; } - const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_cfg = - hal_audio_cfg.pcmConfig(); + const PcmConfiguration& pcm_cfg = + hal_audio_cfg.get<AudioConfiguration::pcmConfig>(); *interval_us = pcm_cfg.dataIntervalUs; return true; } -bool BluetoothAudioPortOut::LoadAudioConfig(audio_config_t* audio_cfg) const { +bool BluetoothAudioPortAidlOut::LoadAudioConfig( + audio_config_t* audio_cfg) const { if (!in_use()) { - LOG(ERROR) << __func__ << ": BluetoothAudioPortOut is not in use"; + LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlOut is not in use"; audio_cfg->sample_rate = kBluetoothDefaultSampleRate; audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask; audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample; return false; } - const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration& - hal_audio_cfg = - BluetoothAudioSessionControl_2_2::GetAudioConfig(session_type_); - if (hal_audio_cfg.getDiscriminator() != - ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration:: - hidl_discriminator::pcmConfig) { + const AudioConfiguration& hal_audio_cfg = + BluetoothAudioSessionControl::GetAudioConfig(session_type_); + if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) { audio_cfg->sample_rate = kBluetoothDefaultSampleRate; audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask; audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample; return false; } - const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_cfg = - hal_audio_cfg.pcmConfig(); + const PcmConfiguration& pcm_cfg = + hal_audio_cfg.get<AudioConfiguration::pcmConfig>(); LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_) - << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << ", PcmConfig=[" - << toString(pcm_cfg) << "]"; - if (pcm_cfg.sampleRate == SampleRate_2_1::RATE_UNKNOWN || - pcm_cfg.channelMode == ChannelMode::UNKNOWN || - pcm_cfg.bitsPerSample == BitsPerSample::BITS_UNKNOWN) { + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << ", PcmConfig=[" << pcm_cfg.toString() + << "]"; + if (pcm_cfg.channelMode == ChannelMode::UNKNOWN) { return false; } - audio_cfg->sample_rate = SampleRateToAudioFormat(pcm_cfg.sampleRate); + audio_cfg->sample_rate = pcm_cfg.sampleRateHz; audio_cfg->channel_mask = (is_stereo_to_mono_ ? AUDIO_CHANNEL_OUT_STEREO @@ -339,51 +338,48 @@ bool BluetoothAudioPortOut::LoadAudioConfig(audio_config_t* audio_cfg) const { return true; } -bool BluetoothAudioPortIn::LoadAudioConfig(audio_config_t* audio_cfg) const { +bool BluetoothAudioPortAidlIn::LoadAudioConfig( + audio_config_t* audio_cfg) const { if (!in_use()) { - LOG(ERROR) << __func__ << ": BluetoothAudioPortIn is not in use"; + LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlIn is not in use"; audio_cfg->sample_rate = kBluetoothDefaultSampleRate; audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask; audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample; return false; } - const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration& - hal_audio_cfg = - BluetoothAudioSessionControl_2_2::GetAudioConfig(session_type_); - if (hal_audio_cfg.getDiscriminator() != - ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration:: - hidl_discriminator::pcmConfig) { + const AudioConfiguration& hal_audio_cfg = + BluetoothAudioSessionControl::GetAudioConfig(session_type_); + if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) { audio_cfg->sample_rate = kBluetoothDefaultSampleRate; audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask; audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample; return false; } - const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_cfg = - hal_audio_cfg.pcmConfig(); + const PcmConfiguration& pcm_cfg = + hal_audio_cfg.get<AudioConfiguration::pcmConfig>(); LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_) - << ", state=" << state_ << ", PcmConfig=[" << toString(pcm_cfg) + << ", state=" << state_ << ", PcmConfig=[" << pcm_cfg.toString() << "]"; - if (pcm_cfg.sampleRate == SampleRate_2_1::RATE_UNKNOWN || - pcm_cfg.channelMode == ChannelMode::UNKNOWN || - pcm_cfg.bitsPerSample == BitsPerSample::BITS_UNKNOWN) { + if (pcm_cfg.channelMode == ChannelMode::UNKNOWN) { return false; } - audio_cfg->sample_rate = SampleRateToAudioFormat(pcm_cfg.sampleRate); + audio_cfg->sample_rate = pcm_cfg.sampleRateHz; audio_cfg->channel_mask = InputChannelModeToAudioFormat(pcm_cfg.channelMode); audio_cfg->format = BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample); return true; } -bool BluetoothAudioPort::CondwaitState(BluetoothStreamState state) { +bool BluetoothAudioPortAidl::CondwaitState(BluetoothStreamState state) { bool retval; std::unique_lock<std::mutex> port_lock(cv_mutex_); switch (state) { case BluetoothStreamState::STARTING: LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_) - << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for STARTED"; + << ", cookie=" << StringPrintf("%#hx", cookie_) + << " waiting for STARTED"; retval = internal_cv_.wait_for( port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs), [this] { return this->state_ != BluetoothStreamState::STARTING; }); @@ -391,7 +387,8 @@ bool BluetoothAudioPort::CondwaitState(BluetoothStreamState state) { break; case BluetoothStreamState::SUSPENDING: LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_) - << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for SUSPENDED"; + << ", cookie=" << StringPrintf("%#hx", cookie_) + << " waiting for SUSPENDED"; retval = internal_cv_.wait_for( port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs), [this] { return this->state_ != BluetoothStreamState::SUSPENDING; }); @@ -399,92 +396,107 @@ bool BluetoothAudioPort::CondwaitState(BluetoothStreamState state) { break; default: LOG(WARNING) << __func__ << ": session_type=" << toString(session_type_) - << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for KNOWN"; + << ", cookie=" << StringPrintf("%#hx", cookie_) + << " waiting for KNOWN"; return false; } return retval; // false if any failure like timeout } -bool BluetoothAudioPort::Start() { +bool BluetoothAudioPortAidl::Start() { if (!in_use()) { - LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use"; + LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use"; return false; } - LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_) - << ", state=" << state_ << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") << " request"; + LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ + << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") + << " request"; bool retval = false; if (state_ == BluetoothStreamState::STANDBY) { state_ = BluetoothStreamState::STARTING; - if (BluetoothAudioSessionControl_2_2::StartStream(session_type_)) { + if (BluetoothAudioSessionControl::StartStream(session_type_)) { retval = CondwaitState(BluetoothStreamState::STARTING); } else { LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_) - << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " Hal fails"; + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << " Hal fails"; } } if (retval) { LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) - << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ - << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") << " done"; + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ + << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") + << " done"; } else { LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_) - << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " failure"; + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << " failure"; } return retval; // false if any failure like timeout } -bool BluetoothAudioPort::Suspend() { +bool BluetoothAudioPortAidl::Suspend() { if (!in_use()) { - LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use"; + LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use"; return false; } - LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_) + LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) + << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " request"; bool retval = false; if (state_ == BluetoothStreamState::STARTED) { state_ = BluetoothStreamState::SUSPENDING; - if (BluetoothAudioSessionControl_2_2::SuspendStream(session_type_)) { + if (BluetoothAudioSessionControl::SuspendStream(session_type_)) { retval = CondwaitState(BluetoothStreamState::SUSPENDING); } else { LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_) - << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " Hal fails"; + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << " Hal fails"; } } if (retval) { LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) - << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " done"; + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << " done"; } else { LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_) - << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " failure"; + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << " failure"; } return retval; // false if any failure like timeout } -void BluetoothAudioPort::Stop() { +void BluetoothAudioPortAidl::Stop() { if (!in_use()) { - LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use"; + LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use"; return; } - LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_) + LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) + << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " request"; state_ = BluetoothStreamState::DISABLED; - BluetoothAudioSessionControl_2_2::StopStream(session_type_); - LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_) + BluetoothAudioSessionControl::StopStream(session_type_); + LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) + << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " done"; } -size_t BluetoothAudioPortOut::WriteData(const void* buffer, size_t bytes) const { +size_t BluetoothAudioPortAidlOut::WriteData(const void* buffer, + size_t bytes) const { if (!in_use()) return 0; if (!is_stereo_to_mono_) { - return BluetoothAudioSessionControl_2_2::OutWritePcmData(session_type_, - buffer, bytes); + return BluetoothAudioSessionControl::OutWritePcmData(session_type_, buffer, + bytes); } // WAR to mix the stereo into Mono (16 bits per sample) @@ -494,51 +506,62 @@ size_t BluetoothAudioPortOut::WriteData(const void* buffer, size_t bytes) const std::unique_ptr<int16_t[]> dst{new int16_t[write_frames]}; downmix_to_mono_i16_from_stereo_i16(dst.get(), src, write_frames); // a frame is 16 bits, and the size of a mono frame is equal to half a stereo. - return BluetoothAudioSessionControl_2_2::OutWritePcmData( - session_type_, dst.get(), write_frames * 2) * + return BluetoothAudioSessionControl::OutWritePcmData(session_type_, dst.get(), + write_frames * 2) * 2; } -size_t BluetoothAudioPortIn::ReadData(void* buffer, size_t bytes) const { +size_t BluetoothAudioPortAidlIn::ReadData(void* buffer, size_t bytes) const { if (!in_use()) return 0; - return BluetoothAudioSessionControl_2_2::InReadPcmData(session_type_, buffer, - bytes); + return BluetoothAudioSessionControl::InReadPcmData(session_type_, buffer, + bytes); } -bool BluetoothAudioPort::GetPresentationPosition(uint64_t* delay_ns, - uint64_t* bytes, - timespec* timestamp) const { +bool BluetoothAudioPortAidl::GetPresentationPosition( + uint64_t* delay_ns, uint64_t* bytes, timespec* timestamp) const { if (!in_use()) { - LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use"; + LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use"; return false; } - bool retval = BluetoothAudioSessionControl_2_2::GetPresentationPosition( - session_type_, delay_ns, bytes, timestamp); - LOG(VERBOSE) << __func__ << ": session_type=" << StringPrintf("%#hhx", session_type_) - << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << ", delay=" << *delay_ns - << "ns, data=" << *bytes << " bytes, timestamp=" << timestamp->tv_sec << "." + PresentationPosition presentation_position; + bool retval = BluetoothAudioSessionControl::GetPresentationPosition( + session_type_, presentation_position); + *delay_ns = presentation_position.remoteDeviceAudioDelayNanos; + *bytes = presentation_position.transmittedOctets; + *timestamp = {.tv_sec = static_cast<__kernel_old_time_t>( + presentation_position.transmittedOctetsTimestamp.tvSec), + .tv_nsec = static_cast<long>( + presentation_position.transmittedOctetsTimestamp.tvNSec)}; + LOG(VERBOSE) << __func__ + << ": session_type=" << StringPrintf("%#hhx", session_type_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << ", delay=" << *delay_ns + << "ns, data=" << *bytes + << " bytes, timestamp=" << timestamp->tv_sec << "." << StringPrintf("%09ld", timestamp->tv_nsec) << "s"; return retval; } -void BluetoothAudioPort::UpdateMetadata( +void BluetoothAudioPortAidl::UpdateSourceMetadata( const source_metadata* source_metadata) const { if (!in_use()) { - LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use"; + LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use"; return; } - LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_) - << ", state=" << state_ << ", " << source_metadata->track_count << " track(s)"; + LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << ", " << source_metadata->track_count + << " track(s)"; if (source_metadata->track_count == 0) return; - BluetoothAudioSessionControl_2_2::UpdateTracksMetadata(session_type_, - source_metadata); + BluetoothAudioSessionControl::UpdateSourceMetadata(session_type_, + *source_metadata); } -void BluetoothAudioPort::UpdateSinkMetadata( +void BluetoothAudioPortAidl::UpdateSinkMetadata( const sink_metadata* sink_metadata) const { if (!in_use()) { - LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use"; + LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use"; return; } LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_) @@ -546,16 +569,17 @@ void BluetoothAudioPort::UpdateSinkMetadata( << ", state=" << state_ << ", " << sink_metadata->track_count << " track(s)"; if (sink_metadata->track_count == 0) return; - BluetoothAudioSessionControl_2_2::UpdateSinkMetadata(session_type_, - sink_metadata); + BluetoothAudioSessionControl::UpdateSinkMetadata(session_type_, + *sink_metadata); } -BluetoothStreamState BluetoothAudioPort::GetState() const { return state_; } +BluetoothStreamState BluetoothAudioPortAidl::GetState() const { return state_; } -void BluetoothAudioPort::SetState(BluetoothStreamState state) { +void BluetoothAudioPortAidl::SetState(BluetoothStreamState state) { state_ = state; } +} // namespace aidl } // namespace audio } // namespace bluetooth -} // namespace android +} // namespace android
\ No newline at end of file diff --git a/system/audio_bluetooth_hw/device_port_proxy.h b/system/audio_bluetooth_hw/device_port_proxy.h index cc5342d50f..dab4970ca6 100644 --- a/system/audio_bluetooth_hw/device_port_proxy.h +++ b/system/audio_bluetooth_hw/device_port_proxy.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,10 @@ #pragma once -#include <android/hardware/bluetooth/audio/2.2/types.h> +#include <aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.h> +#include <aidl/android/hardware/bluetooth/audio/SessionType.h> #include <hardware/audio.h> + #include <condition_variable> #include <mutex> #include <unordered_map> @@ -28,112 +30,184 @@ namespace android { namespace bluetooth { namespace audio { -using SessionType_2_1 = - ::android::hardware::bluetooth::audio::V2_1::SessionType; - -// Proxy for Bluetooth Audio HW Module to communicate with Bluetooth Audio -// Session Control. All methods are not thread safe, so users must acquire a -// lock. Note: currently, in stream_apis.cc, if GetState() is only used for -// verbose logging, it is not locked, so the state may not be synchronized. +/*** + * Proxy for Bluetooth Audio HW Module to communicate with Bluetooth Audio + * Session Control. All methods are not thread safe, so users must acquire a + * lock. Note: currently, in stream_apis.cc, if GetState() is only used for + * verbose logging, it is not locked, so the state may not be synchronized. + ***/ class BluetoothAudioPort { public: - BluetoothAudioPort(); + BluetoothAudioPort(){}; virtual ~BluetoothAudioPort() = default; - // Fetch output control / data path of BluetoothAudioPort and setup - // callbacks into BluetoothAudioProvider. If SetUp() returns false, the audio - // HAL must delete this BluetoothAudioPort and return EINVAL to caller - bool SetUp(audio_devices_t devices); + /*** + * Fetch output control / data path of BluetoothAudioPort and setup + * callbacks into BluetoothAudioProvider. If SetUp() returns false, the audio + * HAL must delete this BluetoothAudioPort and return EINVAL to caller + ***/ + virtual bool SetUp(audio_devices_t) { return false; } + + /*** + * Unregister this BluetoothAudioPort from BluetoothAudioSessionControl. + * Audio HAL must delete this BluetoothAudioPort after calling this. + ***/ + virtual void TearDown() {} + + /*** + * When the Audio framework / HAL tries to query audio config about format, + * channel mask and sample rate, it uses this function to fetch from the + * Bluetooth stack + ***/ + virtual bool LoadAudioConfig(audio_config_t*) const { return false; }; + + /*** + * WAR to support Mono mode / 16 bits per sample + ***/ + virtual void ForcePcmStereoToMono(bool) {} + + /*** + * When the Audio framework / HAL wants to change the stream state, it invokes + * these 3 functions to control the Bluetooth stack (Audio Control Path). + * Note: Both Start() and Suspend() will return true when there are no errors. + * Called by Audio framework / HAL to start the stream + ***/ + virtual bool Start() { return false; } + + /*** + * Called by Audio framework / HAL to suspend the stream + ***/ + virtual bool Suspend() { return false; }; + + /*** + virtual bool Suspend() { return false; } + * Called by Audio framework / HAL to stop the stream + ***/ + virtual void Stop() {} + + /*** + * Called by the Audio framework / HAL to fetch information about audio frames + * presented to an external sink, or frames presented fror an internal sink + ***/ + virtual bool GetPresentationPosition(uint64_t*, uint64_t*, timespec*) const { + return false; + } + + /*** + * Called by the Audio framework / HAL when the metadata of the stream's + * source has been changed. + ***/ + virtual void UpdateSourceMetadata(const source_metadata*) const {}; + + /*** + * Return the current BluetoothStreamState + ***/ + virtual BluetoothStreamState GetState() const { + return static_cast<BluetoothStreamState>(0); + } - // Unregister this BluetoothAudioPort from BluetoothAudioSessionControl. - // Audio HAL must delete this BluetoothAudioPort after calling this. - void TearDown(); + /*** + * Set the current BluetoothStreamState + ***/ + virtual void SetState(BluetoothStreamState state) {} - // When the Audio framework / HAL tries to query audio config about format, - // channel mask and sample rate, it uses this function to fetch from the - // Bluetooth stack - virtual bool LoadAudioConfig(audio_config_t* audio_cfg) const = 0; + virtual bool IsA2dp() const { return false; } - // WAR to support Mono mode / 16 bits per sample - void ForcePcmStereoToMono(bool force) { - is_stereo_to_mono_ = force; - } + virtual bool GetPreferredDataIntervalUs(size_t* interval_us) const { + return false; + }; + + virtual size_t WriteData(const void* buffer, size_t bytes) const { + return 0; + }; + virtual size_t ReadData(void* buffer, size_t bytes) const { return 0; }; +}; + +namespace aidl { + +using ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus; +using ::aidl::android::hardware::bluetooth::audio::SessionType; + +class BluetoothAudioPortAidl : public BluetoothAudioPort { + public: + BluetoothAudioPortAidl(); + virtual ~BluetoothAudioPortAidl() = default; + + bool SetUp(audio_devices_t devices) override; + + void TearDown() override; + + void ForcePcmStereoToMono(bool force) override { is_stereo_to_mono_ = force; } - // When the Audio framework / HAL wants to change the stream state, it invokes - // these 3 functions to control the Bluetooth stack (Audio Control Path). - // Note: Both Start() and Suspend() will return ture when there are no errors. - // Called by Audio framework / HAL to start the stream - bool Start(); - // Called by Audio framework / HAL to suspend the stream - bool Suspend(); - // Called by Audio framework / HAL to stop the stream - void Stop(); + bool Start() override; + bool Suspend() override; + void Stop() override; - // Called by the Audio framework / HAL to fetch informaiton about audio frames - // presented to an external sink, or frames presented fror an internal sink - bool GetPresentationPosition(uint64_t* delay_ns, uint64_t* bytes, - timespec* timestamp) const; + bool GetPresentationPosition(uint64_t* delay_ns, uint64_t* byte, + timespec* timestamp) const override; - // Called by the Audio framework / HAL when the metadata of the stream's - // source has been changed. - void UpdateMetadata(const source_metadata* source_metadata) const; + void UpdateSourceMetadata( + const source_metadata* source_metadata) const override; - void UpdateSinkMetadata(const sink_metadata* sink_metadata) const; + /*** + * Called by the Audio framework / HAL when the metadata of the stream's + * sink has been changed. + ***/ + virtual void UpdateSinkMetadata(const sink_metadata* sink_metadata) const; - // Return the current BluetoothStreamState - BluetoothStreamState GetState() const; + BluetoothStreamState GetState() const override; - // Set the current BluetoothStreamState - void SetState(BluetoothStreamState state); + void SetState(BluetoothStreamState state) override; - bool IsA2dp() const { - return session_type_ == SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH || - session_type_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH; + bool IsA2dp() const override { + return session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH || + session_type_ == + SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH; } - bool GetPreferredDataIntervalUs(size_t* interval_us) const; + bool GetPreferredDataIntervalUs(size_t* interval_us) const override; protected: uint16_t cookie_; BluetoothStreamState state_; - SessionType_2_1 session_type_; + SessionType session_type_; // WR to support Mono: True if fetching Stereo and mixing into Mono bool is_stereo_to_mono_ = false; - bool in_use() const; + virtual bool in_use() const; private: mutable std::mutex cv_mutex_; std::condition_variable internal_cv_; // Check and initialize session type for |devices| If failed, this - // BluetoothAudioPort is not initialized and must be deleted. + // BluetoothAudioPortAidl is not initialized and must be deleted. bool init_session_type(audio_devices_t device); bool CondwaitState(BluetoothStreamState state); - void ControlResultHandler( - const ::android::hardware::bluetooth::audio::V2_0::Status& status); + void ControlResultHandler(const BluetoothAudioStatus& status); void SessionChangedHandler(); }; -class BluetoothAudioPortOut : public BluetoothAudioPort { +class BluetoothAudioPortAidlOut : public BluetoothAudioPortAidl { public: - ~BluetoothAudioPortOut() = default; + ~BluetoothAudioPortAidlOut(); // The audio data path to the Bluetooth stack (Software encoding) - size_t WriteData(const void* buffer, size_t bytes) const; - bool LoadAudioConfig(audio_config_t* audio_cfg) const; + size_t WriteData(const void* buffer, size_t bytes) const override; + bool LoadAudioConfig(audio_config_t* audio_cfg) const override; }; -class BluetoothAudioPortIn : public BluetoothAudioPort { +class BluetoothAudioPortAidlIn : public BluetoothAudioPortAidl { public: - ~BluetoothAudioPortIn() = default; + ~BluetoothAudioPortAidlIn(); // The audio data path from the Bluetooth stack (Software decoded) - size_t ReadData(void* buffer, size_t bytes) const; - bool LoadAudioConfig(audio_config_t* audio_cfg) const; + size_t ReadData(void* buffer, size_t bytes) const override; + bool LoadAudioConfig(audio_config_t* audio_cfg) const override; }; +} // namespace aidl } // namespace audio } // namespace bluetooth } // namespace android diff --git a/system/audio_bluetooth_hw/device_port_proxy_hidl.cc b/system/audio_bluetooth_hw/device_port_proxy_hidl.cc new file mode 100644 index 0000000000..fbe7745f73 --- /dev/null +++ b/system/audio_bluetooth_hw/device_port_proxy_hidl.cc @@ -0,0 +1,608 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "BTAudioHalDeviceProxyHIDL" + +#include "device_port_proxy_hidl.h" + +#include <android-base/logging.h> +#include <android-base/stringprintf.h> +#include <audio_utils/primitives.h> +#include <inttypes.h> +#include <log/log.h> +#include <stdlib.h> + +#include "BluetoothAudioSessionControl_2_1.h" +#include "stream_apis.h" +#include "utils.h" + +namespace android { +namespace bluetooth { +namespace audio { +namespace hidl { + +using ::android::base::StringPrintf; +using ::android::bluetooth::audio::BluetoothAudioSessionControl_2_1; +using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample; +using ::android::hardware::bluetooth::audio::V2_0::ChannelMode; +using ::android::hardware::bluetooth::audio::V2_0::PcmParameters; +using SampleRate = ::android::hardware::bluetooth::audio::V2_0::SampleRate; +using SampleRate_2_1 = ::android::hardware::bluetooth::audio::V2_1::SampleRate; +using BluetoothAudioStatusHidl = + ::android::hardware::bluetooth::audio::V2_0::Status; +using ControlResultCallback = std::function<void( + uint16_t cookie, bool start_resp, const BluetoothAudioStatusHidl& status)>; +using SessionChangedCallback = std::function<void(uint16_t cookie)>; + +namespace { + +unsigned int SampleRateToAudioFormat(SampleRate_2_1 sample_rate) { + switch (sample_rate) { + case SampleRate_2_1::RATE_8000: + return 8000; + case SampleRate_2_1::RATE_16000: + return 16000; + case SampleRate_2_1::RATE_24000: + return 24000; + case SampleRate_2_1::RATE_32000: + return 32000; + case SampleRate_2_1::RATE_44100: + return 44100; + case SampleRate_2_1::RATE_48000: + return 48000; + case SampleRate_2_1::RATE_88200: + return 88200; + case SampleRate_2_1::RATE_96000: + return 96000; + case SampleRate_2_1::RATE_176400: + return 176400; + case SampleRate_2_1::RATE_192000: + return 192000; + default: + return kBluetoothDefaultSampleRate; + } +} +audio_channel_mask_t OutputChannelModeToAudioFormat(ChannelMode channel_mode) { + switch (channel_mode) { + case ChannelMode::MONO: + return AUDIO_CHANNEL_OUT_MONO; + case ChannelMode::STEREO: + return AUDIO_CHANNEL_OUT_STEREO; + default: + return kBluetoothDefaultOutputChannelModeMask; + } +} + +audio_channel_mask_t InputChannelModeToAudioFormat(ChannelMode channel_mode) { + switch (channel_mode) { + case ChannelMode::MONO: + return AUDIO_CHANNEL_IN_MONO; + case ChannelMode::STEREO: + return AUDIO_CHANNEL_IN_STEREO; + default: + return kBluetoothDefaultInputChannelModeMask; + } +} + +audio_format_t BitsPerSampleToAudioFormat(BitsPerSample bits_per_sample) { + switch (bits_per_sample) { + case BitsPerSample::BITS_16: + return AUDIO_FORMAT_PCM_16_BIT; + case BitsPerSample::BITS_24: + return AUDIO_FORMAT_PCM_24_BIT_PACKED; + case BitsPerSample::BITS_32: + return AUDIO_FORMAT_PCM_32_BIT; + default: + return kBluetoothDefaultAudioFormatBitsPerSample; + } +} + +// The maximum time to wait in std::condition_variable::wait_for() +constexpr unsigned int kMaxWaitingTimeMs = 4500; + +} // namespace + +BluetoothAudioPortHidl::BluetoothAudioPortHidl() + : session_type_hidl_(SessionType_2_1::UNKNOWN), + cookie_(android::bluetooth::audio::kObserversCookieUndefined), + state_(BluetoothStreamState::DISABLED) {} + +BluetoothAudioPortHidlOut::~BluetoothAudioPortHidlOut() { + if (BluetoothAudioPortHidl::in_use()) BluetoothAudioPortHidl::TearDown(); +} + +BluetoothAudioPortHidlIn::~BluetoothAudioPortHidlIn() { + if (BluetoothAudioPortHidl::in_use()) BluetoothAudioPortHidl::TearDown(); +} + +bool BluetoothAudioPortHidl::SetUp(audio_devices_t devices) { + if (!init_session_type(devices)) return false; + + state_ = BluetoothStreamState::STANDBY; + + auto control_result_cb = [port = this]( + uint16_t cookie, bool start_resp, + const BluetoothAudioStatusHidl& status) { + if (!port->in_use()) { + LOG(ERROR) << "control_result_cb: BluetoothAudioPort is not in use"; + return; + } + if (port->cookie_ != cookie) { + LOG(ERROR) << "control_result_cb: proxy of device port (cookie=" + << StringPrintf("%#hx", cookie) << ") is corrupted"; + return; + } + port->ControlResultHandler(status); + }; + auto session_changed_cb = [port = this](uint16_t cookie) { + if (!port->in_use()) { + LOG(ERROR) << "session_changed_cb: BluetoothAudioPort is not in use"; + return; + } + if (port->cookie_ != cookie) { + LOG(ERROR) << "session_changed_cb: proxy of device port (cookie=" + << StringPrintf("%#hx", cookie) << ") is corrupted"; + return; + } + port->SessionChangedHandler(); + }; + ::android::bluetooth::audio::PortStatusCallbacks cbacks = { + .control_result_cb_ = control_result_cb, + .session_changed_cb_ = session_changed_cb}; + cookie_ = BluetoothAudioSessionControl_2_1::RegisterControlResultCback( + session_type_hidl_, cbacks); + LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_); + + return (cookie_ != android::bluetooth::audio::kObserversCookieUndefined); +} + +bool BluetoothAudioPortHidl::init_session_type(audio_devices_t device) { + switch (device) { + case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP: + case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES: + case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER: + LOG(VERBOSE) + << __func__ + << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) (" + << StringPrintf("%#x", device) << ")"; + session_type_hidl_ = SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH; + break; + case AUDIO_DEVICE_OUT_HEARING_AID: + LOG(VERBOSE) << __func__ + << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) (" + << StringPrintf("%#x", device) << ")"; + session_type_hidl_ = + SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH; + break; + case AUDIO_DEVICE_OUT_BLE_HEADSET: + LOG(VERBOSE) << __func__ + << ": device=AUDIO_DEVICE_OUT_BLE_HEADSET (MEDIA/VOICE) (" + << StringPrintf("%#x", device) << ")"; + session_type_hidl_ = SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH; + break; + case AUDIO_DEVICE_OUT_BLE_SPEAKER: + LOG(VERBOSE) << __func__ + << ": device=AUDIO_DEVICE_OUT_BLE_SPEAKER (MEDIA) (" + << StringPrintf("%#x", device) << ")"; + session_type_hidl_ = SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH; + break; + case AUDIO_DEVICE_IN_BLE_HEADSET: + LOG(VERBOSE) << __func__ + << ": device=AUDIO_DEVICE_IN_BLE_HEADSET (VOICE) (" + << StringPrintf("%#x", device) << ")"; + session_type_hidl_ = SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH; + break; + default: + LOG(ERROR) << __func__ + << ": unknown device=" << StringPrintf("%#x", device); + return false; + } + + if (!BluetoothAudioSessionControl_2_1::IsSessionReady(session_type_hidl_)) { + LOG(ERROR) << __func__ << ": device=" << StringPrintf("%#x", device) + << ", session_type=" << toString(session_type_hidl_) + << " is not ready"; + return false; + } + return true; +} + +void BluetoothAudioPortHidl::TearDown() { + if (!in_use()) { + LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << " unknown monitor"; + return; + } + + LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_); + BluetoothAudioSessionControl_2_1::UnregisterControlResultCback( + session_type_hidl_, cookie_); + cookie_ = android::bluetooth::audio::kObserversCookieUndefined; +} + +void BluetoothAudioPortHidl::ControlResultHandler( + const BluetoothAudioStatusHidl& status) { + if (!in_use()) { + LOG(ERROR) << __func__ << ": BluetoothAudioPortis not in use"; + return; + } + std::unique_lock<std::mutex> port_lock(cv_mutex_); + BluetoothStreamState previous_state = state_; + LOG(INFO) << "control_result_cb: session_type=" + << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", previous_state=" << previous_state + << ", status=" << toString(status); + + switch (previous_state) { + case BluetoothStreamState::STARTING: + if (status == BluetoothAudioStatusHidl::SUCCESS) { + state_ = BluetoothStreamState::STARTED; + } else { + // Set to standby since the stack may be busy switching between outputs + LOG(WARNING) << "control_result_cb: status=" << toString(status) + << " failure for session_type=" + << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", previous_state=" << previous_state; + state_ = BluetoothStreamState::STANDBY; + } + break; + case BluetoothStreamState::SUSPENDING: + if (status == BluetoothAudioStatusHidl::SUCCESS) { + state_ = BluetoothStreamState::STANDBY; + } else { + // It will be failed if the headset is disconnecting, and set to disable + // to wait for re-init again + LOG(WARNING) << "control_result_cb: status=" << toString(status) + << " failure for session_type=" + << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", previous_state=" << previous_state; + state_ = BluetoothStreamState::DISABLED; + } + break; + default: + LOG(ERROR) << "control_result_cb: unexpected status=" << toString(status) + << " for session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", previous_state=" << previous_state; + return; + } + port_lock.unlock(); + internal_cv_.notify_all(); +} + +void BluetoothAudioPortHidl::SessionChangedHandler() { + if (!in_use()) { + LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use"; + return; + } + std::unique_lock<std::mutex> port_lock(cv_mutex_); + BluetoothStreamState previous_state = state_; + LOG(INFO) << "session_changed_cb: session_type=" + << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", previous_state=" << previous_state; + state_ = BluetoothStreamState::DISABLED; + port_lock.unlock(); + internal_cv_.notify_all(); +} + +bool BluetoothAudioPortHidl::in_use() const { + return (cookie_ != android::bluetooth::audio::kObserversCookieUndefined); +} + +bool BluetoothAudioPortHidl::GetPreferredDataIntervalUs( + size_t* interval_us) const { + if (!in_use()) { + return false; + } + + const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration& + hal_audio_cfg = + BluetoothAudioSessionControl_2_1::GetAudioConfig(session_type_hidl_); + if (hal_audio_cfg.getDiscriminator() != + ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration:: + hidl_discriminator::pcmConfig) { + return false; + } + + const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_cfg = + hal_audio_cfg.pcmConfig(); + *interval_us = pcm_cfg.dataIntervalUs; + return true; +} + +bool BluetoothAudioPortHidl::CondwaitState(BluetoothStreamState state) { + bool retval; + std::unique_lock<std::mutex> port_lock(cv_mutex_); + switch (state) { + case BluetoothStreamState::STARTING: + LOG(VERBOSE) << __func__ + << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << " waiting for STARTED"; + retval = internal_cv_.wait_for( + port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs), + [this] { return this->state_ != BluetoothStreamState::STARTING; }); + retval = retval && state_ == BluetoothStreamState::STARTED; + break; + case BluetoothStreamState::SUSPENDING: + LOG(VERBOSE) << __func__ + << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << " waiting for SUSPENDED"; + retval = internal_cv_.wait_for( + port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs), + [this] { return this->state_ != BluetoothStreamState::SUSPENDING; }); + retval = retval && state_ == BluetoothStreamState::STANDBY; + break; + default: + LOG(WARNING) << __func__ + << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << " waiting for KNOWN"; + return false; + } + + return retval; // false if any failure like timeout +} + +bool BluetoothAudioPortHidl::Start() { + if (!in_use()) { + LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use"; + return false; + } + + LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ + << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") + << " request"; + bool retval = false; + if (state_ == BluetoothStreamState::STANDBY) { + state_ = BluetoothStreamState::STARTING; + if (BluetoothAudioSessionControl_2_1::StartStream(session_type_hidl_)) { + retval = CondwaitState(BluetoothStreamState::STARTING); + } else { + LOG(ERROR) << __func__ + << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << " Hal fails"; + } + } + + if (retval) { + LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ + << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") + << " done"; + } else { + LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << " failure"; + } + + return retval; // false if any failure like timeout +} + +bool BluetoothAudioPortHidl::Suspend() { + if (!in_use()) { + LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use"; + return false; + } + + LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << " request"; + bool retval = false; + if (state_ == BluetoothStreamState::STARTED) { + state_ = BluetoothStreamState::SUSPENDING; + if (BluetoothAudioSessionControl_2_1::SuspendStream(session_type_hidl_)) { + retval = CondwaitState(BluetoothStreamState::SUSPENDING); + } else { + LOG(ERROR) << __func__ + << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << " Hal fails"; + } + } + + if (retval) { + LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << " done"; + } else { + LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << " failure"; + } + + return retval; // false if any failure like timeout +} + +void BluetoothAudioPortHidl::Stop() { + if (!in_use()) { + LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use"; + return; + } + LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << " request"; + state_ = BluetoothStreamState::DISABLED; + BluetoothAudioSessionControl_2_1::StopStream(session_type_hidl_); + LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << " done"; +} + +bool BluetoothAudioPortHidl::GetPresentationPosition( + uint64_t* delay_ns, uint64_t* bytes, timespec* timestamp) const { + if (!in_use()) { + LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use"; + return false; + } + bool retval = BluetoothAudioSessionControl_2_1::GetPresentationPosition( + session_type_hidl_, delay_ns, bytes, timestamp); + LOG(VERBOSE) << __func__ + << ": session_type=" << StringPrintf("%#hhx", session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << ", delay=" << *delay_ns + << "ns, data=" << *bytes + << " bytes, timestamp=" << timestamp->tv_sec << "." + << StringPrintf("%09ld", timestamp->tv_nsec) << "s"; + + return retval; +} + +void BluetoothAudioPortHidl::UpdateSourceMetadata( + const source_metadata* source_metadata) const { + if (!in_use()) { + LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use"; + return; + } + LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" << StringPrintf("%#hx", cookie_) + << ", state=" << state_ << ", " << source_metadata->track_count + << " track(s)"; + if (source_metadata->track_count == 0) return; + BluetoothAudioSessionControl_2_1::UpdateTracksMetadata(session_type_hidl_, + source_metadata); +} + +BluetoothStreamState BluetoothAudioPortHidl::GetState() const { return state_; } + +void BluetoothAudioPortHidl::SetState(BluetoothStreamState state) { + state_ = state; +} + +size_t BluetoothAudioPortHidlOut::WriteData(const void* buffer, + size_t bytes) const { + if (!BluetoothAudioPortHidl::in_use()) return 0; + if (!BluetoothAudioPortHidl::is_stereo_to_mono_) { + return BluetoothAudioSessionControl_2_1::OutWritePcmData(session_type_hidl_, + buffer, bytes); + } + + // WAR to mix the stereo into Mono (16 bits per sample) + const size_t write_frames = bytes >> 2; + if (write_frames == 0) return 0; + auto src = static_cast<const int16_t*>(buffer); + std::unique_ptr<int16_t[]> dst{new int16_t[write_frames]}; + downmix_to_mono_i16_from_stereo_i16(dst.get(), src, write_frames); + // a frame is 16 bits, and the size of a mono frame is equal to half a stereo. + return BluetoothAudioSessionControl_2_1::OutWritePcmData( + session_type_hidl_, dst.get(), write_frames * 2) * + 2; +} + +size_t BluetoothAudioPortHidlIn::ReadData(void* buffer, size_t bytes) const { + if (!BluetoothAudioPortHidl::in_use()) return 0; + return BluetoothAudioSessionControl_2_1::InReadPcmData(session_type_hidl_, + buffer, bytes); +} + +bool BluetoothAudioPortHidlIn::LoadAudioConfig( + audio_config_t* audio_cfg) const { + if (!BluetoothAudioPortHidl::in_use()) { + LOG(ERROR) << __func__ << ": BluetoothAudioPortIn is not in use"; + audio_cfg->sample_rate = kBluetoothDefaultSampleRate; + audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask; + audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample; + return false; + } + + const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration& + hal_audio_cfg = + BluetoothAudioSessionControl_2_1::GetAudioConfig(session_type_hidl_); + if (hal_audio_cfg.getDiscriminator() != + ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration:: + hidl_discriminator::pcmConfig) { + audio_cfg->sample_rate = kBluetoothDefaultSampleRate; + audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask; + audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample; + return false; + } + const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_cfg = + hal_audio_cfg.pcmConfig(); + LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" + << StringPrintf("%#hx", BluetoothAudioPortHidl::cookie_) + << ", state=" << BluetoothAudioPortHidl::state_ + << ", PcmConfig=[" << toString(pcm_cfg) << "]"; + if (pcm_cfg.sampleRate == SampleRate_2_1::RATE_UNKNOWN || + pcm_cfg.channelMode == ChannelMode::UNKNOWN || + pcm_cfg.bitsPerSample == BitsPerSample::BITS_UNKNOWN) { + return false; + } + + audio_cfg->sample_rate = SampleRateToAudioFormat(pcm_cfg.sampleRate); + audio_cfg->channel_mask = InputChannelModeToAudioFormat(pcm_cfg.channelMode); + audio_cfg->format = BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample); + return true; +} + +bool BluetoothAudioPortHidlOut::LoadAudioConfig( + audio_config_t* audio_cfg) const { + if (!BluetoothAudioPortHidl::in_use()) { + LOG(ERROR) << __func__ << ": BluetoothAudioPortOut is not in use"; + audio_cfg->sample_rate = kBluetoothDefaultSampleRate; + audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask; + audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample; + return false; + } + + const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration& + hal_audio_cfg = + BluetoothAudioSessionControl_2_1::GetAudioConfig(session_type_hidl_); + if (hal_audio_cfg.getDiscriminator() != + ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration:: + hidl_discriminator::pcmConfig) { + audio_cfg->sample_rate = kBluetoothDefaultSampleRate; + audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask; + audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample; + return false; + } + const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_cfg = + hal_audio_cfg.pcmConfig(); + LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_hidl_) + << ", cookie=" + << StringPrintf("%#hx", BluetoothAudioPortHidl::cookie_) + << ", state=" << BluetoothAudioPortHidl::state_ + << ", PcmConfig=[" << toString(pcm_cfg) << "]"; + if (pcm_cfg.sampleRate == SampleRate_2_1::RATE_UNKNOWN || + pcm_cfg.channelMode == ChannelMode::UNKNOWN || + pcm_cfg.bitsPerSample == BitsPerSample::BITS_UNKNOWN) { + return false; + } + audio_cfg->sample_rate = SampleRateToAudioFormat(pcm_cfg.sampleRate); + audio_cfg->channel_mask = + (BluetoothAudioPortHidl::is_stereo_to_mono_ + ? AUDIO_CHANNEL_OUT_STEREO + : OutputChannelModeToAudioFormat(pcm_cfg.channelMode)); + audio_cfg->format = BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample); + return true; +} + +} // namespace hidl +} // namespace audio +} // namespace bluetooth +} // namespace android
\ No newline at end of file diff --git a/system/audio_bluetooth_hw/device_port_proxy_hidl.h b/system/audio_bluetooth_hw/device_port_proxy_hidl.h new file mode 100644 index 0000000000..f37370daaf --- /dev/null +++ b/system/audio_bluetooth_hw/device_port_proxy_hidl.h @@ -0,0 +1,116 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <android/hardware/bluetooth/audio/2.1/types.h> +#include <hardware/audio.h> + +#include <condition_variable> +#include <mutex> +#include <unordered_map> + +#include "device_port_proxy.h" + +enum class BluetoothStreamState : uint8_t; + +namespace android { +namespace bluetooth { +namespace audio { +namespace hidl { + +using SessionType_2_1 = + ::android::hardware::bluetooth::audio::V2_1::SessionType; + +class BluetoothAudioPortHidl : public BluetoothAudioPort { + public: + BluetoothAudioPortHidl(); + virtual ~BluetoothAudioPortHidl() = default; + + bool SetUp(audio_devices_t devices) override; + + void TearDown() override; + + void ForcePcmStereoToMono(bool force) override { is_stereo_to_mono_ = force; } + + bool Start() override; + + bool Suspend() override; + + void Stop() override; + + bool GetPresentationPosition(uint64_t* delay_ns, uint64_t* bytes, + timespec* timestamp) const override; + + void UpdateSourceMetadata( + const source_metadata* source_metadata) const override; + + BluetoothStreamState GetState() const override; + + void SetState(BluetoothStreamState state) override; + + bool IsA2dp() const override { + return session_type_hidl_ == + SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH || + session_type_hidl_ == + SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH; + } + + bool GetPreferredDataIntervalUs(size_t* interval_us) const override; + + protected: + SessionType_2_1 session_type_hidl_; + uint16_t cookie_; + BluetoothStreamState state_; + // WR to support Mono: True if fetching Stereo and mixing into Mono + bool is_stereo_to_mono_ = false; + + bool in_use() const; + + private: + mutable std::mutex cv_mutex_; + std::condition_variable internal_cv_; + + bool init_session_type(audio_devices_t device); + + bool CondwaitState(BluetoothStreamState state); + + void ControlResultHandler( + const ::android::hardware::bluetooth::audio::V2_0::Status& status); + + void SessionChangedHandler(); +}; + +class BluetoothAudioPortHidlOut : public BluetoothAudioPortHidl { + public: + ~BluetoothAudioPortHidlOut(); + + size_t WriteData(const void* buffer, size_t bytes) const override; + bool LoadAudioConfig(audio_config_t* audio_cfg) const override; +}; + +class BluetoothAudioPortHidlIn : public BluetoothAudioPortHidl { + public: + ~BluetoothAudioPortHidlIn(); + + size_t ReadData(void* buffer, size_t bytes) const override; + bool LoadAudioConfig(audio_config_t* audio_cfg) const override; +}; + +} // namespace hidl +} // namespace audio +} // namespace bluetooth +} // namespace android
\ No newline at end of file diff --git a/system/audio_bluetooth_hw/stream_apis.cc b/system/audio_bluetooth_hw/stream_apis.cc index 77e1bb08b0..5bc992309a 100644 --- a/system/audio_bluetooth_hw/stream_apis.cc +++ b/system/audio_bluetooth_hw/stream_apis.cc @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "device_port_proxy.h" #define LOG_TAG "BTAudioHalStream" #include <android-base/logging.h> @@ -26,11 +27,11 @@ #include <time.h> #include <unistd.h> +#include "BluetoothAudioSession.h" #include "stream_apis.h" #include "utils.h" using ::android::base::StringPrintf; -using ::android::bluetooth::audio::BluetoothAudioPortOut; using ::android::bluetooth::audio::utils::GetAudioParamString; using ::android::bluetooth::audio::utils::ParseAudioParams; @@ -66,7 +67,7 @@ void out_calculate_feeding_delay_ms(const BluetoothStreamOut* out, bool timestamp_fetched = false; std::unique_lock<std::mutex> lock(out->mutex_); - if (out->bluetooth_output_.GetPresentationPosition( + if (out->bluetooth_output_->GetPresentationPosition( &delay_report_ns, &absorbed_bytes, &absorbed_timestamp)) { delay_report_ms = delay_report_ns / 1000000; // assume kMinimumDelayMs (50ms) < delay_report_ns < kMaximumDelayMs @@ -76,7 +77,7 @@ void out_calculate_feeding_delay_ms(const BluetoothStreamOut* out, delay_report_ms < kMaximumDelayMs) { timestamp_fetched = true; } else if (delay_report_ms >= kMaximumDelayMs) { - LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", delay_report=" << delay_report_ns << "ns abnormal"; } } @@ -91,10 +92,10 @@ void out_calculate_feeding_delay_ms(const BluetoothStreamOut* out, if (timestamp != nullptr) { clock_gettime(CLOCK_MONOTONIC, &absorbed_timestamp); } - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " uses the legacy delay " << delay_report_ms << " ms"; } - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", delay=" << delay_report_ms << "ms, data=" << absorbed_bytes << " bytes, timestamp=" << absorbed_timestamp.tv_sec << "." << StringPrintf("%09ld", absorbed_timestamp.tv_nsec) << "s"; @@ -139,14 +140,14 @@ void in_calculate_starving_delay_ms(const BluetoothStreamIn* in, struct timespec dispersed_timestamp = {}; std::unique_lock<std::mutex> lock(in->mutex_); - in->bluetooth_input_.GetPresentationPosition( + in->bluetooth_input_->GetPresentationPosition( &delay_report_ns, &dispersed_bytes, &dispersed_timestamp); delay_report_ms = delay_report_ns / 1000000; const uint64_t latency_frames = delay_report_ms * in->sample_rate_ / 1000; *frames = dispersed_bytes / audio_stream_in_frame_size(&in->stream_in_); - LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState() << ", delay=" << delay_report_ms << "ms, data=" << dispersed_bytes << " bytes, timestamp=" << dispersed_timestamp.tv_sec << "." @@ -198,12 +199,12 @@ std::ostream& operator<<(std::ostream& os, const BluetoothStreamState& state) { static uint32_t out_get_sample_rate(const struct audio_stream* stream) { const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream); audio_config_t audio_cfg; - if (out->bluetooth_output_.LoadAudioConfig(&audio_cfg)) { - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + if (out->bluetooth_output_->LoadAudioConfig(&audio_cfg)) { + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " audio_cfg=" << audio_cfg; return audio_cfg.sample_rate; } else { - LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", sample_rate=" << out->sample_rate_ << " failed"; return out->sample_rate_; } @@ -211,7 +212,7 @@ static uint32_t out_get_sample_rate(const struct audio_stream* stream) { static int out_set_sample_rate(struct audio_stream* stream, uint32_t rate) { auto* out = reinterpret_cast<BluetoothStreamOut*>(stream); - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", sample_rate=" << out->sample_rate_; return (rate == out->sample_rate_ ? 0 : -1); } @@ -220,7 +221,7 @@ static size_t out_get_buffer_size(const struct audio_stream* stream) { const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream); size_t buffer_size = out->frames_count_ * audio_stream_out_frame_size(&out->stream_out_); - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", buffer_size=" << buffer_size; return buffer_size; } @@ -229,13 +230,14 @@ static audio_channel_mask_t out_get_channels( const struct audio_stream* stream) { const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream); audio_config_t audio_cfg; - if (out->bluetooth_output_.LoadAudioConfig(&audio_cfg)) { - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + if (out->bluetooth_output_->LoadAudioConfig(&audio_cfg)) { + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " audio_cfg=" << audio_cfg; return audio_cfg.channel_mask; } else { - LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState() - << ", channels=" << StringPrintf("%#x", out->channel_mask_) << " failure"; + LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_->GetState() + << ", channels=" << StringPrintf("%#x", out->channel_mask_) + << " failure"; return out->channel_mask_; } } @@ -243,12 +245,12 @@ static audio_channel_mask_t out_get_channels( static audio_format_t out_get_format(const struct audio_stream* stream) { const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream); audio_config_t audio_cfg; - if (out->bluetooth_output_.LoadAudioConfig(&audio_cfg)) { - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + if (out->bluetooth_output_->LoadAudioConfig(&audio_cfg)) { + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " audio_cfg=" << audio_cfg; return audio_cfg.format; } else { - LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", format=" << out->format_ << " failure"; return out->format_; } @@ -256,7 +258,7 @@ static audio_format_t out_get_format(const struct audio_stream* stream) { static int out_set_format(struct audio_stream* stream, audio_format_t format) { auto* out = reinterpret_cast<BluetoothStreamOut*>(stream); - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", format=" << out->format_; return (format == out->format_ ? 0 : -1); } @@ -268,23 +270,23 @@ static int out_standby(struct audio_stream* stream) { // out->last_write_time_us_ = 0; unnecessary as a stale write time has same // effect - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " being standby (suspend)"; - if (out->bluetooth_output_.GetState() == BluetoothStreamState::STARTED) { + if (out->bluetooth_output_->GetState() == BluetoothStreamState::STARTED) { out->frames_rendered_ = 0; - retval = (out->bluetooth_output_.Suspend() ? 0 : -EIO); - } else if (out->bluetooth_output_.GetState() == + retval = (out->bluetooth_output_->Suspend() ? 0 : -EIO); + } else if (out->bluetooth_output_->GetState() == BluetoothStreamState::STARTING || - out->bluetooth_output_.GetState() == + out->bluetooth_output_->GetState() == BluetoothStreamState::SUSPENDING) { - LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " NOT ready to be standby"; retval = -EBUSY; } else { - LOG(DEBUG) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(DEBUG) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " standby already"; } - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " standby (suspend) retval=" << retval; return retval; @@ -292,7 +294,7 @@ static int out_standby(struct audio_stream* stream) { static int out_dump(const struct audio_stream* stream, int fd) { const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream); - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState(); + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState(); return 0; } @@ -302,7 +304,7 @@ static int out_set_parameters(struct audio_stream* stream, std::unique_lock<std::mutex> lock(out->mutex_); int retval = 0; - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", kvpairs=[" << kvpairs << "]"; std::unordered_map<std::string, std::string> params = @@ -316,73 +318,78 @@ static int out_set_parameters(struct audio_stream* stream, if (params.find(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES) != params.end() || params.find(AUDIO_PARAMETER_STREAM_SUP_CHANNELS) != params.end() || params.find(AUDIO_PARAMETER_STREAM_SUP_FORMATS) != params.end()) { - if (out->bluetooth_output_.LoadAudioConfig(&audio_cfg)) { + if (out->bluetooth_output_->LoadAudioConfig(&audio_cfg)) { out->sample_rate_ = audio_cfg.sample_rate; out->channel_mask_ = audio_cfg.channel_mask; out->format_ = audio_cfg.format; - LOG(VERBOSE) << "state=" << out->bluetooth_output_.GetState() << ", sample_rate=" << out->sample_rate_ - << ", channels=" << StringPrintf("%#x", out->channel_mask_) << ", format=" << out->format_; + LOG(VERBOSE) << "state=" << out->bluetooth_output_->GetState() + << ", sample_rate=" << out->sample_rate_ + << ", channels=" << StringPrintf("%#x", out->channel_mask_) + << ", format=" << out->format_; } else { LOG(WARNING) << __func__ - << ": state=" << out->bluetooth_output_.GetState() + << ": state=" << out->bluetooth_output_->GetState() << " failed to get audio config"; } } if (params.find("routing") != params.end()) { auto routing_param = params.find("routing"); - LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", stream param '" << routing_param->first.c_str() << "=" << routing_param->second.c_str() << "'"; } if (params.find("A2dpSuspended") != params.end() && - out->bluetooth_output_.IsA2dp()) { + out->bluetooth_output_->IsA2dp()) { if (params["A2dpSuspended"] == "true") { - LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " stream param stopped"; out->frames_rendered_ = 0; - if (out->bluetooth_output_.GetState() == BluetoothStreamState::STARTED) { - out->bluetooth_output_.Suspend(); - out->bluetooth_output_.SetState(BluetoothStreamState::DISABLED); - } else if (out->bluetooth_output_.GetState() != + if (out->bluetooth_output_->GetState() == BluetoothStreamState::STARTED) { + out->bluetooth_output_->Suspend(); + out->bluetooth_output_->SetState(BluetoothStreamState::DISABLED); + } else if (out->bluetooth_output_->GetState() != BluetoothStreamState::DISABLED) { - out->bluetooth_output_.Stop(); + out->bluetooth_output_->Stop(); } } else { - LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " stream param standby"; - if (out->bluetooth_output_.GetState() == BluetoothStreamState::DISABLED) { - out->bluetooth_output_.SetState(BluetoothStreamState::STANDBY); + if (out->bluetooth_output_->GetState() == + BluetoothStreamState::DISABLED) { + out->bluetooth_output_->SetState(BluetoothStreamState::STANDBY); } } } if (params.find("closing") != params.end()) { if (params["closing"] == "true") { - LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " stream param closing, disallow any writes?"; - if (out->bluetooth_output_.GetState() != BluetoothStreamState::DISABLED) { + if (out->bluetooth_output_->GetState() != + BluetoothStreamState::DISABLED) { out->frames_rendered_ = 0; out->frames_presented_ = 0; - out->bluetooth_output_.Stop(); + out->bluetooth_output_->Stop(); } } } if (params.find("exiting") != params.end()) { if (params["exiting"] == "1") { - LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " stream param exiting"; - if (out->bluetooth_output_.GetState() != BluetoothStreamState::DISABLED) { + if (out->bluetooth_output_->GetState() != + BluetoothStreamState::DISABLED) { out->frames_rendered_ = 0; out->frames_presented_ = 0; - out->bluetooth_output_.Stop(); + out->bluetooth_output_->Stop(); } } } - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", kvpairs=[" << kvpairs << "], retval=" << retval; return retval; } @@ -392,18 +399,18 @@ static char* out_get_parameters(const struct audio_stream* stream, const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream); std::unique_lock<std::mutex> lock(out->mutex_); - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", keys=[" << keys << "]"; std::unordered_map<std::string, std::string> params = ParseAudioParams(keys); if (params.empty()) return strdup(""); audio_config_t audio_cfg; - if (out->bluetooth_output_.LoadAudioConfig(&audio_cfg)) { - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + if (out->bluetooth_output_->LoadAudioConfig(&audio_cfg)) { + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " audio_cfg=" << audio_cfg; } else { - LOG(ERROR) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(ERROR) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " failed to get audio config"; } @@ -467,7 +474,7 @@ static char* out_get_parameters(const struct audio_stream* stream, result += ptr.first + "=" + ptr.second + ";"; } - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", result=[" << result << "]"; return strdup(result.c_str()); } @@ -476,7 +483,7 @@ static uint32_t out_get_latency_ms(const struct audio_stream_out* stream) { const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream); uint32_t latency_ms = 0; out_calculate_feeding_delay_ms(out, &latency_ms); - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", latency=" << latency_ms << "ms"; return latency_ms; } @@ -484,7 +491,7 @@ static uint32_t out_get_latency_ms(const struct audio_stream_out* stream) { static int out_set_volume(struct audio_stream_out* stream, float left, float right) { auto* out = reinterpret_cast<BluetoothStreamOut*>(stream); - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", Left=" << left << ", Right=" << right; return -1; } @@ -495,14 +502,15 @@ static ssize_t out_write(struct audio_stream_out* stream, const void* buffer, std::unique_lock<std::mutex> lock(out->mutex_); size_t totalWritten = 0; - if (out->bluetooth_output_.GetState() != BluetoothStreamState::STARTED) { - LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState() + if (out->bluetooth_output_->GetState() != BluetoothStreamState::STARTED) { + LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " first time bytes=" << bytes; lock.unlock(); if (stream->resume(stream)) { - LOG(ERROR) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(ERROR) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " failed to resume"; - if (out->bluetooth_output_.GetState() == BluetoothStreamState::DISABLED) { + if (out->bluetooth_output_->GetState() == + BluetoothStreamState::DISABLED) { // drop data for cases of A2dpSuspended=true / closing=true totalWritten = bytes; } @@ -512,7 +520,7 @@ static ssize_t out_write(struct audio_stream_out* stream, const void* buffer, lock.lock(); } lock.unlock(); - totalWritten = out->bluetooth_output_.WriteData(buffer, bytes); + totalWritten = out->bluetooth_output_->WriteData(buffer, bytes); lock.lock(); struct timespec ts = {.tv_sec = 0, .tv_nsec = 0}; @@ -563,7 +571,7 @@ static int out_get_render_position(const struct audio_stream_out* stream, *dsp_frames = 0; } - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", dsp_frames=" << *dsp_frames; return 0; } @@ -571,7 +579,7 @@ static int out_get_render_position(const struct audio_stream_out* stream, static int out_add_audio_effect(const struct audio_stream* stream, effect_handle_t effect) { const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream); - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", effect=" << effect; return 0; } @@ -579,7 +587,7 @@ static int out_add_audio_effect(const struct audio_stream* stream, static int out_remove_audio_effect(const struct audio_stream* stream, effect_handle_t effect) { const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream); - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", effect=" << effect; return 0; } @@ -588,7 +596,7 @@ static int out_get_next_write_timestamp(const struct audio_stream_out* stream, int64_t* timestamp) { const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream); *timestamp = 0; - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", timestamp=" << *timestamp; return -EINVAL; } @@ -597,23 +605,23 @@ static int out_pause(struct audio_stream_out* stream) { auto* out = reinterpret_cast<BluetoothStreamOut*>(stream); std::unique_lock<std::mutex> lock(out->mutex_); int retval = 0; - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", pausing (suspend)"; - if (out->bluetooth_output_.GetState() == BluetoothStreamState::STARTED) { + if (out->bluetooth_output_->GetState() == BluetoothStreamState::STARTED) { out->frames_rendered_ = 0; - retval = (out->bluetooth_output_.Suspend() ? 0 : -EIO); - } else if (out->bluetooth_output_.GetState() == + retval = (out->bluetooth_output_->Suspend() ? 0 : -EIO); + } else if (out->bluetooth_output_->GetState() == BluetoothStreamState::STARTING || - out->bluetooth_output_.GetState() == + out->bluetooth_output_->GetState() == BluetoothStreamState::SUSPENDING) { - LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " NOT ready to pause?!"; retval = -EBUSY; } else { - LOG(DEBUG) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(DEBUG) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " paused already"; } - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", pausing (suspend) retval=" << retval; return retval; @@ -624,27 +632,27 @@ static int out_resume(struct audio_stream_out* stream) { std::unique_lock<std::mutex> lock(out->mutex_); int retval = 0; - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", resuming (start)"; - if (out->bluetooth_output_.GetState() == BluetoothStreamState::STANDBY) { - retval = (out->bluetooth_output_.Start() ? 0 : -EIO); - } else if (out->bluetooth_output_.GetState() == + if (out->bluetooth_output_->GetState() == BluetoothStreamState::STANDBY) { + retval = (out->bluetooth_output_->Start() ? 0 : -EIO); + } else if (out->bluetooth_output_->GetState() == BluetoothStreamState::STARTING || - out->bluetooth_output_.GetState() == + out->bluetooth_output_->GetState() == BluetoothStreamState::SUSPENDING) { - LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " NOT ready to resume?!"; retval = -EBUSY; - } else if (out->bluetooth_output_.GetState() == + } else if (out->bluetooth_output_->GetState() == BluetoothStreamState::DISABLED) { - LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " NOT allow to resume?!"; retval = -EINVAL; } else { - LOG(DEBUG) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(DEBUG) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " resumed already"; } - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", resuming (start) retval=" << retval; return retval; @@ -659,7 +667,7 @@ static int out_get_presentation_position(const struct audio_stream_out* stream, const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream); out_calculate_feeding_delay_ms(out, nullptr, frames, timestamp); - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", frames=" << *frames << ", timestamp=" << timestamp->tv_sec << "." << StringPrintf("%09ld", timestamp->tv_nsec) << "s"; return 0; @@ -673,9 +681,9 @@ static void out_update_source_metadata( if (source_metadata == nullptr || source_metadata->track_count == 0) { return; } - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", " << source_metadata->track_count << " track(s)"; - out->bluetooth_output_.UpdateMetadata(source_metadata); + out->bluetooth_output_->UpdateSourceMetadata(source_metadata); } static size_t frame_count(size_t microseconds, uint32_t sample_rate) { @@ -690,7 +698,19 @@ int adev_open_output_stream(struct audio_hw_device* dev, const char* address __unused) { *stream_out = nullptr; auto* out = new BluetoothStreamOut{}; - if (!out->bluetooth_output_.SetUp(devices)) { + if (::aidl::android::hardware::bluetooth::audio::BluetoothAudioSession:: + IsAidlAvailable()) { + out->bluetooth_output_ = std::make_unique< + ::android::bluetooth::audio::aidl::BluetoothAudioPortAidlOut>(); + out->is_aidl = true; + } else { + out->bluetooth_output_ = std::make_unique< + ::android::bluetooth::audio::hidl::BluetoothAudioPortHidlOut>(); + out->is_aidl = false; + } + if (!out->bluetooth_output_->SetUp(devices)) { + out->bluetooth_output_ = nullptr; + LOG(ERROR) << __func__ << ": cannot init HAL"; delete out; return -EINVAL; } @@ -718,15 +738,17 @@ int adev_open_output_stream(struct audio_hw_device* dev, out->stream_out_.get_presentation_position = out_get_presentation_position; out->stream_out_.update_source_metadata = out_update_source_metadata; - if (!out->bluetooth_output_.LoadAudioConfig(config)) { - LOG(ERROR) << __func__ << ": state=" << out->bluetooth_output_.GetState() + if (!out->bluetooth_output_->LoadAudioConfig(config)) { + LOG(ERROR) << __func__ << ": state=" << out->bluetooth_output_->GetState() << " failed to get audio config"; } // WAR to support Mono / 16 bits per sample as the Bluetooth stack required - if (config->channel_mask == AUDIO_CHANNEL_OUT_MONO && config->format == AUDIO_FORMAT_PCM_16_BIT) { - LOG(INFO) << __func__ << ": force channels=" << StringPrintf("%#x", out->channel_mask_) + if (config->channel_mask == AUDIO_CHANNEL_OUT_MONO && + config->format == AUDIO_FORMAT_PCM_16_BIT) { + LOG(INFO) << __func__ + << ": force channels=" << StringPrintf("%#x", out->channel_mask_) << " to be AUDIO_CHANNEL_OUT_STEREO"; - out->bluetooth_output_.ForcePcmStereoToMono(true); + out->bluetooth_output_->ForcePcmStereoToMono(true); config->channel_mask = AUDIO_CHANNEL_OUT_STEREO; } out->sample_rate_ = config->sample_rate; @@ -735,7 +757,7 @@ int adev_open_output_stream(struct audio_hw_device* dev, // frame is number of samples per channel size_t preferred_data_interval_us = kBluetoothDefaultOutputBufferMs * 1000; - if (out->bluetooth_output_.GetPreferredDataIntervalUs( + if (out->bluetooth_output_->GetPreferredDataIntervalUs( &preferred_data_interval_us) && preferred_data_interval_us != 0) { out->preferred_data_interval_us = preferred_data_interval_us; @@ -766,11 +788,11 @@ int adev_open_output_stream(struct audio_hw_device* dev, bluetooth_device->opened_stream_outs_.push_back(out); } *stream_out = &out->stream_out_; - LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", sample_rate=" << out->sample_rate_ << ", channels=" << StringPrintf("%#x", out->channel_mask_) - << ", format=" << out->format_ - << ", preferred_data_interval_us=" << out->preferred_data_interval_us + << ", format=" << out->format_ << ", preferred_data_interval_us=" + << out->preferred_data_interval_us << ", frames=" << out->frames_count_; return 0; } @@ -778,20 +800,20 @@ int adev_open_output_stream(struct audio_hw_device* dev, void adev_close_output_stream(struct audio_hw_device* dev, struct audio_stream_out* stream) { auto* out = reinterpret_cast<BluetoothStreamOut*>(stream); - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", stopping"; { auto* bluetooth_device = reinterpret_cast<BluetoothAudioDevice*>(dev); std::lock_guard<std::mutex> guard(bluetooth_device->mutex_); bluetooth_device->opened_stream_outs_.remove(out); } - if (out->bluetooth_output_.GetState() != BluetoothStreamState::DISABLED) { + if (out->bluetooth_output_->GetState() != BluetoothStreamState::DISABLED) { out->frames_rendered_ = 0; out->frames_presented_ = 0; - out->bluetooth_output_.Stop(); + out->bluetooth_output_->Stop(); } - out->bluetooth_output_.TearDown(); - LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() + out->bluetooth_output_->TearDown(); + LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState() << ", stopped"; delete out; } @@ -812,7 +834,7 @@ static uint32_t in_get_sample_rate(const struct audio_stream* stream) { static int in_set_sample_rate(struct audio_stream* stream, uint32_t rate) { const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); - LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState() << ", sample_rate=" << in->sample_rate_; return (rate == in->sample_rate_ ? 0 : -ENOSYS); } @@ -821,7 +843,7 @@ static size_t in_get_buffer_size(const struct audio_stream* stream) { const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); size_t buffer_size = in->frames_count_ * audio_stream_in_frame_size(&in->stream_in_); - LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState() << ", buffer_size=" << buffer_size; return buffer_size; } @@ -829,12 +851,12 @@ static size_t in_get_buffer_size(const struct audio_stream* stream) { static audio_channel_mask_t in_get_channels(const struct audio_stream* stream) { const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); audio_config_t audio_cfg; - if (in->bluetooth_input_.LoadAudioConfig(&audio_cfg)) { - LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState() + if (in->bluetooth_input_->LoadAudioConfig(&audio_cfg)) { + LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState() << " audio_cfg=" << audio_cfg; return audio_cfg.channel_mask; } else { - LOG(WARNING) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(WARNING) << __func__ << ": state=" << in->bluetooth_input_->GetState() << ", channels=" << StringPrintf("%#x", in->channel_mask_) << " failure"; return in->channel_mask_; @@ -844,12 +866,12 @@ static audio_channel_mask_t in_get_channels(const struct audio_stream* stream) { static audio_format_t in_get_format(const struct audio_stream* stream) { const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); audio_config_t audio_cfg; - if (in->bluetooth_input_.LoadAudioConfig(&audio_cfg)) { - LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState() + if (in->bluetooth_input_->LoadAudioConfig(&audio_cfg)) { + LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState() << " audio_cfg=" << audio_cfg; return audio_cfg.format; } else { - LOG(WARNING) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(WARNING) << __func__ << ": state=" << in->bluetooth_input_->GetState() << ", format=" << in->format_ << " failure"; return in->format_; } @@ -857,7 +879,7 @@ static audio_format_t in_get_format(const struct audio_stream* stream) { static int in_set_format(struct audio_stream* stream, audio_format_t format) { const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); - LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState() << ", format=" << in->format_; return (format == in->format_ ? 0 : -ENOSYS); } @@ -867,7 +889,7 @@ static bool in_state_transition_timeout(BluetoothStreamIn* in, const BluetoothStreamState& state, uint16_t timeout_ms) { /* Don't loose suspend request, AF will not retry */ - while (in->bluetooth_input_.GetState() == state) { + while (in->bluetooth_input_->GetState() == state) { lock.unlock(); usleep(1000); lock.lock(); @@ -888,22 +910,22 @@ static int in_standby(struct audio_stream* stream) { std::unique_lock<std::mutex> lock(in->mutex_); int retval = 0; - LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState() << " being standby (suspend)"; /* Give some time to start up */ if (!in_state_transition_timeout(in, lock, BluetoothStreamState::STARTING, kBluetoothDefaultInputStateTimeoutMs)) { - LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_->GetState() << " NOT ready to by standby"; return retval; } - if (in->bluetooth_input_.GetState() == BluetoothStreamState::STARTED) { - retval = (in->bluetooth_input_.Suspend() ? 0 : -EIO); - } else if (in->bluetooth_input_.GetState() != + if (in->bluetooth_input_->GetState() == BluetoothStreamState::STARTED) { + retval = (in->bluetooth_input_->Suspend() ? 0 : -EIO); + } else if (in->bluetooth_input_->GetState() != BluetoothStreamState::SUSPENDING) { - LOG(DEBUG) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(DEBUG) << __func__ << ": state=" << in->bluetooth_input_->GetState() << " standby already"; return retval; } @@ -911,12 +933,12 @@ static int in_standby(struct audio_stream* stream) { /* Give some time to suspend */ if (!in_state_transition_timeout(in, lock, BluetoothStreamState::SUSPENDING, kBluetoothDefaultInputStateTimeoutMs)) { - LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_->GetState() << " NOT ready to by standby"; return 0; } - LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState() << " standby (suspend) retval=" << retval; return retval; @@ -924,7 +946,7 @@ static int in_standby(struct audio_stream* stream) { static int in_dump(const struct audio_stream* stream, int fd) { const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); - LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState(); + LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState(); return 0; } @@ -935,7 +957,7 @@ static int in_set_parameters(struct audio_stream* stream, const char* kvpairs) { int retval = 0; LOG(INFO) << __func__ - << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState() + << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState() << ", kvpairs=[" << kvpairs << "]"; std::unordered_map<std::string, std::string> params = @@ -955,18 +977,18 @@ static char* in_get_parameters(const struct audio_stream* stream, std::unique_lock<std::mutex> lock(in->mutex_); LOG(VERBOSE) << __func__ - << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState() + << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState() << ", keys=[" << keys << "]"; std::unordered_map<std::string, std::string> params = ParseAudioParams(keys); if (params.empty()) return strdup(""); audio_config_t audio_cfg; - if (in->bluetooth_input_.LoadAudioConfig(&audio_cfg)) { - LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState() + if (in->bluetooth_input_->LoadAudioConfig(&audio_cfg)) { + LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState() << " audio_cfg=" << audio_cfg; } else { - LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_->GetState() << " failed to get audio config"; } @@ -985,7 +1007,7 @@ static char* in_get_parameters(const struct audio_stream* stream, static int in_add_audio_effect(const struct audio_stream* stream, effect_handle_t effect) { const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); - LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState() << ", effect=" << effect; return 0; } @@ -993,7 +1015,7 @@ static int in_add_audio_effect(const struct audio_stream* stream, static int in_remove_audio_effect(const struct audio_stream* stream, effect_handle_t effect) { const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); - LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState() << ", effect=" << effect; return 0; } @@ -1001,7 +1023,7 @@ static int in_remove_audio_effect(const struct audio_stream* stream, static int in_set_gain(struct audio_stream_in* stream, float gain) { const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); LOG(VERBOSE) << __func__ - << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState(); + << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState(); return 0; } @@ -1017,41 +1039,41 @@ static ssize_t in_read(struct audio_stream_in* stream, void* buffer, kBluetoothDefaultInputStateTimeoutMs)) return -EBUSY; - if (in->bluetooth_input_.GetState() != BluetoothStreamState::STARTED) { - LOG(INFO) << __func__ << ": state=" << in->bluetooth_input_.GetState() + if (in->bluetooth_input_->GetState() != BluetoothStreamState::STARTED) { + LOG(INFO) << __func__ << ": state=" << in->bluetooth_input_->GetState() << " first time bytes=" << bytes; int retval = 0; - LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState() << ", starting"; - if (in->bluetooth_input_.GetState() == BluetoothStreamState::STANDBY) { - retval = (in->bluetooth_input_.Start() ? 0 : -EIO); - } else if (in->bluetooth_input_.GetState() == + if (in->bluetooth_input_->GetState() == BluetoothStreamState::STANDBY) { + retval = (in->bluetooth_input_->Start() ? 0 : -EIO); + } else if (in->bluetooth_input_->GetState() == BluetoothStreamState::SUSPENDING) { - LOG(WARNING) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(WARNING) << __func__ << ": state=" << in->bluetooth_input_->GetState() << " NOT ready to start?!"; retval = -EBUSY; - } else if (in->bluetooth_input_.GetState() == + } else if (in->bluetooth_input_->GetState() == BluetoothStreamState::DISABLED) { - LOG(WARNING) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(WARNING) << __func__ << ": state=" << in->bluetooth_input_->GetState() << " NOT allow to start?!"; retval = -EINVAL; } else { - LOG(DEBUG) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(DEBUG) << __func__ << ": state=" << in->bluetooth_input_->GetState() << " started already"; } - LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState() << ", starting (start) retval=" << retval; if (retval) { - LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_->GetState() << " failed to start"; return retval; } } lock.unlock(); - totalRead = in->bluetooth_input_.ReadData(buffer, bytes); + totalRead = in->bluetooth_input_->ReadData(buffer, bytes); lock.lock(); struct timespec ts = {.tv_sec = 0, .tv_nsec = 0}; @@ -1067,7 +1089,7 @@ static ssize_t in_read(struct audio_stream_in* stream, void* buffer, static uint32_t in_get_input_frames_lost(struct audio_stream_in* stream) { const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); LOG(VERBOSE) << __func__ - << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState(); + << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState(); return 0; } @@ -1079,8 +1101,8 @@ static int in_get_capture_position(const struct audio_stream_in* stream, } const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); - if (in->bluetooth_input_.GetState() == BluetoothStreamState::STANDBY) { - LOG(WARNING) << __func__ << ": state= " << in->bluetooth_input_.GetState(); + if (in->bluetooth_input_->GetState() == BluetoothStreamState::STANDBY) { + LOG(WARNING) << __func__ << ": state= " << in->bluetooth_input_->GetState(); return -ENOSYS; } @@ -1092,7 +1114,7 @@ static int in_get_capture_position(const struct audio_stream_in* stream, static int in_start(const struct audio_stream_in* stream) { const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); LOG(VERBOSE) << __func__ - << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState(); + << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState(); return 0; } @@ -1100,7 +1122,7 @@ static int in_start(const struct audio_stream_in* stream) { static int in_stop(const struct audio_stream_in* stream) { const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); LOG(VERBOSE) << __func__ - << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState(); + << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState(); return 0; } @@ -1110,7 +1132,7 @@ static int in_create_mmap_buffer(const struct audio_stream_in* stream, struct audio_mmap_buffer_info* info) { const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); LOG(VERBOSE) << __func__ - << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState(); + << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState(); return -ENOSYS; } @@ -1119,7 +1141,7 @@ static int in_get_mmap_position(const struct audio_stream_in* stream, struct audio_mmap_position* position) { const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); LOG(VERBOSE) << __func__ - << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState(); + << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState(); return -ENOSYS; } @@ -1129,7 +1151,7 @@ static int in_get_active_microphones( struct audio_microphone_characteristic_t* mic_array, size_t* mic_count) { const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); LOG(VERBOSE) << __func__ - << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState(); + << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState(); return -ENOSYS; } @@ -1138,7 +1160,7 @@ static int in_set_microphone_direction(const struct audio_stream_in* stream, audio_microphone_direction_t direction) { const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); LOG(VERBOSE) << __func__ - << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState(); + << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState(); return -ENOSYS; } @@ -1147,7 +1169,7 @@ static int in_set_microphone_field_dimension( const struct audio_stream_in* stream, float zoom) { const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); LOG(VERBOSE) << __func__ - << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState(); + << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState(); return -ENOSYS; } @@ -1160,10 +1182,17 @@ static void in_update_sink_metadata(struct audio_stream_in* stream, } const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream); - LOG(INFO) << __func__ << ": state=" << in->bluetooth_input_.GetState() << ", " - << sink_metadata->track_count << " track(s)"; + LOG(INFO) << __func__ << ": state=" << in->bluetooth_input_->GetState() + << ", " << sink_metadata->track_count << " track(s)"; - in->bluetooth_input_.UpdateSinkMetadata(sink_metadata); + if (!in->is_aidl) { + LOG(WARNING) << __func__ + << " is only supported in AIDL but using HIDL now!"; + return; + } + static_cast<::android::bluetooth::audio::aidl::BluetoothAudioPortAidl*>( + in->bluetooth_input_.get()) + ->UpdateSinkMetadata(sink_metadata); } int adev_open_input_stream(struct audio_hw_device* dev, @@ -1175,7 +1204,19 @@ int adev_open_input_stream(struct audio_hw_device* dev, audio_source_t source __unused) { *stream_in = nullptr; auto* in = new BluetoothStreamIn{}; - if (!in->bluetooth_input_.SetUp(devices)) { + if (::aidl::android::hardware::bluetooth::audio::BluetoothAudioSession:: + IsAidlAvailable()) { + in->bluetooth_input_ = std::make_unique< + ::android::bluetooth::audio::aidl::BluetoothAudioPortAidlIn>(); + in->is_aidl = true; + } else { + in->bluetooth_input_ = std::make_unique< + ::android::bluetooth::audio::hidl::BluetoothAudioPortHidlIn>(); + in->is_aidl = false; + } + if (!in->bluetooth_input_->SetUp(devices)) { + in->bluetooth_input_ = nullptr; + LOG(ERROR) << __func__ << ": cannot init HAL"; delete in; return -EINVAL; } @@ -1208,8 +1249,8 @@ int adev_open_input_stream(struct audio_hw_device* dev, in_set_microphone_field_dimension; in->stream_in_.update_sink_metadata = in_update_sink_metadata; - if (!in->bluetooth_input_.LoadAudioConfig(config)) { - LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_.GetState() + if (!in->bluetooth_input_->LoadAudioConfig(config)) { + LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_->GetState() << " failed to get audio config"; return -EINVAL; } @@ -1220,7 +1261,7 @@ int adev_open_input_stream(struct audio_hw_device* dev, // frame is number of samples per channel size_t preferred_data_interval_us = kBluetoothDefaultInputBufferMs * 1000; - if (in->bluetooth_input_.GetPreferredDataIntervalUs( + if (in->bluetooth_input_->GetPreferredDataIntervalUs( &preferred_data_interval_us) && preferred_data_interval_us != 0) { in->preferred_data_interval_us = preferred_data_interval_us; @@ -1233,7 +1274,7 @@ int adev_open_input_stream(struct audio_hw_device* dev, in->frames_presented_ = 0; *stream_in = &in->stream_in_; - LOG(INFO) << __func__ << ": state=" << in->bluetooth_input_.GetState() + LOG(INFO) << __func__ << ": state=" << in->bluetooth_input_->GetState() << ", sample_rate=" << in->sample_rate_ << ", channels=" << StringPrintf("%#x", in->channel_mask_) << ", format=" << in->format_ @@ -1247,12 +1288,12 @@ void adev_close_input_stream(struct audio_hw_device* dev, struct audio_stream_in* stream) { auto* in = reinterpret_cast<BluetoothStreamIn*>(stream); - if (in->bluetooth_input_.GetState() != BluetoothStreamState::DISABLED) { - in->bluetooth_input_.Stop(); + if (in->bluetooth_input_->GetState() != BluetoothStreamState::DISABLED) { + in->bluetooth_input_->Stop(); } - in->bluetooth_input_.TearDown(); - LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState() + in->bluetooth_input_->TearDown(); + LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState() << ", stopped"; delete in; diff --git a/system/audio_bluetooth_hw/stream_apis.h b/system/audio_bluetooth_hw/stream_apis.h index cf90281591..76845d9ee5 100644 --- a/system/audio_bluetooth_hw/stream_apis.h +++ b/system/audio_bluetooth_hw/stream_apis.h @@ -18,9 +18,11 @@ #include <hardware/audio.h> #include <system/audio.h> + #include <list> #include "device_port_proxy.h" +#include "device_port_proxy_hidl.h" constexpr unsigned int kBluetoothDefaultSampleRate = 44100; constexpr audio_format_t kBluetoothDefaultAudioFormatBitsPerSample = @@ -52,7 +54,9 @@ struct BluetoothStreamOut { // Must be the first member so it can be cast from audio_stream // or audio_stream_out pointer audio_stream_out stream_out_{}; - ::android::bluetooth::audio::BluetoothAudioPortOut bluetooth_output_; + std::unique_ptr<::android::bluetooth::audio::BluetoothAudioPort> + bluetooth_output_; + bool is_aidl; int64_t last_write_time_us_; // Audio PCM Configs uint32_t sample_rate_; @@ -83,7 +87,9 @@ struct BluetoothStreamIn { // Must be the first member so it can be cast from audio_stream // or audio_stream_in pointer audio_stream_in stream_in_; - ::android::bluetooth::audio::BluetoothAudioPortIn bluetooth_input_; + std::unique_ptr<::android::bluetooth::audio::BluetoothAudioPort> + bluetooth_input_; + bool is_aidl; int64_t last_read_time_us_; // Audio PCM Configs uint32_t sample_rate_; diff --git a/system/audio_hal_interface/Android.bp b/system/audio_hal_interface/Android.bp index ac8b4105d4..49175192d3 100644 --- a/system/audio_hal_interface/Android.bp +++ b/system/audio_hal_interface/Android.bp @@ -23,7 +23,6 @@ cc_library_static { shared_libs: [ "android.hardware.bluetooth.audio@2.0", "android.hardware.bluetooth.audio@2.1", - "android.hardware.bluetooth.audio@2.2", "libhidlbase", ], static_libs: [ @@ -85,7 +84,6 @@ cc_test { shared_libs: [ "android.hardware.bluetooth.audio@2.0", "android.hardware.bluetooth.audio@2.1", - "android.hardware.bluetooth.audio@2.2", "android.hardware.bluetooth.audio-V1-ndk", "libbinder_ndk", "libcutils", diff --git a/system/audio_hal_interface/a2dp_encoding.cc b/system/audio_hal_interface/a2dp_encoding.cc index 854abfdb1e..d0028e1ef9 100644 --- a/system/audio_hal_interface/a2dp_encoding.cc +++ b/system/audio_hal_interface/a2dp_encoding.cc @@ -138,13 +138,11 @@ void set_remote_delay(uint16_t delay_report) { } // Set low latency buffer mode allowed or disallowed -bool set_audio_low_latency_mode_allowed(bool allowed){ +void set_audio_low_latency_mode_allowed(bool allowed) { if (HalVersionManager::GetHalTransport() == - BluetoothAudioHalTransport::HIDL) { - hidl::a2dp::set_low_latency_mode_allowed(allowed); - return true; + BluetoothAudioHalTransport::AIDL) { + aidl::a2dp::set_low_latency_mode_allowed(allowed); } - return false; } } // namespace a2dp diff --git a/system/audio_hal_interface/a2dp_encoding.h b/system/audio_hal_interface/a2dp_encoding.h index 8e149ac55e..51d5c9f309 100644 --- a/system/audio_hal_interface/a2dp_encoding.h +++ b/system/audio_hal_interface/a2dp_encoding.h @@ -44,7 +44,7 @@ void cleanup(); bool setup_codec(); // Set low latency buffer mode allowed or disallowed -bool set_audio_low_latency_mode_allowed(bool allowed); +void set_audio_low_latency_mode_allowed(bool allowed); // Send command to the BluetoothAudio HAL: StartSession, EndSession, // StreamStarted, StreamSuspended diff --git a/system/audio_hal_interface/a2dp_encoding_host.cc b/system/audio_hal_interface/a2dp_encoding_host.cc index 9ffff8b0d7..b0b6340c66 100644 --- a/system/audio_hal_interface/a2dp_encoding_host.cc +++ b/system/audio_hal_interface/a2dp_encoding_host.cc @@ -244,8 +244,7 @@ void end_session() { remote_delay_report_ = 0; } -bool set_audio_low_latency_mode_allowed(bool allowed){ - return true; +void set_audio_low_latency_mode_allowed(bool allowed){ } diff --git a/system/audio_hal_interface/aidl/a2dp_encoding.cc b/system/audio_hal_interface/aidl/a2dp_encoding.cc index 551398c00d..da1cb432d6 100644 --- a/system/audio_hal_interface/aidl/a2dp_encoding.cc +++ b/system/audio_hal_interface/aidl/a2dp_encoding.cc @@ -208,6 +208,7 @@ uint16_t remote_delay = 0; bool btaudio_a2dp_disabled = false; bool is_configured = false; +bool is_low_latency_mode_allowed = false; BluetoothAudioCtrlAck a2dp_ack_to_bt_audio_ctrl_ack(tA2DP_CTRL_ACK ack) { switch (ack) { @@ -470,6 +471,7 @@ void start_session() { LOG(ERROR) << __func__ << ": BluetoothAudio HAL is not enabled"; return; } + active_hal_interface->SetLowLatencyModeAllowed(is_low_latency_mode_allowed); active_hal_interface->StartSession(); } @@ -552,6 +554,16 @@ void set_remote_delay(uint16_t delay_report) { ->SetRemoteDelay(delay_report); } +// Set low latency buffer mode allowed or disallowed +void set_low_latency_mode_allowed(bool allowed) { + is_low_latency_mode_allowed = allowed; + if (!is_hal_enabled()) { + LOG(ERROR) << __func__ << ": BluetoothAudio HAL is not enabled"; + return; + } + active_hal_interface->SetLowLatencyModeAllowed(allowed); +} + } // namespace a2dp } // namespace aidl } // namespace audio diff --git a/system/audio_hal_interface/aidl/a2dp_encoding.h b/system/audio_hal_interface/aidl/a2dp_encoding.h index c18adbc21a..a49c767589 100644 --- a/system/audio_hal_interface/aidl/a2dp_encoding.h +++ b/system/audio_hal_interface/aidl/a2dp_encoding.h @@ -81,6 +81,10 @@ size_t read(uint8_t* p_buf, uint32_t len); ***/ void set_remote_delay(uint16_t delay_report); +/*** + * Set low latency buffer mode allowed or disallowed + ***/ +void set_low_latency_mode_allowed(bool allowed); } // namespace a2dp } // namespace aidl } // namespace audio diff --git a/system/audio_hal_interface/aidl/audio_aidl_interfaces.h b/system/audio_hal_interface/aidl/audio_aidl_interfaces.h index 9eb606f079..3c25d24d35 100644 --- a/system/audio_hal_interface/aidl/audio_aidl_interfaces.h +++ b/system/audio_hal_interface/aidl/audio_aidl_interfaces.h @@ -37,7 +37,6 @@ #include <aidl/android/hardware/bluetooth/audio/AudioConfiguration.h> #include <aidl/android/hardware/bluetooth/audio/AudioLocation.h> #include <aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.h> -#include <aidl/android/hardware/bluetooth/audio/BroadcastConfiguration.h> #include <aidl/android/hardware/bluetooth/audio/ChannelMode.h> #include <aidl/android/hardware/bluetooth/audio/CodecCapabilities.h> #include <aidl/android/hardware/bluetooth/audio/CodecConfiguration.h> @@ -45,16 +44,17 @@ #include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.h> #include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.h> #include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.h> +#include <aidl/android/hardware/bluetooth/audio/LatencyMode.h> #include <aidl/android/hardware/bluetooth/audio/Lc3Capabilities.h> #include <aidl/android/hardware/bluetooth/audio/Lc3Configuration.h> #include <aidl/android/hardware/bluetooth/audio/LdacCapabilities.h> #include <aidl/android/hardware/bluetooth/audio/LdacChannelMode.h> #include <aidl/android/hardware/bluetooth/audio/LdacConfiguration.h> #include <aidl/android/hardware/bluetooth/audio/LdacQualityIndex.h> +#include <aidl/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.h> #include <aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.h> #include <aidl/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.h> #include <aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.h> -#include <aidl/android/hardware/bluetooth/audio/LeAudioMode.h> #include <aidl/android/hardware/bluetooth/audio/PcmCapabilities.h> #include <aidl/android/hardware/bluetooth/audio/PcmConfiguration.h> #include <aidl/android/hardware/bluetooth/audio/PresentationPosition.h> @@ -63,8 +63,6 @@ #include <aidl/android/hardware/bluetooth/audio/SbcChannelMode.h> #include <aidl/android/hardware/bluetooth/audio/SbcConfiguration.h> #include <aidl/android/hardware/bluetooth/audio/SessionType.h> -#include <aidl/android/hardware/bluetooth/audio/UnicastConfiguration.h> - #ifdef LOG_INFO diff --git a/system/audio_hal_interface/aidl/bluetooth_audio_port_impl.cc b/system/audio_hal_interface/aidl/bluetooth_audio_port_impl.cc index bd5f4b1a02..49edde2e73 100644 --- a/system/audio_hal_interface/aidl/bluetooth_audio_port_impl.cc +++ b/system/audio_hal_interface/aidl/bluetooth_audio_port_impl.cc @@ -16,6 +16,7 @@ #include "bluetooth_audio_port_impl.h" +#include "btif/include/btif_common.h" #include "common/stop_watch_legacy.h" namespace bluetooth { @@ -132,6 +133,13 @@ ndk::ScopedAStatus BluetoothAudioPortImpl::updateSinkMetadata( return ndk::ScopedAStatus::ok(); } +ndk::ScopedAStatus BluetoothAudioPortImpl::setLatencyMode( + LatencyMode latency_mode) { + bool is_low_latency = latency_mode == LatencyMode::LOW_LATENCY ? true : false; + invoke_switch_buffer_size_cb(is_low_latency); + return ndk::ScopedAStatus::ok(); +} + PresentationPosition::TimeSpec BluetoothAudioPortImpl::timespec_convert_to_hal( const timespec& ts) { return {.tvSec = static_cast<int64_t>(ts.tv_sec), diff --git a/system/audio_hal_interface/aidl/bluetooth_audio_port_impl.h b/system/audio_hal_interface/aidl/bluetooth_audio_port_impl.h index 99823cee5d..30d98b25b1 100644 --- a/system/audio_hal_interface/aidl/bluetooth_audio_port_impl.h +++ b/system/audio_hal_interface/aidl/bluetooth_audio_port_impl.h @@ -26,7 +26,9 @@ namespace aidl { using ::aidl::android::hardware::audio::common::SinkMetadata; using ::aidl::android::hardware::audio::common::SourceMetadata; using ::aidl::android::hardware::bluetooth::audio::BnBluetoothAudioPort; +using ::aidl::android::hardware::bluetooth::audio::CodecType; using ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider; +using ::aidl::android::hardware::bluetooth::audio::LatencyMode; using ::aidl::android::hardware::bluetooth::audio::PresentationPosition; class BluetoothAudioPortImpl : public BnBluetoothAudioPort { @@ -50,6 +52,8 @@ class BluetoothAudioPortImpl : public BnBluetoothAudioPort { ndk::ScopedAStatus updateSinkMetadata( const SinkMetadata& sink_metadata) override; + ndk::ScopedAStatus setLatencyMode(LatencyMode latency_mode) override; + protected: virtual ~BluetoothAudioPortImpl(); diff --git a/system/audio_hal_interface/aidl/client_interface.cc b/system/audio_hal_interface/aidl/client_interface.cc index 9626ecdb40..6bf3bd7db2 100644 --- a/system/audio_hal_interface/aidl/client_interface.cc +++ b/system/audio_hal_interface/aidl/client_interface.cc @@ -232,6 +232,24 @@ bool BluetoothAudioClientInterface::UpdateAudioConfig( return true; } +bool BluetoothAudioClientInterface::SetLowLatencyModeAllowed(bool allowed) { + is_low_latency_allowed_ = allowed; + if (provider_ == nullptr) { + LOG(INFO) << __func__ + << ": BluetoothAudioHal nullptr"; + return false; + } + + auto aidl_retval = provider_->setLowLatencyModeAllowed(allowed); + if (!aidl_retval.isOk()) { + LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " + << aidl_retval.getDescription(); + return false; + } + return true; +} + + int BluetoothAudioClientInterface::StartSession() { std::lock_guard<std::mutex> guard(internal_mutex_); if (provider_ == nullptr) { @@ -249,9 +267,12 @@ int BluetoothAudioClientInterface::StartSession() { std::unique_ptr<DataMQ> data_mq; DataMQDesc mq_desc; - + std::vector<LatencyMode> latency_modes = {LatencyMode::FREE}; + if (is_low_latency_allowed_) { + latency_modes.push_back(LatencyMode::LOW_LATENCY); + } auto aidl_retval = provider_->startSession( - stack_if, transport_->GetAudioConfiguration(), &mq_desc); + stack_if, transport_->GetAudioConfiguration(), latency_modes, &mq_desc); if (!aidl_retval.isOk()) { LOG(FATAL) << __func__ << ": BluetoothAudioHal failure: " << aidl_retval.getDescription(); diff --git a/system/audio_hal_interface/aidl/client_interface.h b/system/audio_hal_interface/aidl/client_interface.h index 8e443727da..e423585313 100644 --- a/system/audio_hal_interface/aidl/client_interface.h +++ b/system/audio_hal_interface/aidl/client_interface.h @@ -43,6 +43,7 @@ using ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioPort; using ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider; using ::aidl::android::hardware::bluetooth::audio:: IBluetoothAudioProviderFactory; +using ::aidl::android::hardware::bluetooth::audio::LatencyMode; using ::aidl::android::hardware::bluetooth::audio::PcmConfiguration; using ::aidl::android::hardware::common::fmq::MQDescriptor; @@ -84,6 +85,8 @@ class BluetoothAudioClientInterface { bool UpdateAudioConfig(const AudioConfiguration& audioConfig); + bool SetLowLatencyModeAllowed(bool allowed); + void FlushAudioData(); static constexpr PcmConfiguration kInvalidPcmConfiguration = {}; @@ -117,6 +120,7 @@ class BluetoothAudioClientInterface { static inline bool aidl_available = true; IBluetoothTransportInstance* transport_; std::vector<AudioCapabilities> capabilities_; + bool is_low_latency_allowed_{false}; }; /*** diff --git a/system/audio_hal_interface/aidl/codec_status.cc b/system/audio_hal_interface/aidl/codec_status.cc index 0e4e93f680..996a67eb36 100644 --- a/system/audio_hal_interface/aidl/codec_status.cc +++ b/system/audio_hal_interface/aidl/codec_status.cc @@ -18,6 +18,8 @@ #include "codec_status.h" +#include <unordered_set> + #include "a2dp_aac_constants.h" #include "a2dp_sbc_constants.h" #include "a2dp_vendor_aptx_constants.h" @@ -456,23 +458,23 @@ bool UpdateOffloadingCapabilities( audio_hal_capabilities = BluetoothAudioSinkClientInterface::GetAudioCapabilities( SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH); - uint32_t codec_type_masks = static_cast<uint32_t>(CodecType::UNKNOWN); + std::unordered_set<CodecType> codec_type_set; for (auto preference : framework_preference) { switch (preference.codec_type) { case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC: - codec_type_masks |= static_cast<uint32_t>(CodecType::SBC); + codec_type_set.insert(CodecType::SBC); break; case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC: - codec_type_masks |= static_cast<uint32_t>(CodecType::AAC); + codec_type_set.insert(CodecType::AAC); break; case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX: - codec_type_masks |= static_cast<uint32_t>(CodecType::APTX); + codec_type_set.insert(CodecType::APTX); break; case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD: - codec_type_masks |= static_cast<uint32_t>(CodecType::APTX_HD); + codec_type_set.insert(CodecType::APTX_HD); break; case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC: - codec_type_masks |= static_cast<uint32_t>(CodecType::LDAC); + codec_type_set.insert(CodecType::LDAC); break; case BTAV_A2DP_CODEC_INDEX_SINK_SBC: [[fallthrough]]; @@ -492,9 +494,9 @@ bool UpdateOffloadingCapabilities( } offloading_preference.clear(); for (auto capability : audio_hal_capabilities) { - if ((static_cast<uint32_t>( - capability.get<AudioCapabilities::a2dpCapabilities>().codecType) & - codec_type_masks) != 0) { + auto codec_type = + capability.get<AudioCapabilities::a2dpCapabilities>().codecType; + if (codec_type_set.find(codec_type) != codec_type_set.end()) { LOG(INFO) << __func__ << ": enabled offloading capability=" << capability.toString(); offloading_preference.push_back(capability); diff --git a/system/audio_hal_interface/aidl/le_audio_software.cc b/system/audio_hal_interface/aidl/le_audio_software.cc index 58aa51622d..e555917fd0 100644 --- a/system/audio_hal_interface/aidl/le_audio_software.cc +++ b/system/audio_hal_interface/aidl/le_audio_software.cc @@ -36,9 +36,7 @@ using ::aidl::android::hardware::bluetooth::audio::ChannelMode; using ::aidl::android::hardware::bluetooth::audio::CodecType; using ::aidl::android::hardware::bluetooth::audio::Lc3Configuration; using ::aidl::android::hardware::bluetooth::audio::LeAudioCodecConfiguration; -using ::aidl::android::hardware::bluetooth::audio::LeAudioMode; using ::aidl::android::hardware::bluetooth::audio::PcmConfiguration; -using ::aidl::android::hardware::bluetooth::audio::UnicastConfiguration; using ::bluetooth::audio::aidl::AudioConfiguration; using ::bluetooth::audio::aidl::BluetoothAudioCtrlAck; using ::bluetooth::audio::le_audio::LeAudioClientInterface; @@ -385,6 +383,7 @@ bool hal_ucast_capability_to_stack_format( auto sample_rate_hz = hal_lc3_capability.samplingFrequencyHz[0]; auto frame_duration_us = hal_lc3_capability.frameDurationUs[0]; auto octets_per_frame = hal_lc3_capability.octetsPerFrame[0]; + auto channel_count = hal_capability.channelCountPerDevice; if (sampling_freq_map.find(sample_rate_hz) == sampling_freq_map.end() || frame_duration_map.find(frame_duration_us) == frame_duration_map.end() || @@ -406,8 +405,8 @@ bool hal_ucast_capability_to_stack_format( {.sampling_frequency = sampling_freq_map[sample_rate_hz], .frame_duration = frame_duration_map[frame_duration_us], .octets_per_codec_frame = octets_per_frame_map[octets_per_frame], - .audio_channel_allocation = audio_location_map[supportedChannel]})}; - + .audio_channel_allocation = audio_location_map[supportedChannel], + .channel_count = static_cast<uint8_t>(channel_count)})}; return true; } @@ -471,8 +470,8 @@ AudioConfiguration offload_config_to_hal_audio_config( .octetsPerFrame = static_cast<int32_t>(offload_config.octets_per_frame), .blocksPerSdu = static_cast<int8_t>(offload_config.blocks_per_sdu), }; - UnicastConfiguration ucast_config = { - .peerDelay = static_cast<int32_t>(offload_config.peer_delay), + LeAudioConfiguration ucast_config = { + .peerDelayUs = static_cast<int32_t>(offload_config.peer_delay_ms * 1000), .leAudioCodecConfig = LeAudioCodecConfiguration(lc3_config)}; for (auto& [handle, location] : offload_config.stream_map) { @@ -482,11 +481,7 @@ AudioConfiguration offload_config_to_hal_audio_config( }); } - LeAudioConfiguration le_audio_config{ - .mode = LeAudioMode::UNICAST, - .modeConfig = LeAudioConfiguration::LeAudioModeConfig(ucast_config), - }; - return AudioConfiguration(le_audio_config); + return AudioConfiguration(ucast_config); } } // namespace le_audio diff --git a/system/audio_hal_interface/aidl/transport_instance.h b/system/audio_hal_interface/aidl/transport_instance.h index 0dc24cee12..1f47444a37 100644 --- a/system/audio_hal_interface/aidl/transport_instance.h +++ b/system/audio_hal_interface/aidl/transport_instance.h @@ -26,6 +26,7 @@ namespace audio { namespace aidl { using ::aidl::android::hardware::bluetooth::audio::AudioConfiguration; +using ::aidl::android::hardware::bluetooth::audio::LatencyMode; using ::aidl::android::hardware::bluetooth::audio::SessionType; /*** @@ -58,6 +59,9 @@ class IBluetoothTransportInstance { audio_config_.set<AudioConfiguration::leAudioConfig>( audio_config.get<AudioConfiguration::leAudioConfig>()); break; + case AudioConfiguration::leAudioBroadcastConfig: + audio_config_.set<AudioConfiguration::leAudioBroadcastConfig>( + audio_config.get<AudioConfiguration::leAudioBroadcastConfig>()); } } diff --git a/system/audio_hal_interface/fuzzer/Android.bp b/system/audio_hal_interface/fuzzer/Android.bp index f3ec5a7bad..f1724af3d4 100644 --- a/system/audio_hal_interface/fuzzer/Android.bp +++ b/system/audio_hal_interface/fuzzer/Android.bp @@ -43,7 +43,6 @@ cc_defaults { "android.hardware.bluetooth.a2dp@1.0", "android.hardware.bluetooth.audio@2.0", "android.hardware.bluetooth.audio@2.1", - "android.hardware.bluetooth.audio@2.2", "android.system.suspend.control-V1-ndk", "android.system.suspend-V1-ndk", ], @@ -64,12 +63,12 @@ cc_defaults { "libbt-utils", "libbtdevice", "libcgrouprc", + "libflatbuffers-cpp", "libhidlbase", "libbt-stack", "libg722codec", "libudrv-uipc", "libbt-common", - "liblc3codec", "liblc3", "libstatslog_bt", "libvndksupport", diff --git a/system/audio_hal_interface/fuzzer/libbt_audio_hal_client_interface_fuzzer.cpp b/system/audio_hal_interface/fuzzer/libbt_audio_hal_client_interface_fuzzer.cpp index e32ff3684f..9f43485ed7 100644 --- a/system/audio_hal_interface/fuzzer/libbt_audio_hal_client_interface_fuzzer.cpp +++ b/system/audio_hal_interface/fuzzer/libbt_audio_hal_client_interface_fuzzer.cpp @@ -169,8 +169,6 @@ class TestSinkTransport void ResetPresentationPosition() override{}; void LogBytesRead(size_t) override{}; - - void SinkMetadataChanged(const sink_metadata_t&) override{}; }; class TestSourceTransport @@ -204,8 +202,6 @@ class TestSourceTransport void ResetPresentationPosition() override{}; void LogBytesWritten(size_t) override{}; - - void SinkMetadataChanged(const sink_metadata_t&) override{}; }; class ClientInterfaceFuzzer { diff --git a/system/audio_hal_interface/hal_version_manager.cc b/system/audio_hal_interface/hal_version_manager.cc index d46f6a6640..a2c192f37d 100644 --- a/system/audio_hal_interface/hal_version_manager.cc +++ b/system/audio_hal_interface/hal_version_manager.cc @@ -48,30 +48,12 @@ BluetoothAudioHalTransport HalVersionManager::GetHalTransport() { return BluetoothAudioHalTransport::AIDL; case BluetoothAudioHalVersion::VERSION_2_0: case BluetoothAudioHalVersion::VERSION_2_1: - case BluetoothAudioHalVersion::VERSION_2_2: return BluetoothAudioHalTransport::HIDL; default: return BluetoothAudioHalTransport::UNKNOWN; } } -android::sp<IBluetoothAudioProvidersFactory_2_2> -HalVersionManager::GetProvidersFactory_2_2() { - std::lock_guard<std::mutex> guard(instance_ptr->mutex_); - if (instance_ptr->hal_version_ != BluetoothAudioHalVersion::VERSION_2_2) { - return nullptr; - } - android::sp<IBluetoothAudioProvidersFactory_2_2> providers_factory = - IBluetoothAudioProvidersFactory_2_2::getService(); - CHECK(providers_factory) - << "V2_2::IBluetoothAudioProvidersFactory::getService() failed"; - - LOG(INFO) << "V2_2::IBluetoothAudioProvidersFactory::getService() returned " - << providers_factory.get() - << (providers_factory->isRemote() ? " (remote)" : " (local)"); - return providers_factory; -} - android::sp<IBluetoothAudioProvidersFactory_2_1> HalVersionManager::GetProvidersFactory_2_1() { std::lock_guard<std::mutex> guard(instance_ptr->mutex_); @@ -124,19 +106,6 @@ HalVersionManager::HalVersionManager() { instance_count = instanceNames.size(); }; auto hidl_retval = service_manager->listManifestByInterface( - kFullyQualifiedInterfaceName_2_2, listManifestByInterface_cb); - if (!hidl_retval.isOk()) { - LOG(FATAL) << __func__ << ": IServiceManager::listByInterface failure: " - << hidl_retval.description(); - return; - } - - if (instance_count > 0) { - hal_version_ = BluetoothAudioHalVersion::VERSION_2_2; - return; - } - - hidl_retval = service_manager->listManifestByInterface( kFullyQualifiedInterfaceName_2_1, listManifestByInterface_cb); if (!hidl_retval.isOk()) { LOG(FATAL) << __func__ << ": IServiceManager::listByInterface failure: " diff --git a/system/audio_hal_interface/hal_version_manager.h b/system/audio_hal_interface/hal_version_manager.h index 12a2ecacfe..99dc0e9311 100644 --- a/system/audio_hal_interface/hal_version_manager.h +++ b/system/audio_hal_interface/hal_version_manager.h @@ -16,8 +16,8 @@ #pragma once -#include <android/hardware/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.h> -#include <android/hardware/bluetooth/audio/2.2/types.h> +#include <android/hardware/bluetooth/audio/2.1/IBluetoothAudioProvidersFactory.h> +#include <android/hardware/bluetooth/audio/2.1/types.h> namespace bluetooth { namespace audio { @@ -28,22 +28,17 @@ using IBluetoothAudioProvidersFactory_2_0 = ::android::hardware::bluetooth:: audio::V2_0::IBluetoothAudioProvidersFactory; using IBluetoothAudioProvidersFactory_2_1 = ::android::hardware::bluetooth:: audio::V2_1::IBluetoothAudioProvidersFactory; -using IBluetoothAudioProvidersFactory_2_2 = ::android::hardware::bluetooth:: - audio::V2_2::IBluetoothAudioProvidersFactory; constexpr char kFullyQualifiedInterfaceName_2_0[] = "android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory"; constexpr char kFullyQualifiedInterfaceName_2_1[] = "android.hardware.bluetooth.audio@2.1::IBluetoothAudioProvidersFactory"; -constexpr char kFullyQualifiedInterfaceName_2_2[] = - "android.hardware.bluetooth.audio@2.2::IBluetoothAudioProvidersFactory"; enum class BluetoothAudioHalVersion : uint8_t { - VERSION_2_0 = 0, + VERSION_UNAVAILABLE = 0, + VERSION_2_0, VERSION_2_1, - VERSION_2_2, VERSION_AIDL_V1, - VERSION_UNAVAILABLE, }; enum class BluetoothAudioHalTransport : uint8_t { @@ -61,9 +56,6 @@ class HalVersionManager { static BluetoothAudioHalTransport GetHalTransport(); - static android::sp<IBluetoothAudioProvidersFactory_2_2> - GetProvidersFactory_2_2(); - static android::sp<IBluetoothAudioProvidersFactory_2_1> GetProvidersFactory_2_1(); diff --git a/system/audio_hal_interface/hal_version_manager_host.cc b/system/audio_hal_interface/hal_version_manager_host.cc index 8b1c781d2f..b680ce06ff 100644 --- a/system/audio_hal_interface/hal_version_manager_host.cc +++ b/system/audio_hal_interface/hal_version_manager_host.cc @@ -29,11 +29,6 @@ BluetoothAudioHalTransport HalVersionManager::GetHalTransport() { return BluetoothAudioHalTransport::UNKNOWN; } -android::sp<IBluetoothAudioProvidersFactory_2_2> -HalVersionManager::GetProvidersFactory_2_2() { - return nullptr; -} - android::sp<IBluetoothAudioProvidersFactory_2_1> HalVersionManager::GetProvidersFactory_2_1() { return nullptr; diff --git a/system/audio_hal_interface/hidl/a2dp_encoding_hidl.cc b/system/audio_hal_interface/hidl/a2dp_encoding_hidl.cc index 6372aef40f..beeb823518 100644 --- a/system/audio_hal_interface/hidl/a2dp_encoding_hidl.cc +++ b/system/audio_hal_interface/hidl/a2dp_encoding_hidl.cc @@ -163,8 +163,6 @@ class A2dpTransport } } - void SinkMetadataChanged(const sink_metadata_t&) override {} - tA2DP_CTRL_CMD GetPendingCmd() const { return a2dp_pending_cmd_; } void ResetPendingCmd() { a2dp_pending_cmd_ = A2DP_CTRL_CMD_NONE; } @@ -553,15 +551,6 @@ void set_remote_delay(uint16_t delay_report) { ->SetRemoteDelay(delay_report); } -// Set low latency buffer mode allowed or disallowed -void set_low_latency_mode_allowed(bool allowed) { - if (!is_hal_2_0_enabled()) { - LOG(ERROR) << __func__ << ": BluetoothAudio HAL is not enabled"; - return; - } - active_hal_interface->SetLowLatencyModeAllowed(allowed); -} - } // namespace a2dp } // namespace hidl } // namespace audio diff --git a/system/audio_hal_interface/hidl/a2dp_encoding_hidl.h b/system/audio_hal_interface/hidl/a2dp_encoding_hidl.h index d8689b29fa..98a8f68632 100644 --- a/system/audio_hal_interface/hidl/a2dp_encoding_hidl.h +++ b/system/audio_hal_interface/hidl/a2dp_encoding_hidl.h @@ -57,9 +57,6 @@ size_t read(uint8_t* p_buf, uint32_t len); // Update A2DP delay report to BluetoothAudio HAL void set_remote_delay(uint16_t delay_report); -// Set low latency buffer mode allowed or disallowed -void set_low_latency_mode_allowed(bool allowed); - } // namespace a2dp } // namespace hidl } // namespace audio diff --git a/system/audio_hal_interface/hidl/client_interface_hidl.cc b/system/audio_hal_interface/hidl/client_interface_hidl.cc index 95efe6d42d..056ca04b75 100644 --- a/system/audio_hal_interface/hidl/client_interface_hidl.cc +++ b/system/audio_hal_interface/hidl/client_interface_hidl.cc @@ -18,7 +18,7 @@ #include "client_interface_hidl.h" -#include <android/hardware/bluetooth/audio/2.2/IBluetoothAudioPort.h> +#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioPort.h> #include <base/logging.h> #include <hidl/MQDescriptor.h> @@ -35,9 +35,8 @@ namespace hidl { using ::android::hardware::hidl_vec; using ::android::hardware::Return; using ::android::hardware::Void; -using ::android::hardware::audio::common::V5_0::SinkMetadata; using ::android::hardware::audio::common::V5_0::SourceMetadata; -using ::android::hardware::bluetooth::audio::V2_2::IBluetoothAudioPort; +using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort; using ::bluetooth::common::StopWatchLegacy; using DataMQ = ::android::hardware::MessageQueue< @@ -156,24 +155,6 @@ class BluetoothAudioPortImpl : public IBluetoothAudioPort { return Void(); } - Return<void> updateSinkMetadata(const SinkMetadata& sinkMetadata) override { - StopWatchLegacy stop_watch(__func__); - LOG(INFO) << __func__ << ": " << sinkMetadata.tracks.size() << " track(s)"; - // refer to StreamIn.impl.h within Audio HAL (AUDIO_HAL_VERSION_5_0) - std::vector<record_track_metadata> metadata_vec; - metadata_vec.reserve(sinkMetadata.tracks.size()); - for (const auto& metadata : sinkMetadata.tracks) { - metadata_vec.push_back({ - .source = static_cast<audio_source_t>(metadata.source), - .gain = metadata.gain, - }); - } - const sink_metadata_t sink_metadata = {.track_count = metadata_vec.size(), - .tracks = metadata_vec.data()}; - transport_instance_->SinkMetadataChanged(sink_metadata); - return Void(); - } - private: IBluetoothTransportInstance* transport_instance_; const android::sp<IBluetoothAudioProvider> provider_; @@ -220,7 +201,6 @@ BluetoothAudioClientInterface::BluetoothAudioClientInterface( IBluetoothTransportInstance* instance) : provider_(nullptr), provider_2_1_(nullptr), - provider_2_2_(nullptr), session_started_(false), mDataMQ(nullptr), transport_(instance) { @@ -300,37 +280,6 @@ BluetoothAudioClientInterface::GetAudioCapabilities_2_1( return capabilities_2_1; } -std::vector<AudioCapabilities_2_2> -BluetoothAudioClientInterface::GetAudioCapabilities_2_2( - SessionType_2_1 session_type_2_1) { - std::vector<AudioCapabilities_2_2> capabilities_2_2(0); - if (HalVersionManager::GetHalVersion() != - BluetoothAudioHalVersion::VERSION_2_2) { - LOG(ERROR) << __func__ << ", can't get capability for HAL 2.2"; - return capabilities_2_2; - } - - android::sp<IBluetoothAudioProvidersFactory_2_2> providersFactory = - HalVersionManager::GetProvidersFactory_2_2(); - CHECK(providersFactory != nullptr) - << "IBluetoothAudioProvidersFactory::getService() failed"; - auto getProviderCapabilities_cb = - [&capabilities_2_2]( - const hidl_vec<AudioCapabilities_2_2>& audioCapabilities_2_2) { - for (auto capability_2_2 : audioCapabilities_2_2) { - capabilities_2_2.push_back(capability_2_2); - } - }; - auto hidl_retval = providersFactory->getProviderCapabilities_2_2( - session_type_2_1, getProviderCapabilities_cb); - if (!hidl_retval.isOk()) { - LOG(FATAL) << __func__ - << ": BluetoothAudioHal::getProviderCapabilities failure: " - << hidl_retval.description(); - } - return capabilities_2_2; -} - void BluetoothAudioClientInterface::FetchAudioProvider() { if (provider_ != nullptr) { LOG(WARNING) << __func__ << ": reflash"; @@ -467,74 +416,6 @@ void BluetoothAudioClientInterface::FetchAudioProvider_2_1() { << (provider_2_1_->isRemote() ? " (remote)" : " (local)"); } -void BluetoothAudioClientInterface::FetchAudioProvider_2_2() { - if (provider_2_2_ != nullptr) { - LOG(WARNING) << __func__ << ": reflash"; - } - - android::sp<IBluetoothAudioProvidersFactory_2_2> providersFactory = - HalVersionManager::GetProvidersFactory_2_2(); - CHECK(providersFactory != nullptr) - << "IBluetoothAudioProvidersFactory_2_1::getService() failed"; - - auto getProviderCapabilities_cb = - [&capabilities_2_1 = this->capabilities_2_1_]( - const hidl_vec<AudioCapabilities_2_1>& audioCapabilities_2_1) { - capabilities_2_1.clear(); - for (auto capability_2_1 : audioCapabilities_2_1) { - capabilities_2_1.push_back(capability_2_1); - } - }; - auto hidl_retval = providersFactory->getProviderCapabilities_2_1( - transport_->GetSessionType_2_1(), getProviderCapabilities_cb); - if (!hidl_retval.isOk()) { - LOG(FATAL) << __func__ - << ": BluetoothAudioHal::getProviderCapabilities failure: " - << hidl_retval.description(); - return; - } - if (capabilities_2_1_.empty()) { - LOG(WARNING) << __func__ << ": SessionType=" - << toString(transport_->GetSessionType_2_1()) - << " Not supported by BluetoothAudioHal"; - return; - } - LOG(INFO) << __func__ << ": BluetoothAudioHal SessionType=" - << toString(transport_->GetSessionType_2_1()) << " has " - << capabilities_2_1_.size() << " AudioCapabilities"; - - std::promise<void> openProvider_promise; - auto openProvider_future = openProvider_promise.get_future(); - auto openProvider_cb = - [&provider_2_2_ = this->provider_2_2_, &openProvider_promise]( - BluetoothAudioStatus status, - const android::sp<IBluetoothAudioProvider_2_2>& provider_2_2) { - LOG(INFO) << "openProvider_cb(" << toString(status) << ")"; - if (status == BluetoothAudioStatus::SUCCESS) { - provider_2_2_ = provider_2_2; - } - ALOGE_IF(!provider_2_2_, "Failed to open BluetoothAudio provider_2_2"); - openProvider_promise.set_value(); - }; - hidl_retval = providersFactory->openProvider_2_2( - transport_->GetSessionType_2_1(), openProvider_cb); - openProvider_future.get(); - if (!hidl_retval.isOk()) { - LOG(FATAL) << __func__ << ": BluetoothAudioHal::openProvider failure: " - << hidl_retval.description(); - } - CHECK(provider_2_2_ != nullptr); - - if (!provider_2_2_->linkToDeath(death_recipient_, 0).isOk()) { - LOG(FATAL) << __func__ << ": BluetoothAudioDeathRecipient failure: " - << hidl_retval.description(); - } - - LOG(INFO) << "IBluetoothAudioProvidersFactory::openProvider() returned " - << provider_2_2_.get() - << (provider_2_2_->isRemote() ? " (remote)" : " (local)"); -} - BluetoothAudioSinkClientInterface::BluetoothAudioSinkClientInterface( IBluetoothSinkTransportInstance* sink, bluetooth::common::MessageLoopThread* message_loop) @@ -548,13 +429,6 @@ BluetoothAudioSinkClientInterface::BluetoothAudioSinkClientInterface( } if ((HalVersionManager::GetHalVersion() == - BluetoothAudioHalVersion::VERSION_2_2) && - (sink_->GetSessionType_2_1() != SessionType_2_1::UNKNOWN)) { - FetchAudioProvider_2_2(); - return; - } - - if ((HalVersionManager::GetHalVersion() == BluetoothAudioHalVersion::VERSION_2_1) && (sink_->GetSessionType_2_1() != SessionType_2_1::UNKNOWN)) { FetchAudioProvider_2_1(); @@ -578,13 +452,6 @@ BluetoothAudioSinkClientInterface::~BluetoothAudioSinkClientInterface() { << hidl_retval.description(); } } - if (provider_2_2_ != nullptr) { - auto hidl_retval = provider_2_2_->unlinkToDeath(death_recipient_); - if (!hidl_retval.isOk()) { - LOG(FATAL) << __func__ << ": BluetoothAudioDeathRecipient failure: " - << hidl_retval.description(); - } - } } BluetoothAudioSourceClientInterface::BluetoothAudioSourceClientInterface( @@ -600,12 +467,6 @@ BluetoothAudioSourceClientInterface::BluetoothAudioSourceClientInterface( } if ((HalVersionManager::GetHalVersion() == - BluetoothAudioHalVersion::VERSION_2_2) && - (source_->GetSessionType_2_1() != SessionType_2_1::UNKNOWN)) { - FetchAudioProvider_2_2(); - return; - } - if ((HalVersionManager::GetHalVersion() == BluetoothAudioHalVersion::VERSION_2_1) && (source_->GetSessionType_2_1() != SessionType_2_1::UNKNOWN)) { FetchAudioProvider_2_1(); @@ -629,13 +490,6 @@ BluetoothAudioSourceClientInterface::~BluetoothAudioSourceClientInterface() { << hidl_retval.description(); } } - if (provider_2_2_ != nullptr) { - auto hidl_retval = provider_2_2_->unlinkToDeath(death_recipient_); - if (!hidl_retval.isOk()) { - LOG(FATAL) << __func__ << ": BluetoothAudioDeathRecipient failure: " - << hidl_retval.description(); - } - } } bool BluetoothAudioClientInterface::UpdateAudioConfig( @@ -692,61 +546,6 @@ bool BluetoothAudioClientInterface::UpdateAudioConfig_2_1( return true; } -bool BluetoothAudioClientInterface::UpdateAudioConfig_2_2( - const AudioConfiguration_2_2& audio_config_2_2) { - bool is_software_session = - (transport_->GetSessionType_2_1() == - SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH || - transport_->GetSessionType_2_1() == - SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH || - transport_->GetSessionType_2_1() == - SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH || - transport_->GetSessionType_2_1() == - SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH); - bool is_a2dp_offload_session = - (transport_->GetSessionType_2_1() == - SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH); - bool is_leaudio_offload_session = - (transport_->GetSessionType_2_1() == - SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH || - transport_->GetSessionType_2_1() == - SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH); - auto audio_config_discriminator = audio_config_2_2.getDiscriminator(); - bool is_software_audio_config = - (is_software_session && - audio_config_discriminator == - AudioConfiguration_2_2::hidl_discriminator::pcmConfig); - bool is_a2dp_offload_audio_config = - (is_a2dp_offload_session && - audio_config_discriminator == - AudioConfiguration_2_2::hidl_discriminator::codecConfig); - bool is_leaudio_offload_audio_config = - (is_leaudio_offload_session && - audio_config_discriminator == - AudioConfiguration_2_2::hidl_discriminator::leAudioConfig); - if (!is_software_audio_config && !is_a2dp_offload_audio_config && - !is_leaudio_offload_audio_config) { - return false; - } - - transport_->UpdateAudioConfiguration_2_2(audio_config_2_2); - - if (provider_2_2_ == nullptr) { - LOG(INFO) << __func__ - << ": BluetoothAudioHal nullptr, update it as session started"; - return true; - } - - ::android::hardware::Return<void> hidl_retval; - hidl_retval = provider_2_2_->updateAudioConfiguration(audio_config_2_2); - - if (!hidl_retval.isOk()) { - LOG(ERROR) << __func__ - << ": BluetoothAudioHal failure: " << hidl_retval.description(); - } - return true; -} - int BluetoothAudioClientInterface::StartSession() { std::lock_guard<std::mutex> guard(internal_mutex_); if (provider_ == nullptr) { @@ -867,71 +666,6 @@ int BluetoothAudioClientInterface::StartSession_2_1() { } } -int BluetoothAudioClientInterface::StartSession_2_2() { - std::lock_guard<std::mutex> guard(internal_mutex_); - if (provider_2_2_ == nullptr) { - LOG(ERROR) << __func__ << ": BluetoothAudioHal nullptr"; - session_started_ = false; - return -EINVAL; - } - if (session_started_) { - LOG(ERROR) << __func__ << ": session started already"; - return -EBUSY; - } - - android::sp<IBluetoothAudioPort> stack_if = - new BluetoothAudioPortImpl(transport_, provider_2_2_); - - std::unique_ptr<DataMQ> tempDataMQ; - BluetoothAudioStatus session_status; - - std::promise<void> hidl_startSession_promise; - auto hidl_startSession_future = hidl_startSession_promise.get_future(); - auto hidl_cb = [&session_status, &tempDataMQ, &hidl_startSession_promise]( - BluetoothAudioStatus status, - const DataMQ::Descriptor& dataMQ) { - LOG(INFO) << "startSession_cb(" << toString(status) << ")"; - session_status = status; - if (status == BluetoothAudioStatus::SUCCESS && dataMQ.isHandleValid()) { - tempDataMQ.reset(new DataMQ(dataMQ)); - } - hidl_startSession_promise.set_value(); - }; - auto hidl_retval = provider_2_2_->startSession_2_2( - stack_if, transport_->GetAudioConfiguration_2_2(), hidl_cb); - hidl_startSession_future.get(); - if (!hidl_retval.isOk()) { - LOG(FATAL) << __func__ - << ": BluetoothAudioHal failure: " << hidl_retval.description(); - return -EPROTO; - } - - if (tempDataMQ && tempDataMQ->isValid()) { - mDataMQ = std::move(tempDataMQ); - } else if ( - (transport_->GetSessionType_2_1() == - SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH || - transport_->GetSessionType_2_1() == - SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH || - transport_->GetSessionType_2_1() == - SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) && - session_status == BluetoothAudioStatus::SUCCESS) { - transport_->ResetPresentationPosition(); - session_started_ = true; - return 0; - } - if (mDataMQ && mDataMQ->isValid()) { - transport_->ResetPresentationPosition(); - session_started_ = true; - return 0; - } else { - ALOGE_IF(!mDataMQ, "Failed to obtain audio data path"); - ALOGE_IF(mDataMQ && !mDataMQ->isValid(), "Audio data path is invalid"); - session_started_ = false; - return -EIO; - } -} - void BluetoothAudioClientInterface::StreamStarted( const BluetoothAudioCtrlAck& ack) { if (ack == BluetoothAudioCtrlAck::PENDING) { @@ -941,9 +675,7 @@ void BluetoothAudioClientInterface::StreamStarted( BluetoothAudioStatus status = BluetoothAudioCtrlAckToHalStatus(ack); ::android::hardware::Return<void> hidl_retval; - if (provider_2_2_ != nullptr) { - hidl_retval = provider_2_2_->streamStarted(status); - } else if (provider_2_1_ != nullptr) { + if (provider_2_1_ != nullptr) { hidl_retval = provider_2_1_->streamStarted(status); } else if (provider_ != nullptr) { hidl_retval = provider_->streamStarted(status); @@ -967,9 +699,7 @@ void BluetoothAudioClientInterface::StreamSuspended( BluetoothAudioStatus status = BluetoothAudioCtrlAckToHalStatus(ack); ::android::hardware::Return<void> hidl_retval; - if (provider_2_2_ != nullptr) { - hidl_retval = provider_2_2_->streamSuspended(status); - } else if (provider_2_1_ != nullptr) { + if (provider_2_1_ != nullptr) { hidl_retval = provider_2_1_->streamSuspended(status); } else if (provider_ != nullptr) { hidl_retval = provider_->streamSuspended(status); @@ -995,9 +725,7 @@ int BluetoothAudioClientInterface::EndSession() { mDataMQ = nullptr; ::android::hardware::Return<void> hidl_retval; - if (provider_2_2_ != nullptr) { - hidl_retval = provider_2_2_->endSession(); - } else if (provider_2_1_ != nullptr) { + if (provider_2_1_ != nullptr) { hidl_retval = provider_2_1_->endSession(); } else if (provider_ != nullptr) { hidl_retval = provider_->endSession(); @@ -1088,11 +816,8 @@ void BluetoothAudioClientInterface::RenewAudioProviderAndSession() { // NOTE: must be invoked on the same thread where this // BluetoothAudioClientInterface is running auto hal_version = HalVersionManager::GetHalVersion(); - if ((hal_version == BluetoothAudioHalVersion::VERSION_2_2) && + if ((hal_version == BluetoothAudioHalVersion::VERSION_2_1) && (transport_->GetSessionType_2_1() != SessionType_2_1::UNKNOWN)) { - FetchAudioProvider_2_2(); - } else if ((hal_version == BluetoothAudioHalVersion::VERSION_2_1) && - (transport_->GetSessionType_2_1() != SessionType_2_1::UNKNOWN)) { FetchAudioProvider_2_1(); } else if (transport_->GetSessionType() != SessionType::UNKNOWN) { FetchAudioProvider(); @@ -1105,9 +830,7 @@ void BluetoothAudioClientInterface::RenewAudioProviderAndSession() { LOG(INFO) << __func__ << ": Restart the session while audio HAL recovering"; session_started_ = false; - if (provider_2_2_ != nullptr) - StartSession_2_2(); - else if (provider_2_1_ != nullptr) + if (provider_2_1_ != nullptr) StartSession_2_1(); else StartSession(); @@ -1166,14 +889,6 @@ size_t BluetoothAudioSourceClientInterface::WriteAudioData(const uint8_t* p_buf, return total_written; } -void BluetoothAudioClientInterface::SetLowLatencyModeAllowed(bool allowed) { - if (!IsValid()) { - LOG(ERROR) << __func__ << ": BluetoothAudioHal is not valid"; - return; - } - provider_2_2_->setLowLatencyModeAllowed(allowed); -} - } // namespace hidl } // namespace audio } // namespace bluetooth diff --git a/system/audio_hal_interface/hidl/client_interface_hidl.h b/system/audio_hal_interface/hidl/client_interface_hidl.h index cb36613bbb..2ca53e2a6e 100644 --- a/system/audio_hal_interface/hidl/client_interface_hidl.h +++ b/system/audio_hal_interface/hidl/client_interface_hidl.h @@ -16,8 +16,8 @@ #pragma once -#include <android/hardware/bluetooth/audio/2.2/IBluetoothAudioProvider.h> -#include <android/hardware/bluetooth/audio/2.2/types.h> +#include <android/hardware/bluetooth/audio/2.1/IBluetoothAudioProvider.h> +#include <android/hardware/bluetooth/audio/2.1/types.h> #include <fmq/MessageQueue.h> #include <hardware/audio.h> #include <time.h> @@ -34,27 +34,20 @@ namespace bluetooth { namespace audio { namespace hidl { -using ::android::hardware::bluetooth::audio::V2_2::IBluetoothAudioPort; using AudioCapabilities = ::android::hardware::bluetooth::audio::V2_0::AudioCapabilities; using AudioCapabilities_2_1 = ::android::hardware::bluetooth::audio::V2_1::AudioCapabilities; -using AudioCapabilities_2_2 = - ::android::hardware::bluetooth::audio::V2_2::AudioCapabilities; using AudioConfiguration = ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration; using AudioConfiguration_2_1 = ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration; -using AudioConfiguration_2_2 = - ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration; using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample; using ::android::hardware::bluetooth::audio::V2_0::ChannelMode; using IBluetoothAudioProvider = ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioProvider; using IBluetoothAudioProvider_2_1 = ::android::hardware::bluetooth::audio::V2_1::IBluetoothAudioProvider; -using IBluetoothAudioProvider_2_2 = - ::android::hardware::bluetooth::audio::V2_2::IBluetoothAudioProvider; using PcmParameters = ::android::hardware::bluetooth::audio::V2_0::PcmParameters; using PcmParameters_2_1 = @@ -107,22 +100,13 @@ class IBluetoothTransportInstance { : session_type_(sessionType), session_type_2_1_(SessionType_2_1::UNKNOWN), audio_config_(std::move(audioConfig)), - audio_config_2_1_({}), - audio_config_2_2_({}){}; + audio_config_2_1_({}){}; IBluetoothTransportInstance(SessionType_2_1 sessionType_2_1, AudioConfiguration_2_1 audioConfig_2_1) : session_type_(SessionType::UNKNOWN), session_type_2_1_(sessionType_2_1), audio_config_({}), - audio_config_2_1_(std::move(audioConfig_2_1)), - audio_config_2_2_({}){}; - IBluetoothTransportInstance(SessionType_2_1 sessionType_2_1, - AudioConfiguration_2_2 audioConfig_2_2) - : session_type_(SessionType::UNKNOWN), - session_type_2_1_(sessionType_2_1), - audio_config_({}), - audio_config_2_1_({}), - audio_config_2_2_(std::move(audioConfig_2_2)){}; + audio_config_2_1_(std::move(audioConfig_2_1)){}; virtual ~IBluetoothTransportInstance() = default; SessionType GetSessionType() const { return session_type_; } @@ -132,9 +116,6 @@ class IBluetoothTransportInstance { AudioConfiguration_2_1 GetAudioConfiguration_2_1() const { return audio_config_2_1_; } - AudioConfiguration_2_2 GetAudioConfiguration_2_2() const { - return audio_config_2_2_; - } void UpdateAudioConfiguration(const AudioConfiguration& audio_config) { audio_config_ = audio_config; @@ -143,10 +124,6 @@ class IBluetoothTransportInstance { const AudioConfiguration_2_1& audio_config_2_1) { audio_config_2_1_ = audio_config_2_1; } - void UpdateAudioConfiguration_2_2( - const AudioConfiguration_2_2& audio_config_2_2) { - audio_config_2_2_ = audio_config_2_2; - } virtual BluetoothAudioCtrlAck StartRequest() = 0; @@ -159,7 +136,6 @@ class IBluetoothTransportInstance { timespec* data_position) = 0; virtual void MetadataChanged(const source_metadata_t& source_metadata) = 0; - virtual void SinkMetadataChanged(const sink_metadata_t& sink_metadata) = 0; // Invoked when the transport is requested to reset presentation position virtual void ResetPresentationPosition() = 0; @@ -169,7 +145,6 @@ class IBluetoothTransportInstance { const SessionType_2_1 session_type_2_1_; AudioConfiguration audio_config_; AudioConfiguration_2_1 audio_config_2_1_; - AudioConfiguration_2_2 audio_config_2_2_; }; // An IBluetoothSinkTransportInstance needs to be implemented by a Bluetooth @@ -177,15 +152,12 @@ class IBluetoothTransportInstance { // from Audio HAL. class IBluetoothSinkTransportInstance : public IBluetoothTransportInstance { public: - IBluetoothSinkTransportInstance(SessionType_2_1 sessionType_2_1, - AudioConfiguration_2_2 audioConfig_2_2) - : IBluetoothTransportInstance{sessionType_2_1, audioConfig_2_2} {} - IBluetoothSinkTransportInstance(SessionType_2_1 sessionType_2_1, - AudioConfiguration_2_1 audioConfig_2_1) - : IBluetoothTransportInstance{sessionType_2_1, audioConfig_2_1} {} IBluetoothSinkTransportInstance(SessionType sessionType, AudioConfiguration audioConfig) : IBluetoothTransportInstance{sessionType, audioConfig} {} + IBluetoothSinkTransportInstance(SessionType_2_1 sessionType_2_1, + AudioConfiguration_2_1 audioConfig_2_1) + : IBluetoothTransportInstance{sessionType_2_1, audioConfig_2_1} {} virtual ~IBluetoothSinkTransportInstance() = default; // Invoked when the transport is requested to log bytes read @@ -200,9 +172,6 @@ class IBluetoothSourceTransportInstance : public IBluetoothTransportInstance { IBluetoothSourceTransportInstance(SessionType_2_1 sessionType_2_1, AudioConfiguration_2_1 audioConfig_2_1) : IBluetoothTransportInstance{sessionType_2_1, audioConfig_2_1} {} - IBluetoothSourceTransportInstance(SessionType_2_1 sessionType_2_1, - AudioConfiguration_2_2 audioConfig_2_2) - : IBluetoothTransportInstance{sessionType_2_1, audioConfig_2_2} {} virtual ~IBluetoothSourceTransportInstance() = default; // Invoked when the transport is requested to log bytes written @@ -223,8 +192,7 @@ class BluetoothAudioClientInterface { virtual ~BluetoothAudioClientInterface() = default; bool IsValid() const { - return provider_ != nullptr || provider_2_1_ != nullptr || - provider_2_2_ != nullptr; + return provider_ != nullptr || provider_2_1_ != nullptr; } std::vector<AudioCapabilities> GetAudioCapabilities() const; @@ -233,8 +201,6 @@ class BluetoothAudioClientInterface { SessionType session_type); static std::vector<AudioCapabilities_2_1> GetAudioCapabilities_2_1( SessionType_2_1 session_type_2_1); - static std::vector<AudioCapabilities_2_2> GetAudioCapabilities_2_2( - SessionType_2_1 session_type_2_1); void StreamStarted(const BluetoothAudioCtrlAck& ack); @@ -242,7 +208,6 @@ class BluetoothAudioClientInterface { int StartSession(); int StartSession_2_1(); - int StartSession_2_2(); // Renew the connection and usually is used when HIDL restarted void RenewAudioProviderAndSession(); @@ -251,12 +216,9 @@ class BluetoothAudioClientInterface { bool UpdateAudioConfig(const AudioConfiguration& audioConfig); bool UpdateAudioConfig_2_1(const AudioConfiguration_2_1& audioConfig_2_1); - bool UpdateAudioConfig_2_2(const AudioConfiguration_2_2& audioConfig_2_2); void FlushAudioData(); - void SetLowLatencyModeAllowed(bool allowed); - static constexpr PcmParameters kInvalidPcmConfiguration = { .sampleRate = SampleRate::RATE_UNKNOWN, .channelMode = ChannelMode::UNKNOWN, @@ -268,12 +230,9 @@ class BluetoothAudioClientInterface { void FetchAudioProvider(); // Helper function to connect to an IBluetoothAudioProvider 2.1 void FetchAudioProvider_2_1(); - // Helper function to connect to an IBluetoothAudioProvider 2.2 - void FetchAudioProvider_2_2(); android::sp<IBluetoothAudioProvider> provider_; android::sp<IBluetoothAudioProvider_2_1> provider_2_1_; - android::sp<IBluetoothAudioProvider_2_2> provider_2_2_; bool session_started_; std::unique_ptr<::android::hardware::MessageQueue< uint8_t, ::android::hardware::kSynchronizedReadWrite>> @@ -284,7 +243,6 @@ class BluetoothAudioClientInterface { IBluetoothTransportInstance* transport_; std::vector<AudioCapabilities> capabilities_; std::vector<AudioCapabilities_2_1> capabilities_2_1_; - std::vector<AudioCapabilities_2_2> capabilities_2_2_; }; // The client interface connects an IBluetoothTransportInstance to diff --git a/system/audio_hal_interface/hidl/client_interface_hidl_unittest.cc b/system/audio_hal_interface/hidl/client_interface_hidl_unittest.cc index 7defcdfbb4..7f45cb050e 100644 --- a/system/audio_hal_interface/hidl/client_interface_hidl_unittest.cc +++ b/system/audio_hal_interface/hidl/client_interface_hidl_unittest.cc @@ -164,8 +164,6 @@ class TestSinkTransport } void MetadataChanged( const source_metadata_t& source_metadata __unused) override {} - void SinkMetadataChanged( - const sink_metadata_t& sink_metadata __unused) override {} void ResetPresentationPosition() override{}; void LogBytesRead(size_t bytes_readed __unused) override{}; }; @@ -205,8 +203,6 @@ class TestSourceTransport } void MetadataChanged( const source_metadata_t& source_metadata __unused) override {} - void SinkMetadataChanged( - const sink_metadata_t& sink_metadata __unused) override {} void ResetPresentationPosition() override{}; void LogBytesWritten(size_t bytes_written __unused) override{}; }; diff --git a/system/audio_hal_interface/hidl/codec_status_hidl.h b/system/audio_hal_interface/hidl/codec_status_hidl.h index 7f010b8d15..8ed431c80e 100644 --- a/system/audio_hal_interface/hidl/codec_status_hidl.h +++ b/system/audio_hal_interface/hidl/codec_status_hidl.h @@ -16,7 +16,7 @@ #pragma once -#include <android/hardware/bluetooth/audio/2.2/types.h> +#include <android/hardware/bluetooth/audio/2.1/types.h> #include <vector> diff --git a/system/audio_hal_interface/hidl/hearing_aid_software_encoding_hidl.cc b/system/audio_hal_interface/hidl/hearing_aid_software_encoding_hidl.cc index 3bb48b6949..ed2f963dcf 100644 --- a/system/audio_hal_interface/hidl/hearing_aid_software_encoding_hidl.cc +++ b/system/audio_hal_interface/hidl/hearing_aid_software_encoding_hidl.cc @@ -106,8 +106,6 @@ class HearingAidTransport } } - void SinkMetadataChanged(const sink_metadata_t&) override {} - void ResetPresentationPosition() override { VLOG(2) << __func__ << ": called."; remote_delay_report_ms_ = 0; diff --git a/system/audio_hal_interface/hidl/le_audio_software_hidl.cc b/system/audio_hal_interface/hidl/le_audio_software_hidl.cc index d2286ad13e..a87b5c26bc 100644 --- a/system/audio_hal_interface/hidl/le_audio_software_hidl.cc +++ b/system/audio_hal_interface/hidl/le_audio_software_hidl.cc @@ -19,12 +19,6 @@ #include "le_audio_software_hidl.h" -#include <unordered_map> -#include <vector> - -#include "codec_status_hidl.h" -#include "hal_version_manager.h" - namespace bluetooth { namespace audio { namespace hidl { @@ -32,20 +26,10 @@ namespace le_audio { using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample; using ::android::hardware::bluetooth::audio::V2_0::ChannelMode; -using ::android::hardware::bluetooth::audio::V2_1::CodecType; -using ::android::hardware::bluetooth::audio::V2_1::Lc3FrameDuration; -using ::android::hardware::bluetooth::audio::V2_1::Lc3Parameters; -using ::android::hardware::bluetooth::audio::V2_2::AudioLocation; +using ::android::hardware::bluetooth::audio::V2_0::CodecType; using ::bluetooth::audio::hidl::SampleRate_2_1; using ::bluetooth::audio::hidl::SessionType; using ::bluetooth::audio::hidl::SessionType_2_1; -using AudioCapabilities_2_2 = - ::android::hardware::bluetooth::audio::V2_2::AudioCapabilities; -using ::android::hardware::bluetooth::audio::V2_2::LeAudioMode; -using ::android::hardware::bluetooth::audio::V2_2::UnicastConfig; -using ::android::hardware::bluetooth::audio::V2_2::UnicastStreamMap; -using ::le_audio::set_configurations::SetConfiguration; -using ::le_audio::types::LeAudioLc3Config; using ::bluetooth::audio::le_audio::LeAudioClientInterface; @@ -102,46 +86,6 @@ static ChannelMode le_audio_channel_mode2audio_hal(uint8_t channels_count) { return ChannelMode::UNKNOWN; } -static Lc3FrameDuration le_audio_frame_duration2audio_hal( - uint8_t frame_duration) { - switch (frame_duration) { - case 10000: - return Lc3FrameDuration::DURATION_10000US; - case 7500: - return Lc3FrameDuration::DURATION_7500US; - } - // TODO: handle error in the aidl version - return Lc3FrameDuration::DURATION_10000US; -} - -AudioConfiguration_2_2 offload_config_to_hal_audio_config( - const ::le_audio::offload_config& offload_config) { - AudioConfiguration_2_2 audio_config; - std::vector<UnicastStreamMap> unicast_map; - for (auto& [handle, location] : offload_config.stream_map) { - UnicastStreamMap stream = {.streamHandle = handle, - .audioChannelAllocation = location}; - unicast_map.emplace_back(stream); - } - hidl_vec<UnicastStreamMap> hal_map; - hal_map.setToExternal(unicast_map.data(), unicast_map.size()); - LeAudioConfiguration le_audio_config; - le_audio_config.mode = LeAudioMode::UNICAST; - le_audio_config.config.unicastConfig() = { - .streamMap = std::move(hal_map), - .peerDelay = offload_config.peer_delay, - .lc3Config = {.pcmBitDepth = le_audio_bits_per_sample2audio_hal( - offload_config.bits_per_sample), - .samplingFrequency = le_audio_sample_rate2audio_hal( - offload_config.sampling_rate), - .frameDuration = le_audio_frame_duration2audio_hal( - offload_config.frame_duration), - .octetsPerFrame = offload_config.octets_per_frame, - .blocksPerSdu = offload_config.blocks_per_sdu}}; - audio_config.leAudioConfig(le_audio_config); - return audio_config; -} - bool is_source_hal_enabled() { return LeAudioSourceTransport::interface != nullptr; } @@ -218,19 +162,6 @@ void LeAudioTransport::MetadataChanged( stream_cb_.on_metadata_update_(source_metadata); } -void LeAudioTransport::SinkMetadataChanged( - const sink_metadata_t& sink_metadata) { - auto track_count = sink_metadata.track_count; - - if (track_count == 0) { - LOG(WARNING) << ", invalid number of metadata changed tracks"; - return; - } - - if (stream_cb_.on_sink_metadata_update_) - stream_cb_.on_sink_metadata_update_(sink_metadata); -} - void LeAudioTransport::ResetPresentationPosition() { VLOG(2) << __func__ << ": called."; remote_delay_report_ms_ = 0; @@ -279,8 +210,7 @@ void flush_sink() { LeAudioSinkTransport::LeAudioSinkTransport(SessionType_2_1 session_type, StreamCallbacks stream_cb) - : IBluetoothSinkTransportInstance(session_type, - (AudioConfiguration_2_2){}) { + : IBluetoothSinkTransportInstance(session_type, {}) { transport_ = new LeAudioTransport(flush_sink, std::move(stream_cb), {SampleRate_2_1::RATE_16000, ChannelMode::STEREO, @@ -311,11 +241,6 @@ void LeAudioSinkTransport::MetadataChanged( transport_->MetadataChanged(source_metadata); } -void LeAudioSinkTransport::SinkMetadataChanged( - const sink_metadata_t& sink_metadata) { - transport_->SinkMetadataChanged(sink_metadata); -} - void LeAudioSinkTransport::ResetPresentationPosition() { transport_->ResetPresentationPosition(); } @@ -354,8 +279,7 @@ void flush_source() { LeAudioSourceTransport::LeAudioSourceTransport(SessionType_2_1 session_type, StreamCallbacks stream_cb) - : IBluetoothSourceTransportInstance(session_type, - (AudioConfiguration_2_2){}) { + : IBluetoothSourceTransportInstance(session_type, {}) { transport_ = new LeAudioTransport(flush_source, std::move(stream_cb), {SampleRate_2_1::RATE_16000, ChannelMode::MONO, @@ -386,11 +310,6 @@ void LeAudioSourceTransport::MetadataChanged( transport_->MetadataChanged(source_metadata); } -void LeAudioSourceTransport::SinkMetadataChanged( - const sink_metadata_t& sink_metadata) { - transport_->SinkMetadataChanged(sink_metadata); -} - void LeAudioSourceTransport::ResetPresentationPosition() { transport_->ResetPresentationPosition(); } @@ -421,139 +340,6 @@ void LeAudioSourceTransport::ClearPendingStartStream(void) { transport_->ClearPendingStartStream(); } -std::unordered_map<SampleRate_2_1, uint8_t> sampling_freq_map{ - {SampleRate_2_1::RATE_8000, - ::le_audio::codec_spec_conf::kLeAudioSamplingFreq8000Hz}, - {SampleRate_2_1::RATE_16000, - ::le_audio::codec_spec_conf::kLeAudioSamplingFreq16000Hz}, - {SampleRate_2_1::RATE_24000, - ::le_audio::codec_spec_conf::kLeAudioSamplingFreq24000Hz}, - {SampleRate_2_1::RATE_32000, - ::le_audio::codec_spec_conf::kLeAudioSamplingFreq32000Hz}, - {SampleRate_2_1::RATE_44100, - ::le_audio::codec_spec_conf::kLeAudioSamplingFreq44100Hz}, - {SampleRate_2_1::RATE_48000, - ::le_audio::codec_spec_conf::kLeAudioSamplingFreq48000Hz}, - {SampleRate_2_1::RATE_88200, - ::le_audio::codec_spec_conf::kLeAudioSamplingFreq88200Hz}, - {SampleRate_2_1::RATE_96000, - ::le_audio::codec_spec_conf::kLeAudioSamplingFreq96000Hz}, - {SampleRate_2_1::RATE_176400, - ::le_audio::codec_spec_conf::kLeAudioSamplingFreq176400Hz}, - {SampleRate_2_1::RATE_192000, - ::le_audio::codec_spec_conf::kLeAudioSamplingFreq192000Hz}}; - -std::unordered_map<Lc3FrameDuration, uint8_t> frame_duration_map{ - {Lc3FrameDuration::DURATION_7500US, - ::le_audio::codec_spec_conf::kLeAudioCodecLC3FrameDur7500us}, - {Lc3FrameDuration::DURATION_10000US, - ::le_audio::codec_spec_conf::kLeAudioCodecLC3FrameDur10000us}}; - -std::unordered_map<uint32_t, uint16_t> octets_per_frame_map{ - {30, ::le_audio::codec_spec_conf::kLeAudioCodecLC3FrameLen30}, - {40, ::le_audio::codec_spec_conf::kLeAudioCodecLC3FrameLen40}, - {120, ::le_audio::codec_spec_conf::kLeAudioCodecLC3FrameLen120}}; - -std::unordered_map<AudioLocation, uint32_t> audio_location_map{ - {AudioLocation::UNKNOWN, - ::le_audio::codec_spec_conf::kLeAudioLocationMonoUnspecified}, - {AudioLocation::FRONT_LEFT, - ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft}, - {AudioLocation::FRONT_RIGHT, - ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight}, - {static_cast<AudioLocation>(AudioLocation::FRONT_LEFT | - AudioLocation::FRONT_RIGHT), - ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft | - ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight}}; - -bool halConfigToCodecCapabilitySetting( - UnicastCapability halConfig, CodecCapabilitySetting& codecCapability) { - if (halConfig.codecType != CodecType::LC3) { - LOG(WARNING) << "Unsupported codecType: " << toString(halConfig.codecType); - return false; - } - - Lc3Parameters halLc3Config = halConfig.capabilities; - AudioLocation supportedChannel = halConfig.supportedChannel; - - if (sampling_freq_map.find(halLc3Config.samplingFrequency) == - sampling_freq_map.end() || - frame_duration_map.find(halLc3Config.frameDuration) == - frame_duration_map.end() || - octets_per_frame_map.find(halLc3Config.octetsPerFrame) == - octets_per_frame_map.end() || - audio_location_map.find(supportedChannel) == audio_location_map.end()) { - LOG(ERROR) << __func__ << ": Failed to convert HAL format to stack format" - << "\nsample rate = " << (uint8_t)halLc3Config.samplingFrequency - << "\nframe duration = " << (uint8_t)halLc3Config.frameDuration - << "\noctets per frame= " << halLc3Config.octetsPerFrame - << "\naudio location = " << (uint8_t)supportedChannel; - - return false; - } - - codecCapability = { - .id = ::le_audio::set_configurations::LeAudioCodecIdLc3, - .config = LeAudioLc3Config( - {.sampling_frequency = - sampling_freq_map[halLc3Config.samplingFrequency], - .frame_duration = frame_duration_map[halLc3Config.frameDuration], - .octets_per_codec_frame = - octets_per_frame_map[halLc3Config.octetsPerFrame], - .audio_channel_allocation = audio_location_map[supportedChannel]})}; - - return true; -} - -std::vector<AudioSetConfiguration> get_offload_capabilities() { - LOG(INFO) << __func__; - std::vector<AudioSetConfiguration> offload_capabilities; - std::vector<AudioCapabilities_2_2> le_audio_hal_capabilities = - BluetoothAudioSinkClientInterface::GetAudioCapabilities_2_2( - SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH); - std::string strCapabilityLog; - - for (auto halCapability : le_audio_hal_capabilities) { - CodecCapabilitySetting encodeCapability; - CodecCapabilitySetting decodeCapability; - UnicastCapability halEncodeConfig = - halCapability.leAudioCapabilities().unicastEncodeCapability; - UnicastCapability halDecodeConfig = - halCapability.leAudioCapabilities().unicastDecodeCapability; - AudioSetConfiguration audioSetConfig = {.name = "offload capability"}; - strCapabilityLog.clear(); - - if (halConfigToCodecCapabilitySetting(halEncodeConfig, encodeCapability)) { - audioSetConfig.confs.push_back(SetConfiguration( - ::le_audio::types::kLeAudioDirectionSink, halEncodeConfig.deviceCount, - halEncodeConfig.deviceCount * halEncodeConfig.channelCountPerDevice, - encodeCapability)); - strCapabilityLog = " Encode Capability: " + toString(halEncodeConfig); - } - - if (halConfigToCodecCapabilitySetting(halDecodeConfig, decodeCapability)) { - audioSetConfig.confs.push_back(SetConfiguration( - ::le_audio::types::kLeAudioDirectionSource, - halDecodeConfig.deviceCount, - halDecodeConfig.deviceCount * halDecodeConfig.channelCountPerDevice, - decodeCapability)); - strCapabilityLog += " Decode Capability: " + toString(halDecodeConfig); - } - - if (!audioSetConfig.confs.empty()) { - offload_capabilities.push_back(audioSetConfig); - LOG(INFO) << __func__ - << ": Supported codec capability =" << strCapabilityLog; - - } else { - LOG(INFO) << __func__ - << ": Unknown codec capability =" << toString(halCapability); - } - } - - return offload_capabilities; -} - } // namespace le_audio } // namespace hidl } // namespace audio diff --git a/system/audio_hal_interface/hidl/le_audio_software_hidl.h b/system/audio_hal_interface/hidl/le_audio_software_hidl.h index 3a161a619a..3b63c07b3c 100644 --- a/system/audio_hal_interface/hidl/le_audio_software_hidl.h +++ b/system/audio_hal_interface/hidl/le_audio_software_hidl.h @@ -26,9 +26,6 @@ namespace hidl { namespace le_audio { using ::android::hardware::bluetooth::audio::V2_1::PcmParameters; -using ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration; -using ::android::hardware::bluetooth::audio::V2_2::UnicastCapability; -using ::bluetooth::audio::hidl::AudioConfiguration_2_2; using ::bluetooth::audio::hidl::BluetoothAudioCtrlAck; using ::le_audio::set_configurations::AudioSetConfiguration; using ::le_audio::set_configurations::CodecCapabilitySetting; @@ -51,15 +48,9 @@ using ::bluetooth::audio::le_audio::StreamCallbacks; void flush_sink(); void flush_source(); -bool halConfigToCodecCapabilitySetting(UnicastCapability halConfig, - CodecCapabilitySetting& codecCapability); bool is_source_hal_enabled(); bool is_sink_hal_enabled(); -AudioConfiguration_2_2 offload_config_to_hal_audio_config( - const ::le_audio::offload_config& offload_config); - -std::vector<AudioSetConfiguration> get_offload_capabilities(); class LeAudioTransport { public: @@ -78,8 +69,6 @@ class LeAudioTransport { void MetadataChanged(const source_metadata_t& source_metadata); - void SinkMetadataChanged(const sink_metadata_t& sink_metadata); - void ResetPresentationPosition(); void LogBytesProcessed(size_t bytes_processed); @@ -125,8 +114,6 @@ class LeAudioSinkTransport void MetadataChanged(const source_metadata_t& source_metadata) override; - void SinkMetadataChanged(const sink_metadata_t& sink_metadata) override; - void ResetPresentationPosition() override; void LogBytesRead(size_t bytes_read) override; @@ -169,8 +156,6 @@ class LeAudioSourceTransport void MetadataChanged(const source_metadata_t& source_metadata) override; - void SinkMetadataChanged(const sink_metadata_t& sink_metadata) override; - void ResetPresentationPosition() override; void LogBytesWritten(size_t bytes_written) override; diff --git a/system/audio_hal_interface/le_audio_software.cc b/system/audio_hal_interface/le_audio_software.cc index c6a5cc65f9..112ad8f9e7 100644 --- a/system/audio_hal_interface/le_audio_software.cc +++ b/system/audio_hal_interface/le_audio_software.cc @@ -38,8 +38,6 @@ namespace { using ::android::hardware::bluetooth::audio::V2_1::PcmParameters; using AudioConfiguration_2_1 = ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration; -using AudioConfiguration_2_2 = - ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration; using AudioConfigurationAIDL = ::aidl::android::hardware::bluetooth::audio::AudioConfiguration; @@ -51,7 +49,7 @@ using ::le_audio::types::CodecLocation; std::vector<AudioSetConfiguration> get_offload_capabilities() { if (HalVersionManager::GetHalTransport() == BluetoothAudioHalTransport::HIDL) { - return hidl::le_audio::get_offload_capabilities(); + return std::vector<AudioSetConfiguration>(0); } return aidl::le_audio::get_offload_capabilities(); } @@ -133,25 +131,6 @@ void LeAudioClientInterface::Sink::StartSession() { hidl::le_audio::LeAudioSinkTransport::interface->StartSession_2_1(); return; } else if (HalVersionManager::GetHalVersion() == - BluetoothAudioHalVersion::VERSION_2_2) { - AudioConfiguration_2_2 audio_config; - if (hidl::le_audio::LeAudioSinkTransport::interface->GetTransportInstance() - ->GetSessionType_2_1() == - hidl::SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { - hidl::le_audio::LeAudioConfiguration le_audio_config = {}; - audio_config.leAudioConfig(le_audio_config); - } else { - audio_config.pcmConfig(hidl::le_audio::LeAudioSinkTransport::instance - ->LeAudioGetSelectedHalPcmConfig()); - } - if (!hidl::le_audio::LeAudioSinkTransport::interface->UpdateAudioConfig_2_2( - audio_config)) { - LOG(ERROR) << __func__ << ": cannot update audio config to HAL"; - return; - } - hidl::le_audio::LeAudioSinkTransport::interface->StartSession_2_2(); - return; - } else if (HalVersionManager::GetHalVersion() == BluetoothAudioHalVersion::VERSION_AIDL_V1) { AudioConfigurationAIDL audio_config; if (aidl::le_audio::LeAudioSinkTransport::interface->GetTransportInstance() @@ -236,13 +215,6 @@ void LeAudioClientInterface::Sink::UpdateAudioConfigToHal( const ::le_audio::offload_config& offload_config) { if (HalVersionManager::GetHalTransport() == BluetoothAudioHalTransport::HIDL) { - if (hidl::le_audio::LeAudioSinkTransport::interface->GetTransportInstance() - ->GetSessionType_2_1() != - hidl::SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { - return; - } - hidl::le_audio::LeAudioSinkTransport::interface->UpdateAudioConfig_2_2( - hidl::le_audio::offload_config_to_hal_audio_config(offload_config)); return; } if (aidl::le_audio::LeAudioSinkTransport::interface->GetTransportInstance() @@ -330,27 +302,6 @@ void LeAudioClientInterface::Source::StartSession() { hidl::le_audio::LeAudioSourceTransport::interface->StartSession_2_1(); return; } else if (HalVersionManager::GetHalVersion() == - BluetoothAudioHalVersion::VERSION_2_2) { - AudioConfiguration_2_2 audio_config; - if (hidl::le_audio::LeAudioSourceTransport:: - interface->GetTransportInstance() - ->GetSessionType_2_1() == - hidl::SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) { - hidl::le_audio::LeAudioConfiguration le_audio_config = {}; - audio_config.leAudioConfig(le_audio_config); - } else { - audio_config.pcmConfig(hidl::le_audio::LeAudioSourceTransport::instance - ->LeAudioGetSelectedHalPcmConfig()); - } - - if (!hidl::le_audio::LeAudioSourceTransport:: - interface->UpdateAudioConfig_2_2(audio_config)) { - LOG(ERROR) << __func__ << ": cannot update audio config to HAL"; - return; - } - hidl::le_audio::LeAudioSourceTransport::interface->StartSession_2_2(); - return; - } else if (HalVersionManager::GetHalVersion() == BluetoothAudioHalVersion::VERSION_AIDL_V1) { AudioConfigurationAIDL audio_config; if (aidl::le_audio::LeAudioSourceTransport:: @@ -439,16 +390,16 @@ void LeAudioClientInterface::Source::UpdateAudioConfigToHal( const ::le_audio::offload_config& offload_config) { if (HalVersionManager::GetHalTransport() == BluetoothAudioHalTransport::HIDL) { - if (hidl::le_audio::LeAudioSourceTransport:: - interface->GetTransportInstance() - ->GetSessionType_2_1() != - hidl::SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) { - return; - } - hidl::le_audio::LeAudioSourceTransport::interface->UpdateAudioConfig_2_2( - hidl::le_audio::offload_config_to_hal_audio_config(offload_config)); return; } + + if (aidl::le_audio::LeAudioSourceTransport::interface->GetTransportInstance() + ->GetSessionType() != + aidl::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) { + return; + } + aidl::le_audio::LeAudioSourceTransport::interface->UpdateAudioConfig( + aidl::le_audio::offload_config_to_hal_audio_config(offload_config)); } size_t LeAudioClientInterface::Source::Write(const uint8_t* p_buf, @@ -478,11 +429,6 @@ LeAudioClientInterface::Sink* LeAudioClientInterface::GetSink( BluetoothAudioHalTransport::HIDL) { hidl::SessionType_2_1 session_type = hidl::SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH; - if (CodecManager::GetInstance()->GetCodecLocation() != - CodecLocation::HOST) { - session_type = - hidl::SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH; - } hidl::le_audio::LeAudioSinkTransport::instance = new hidl::le_audio::LeAudioSinkTransport(session_type, diff --git a/system/binder/Android.bp b/system/binder/Android.bp index 0445ea0c00..36802546c5 100644 --- a/system/binder/Android.bp +++ b/system/binder/Android.bp @@ -110,6 +110,7 @@ filegroup { "android/bluetooth/IBluetoothHeadset.aidl", "android/bluetooth/IBluetoothHearingAid.aidl", "android/bluetooth/IBluetoothHapClient.aidl", + "android/bluetooth/IBluetoothHapClientCallback.aidl", "android/bluetooth/IBluetoothVolumeControl.aidl", "android/bluetooth/IBluetoothHidHost.aidl", "android/bluetooth/IBluetoothLeAudio.aidl", diff --git a/system/binder/android/bluetooth/IBluetoothHapClient.aidl b/system/binder/android/bluetooth/IBluetoothHapClient.aidl index 672ab409c6..ee956c3210 100644 --- a/system/binder/android/bluetooth/IBluetoothHapClient.aidl +++ b/system/binder/android/bluetooth/IBluetoothHapClient.aidl @@ -18,6 +18,7 @@ package android.bluetooth; import android.bluetooth.BluetoothDevice; +import android.bluetooth.IBluetoothHapClientCallback; import android.content.AttributionSource; import com.android.modules.utils.SynchronousResultReceiver; @@ -30,10 +31,6 @@ import com.android.modules.utils.SynchronousResultReceiver; oneway interface IBluetoothHapClient { // Public API @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") - void connect(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") - void disconnect(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") void getConnectedDevices(in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") void getDevicesMatchingConnectionStates(in int[] states, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @@ -43,55 +40,46 @@ oneway interface IBluetoothHapClient { void setConnectionPolicy(in BluetoothDevice device, int connectionPolicy, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") void getConnectionPolicy(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") void getHapGroup(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") void getActivePresetIndex(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") + void getActivePresetInfo(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") - void selectActivePreset(in BluetoothDevice device, int presetIndex, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); + oneway void selectPreset(in BluetoothDevice device, int presetIndex, in AttributionSource attributionSource); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") - void groupSelectActivePreset(int groupId, int presetIndex, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); + oneway void selectPresetForGroup(int groupId, int presetIndex, in AttributionSource attributionSource); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") - void nextActivePreset(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); + oneway void switchToNextPreset(in BluetoothDevice device, in AttributionSource attributionSource); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") - void groupNextActivePreset(int groupId, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); + oneway void switchToNextPresetForGroup(int groupId, in AttributionSource attributionSource); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") - void previousActivePreset(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); + oneway void switchToPreviousPreset(in BluetoothDevice device, in AttributionSource attributionSource); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") - void groupPreviousActivePreset(int groupId, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); + oneway void switchToPreviousPresetForGroup(int groupId, in AttributionSource attributionSource); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") void getPresetInfo(in BluetoothDevice device, int presetIndex, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") - void getAllPresetsInfo(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); + void getAllPresetInfo(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") void getFeatures(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") - void setPresetName(in BluetoothDevice device, int presetIndex, in String name, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); + oneway void setPresetName(in BluetoothDevice device, int presetIndex, in String name, in AttributionSource attributionSource); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") - void groupSetPresetName(int groupId, int presetIndex, in String name, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); + oneway void setPresetNameForGroup(int groupId, int presetIndex, in String name, in AttributionSource attributionSource); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") + void registerCallback(in IBluetoothHapClientCallback callback, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") + void unregisterCallback(in IBluetoothHapClientCallback callback, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); const int PRESET_INDEX_UNAVAILABLE = 0; const int GROUP_ID_UNAVAILABLE = -1; - const int STATUS_SET_NAME_NOT_ALLOWED = 1; - const int STATUS_OPERATION_NOT_SUPPORTED = 2; - const int STATUS_OPERATION_NOT_POSSIBLE = 3; - const int STATUS_INVALID_PRESET_NAME_LENGTH = 4; - const int STATUS_INVALID_PRESET_INDEX = 5; - const int STATUS_GROUP_OPERATION_NOT_SUPPORTED = 6; - const int STATUS_PROCEDURE_ALREADY_IN_PROGRESS = 7; - const int FEATURE_BIT_NUM_TYPE_MONAURAL = 0; const int FEATURE_BIT_NUM_TYPE_BANDED = 1; const int FEATURE_BIT_NUM_SYNCHRONIZATED_PRESETS = 2; const int FEATURE_BIT_NUM_INDEPENDENT_PRESETS = 3; const int FEATURE_BIT_NUM_DYNAMIC_PRESETS = 4; const int FEATURE_BIT_NUM_WRITABLE_PRESETS = 5; - - const int PRESET_INFO_REASON_ALL_PRESET_INFO = 0; - const int PRESET_INFO_REASON_PRESET_INFO_UPDATE = 1; - const int PRESET_INFO_REASON_PRESET_DELETED = 2; - const int PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED = 3; - const int PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE = 4; } diff --git a/system/binder/android/bluetooth/IBluetoothHapClientCallback.aidl b/system/binder/android/bluetooth/IBluetoothHapClientCallback.aidl new file mode 100644 index 0000000000..5e2d8fa30b --- /dev/null +++ b/system/binder/android/bluetooth/IBluetoothHapClientCallback.aidl @@ -0,0 +1,39 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth; + +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothHapPresetInfo; + +import java.util.List; + +/** + * Callback definitions for interacting with HAP Client service + * + * @hide + */ +oneway interface IBluetoothHapClientCallback { + void onActivePresetChanged(in BluetoothDevice device, in int presetIndex); + void onSelectActivePresetFailed(in BluetoothDevice device, in int statusCode); + void onSelectActivePresetForGroupFailed(in int hapGroupId, in int statusCode); + void onPresetInfoChanged(in BluetoothDevice device, + in List<BluetoothHapPresetInfo> presetInfoList, + in int statusCode); + void onHapFeaturesAvailable(in BluetoothDevice device, in int hapFeatures); + void onSetPresetNameFailed(in BluetoothDevice device, in int status); + void onSetPresetNameForGroupFailed(in int hapGroupId, in int status); +} diff --git a/system/binder/android/bluetooth/IBluetoothHearingAid.aidl b/system/binder/android/bluetooth/IBluetoothHearingAid.aidl index cb74ffaa5e..92d74f2e79 100644 --- a/system/binder/android/bluetooth/IBluetoothHearingAid.aidl +++ b/system/binder/android/bluetooth/IBluetoothHearingAid.aidl @@ -46,7 +46,7 @@ oneway interface IBluetoothHearingAid { void setConnectionPolicy(in BluetoothDevice device, int connectionPolicy, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") void getConnectionPolicy(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") void setVolume(int volume, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") diff --git a/system/blueberry/facade/topshim/facade.proto b/system/blueberry/facade/topshim/facade.proto index 0414b77b44..9a8679c525 100644 --- a/system/blueberry/facade/topshim/facade.proto +++ b/system/blueberry/facade/topshim/facade.proto @@ -1,11 +1,14 @@ syntax = "proto3"; +import "google/protobuf/empty.proto"; + package blueberry.facade.topshim; service AdapterService { rpc FetchEvents(FetchEventsRequest) returns (stream FetchEventsResponse) {} rpc ToggleStack(ToggleStackRequest) returns (ToggleStackResponse) {} rpc SetDiscoveryMode(SetDiscoveryModeRequest) returns (SetDiscoveryModeResponse) {} + rpc ClearEventFilter(google.protobuf.Empty) returns (google.protobuf.Empty) {} } enum EventType { diff --git a/system/blueberry/tests/gd/cert/gd_device.py b/system/blueberry/tests/gd/cert/gd_device.py index 4042e536e8..4674905842 100644 --- a/system/blueberry/tests/gd/cert/gd_device.py +++ b/system/blueberry/tests/gd/cert/gd_device.py @@ -15,6 +15,7 @@ # limitations under the License. from abc import ABC +from abc import abstractmethod from datetime import datetime import inspect import logging @@ -22,7 +23,6 @@ import os import pathlib import shutil import signal -import socket import subprocess import time from typing import List @@ -141,6 +141,8 @@ class GdDeviceBase(ABC): """ WAIT_CHANNEL_READY_TIMEOUT_SECONDS = 10 + WAIT_SIGINT_TIMEOUT_SECONDS = 5 + WAIT_SIGKILL_TIMEOUT_SECONDS = 1 def __init__(self, grpc_port: str, grpc_root_server_port: str, signal_port: str, cmd: List[str], label: str, type_identifier: str, name: str, verbose_mode: bool): @@ -279,16 +281,17 @@ class GdDeviceBase(ABC): self.grpc_channel.close() if self.grpc_root_server_port != -1: self.grpc_root_server_channel.close() - stop_signal = signal.SIGINT - self.backing_process.send_signal(stop_signal) + stop_signal = self.gracefully_stop_backing_process() try: - return_code = self.backing_process.wait(timeout=self.WAIT_CHANNEL_READY_TIMEOUT_SECONDS) - except subprocess.TimeoutExpired: + if stop_signal == 0: + raise RuntimeError("Failed to gracefully shutdown backing process") + return_code = self.backing_process.wait(timeout=self.WAIT_SIGINT_TIMEOUT_SECONDS) + except (subprocess.TimeoutExpired, RuntimeError): logging.error("[%s] Failed to interrupt backing process via SIGINT, sending SIGKILL" % self.label) stop_signal = signal.SIGKILL self.backing_process.kill() try: - return_code = self.backing_process.wait(timeout=self.WAIT_CHANNEL_READY_TIMEOUT_SECONDS) + return_code = self.backing_process.wait(timeout=self.WAIT_SIGKILL_TIMEOUT_SECONDS) except subprocess.TimeoutExpired: logging.error("Failed to kill backing process") return_code = -65536 @@ -303,6 +306,10 @@ class GdDeviceBase(ABC): except grpc.FutureTimeoutError: asserts.fail("[%s] wait channel ready timeout" % self.label) + @abstractmethod + def gracefully_stop_backing_process(self): + return NotImplemented + class GdHostOnlyDevice(GdDeviceBase): """ @@ -443,12 +450,19 @@ class GdHostOnlyDevice(GdDeviceBase): logging.warning("[%s] Failed to generated coverage summary, cmd result: %r" % (label, result)) coverage_summary_path.unlink(missing_ok=True) + def gracefully_stop_backing_process(self): + stop_signal = signal.SIGINT + self.backing_process.send_signal(stop_signal) + return stop_signal + class GdAndroidDevice(GdDeviceBase): """Real Android device where the backing process is running on it """ WAIT_FOR_DEVICE_TIMEOUT_SECONDS = 180 + WAIT_FOR_DEVICE_SIGINT_TIMEOUT_SECONDS = 1 + ADB_ABORT_EXIT_CODE = 134 def __init__(self, grpc_port: str, grpc_root_server_port: str, signal_port: str, cmd: List[str], label: str, type_identifier: str, name: str, serial_number: str, verbose_mode: bool): @@ -542,14 +556,14 @@ class GdAndroidDevice(GdDeviceBase): stop_signal = signal.SIGINT self.logcat_process.send_signal(stop_signal) try: - return_code = self.logcat_process.wait(timeout=self.WAIT_CHANNEL_READY_TIMEOUT_SECONDS) + return_code = self.logcat_process.wait(timeout=self.WAIT_FOR_DEVICE_SIGINT_TIMEOUT_SECONDS) except subprocess.TimeoutExpired: logging.error("[%s_%s] Failed to interrupt logcat process via SIGINT, sending SIGKILL" % (self.label, self.serial_number)) stop_signal = signal.SIGKILL self.logcat_process.kill() try: - return_code = self.logcat_process.wait(timeout=self.WAIT_CHANNEL_READY_TIMEOUT_SECONDS) + return_code = self.logcat_process.wait(timeout=self.WAIT_SIGKILL_TIMEOUT_SECONDS) except subprocess.TimeoutExpired: logging.error("Failed to kill logcat_process %s %s" % (self.label, self.serial_number)) return_code = -65536 @@ -557,29 +571,30 @@ class GdAndroidDevice(GdDeviceBase): logging.error("logcat_process %s_%s stopped with code: %d" % (self.label, self.serial_number, return_code)) self.logcat_logger.stop() self.cleanup_port_forwarding() + self.pull_logs(self.log_path_base) + + def pull_logs(self, base_dir): try: self.adb.pull([ "/data/misc/bluetooth/logs/btsnoop_hci.log", - str(os.path.join(self.log_path_base, "%s_btsnoop_hci.log" % self.label)) + str(os.path.join(base_dir, "%s_btsnoop_hci.log" % self.label)) ]) except AdbError as error: # Some tests have no snoop logs, and that's OK if ADB_FILE_NOT_EXIST_ERROR not in str(error): logging.error(PULL_LOG_FILE_ERROR_MSG_PREFIX + str(error)) try: - self.adb.pull([ - "/data/misc/bluedroid/bt_config.conf", - str(os.path.join(self.log_path_base, "%s_bt_config.conf" % self.label)) - ]) + self.adb.pull( + ["/data/misc/bluedroid/bt_config.conf", + str(os.path.join(base_dir, "%s_bt_config.conf" % self.label))]) except AdbError as error: # Some tests have no config file, and that's OK if ADB_FILE_NOT_EXIST_ERROR not in str(error): logging.error(PULL_LOG_FILE_ERROR_MSG_PREFIX + str(error)) try: - self.adb.pull([ - "/data/misc/bluedroid/bt_config.bak", - str(os.path.join(self.log_path_base, "%s_bt_config.bak" % self.label)) - ]) + self.adb.pull( + ["/data/misc/bluedroid/bt_config.bak", + str(os.path.join(base_dir, "%s_bt_config.bak" % self.label))]) except AdbError as error: # Some tests have no config.bak file, and that's OK if ADB_FILE_NOT_EXIST_ERROR not in str(error): @@ -787,3 +802,44 @@ class GdAndroidDevice(GdDeviceBase): pass time.sleep(5) asserts.fail(msg='Device %s booting process timed out.' % self.serial_number) + + def gracefully_stop_backing_process(self): + """ + Gracefully stops backing process + :return: expected backing process exit code on success, 0 on error + """ + backing_process_pid = None + # Since we do not know which segment of self.cmd is the command running + # on the Android device. We have to iterate with trial and error. + cmd = self.cmd + if len(self.cmd) >= 5: + # skip adb -s serial shell to speed up the search + # we don't know if any environment variables are set up before the + # actual command and hence has to try from the 4th argument + cmd = self.cmd[4:] + self.cmd[:4] + for segment in cmd: + try: + # pgrep only takes 16 bytes including null terminator + # -f cannot be used because that include the full command args + current_cmd = pathlib.Path(segment).stem[:15] + # -x matches whole command, cannot avoid as short segment may partially match + # -n returnes the newest command matched + backing_process_pid = int(self.adb.shell("pgrep -n -x {}".format(current_cmd))) + logging.debug("Found backing process name on Android as {}, pid is {}".format( + segment, backing_process_pid)) + except (AdbError, ValueError) as e: + logging.debug("Failed to run pgrep {}".format(e)) + if backing_process_pid is not None: + break + if backing_process_pid is None: + logging.warning("Failed to get pid for cmd {}".format(self.cmd)) + try: + logging.debug(self.adb.shell("ps -A | grep bluetooth")) + except AdbError: + pass + return 0 + stop_signal = signal.SIGINT + self.adb.shell("kill -{} {}".format(stop_signal, backing_process_pid)) + logging.debug("Sent SIGINT to backing process at pid {}".format(backing_process_pid)) + stop_signal = -self.ADB_ABORT_EXIT_CODE + return stop_signal diff --git a/system/blueberry/tests/gd/rust/topshim/facade/automation_helper.py b/system/blueberry/tests/gd/rust/topshim/facade/automation_helper.py index 224dffb32a..63e72c58c4 100644 --- a/system/blueberry/tests/gd/rust/topshim/facade/automation_helper.py +++ b/system/blueberry/tests/gd/rust/topshim/facade/automation_helper.py @@ -20,6 +20,8 @@ import grpc from blueberry.facade.topshim import facade_pb2 from blueberry.facade.topshim import facade_pb2_grpc +from google.protobuf import empty_pb2 as empty_proto + class AdapterAutomationHelper(): # Timeout for async wait @@ -60,6 +62,9 @@ class AdapterAutomationHelper(): async def verify_adapter_started(self): await asyncio.wait_for(self.pending_future, AdapterAutomationHelper.DEFAULT_TIMEOUT) + async def clear_event_filter(self): + await self.adapter_stub.ClearEventFilter(empty_proto.Empty()) + class A2dpAutomationHelper(): """Invoke gRPC on topshim for A2DP testing""" diff --git a/system/blueberry/tests/gd/rust/topshim/facade/suspend_test.py b/system/blueberry/tests/gd/rust/topshim/facade/suspend_test.py new file mode 100644 index 0000000000..d6885bdf31 --- /dev/null +++ b/system/blueberry/tests/gd/rust/topshim/facade/suspend_test.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +# +# Copyright 2021 - 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. + +import asyncio +from mobly import test_runner +from blueberry.tests.gd.rust.topshim.facade import topshim_base_test +from blueberry.tests.gd.rust.topshim.facade.automation_helper import AdapterAutomationHelper +import time + + +class SuspendTest(topshim_base_test.TopshimBaseTest): + + async def _test_verify_event_filter_cleared(self): + self.dut_adapter = AdapterAutomationHelper(port=self.dut_port) + event_loop = asyncio.get_running_loop() + self.dut_adapter.fetch_events(event_loop) + self.dut_adapter.pending_future = event_loop.create_future() + await self.dut_adapter.clear_event_filter() + #TODO(optedoblivion): Replace sleep with a call to LeGetRandom and synchronize on + # the callback + time.sleep(1) + self.dut_adapter.event_handler.cancel() + + def test_verify_event_filter_cleared(self): + asyncio.run(self._test_verify_event_filter_cleared()) + + +if __name__ == "__main__": + test_runner.main() diff --git a/system/blueberry/tests/gd_sl4a/gd_sl4a_device_config.yaml b/system/blueberry/tests/gd_sl4a/gd_sl4a_device_config.yaml new file mode 100644 index 0000000000..19829b8f72 --- /dev/null +++ b/system/blueberry/tests/gd_sl4a/gd_sl4a_device_config.yaml @@ -0,0 +1,35 @@ +_description: Bluetooth cert testing with SL4A +TestBeds: + - Name: AndroidDeviceCert + Controllers: + GdDevice: + - grpc_port: '8898' + grpc_root_server_port: '8896' + signal_port: '8894' + label: cert + serial_number: 'CERT' + name: Cert Device + cmd: + - "adb" + - "-s" + - "$(serial_number)" + - "shell" + - "ASAN_OPTIONS=detect_container_overflow=0" + - "/system/bin/bluetooth_stack_with_facade" + - "--grpc-port=$(grpc_port)" + - "--root-server-port=$(grpc_root_server_port)" + - "--btsnoop=/data/misc/bluetooth/logs/btsnoop_hci.log" + - "--btsnooz=/data/misc/bluetooth/logs/btsnooz_hci.log" + - "--btconfig=/data/misc/bluedroid/bt_config.conf" + - "--signal-port=$(signal_port)" + AndroidDevice: + - label: dut + # Preferred client port number on the PC host side for SL4A + client_port: '8895' + # Preferred server port number forwarded from Android to the host PC + # via adb for SL4A connections + forwarded_port: '8899' + # Preferred server port used by SL4A on Android device + server_port: '8899' + serial: 'DUT' +logpath: "/tmp/logs"
\ No newline at end of file diff --git a/system/blueberry/tests/gd_sl4a/gd_sl4a_test_runner.py b/system/blueberry/tests/gd_sl4a/gd_sl4a_test_runner.py new file mode 100644 index 0000000000..2aab47f39e --- /dev/null +++ b/system/blueberry/tests/gd_sl4a/gd_sl4a_test_runner.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +# +# Copyright 2021 - 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. + +from blueberry.tests.gd_sl4a.hci.le_advanced_scanning_test import LeAdvancedScanningTest + +from mobly import suite_runner +import argparse + +ALL_TESTS = [LeAdvancedScanningTest] + + +def main(): + """ + Local test runner that allows to specify list of tests to and customize + test config file location + """ + parser = argparse.ArgumentParser(description="Run local GD SL4A tests.") + parser.add_argument( + '-c', '--config', type=str, required=True, metavar='<PATH>', help='Path to the test configuration file.') + parser.add_argument( + '--tests', + '--test_case', + nargs='+', + type=str, + metavar='[ClassA[.test_a] ClassB[.test_b] ...]', + help='A list of test classes and optional tests to execute.') + parser.add_argument("--all_tests", "-A", type=bool, dest="all_tests", default=False, nargs="?") + parser.add_argument("--presubmit", type=bool, dest="presubmit", default=False, nargs="?") + parser.add_argument("--postsubmit", type=bool, dest="postsubmit", default=False, nargs="?") + args = parser.parse_args() + test_list = ALL_TESTS + if args.all_tests: + test_list = ALL_TESTS + elif args.presubmit: + test_list = ALL_TESTS + elif args.postsubmit: + test_list = ALL_TESTS + # Do not pass this layer's cmd line argument to next layer + argv = ["--config", args.config] + if args.tests: + argv.append("--tests") + for test in args.tests: + argv.append(test) + + suite_runner.run_suite(test_list, argv=argv) + + +if __name__ == "__main__": + main() diff --git a/system/blueberry/tests/gd_sl4a/hci/le_advanced_scanning_test.py b/system/blueberry/tests/gd_sl4a/hci/le_advanced_scanning_test.py new file mode 100644 index 0000000000..ed22e1a8e5 --- /dev/null +++ b/system/blueberry/tests/gd_sl4a/hci/le_advanced_scanning_test.py @@ -0,0 +1,249 @@ +#!/usr/bin/env python3 +# +# Copyright 2021 - 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. + +import queue +import logging + +from google.protobuf import empty_pb2 as empty_proto + +from bluetooth_packets_python3 import hci_packets +from blueberry.tests.gd_sl4a.lib.bt_constants import ble_scan_settings_modes, ble_address_types, scan_result, ble_scan_settings_phys +from blueberry.tests.gd_sl4a.lib.ble_lib import generate_ble_scan_objects +from blueberry.tests.gd_sl4a.lib.gd_sl4a_base_test import GdSl4aBaseTestClass +from blueberry.facade.hci import le_advertising_manager_facade_pb2 as le_advertising_facade +from blueberry.facade.hci import le_initiator_address_facade_pb2 as le_initiator_address_facade +from blueberry.facade import common_pb2 as common + + +class LeAdvancedScanningTest(GdSl4aBaseTestClass): + + def setup_class(self): + super().setup_class(cert_module='HCI_INTERFACES') + self.default_timeout = 10 # seconds + + def setup_test(self): + super().setup_test() + + def teardown_test(self): + super().teardown_test() + + def set_cert_privacy_policy_with_random_address(self, random_address): + private_policy = le_initiator_address_facade.PrivacyPolicy( + address_policy=le_initiator_address_facade.AddressPolicy.USE_STATIC_ADDRESS, + address_with_type=common.BluetoothAddressWithType( + address=common.BluetoothAddress(address=bytes(random_address, encoding='utf8')), + type=common.RANDOM_DEVICE_ADDRESS)) + self.cert.hci_le_initiator_address.SetPrivacyPolicyForInitiatorAddress(private_policy) + + def set_cert_privacy_policy_with_public_address(self): + public_address_bytes = self.cert.hci_controller.GetMacAddress(empty_proto.Empty()).address + private_policy = le_initiator_address_facade.PrivacyPolicy( + address_policy=le_initiator_address_facade.AddressPolicy.USE_PUBLIC_ADDRESS, + address_with_type=common.BluetoothAddressWithType( + address=common.BluetoothAddress(address=public_address_bytes), type=common.PUBLIC_DEVICE_ADDRESS)) + self.cert.hci_le_initiator_address.SetPrivacyPolicyForInitiatorAddress(private_policy) + # Bluetooth MAC address must be upper case + return public_address_bytes.decode('utf-8').upper() + + def test_scan_filter_device_name_legacy_pdu(self): + # Use public address on cert side + logging.info("Setting public address") + DEVICE_NAME = 'Im_The_CERT!' + public_address = self.set_cert_privacy_policy_with_public_address() + logging.info("Set public address") + + # Setup cert side to advertise + gap_name = hci_packets.GapData() + gap_name.data_type = hci_packets.GapDataType.COMPLETE_LOCAL_NAME + gap_name.data = list(bytes(DEVICE_NAME, encoding='utf8')) + gap_data = le_advertising_facade.GapDataMsg(data=bytes(gap_name.Serialize())) + config = le_advertising_facade.AdvertisingConfig( + advertisement=[gap_data], + interval_min=512, + interval_max=768, + advertising_type=le_advertising_facade.AdvertisingEventType.ADV_IND, + own_address_type=common.USE_PUBLIC_DEVICE_ADDRESS, + channel_map=7, + filter_policy=le_advertising_facade.AdvertisingFilterPolicy.ALL_DEVICES, + tx_power=20) + request = le_advertising_facade.CreateAdvertiserRequest(config=config) + logging.info("Creating advertiser") + create_response = self.cert.hci_le_advertising_manager.CreateAdvertiser(request) + logging.info("Created advertiser") + + # Setup SL4A DUT side to scan + logging.info("Start scanning with public address %s" % public_address) + self.dut.sl4a.bleSetScanSettingsScanMode(ble_scan_settings_modes['low_latency']) + filter_list, scan_settings, scan_callback = generate_ble_scan_objects(self.dut.sl4a) + expected_event_name = scan_result.format(scan_callback) + + # Setup SL4A DUT filter + self.dut.sl4a.bleSetScanFilterDeviceName(DEVICE_NAME) + self.dut.sl4a.bleBuildScanFilter(filter_list) + + # Start scanning on SL4A DUT side + self.dut.sl4a.bleStartBleScan(filter_list, scan_settings, scan_callback) + logging.info("Started scanning") + try: + # Verify if there is scan result + event_info = self.dut.ed.pop_event(expected_event_name, self.default_timeout) + except queue.Empty as error: + logging.error("Could not find initial advertisement.") + return False + # Print out scan result + mac_address = event_info['data']['Result']['deviceInfo']['address'] + logging.info("Filter advertisement with address {}".format(mac_address)) + + # Stop scanning + logging.info("Stop scanning") + self.dut.sl4a.bleStopBleScan(scan_callback) + logging.info("Stopped scanning") + + # Stop advertising + logging.info("Stop advertising") + remove_request = le_advertising_facade.RemoveAdvertiserRequest(advertiser_id=create_response.advertiser_id) + self.cert.hci_le_advertising_manager.RemoveAdvertiser(remove_request) + logging.info("Stopped advertising") + + return True + + def test_scan_filter_device_random_address_legacy_pdu(self): + # Use random address on cert side + logging.info("Setting random address") + RANDOM_ADDRESS = 'D0:05:04:03:02:01' + DEVICE_NAME = 'Im_The_CERT!' + self.set_cert_privacy_policy_with_random_address(RANDOM_ADDRESS) + logging.info("Set random address") + + # Setup cert side to advertise + gap_name = hci_packets.GapData() + gap_name.data_type = hci_packets.GapDataType.COMPLETE_LOCAL_NAME + gap_name.data = list(bytes(DEVICE_NAME, encoding='utf8')) + gap_data = le_advertising_facade.GapDataMsg(data=bytes(gap_name.Serialize())) + config = le_advertising_facade.AdvertisingConfig( + advertisement=[gap_data], + interval_min=512, + interval_max=768, + advertising_type=le_advertising_facade.AdvertisingEventType.ADV_IND, + own_address_type=common.USE_RANDOM_DEVICE_ADDRESS, + channel_map=7, + filter_policy=le_advertising_facade.AdvertisingFilterPolicy.ALL_DEVICES) + request = le_advertising_facade.CreateAdvertiserRequest(config=config) + logging.info("Creating advertiser") + create_response = self.cert.hci_le_advertising_manager.CreateAdvertiser(request) + logging.info("Created advertiser") + + # Setup SL4A DUT side to scan + addr_type = ble_address_types["random"] + logging.info("Start scanning for RANDOM_ADDRESS %s with address type %d" % (RANDOM_ADDRESS, addr_type)) + self.dut.sl4a.bleSetScanSettingsScanMode(ble_scan_settings_modes['low_latency']) + filter_list, scan_settings, scan_callback = generate_ble_scan_objects(self.dut.sl4a) + expected_event_name = scan_result.format(scan_callback) + + # Setup SL4A DUT filter + self.dut.sl4a.bleSetScanFilterDeviceAddressAndType(RANDOM_ADDRESS, int(addr_type)) + self.dut.sl4a.bleBuildScanFilter(filter_list) + + # Start scanning on SL4A DUT side + self.dut.sl4a.bleStartBleScan(filter_list, scan_settings, scan_callback) + logging.info("Started scanning") + try: + # Verify if there is scan result + event_info = self.dut.ed.pop_event(expected_event_name, self.default_timeout) + except queue.Empty as error: + logging.error("Could not find initial advertisement.") + return False + # Print out scan result + mac_address = event_info['data']['Result']['deviceInfo']['address'] + logging.info("Filter advertisement with address {}".format(mac_address)) + + # Stop scanning + logging.info("Stop scanning") + self.dut.sl4a.bleStopBleScan(scan_callback) + logging.info("Stopped scanning") + + # Stop advertising + logging.info("Stop advertising") + remove_request = le_advertising_facade.RemoveAdvertiserRequest(advertiser_id=create_response.advertiser_id) + self.cert.hci_le_advertising_manager.RemoveAdvertiser(remove_request) + logging.info("Stopped advertising") + + return True + + def test_scan_filter_device_public_address_extended_pdu(self): + # Use public address on cert side + logging.info("Setting public address") + DEVICE_NAME = 'Im_The_CERT!' + public_address = self.set_cert_privacy_policy_with_public_address() + logging.info("Set public address") + + # Setup cert side to advertise + gap_name = hci_packets.GapData() + gap_name.data_type = hci_packets.GapDataType.COMPLETE_LOCAL_NAME + gap_name.data = list(bytes(DEVICE_NAME, encoding='utf8')) + gap_data = le_advertising_facade.GapDataMsg(data=bytes(gap_name.Serialize())) + config = le_advertising_facade.AdvertisingConfig( + advertisement=[gap_data], + interval_min=512, + interval_max=768, + advertising_type=le_advertising_facade.AdvertisingEventType.ADV_IND, + own_address_type=common.USE_PUBLIC_DEVICE_ADDRESS, + channel_map=7, + filter_policy=le_advertising_facade.AdvertisingFilterPolicy.ALL_DEVICES) + extended_config = le_advertising_facade.ExtendedAdvertisingConfig( + advertising_config=config, secondary_advertising_phy=ble_scan_settings_phys["1m"]) + request = le_advertising_facade.ExtendedCreateAdvertiserRequest(config=extended_config) + logging.info("Creating advertiser") + create_response = self.cert.hci_le_advertising_manager.ExtendedCreateAdvertiser(request) + logging.info("Created advertiser") + + # Setup SL4A DUT side to scan + addr_type = ble_address_types["public"] + logging.info("Start scanning for PUBLIC_ADDRESS %s with address type %d" % (public_address, addr_type)) + self.dut.sl4a.bleSetScanSettingsScanMode(ble_scan_settings_modes['low_latency']) + self.dut.sl4a.bleSetScanSettingsLegacy(False) + filter_list, scan_settings, scan_callback = generate_ble_scan_objects(self.dut.sl4a) + expected_event_name = scan_result.format(scan_callback) + + # Setup SL4A DUT filter + self.dut.sl4a.bleSetScanFilterDeviceAddressAndType(public_address, int(addr_type)) + self.dut.sl4a.bleBuildScanFilter(filter_list) + + # Start scanning on SL4A DUT side + self.dut.sl4a.bleStartBleScan(filter_list, scan_settings, scan_callback) + logging.info("Started scanning") + try: + # Verify if there is scan result + event_info = self.dut.ed.pop_event(expected_event_name, self.default_timeout) + except queue.Empty as error: + logging.error("Could not find initial advertisement.") + return False + # Print out scan result + mac_address = event_info['data']['Result']['deviceInfo']['address'] + logging.info("Filter advertisement with address {}".format(mac_address)) + + # Stop scanning + logging.info("Stop scanning") + self.dut.sl4a.bleStopBleScan(scan_callback) + logging.info("Stopped scanning") + + # Stop advertising + logging.info("Stop advertising") + remove_request = le_advertising_facade.RemoveAdvertiserRequest(advertiser_id=create_response.advertiser_id) + self.cert.hci_le_advertising_manager.RemoveAdvertiser(remove_request) + logging.info("Stopped advertising") + + return True diff --git a/system/blueberry/tests/gd_sl4a/lib/ble_lib.py b/system/blueberry/tests/gd_sl4a/lib/ble_lib.py new file mode 100644 index 0000000000..93b3eaece2 --- /dev/null +++ b/system/blueberry/tests/gd_sl4a/lib/ble_lib.py @@ -0,0 +1,259 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2016 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +""" +Ble libraries +""" + +import time +import queue +import logging + +from blueberry.tests.gd_sl4a.lib.bt_constants import ble_advertise_settings_modes +from blueberry.tests.gd_sl4a.lib.bt_constants import small_timeout +from blueberry.tests.gd_sl4a.lib.bt_constants import adv_fail +from blueberry.tests.gd_sl4a.lib.bt_constants import adv_succ +from blueberry.tests.gd_sl4a.lib.bt_constants import advertising_set_on_own_address_read +from blueberry.tests.gd_sl4a.lib.bt_constants import advertising_set_started +from blueberry.tests.gd_sl4a.lib.bt_constants import bluetooth_on +from blueberry.tests.gd_sl4a.lib.bt_constants import bluetooth_off +from blueberry.tests.gd_sl4a.lib.bt_constants import bt_default_timeout + + +def enable_bluetooth(sl4a, ed): + if sl4a.bluetoothCheckState(): + return True + + sl4a.bluetoothToggleState(True) + expected_bluetooth_on_event_name = bluetooth_on + try: + ed.pop_event(expected_bluetooth_on_event_name, bt_default_timeout) + except Exception: + logging.info("Failed to toggle Bluetooth on (no broadcast received)") + if sl4a.bluetoothCheckState(): + logging.info(".. actual state is ON") + return True + logging.info(".. actual state is OFF") + return False + + return True + + +def disable_bluetooth(sl4a, ed): + if not sl4a.bluetoothCheckState(): + return True + sl4a.bluetoothToggleState(False) + expected_bluetooth_off_event_name = bluetooth_off + try: + ed.pop_event(expected_bluetooth_off_event_name, bt_default_timeout) + except Exception: + logging.info("Failed to toggle Bluetooth off (no broadcast received)") + if sl4a.bluetoothCheckState(): + logging.info(".. actual state is ON") + return False + logging.info(".. actual state is OFF") + return True + return True + + +def generate_ble_scan_objects(sl4a): + """Generate generic LE scan objects. + + Args: + sl4a: The SL4A object to generate LE scan objects from. + + Returns: + filter_list: The generated scan filter list id. + scan_settings: The generated scan settings id. + scan_callback: The generated scan callback id. + """ + filter_list = sl4a.bleGenFilterList() + scan_settings = sl4a.bleBuildScanSetting() + scan_callback = sl4a.bleGenScanCallback() + return filter_list, scan_settings, scan_callback + + +def generate_ble_advertise_objects(sl4a): + """Generate generic LE advertise objects. + + Args: + sl4a: The SL4A object to generate advertise LE objects from. + + Returns: + advertise_callback: The generated advertise callback id. + advertise_data: The generated advertise data id. + advertise_settings: The generated advertise settings id. + """ + advertise_callback = sl4a.bleGenBleAdvertiseCallback() + advertise_data = sl4a.bleBuildAdvertiseData() + advertise_settings = sl4a.bleBuildAdvertiseSettings() + return advertise_callback, advertise_data, advertise_settings + + +class BleLib(): + + def __init__(self, dut): + self.advertisement_list = [] + self.dut = dut + self.default_timeout = 5 + self.set_advertisement_list = [] + self.generic_uuid = "0000{}-0000-1000-8000-00805f9b34fb" + + def _verify_ble_adv_started(self, advertise_callback): + """Helper for verifying if an advertisment started or not""" + regex = "({}|{})".format(adv_succ.format(advertise_callback), adv_fail.format(advertise_callback)) + try: + event = self.dut.ed.pop_events(regex, 5, small_timeout) + except queue.Empty: + logging.error("Failed to get success or failed event.") + return + if event[0]["name"] == adv_succ.format(advertise_callback): + logging.info("Advertisement started successfully.") + return True + else: + logging.info("Advertisement failed to start.") + return False + + def start_generic_connectable_advertisement(self, line): + """Start a connectable LE advertisement""" + scan_response = None + if line: + scan_response = bool(line) + self.dut.sl4a.bleSetAdvertiseSettingsAdvertiseMode(ble_advertise_settings_modes['low_latency']) + self.dut.sl4a.bleSetAdvertiseSettingsIsConnectable(True) + advertise_callback, advertise_data, advertise_settings = (generate_ble_advertise_objects(self.dut.sl4a)) + if scan_response: + self.dut.sl4a.bleStartBleAdvertisingWithScanResponse(advertise_callback, advertise_data, advertise_settings, + advertise_data) + else: + self.dut.sl4a.bleStartBleAdvertising(advertise_callback, advertise_data, advertise_settings) + if self._verify_ble_adv_started(advertise_callback): + logging.info("Tracking Callback ID: {}".format(advertise_callback)) + self.advertisement_list.append(advertise_callback) + logging.info(self.advertisement_list) + + def start_connectable_advertisement_set(self, line): + """Start Connectable Advertisement Set""" + adv_callback = self.dut.sl4a.bleAdvSetGenCallback() + adv_data = { + "includeDeviceName": True, + } + self.dut.sl4a.bleAdvSetStartAdvertisingSet({ + "connectable": True, + "legacyMode": False, + "primaryPhy": "PHY_LE_1M", + "secondaryPhy": "PHY_LE_1M", + "interval": 320 + }, adv_data, None, None, None, 0, 0, adv_callback) + evt = self.dut.ed.pop_event(advertising_set_started.format(adv_callback), self.default_timeout) + set_id = evt['data']['setId'] + logging.error("did not receive the set started event!") + evt = self.dut.ed.pop_event(advertising_set_on_own_address_read.format(set_id), self.default_timeout) + address = evt['data']['address'] + logging.info("Advertiser address is: {}".format(str(address))) + self.set_advertisement_list.append(adv_callback) + + def stop_all_advertisement_set(self, line): + """Stop all Advertisement Sets""" + for adv in self.set_advertisement_list: + try: + self.dut.sl4a.bleAdvSetStopAdvertisingSet(adv) + except Exception as err: + logging.error("Failed to stop advertisement: {}".format(err)) + + def adv_add_service_uuid_list(self, line): + """Add service UUID to the LE advertisement inputs: + [uuid1 uuid2 ... uuidN]""" + uuids = line.split() + uuid_list = [] + for uuid in uuids: + if len(uuid) == 4: + uuid = self.generic_uuid.format(line) + uuid_list.append(uuid) + self.dut.sl4a.bleSetAdvertiseDataSetServiceUuids(uuid_list) + + def adv_data_include_local_name(self, is_included): + """Include local name in the advertisement. inputs: [true|false]""" + self.dut.sl4a.bleSetAdvertiseDataIncludeDeviceName(bool(is_included)) + + def adv_data_include_tx_power_level(self, is_included): + """Include tx power level in the advertisement. inputs: [true|false]""" + self.dut.sl4a.bleSetAdvertiseDataIncludeTxPowerLevel(bool(is_included)) + + def adv_data_add_manufacturer_data(self, line): + """Include manufacturer id and data to the advertisment: + [id data1 data2 ... dataN]""" + info = line.split() + manu_id = int(info[0]) + manu_data = [] + for data in info[1:]: + manu_data.append(int(data)) + self.dut.sl4a.bleAddAdvertiseDataManufacturerId(manu_id, manu_data) + + def start_generic_nonconnectable_advertisement(self, line): + """Start a nonconnectable LE advertisement""" + self.dut.sl4a.bleSetAdvertiseSettingsAdvertiseMode(ble_advertise_settings_modes['low_latency']) + self.dut.sl4a.bleSetAdvertiseSettingsIsConnectable(False) + advertise_callback, advertise_data, advertise_settings = (generate_ble_advertise_objects(self.dut.sl4a)) + self.dut.sl4a.bleStartBleAdvertising(advertise_callback, advertise_data, advertise_settings) + if self._verify_ble_adv_started(advertise_callback): + logging.info("Tracking Callback ID: {}".format(advertise_callback)) + self.advertisement_list.append(advertise_callback) + logging.info(self.advertisement_list) + + def stop_all_advertisements(self, line): + """Stop all LE advertisements""" + for callback_id in self.advertisement_list: + logging.info("Stopping Advertisement {}".format(callback_id)) + self.dut.sl4a.bleStopBleAdvertising(callback_id) + time.sleep(1) + self.advertisement_list = [] + + def ble_stop_advertisement(self, callback_id): + """Stop an LE advertisement""" + if not callback_id: + logging.info("Need a callback ID") + return + callback_id = int(callback_id) + if callback_id not in self.advertisement_list: + logging.info("Callback not in list of advertisements.") + return + self.dut.sl4a.bleStopBleAdvertising(callback_id) + self.advertisement_list.remove(callback_id) + + def start_max_advertisements(self, line): + scan_response = None + if line: + scan_response = bool(line) + while (True): + try: + self.dut.sl4a.bleSetAdvertiseSettingsAdvertiseMode(ble_advertise_settings_modes['low_latency']) + self.dut.sl4a.bleSetAdvertiseSettingsIsConnectable(True) + advertise_callback, advertise_data, advertise_settings = (generate_ble_advertise_objects(self.dut.sl4a)) + if scan_response: + self.dut.sl4a.bleStartBleAdvertisingWithScanResponse(advertise_callback, advertise_data, + advertise_settings, advertise_data) + else: + self.dut.sl4a.bleStartBleAdvertising(advertise_callback, advertise_data, advertise_settings) + if self._verify_ble_adv_started(advertise_callback): + logging.info("Tracking Callback ID: {}".format(advertise_callback)) + self.advertisement_list.append(advertise_callback) + logging.info(self.advertisement_list) + else: + logging.info("Advertisements active: {}".format(len(self.advertisement_list))) + return False + except Exception as err: + logging.info("Advertisements active: {}".format(len(self.advertisement_list))) + return True diff --git a/system/blueberry/tests/gd_sl4a/lib/bt_constants.py b/system/blueberry/tests/gd_sl4a/lib/bt_constants.py new file mode 100644 index 0000000000..f144ef57f5 --- /dev/null +++ b/system/blueberry/tests/gd_sl4a/lib/bt_constants.py @@ -0,0 +1,740 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2016 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +### Generic Constants Begin ### + +bt_default_timeout = 15 +default_rfcomm_timeout_ms = 10000 +default_bluetooth_socket_timeout_ms = 10000 +pan_connect_timeout = 5 +bt_discovery_timeout = 3 +small_timeout = 0.0001 + +# Time delay (in seconds) at the end of each LE CoC Test to give sufficient time +# for the ACL LE link to be disconnected. The ACL link stays connected after +# L2CAP disconnects. An example of the timeout is L2CAP_LINK_INACTIVITY_TOUT. +# This delay must be greater than the maximum of these timeouts. +# TODO: Investigate the use of broadcast intent +# BluetoothDevice.ACTION_ACL_DISCONNECTED to replace this delay method. +l2cap_max_inactivity_delay_after_disconnect = 5 + +# LE specifications related constants +le_connection_interval_time_step_ms = 1.25 +le_default_supervision_timeout = 2000 +default_le_data_length = 23 +default_le_connection_interval_ms = 30 +le_connection_event_time_step_ms = 0.625 + +# Headers of LE L2CAP Connection-oriented Channels. See section 3.4, Vol +# 3, Part A, Version 5.0. +l2cap_header_size = 4 +l2cap_coc_sdu_length_field_size = 2 +l2cap_coc_header_size = l2cap_header_size + l2cap_coc_sdu_length_field_size + +java_integer = {"min": -2147483648, "max": 2147483647} + +btsnoop_log_path_on_device = "/data/misc/bluetooth/logs/btsnoop_hci.log" +btsnoop_last_log_path_on_device = \ + "/data/misc/bluetooth/logs/btsnoop_hci.log.last" +pairing_variant_passkey_confirmation = 2 + +# Callback strings +scan_result = "BleScan{}onScanResults" +scan_failed = "BleScan{}onScanFailed" +batch_scan_result = "BleScan{}onBatchScanResult" +adv_fail = "BleAdvertise{}onFailure" +adv_succ = "BleAdvertise{}onSuccess" +bluetooth_off = "BluetoothStateChangedOff" +bluetooth_on = "BluetoothStateChangedOn" +mtu_changed = "GattConnect{}onMtuChanged" +advertising_set_started = "AdvertisingSet{}onAdvertisingSetStarted" +advertising_set_stopped = "AdvertisingSet{}onAdvertisingSetStopped" +advertising_set_on_own_address_read = "AdvertisingSet{}onOwnAddressRead" +advertising_set_enabled = "AdvertisingSet{}onAdvertisingEnabled" +advertising_set_data_set = "AdvertisingSet{}onAdvertisingDataSet" +advertising_set_scan_response_set = "AdvertisingSet{}onScanResponseDataSet" +advertising_set_parameters_update = \ + "AdvertisingSet{}onAdvertisingParametersUpdated" +advertising_set_periodic_parameters_updated = \ + "AdvertisingSet{}onPeriodicAdvertisingParametersUpdated" +advertising_set_periodic_data_set = \ + "AdvertisingSet{}onPeriodicAdvertisingDataSet" +advertising_set_periodic_enable = "AdvertisingSet{}onPeriodicAdvertisingEnable" +bluetooth_profile_connection_state_changed = \ + "BluetoothProfileConnectionStateChanged" +bluetooth_le_on = "BleStateChangedOn" +bluetooth_le_off = "BleStateChangedOff" +bluetooth_a2dp_codec_config_changed = "BluetoothA2dpCodecConfigChanged" +# End Callback Strings + +batch_scan_not_supported_list = [ + "Nexus 4", + "Nexus 5", + "Nexus 7", +] + +### Generic Constants End ### + +### Bluetooth Constants Begin ### + +# rfcomm test uuids +rfcomm_secure_uuid = "fa87c0d0-afac-11de-8a39-0800200c9a66" +rfcomm_insecure_uuid = "8ce255c0-200a-11e0-ac64-0800200c9a66" + +# bluetooth socket connection test uuid +bluetooth_socket_conn_test_uuid = "12345678-1234-5678-9abc-123456789abc" + +# Bluetooth Adapter Scan Mode Types +bt_scan_mode_types = {"state_off": -1, "none": 0, "connectable": 1, "connectable_discoverable": 3} + +# Bluetooth Adapter State Constants +bt_adapter_states = { + "off": 10, + "turning_on": 11, + "on": 12, + "turning_off": 13, + "ble_turning_on": 14, + "ble_on": 15, + "ble_turning_off": 16 +} + +# Should be kept in sync with BluetoothProfile.java +bt_profile_constants = { + "headset": 1, + "a2dp": 2, + "health": 3, + "input_device": 4, + "pan": 5, + "pbap_server": 6, + "gatt": 7, + "gatt_server": 8, + "map": 9, + "sap": 10, + "a2dp_sink": 11, + "avrcp_controller": 12, + "headset_client": 16, + "pbap_client": 17, + "map_mce": 18 +} + +# Bluetooth RFCOMM UUIDs as defined by the SIG +bt_rfcomm_uuids = { + "default_uuid": "457807c0-4897-11df-9879-0800200c9a66", + "base_uuid": "00000000-0000-1000-8000-00805F9B34FB", + "sdp": "00000001-0000-1000-8000-00805F9B34FB", + "udp": "00000002-0000-1000-8000-00805F9B34FB", + "rfcomm": "00000003-0000-1000-8000-00805F9B34FB", + "tcp": "00000004-0000-1000-8000-00805F9B34FB", + "tcs_bin": "00000005-0000-1000-8000-00805F9B34FB", + "tcs_at": "00000006-0000-1000-8000-00805F9B34FB", + "att": "00000007-0000-1000-8000-00805F9B34FB", + "obex": "00000008-0000-1000-8000-00805F9B34FB", + "ip": "00000009-0000-1000-8000-00805F9B34FB", + "ftp": "0000000A-0000-1000-8000-00805F9B34FB", + "http": "0000000C-0000-1000-8000-00805F9B34FB", + "wsp": "0000000E-0000-1000-8000-00805F9B34FB", + "bnep": "0000000F-0000-1000-8000-00805F9B34FB", + "upnp": "00000010-0000-1000-8000-00805F9B34FB", + "hidp": "00000011-0000-1000-8000-00805F9B34FB", + "hardcopy_control_channel": "00000012-0000-1000-8000-00805F9B34FB", + "hardcopy_data_channel": "00000014-0000-1000-8000-00805F9B34FB", + "hardcopy_notification": "00000016-0000-1000-8000-00805F9B34FB", + "avctp": "00000017-0000-1000-8000-00805F9B34FB", + "avdtp": "00000019-0000-1000-8000-00805F9B34FB", + "cmtp": "0000001B-0000-1000-8000-00805F9B34FB", + "mcap_control_channel": "0000001E-0000-1000-8000-00805F9B34FB", + "mcap_data_channel": "0000001F-0000-1000-8000-00805F9B34FB", + "l2cap": "00000100-0000-1000-8000-00805F9B34FB" +} + +# Should be kept in sync with BluetoothProfile#STATE_* constants. +bt_profile_states = {"disconnected": 0, "connecting": 1, "connected": 2, "disconnecting": 3} + +# Access Levels from BluetoothDevice. +bt_access_levels = {"access_allowed": 1, "access_denied": 2} + +# Priority levels as defined in BluetoothProfile.java. +bt_priority_levels = {"auto_connect": 1000, "on": 100, "off": 0, "undefined": -1} + +# A2DP codec configuration constants as defined in +# frameworks/base/core/java/android/bluetooth/BluetoothCodecConfig.java +codec_types = {'SBC': 0, 'AAC': 1, 'APTX': 2, 'APTX-HD': 3, 'LDAC': 4, 'MAX': 5, 'INVALID': 1000000} + +codec_priorities = {'DISABLED': -1, 'DEFAULT': 0, 'HIGHEST': 1000000} + +sample_rates = { + 'NONE': 0, + '44100': 0x1 << 0, + '48000': 0x1 << 1, + '88200': 0x1 << 2, + '96000': 0x1 << 3, + '176400': 0x1 << 4, + '192000': 0x1 << 5 +} + +bits_per_samples = {'NONE': 0, '16': 0x1 << 0, '24': 0x1 << 1, '32': 0x1 << 2} + +channel_modes = {'NONE': 0, 'MONO': 0x1 << 0, 'STEREO': 0x1 << 1} + +# Bluetooth HID constants. +hid_connection_timeout = 5 + +# Bluetooth HID EventFacade constants. +hid_on_set_report_event = "onSetReport" +hid_on_get_report_event = "onGetReport" +hid_on_set_protocol_event = "onSetProtocol" +hid_on_intr_data_event = "onInterruptData" +hid_on_virtual_cable_unplug_event = "onVirtualCableUnplug" +hid_id_keyboard = 1 +hid_id_mouse = 2 +hid_default_event_timeout = 15 +hid_default_set_report_payload = "Haha" + +### Bluetooth Constants End ### + +### Bluetooth Low Energy Constants Begin ### + +# Bluetooth Low Energy address types +ble_address_types = {"public": 0, "random": 1} + +# Bluetooth Low Energy scan callback types +ble_scan_settings_callback_types = {"all_matches": 1, "first_match": 2, "match_lost": 4, "found_and_lost": 6} + +# Bluetooth Low Energy scan settings match mode +ble_scan_settings_match_modes = {"aggresive": 1, "sticky": 2} + +# Bluetooth Low Energy scan settings match nums +ble_scan_settings_match_nums = {"one": 1, "few": 2, "max": 3} + +# Bluetooth Low Energy scan settings result types +ble_scan_settings_result_types = {"full": 0, "abbreviated": 1} + +# Bluetooth Low Energy scan settings mode +ble_scan_settings_modes = { + "opportunistic": -1, + "low_power": 0, + "balanced": 1, + "low_latency": 2, + "ambient_discovery": 3, +} + +# Bluetooth Low Energy scan settings report delay millis +ble_scan_settings_report_delay_milli_seconds = {"min": 0, "max": 9223372036854775807} + +# Bluetooth Low Energy scan settings phy +ble_scan_settings_phys = {"1m": 1, "2m": 2, "coded": 3, "all_supported": 255} + +# Bluetooth Low Energy advertise settings types +ble_advertise_settings_types = {"non_connectable": 0, "connectable": 1} + +# Bluetooth Low Energy advertise settings modes +ble_advertise_settings_modes = {"low_power": 0, "balanced": 1, "low_latency": 2} + +# Bluetooth Low Energy advertise settings tx power +ble_advertise_settings_tx_powers = {"ultra_low": 0, "low": 1, "medium": 2, "high": 3} + +# Bluetooth Low Energy service uuids for specific devices +ble_uuids = {"p_service": "0000feef-0000-1000-8000-00805f9b34fb", "hr_service": "0000180d-0000-1000-8000-00805f9b34fb"} + +# Bluetooth Low Energy advertising error codes +ble_advertise_error_code = { + "data_too_large": 1, + "too_many_advertisers": 2, + "advertisement_already_started": 3, + "bluetooth_internal_failure": 4, + "feature_not_supported": 5 +} + +### Bluetooth Low Energy Constants End ### + +### Bluetooth GATT Constants Begin ### + +# Gatt Callback error messages +gatt_cb_err = { + "char_write_req_err": "Characteristic Write Request event not found. Expected {}", + "char_write_err": "Characteristic Write event not found. Expected {}", + "desc_write_req_err": "Descriptor Write Request event not found. Expected {}", + "desc_write_err": "Descriptor Write event not found. Expected {}", + "char_read_err": "Characteristic Read event not found. Expected {}", + "char_read_req_err": "Characteristic Read Request not found. Expected {}", + "desc_read_err": "Descriptor Read event not found. Expected {}", + "desc_read_req_err": "Descriptor Read Request event not found. Expected {}", + "rd_remote_rssi_err": "Read Remote RSSI event not found. Expected {}", + "gatt_serv_disc_err": "GATT Services Discovered event not found. Expected {}", + "serv_added_err": "Service Added event not found. Expected {}", + "mtu_changed_err": "MTU Changed event not found. Expected {}", + "mtu_serv_changed_err": "MTU Server Changed event not found. Expected {}", + "gatt_conn_changed_err": "GATT Connection Changed event not found. Expected {}", + "char_change_err": "GATT Characteristic Changed event not fond. Expected {}", + "phy_read_err": "Phy Read event not fond. Expected {}", + "phy_update_err": "Phy Update event not fond. Expected {}", + "exec_write_err": "GATT Execute Write event not found. Expected {}" +} + +# GATT callback strings as defined in GattClientFacade.java and +# GattServerFacade.java implemented callbacks. +gatt_cb_strings = { + "char_write_req": "GattServer{}onCharacteristicWriteRequest", + "exec_write": "GattServer{}onExecuteWrite", + "char_write": "GattConnect{}onCharacteristicWrite", + "desc_write_req": "GattServer{}onDescriptorWriteRequest", + "desc_write": "GattConnect{}onDescriptorWrite", + "char_read": "GattConnect{}onCharacteristicRead", + "char_read_req": "GattServer{}onCharacteristicReadRequest", + "desc_read": "GattConnect{}onDescriptorRead", + "desc_read_req": "GattServer{}onDescriptorReadRequest", + "rd_remote_rssi": "GattConnect{}onReadRemoteRssi", + "gatt_serv_disc": "GattConnect{}onServicesDiscovered", + "serv_added": "GattServer{}onServiceAdded", + "mtu_changed": "GattConnect{}onMtuChanged", + "mtu_serv_changed": "GattServer{}onMtuChanged", + "gatt_conn_change": "GattConnect{}onConnectionStateChange", + "char_change": "GattConnect{}onCharacteristicChanged", + "phy_read": "GattConnect{}onPhyRead", + "phy_update": "GattConnect{}onPhyUpdate", + "serv_phy_read": "GattServer{}onPhyRead", + "serv_phy_update": "GattServer{}onPhyUpdate", +} + +# GATT event dictionary of expected callbacks and errors. +gatt_event = { + "char_write_req": { + "evt": gatt_cb_strings["char_write_req"], + "err": gatt_cb_err["char_write_req_err"] + }, + "exec_write": { + "evt": gatt_cb_strings["exec_write"], + "err": gatt_cb_err["exec_write_err"] + }, + "char_write": { + "evt": gatt_cb_strings["char_write"], + "err": gatt_cb_err["char_write_err"] + }, + "desc_write_req": { + "evt": gatt_cb_strings["desc_write_req"], + "err": gatt_cb_err["desc_write_req_err"] + }, + "desc_write": { + "evt": gatt_cb_strings["desc_write"], + "err": gatt_cb_err["desc_write_err"] + }, + "char_read": { + "evt": gatt_cb_strings["char_read"], + "err": gatt_cb_err["char_read_err"] + }, + "char_read_req": { + "evt": gatt_cb_strings["char_read_req"], + "err": gatt_cb_err["char_read_req_err"] + }, + "desc_read": { + "evt": gatt_cb_strings["desc_read"], + "err": gatt_cb_err["desc_read_err"] + }, + "desc_read_req": { + "evt": gatt_cb_strings["desc_read_req"], + "err": gatt_cb_err["desc_read_req_err"] + }, + "rd_remote_rssi": { + "evt": gatt_cb_strings["rd_remote_rssi"], + "err": gatt_cb_err["rd_remote_rssi_err"] + }, + "gatt_serv_disc": { + "evt": gatt_cb_strings["gatt_serv_disc"], + "err": gatt_cb_err["gatt_serv_disc_err"] + }, + "serv_added": { + "evt": gatt_cb_strings["serv_added"], + "err": gatt_cb_err["serv_added_err"] + }, + "mtu_changed": { + "evt": gatt_cb_strings["mtu_changed"], + "err": gatt_cb_err["mtu_changed_err"] + }, + "gatt_conn_change": { + "evt": gatt_cb_strings["gatt_conn_change"], + "err": gatt_cb_err["gatt_conn_changed_err"] + }, + "char_change": { + "evt": gatt_cb_strings["char_change"], + "err": gatt_cb_err["char_change_err"] + }, + "phy_read": { + "evt": gatt_cb_strings["phy_read"], + "err": gatt_cb_err["phy_read_err"] + }, + "phy_update": { + "evt": gatt_cb_strings["phy_update"], + "err": gatt_cb_err["phy_update_err"] + }, + "serv_phy_read": { + "evt": gatt_cb_strings["serv_phy_read"], + "err": gatt_cb_err["phy_read_err"] + }, + "serv_phy_update": { + "evt": gatt_cb_strings["serv_phy_update"], + "err": gatt_cb_err["phy_update_err"] + } +} + +# Matches constants of connection states defined in BluetoothGatt.java +gatt_connection_state = {"disconnected": 0, "connecting": 1, "connected": 2, "disconnecting": 3, "closed": 4} + +# Matches constants of Bluetooth GATT Characteristic values as defined +# in BluetoothGattCharacteristic.java +gatt_characteristic = { + "property_broadcast": 0x01, + "property_read": 0x02, + "property_write_no_response": 0x04, + "property_write": 0x08, + "property_notify": 0x10, + "property_indicate": 0x20, + "property_signed_write": 0x40, + "property_extended_props": 0x80, + "permission_read": 0x01, + "permission_read_encrypted": 0x02, + "permission_read_encrypted_mitm": 0x04, + "permission_write": 0x10, + "permission_write_encrypted": 0x20, + "permission_write_encrypted_mitm": 0x40, + "permission_write_signed": 0x80, + "permission_write_signed_mitm": 0x100, + "write_type_default": 0x02, + "write_type_no_response": 0x01, + "write_type_signed": 0x04, +} + +# Matches constants of Bluetooth GATT Characteristic values as defined +# in BluetoothGattDescriptor.java +gatt_descriptor = { + "enable_notification_value": [0x01, 0x00], + "enable_indication_value": [0x02, 0x00], + "disable_notification_value": [0x00, 0x00], + "permission_read": 0x01, + "permission_read_encrypted": 0x02, + "permission_read_encrypted_mitm": 0x04, + "permission_write": 0x10, + "permission_write_encrypted": 0x20, + "permission_write_encrypted_mitm": 0x40, + "permission_write_signed": 0x80, + "permission_write_signed_mitm": 0x100 +} + +# https://www.bluetooth.com/specifications/gatt/descriptors +gatt_char_desc_uuids = { + "char_ext_props": '00002900-0000-1000-8000-00805f9b34fb', + "char_user_desc": '00002901-0000-1000-8000-00805f9b34fb', + "client_char_cfg": '00002902-0000-1000-8000-00805f9b34fb', + "server_char_cfg": '00002903-0000-1000-8000-00805f9b34fb', + "char_fmt_uuid": '00002904-0000-1000-8000-00805f9b34fb', + "char_agreg_fmt": '00002905-0000-1000-8000-00805f9b34fb', + "char_valid_range": '00002906-0000-1000-8000-00805f9b34fb', + "external_report_reference": '00002907-0000-1000-8000-00805f9b34fb', + "report_reference": '00002908-0000-1000-8000-00805f9b34fb' +} + +# https://www.bluetooth.com/specifications/gatt/characteristics +gatt_char_types = { + "device_name": '00002a00-0000-1000-8000-00805f9b34fb', + "appearance": '00002a01-0000-1000-8000-00805f9b34fb', + "peripheral_priv_flag": '00002a02-0000-1000-8000-00805f9b34fb', + "reconnection_address": '00002a03-0000-1000-8000-00805f9b34fb', + "peripheral_pref_conn": '00002a04-0000-1000-8000-00805f9b34fb', + "service_changed": '00002a05-0000-1000-8000-00805f9b34fb', + "system_id": '00002a23-0000-1000-8000-00805f9b34fb', + "model_number_string": '00002a24-0000-1000-8000-00805f9b34fb', + "serial_number_string": '00002a25-0000-1000-8000-00805f9b34fb', + "firmware_revision_string": '00002a26-0000-1000-8000-00805f9b34fb', + "hardware_revision_string": '00002a27-0000-1000-8000-00805f9b34fb', + "software_revision_string": '00002a28-0000-1000-8000-00805f9b34fb', + "manufacturer_name_string": '00002a29-0000-1000-8000-00805f9b34fb', + "pnp_id": '00002a50-0000-1000-8000-00805f9b34fb', +} + +# Matches constants of Bluetooth GATT Characteristic values as defined +# in BluetoothGattCharacteristic.java +gatt_characteristic_value_format = { + "string": 0x1, + "byte": 0x2, + "sint8": 0x21, + "uint8": 0x11, + "sint16": 0x22, + "unit16": 0x12, + "sint32": 0x24, + "uint32": 0x14 +} + +# Matches constants of Bluetooth Gatt Service types as defined in +# BluetoothGattService.java +gatt_service_types = {"primary": 0, "secondary": 1} + +# Matches constants of Bluetooth Gatt Connection Priority values as defined in +# BluetoothGatt.java +gatt_connection_priority = {"balanced": 0, "high": 1, "low_power": 2} + +# Min and max MTU values +gatt_mtu_size = {"min": 23, "max": 217} + +# Gatt Characteristic attribute lengths +gatt_characteristic_attr_length = {"attr_1": 1, "attr_2": 3, "attr_3": 15} + +# Matches constants of Bluetooth Gatt operations status as defined in +# BluetoothGatt.java +gatt_status = {"success": 0, "failure": 0x101} + +# Matches constants of Bluetooth transport values as defined in +# BluetoothDevice.java +gatt_transport = {"auto": 0x00, "bredr": 0x01, "le": 0x02} + +# Matches constants of Bluetooth physical channeling values as defined in +# BluetoothDevice.java +gatt_phy = {"1m": 1, "2m": 2, "le_coded": 3} + +# Matches constants of Bluetooth physical channeling bitmask values as defined +# in BluetoothDevice.java +gatt_phy_mask = {"1m_mask": 1, "2m_mask": 2, "coded_mask": 4} + +# Values as defiend in the Bluetooth GATT specification +gatt_server_responses = { + "GATT_SUCCESS": 0x0, + "GATT_FAILURE": 0x1, + "GATT_READ_NOT_PERMITTED": 0x2, + "GATT_WRITE_NOT_PERMITTED": 0x3, + "GATT_INVALID_PDU": 0x4, + "GATT_INSUFFICIENT_AUTHENTICATION": 0x5, + "GATT_REQUEST_NOT_SUPPORTED": 0x6, + "GATT_INVALID_OFFSET": 0x7, + "GATT_INSUFFICIENT_AUTHORIZATION": 0x8, + "GATT_INVALID_ATTRIBUTE_LENGTH": 0xd, + "GATT_INSUFFICIENT_ENCRYPTION": 0xf, + "GATT_CONNECTION_CONGESTED": 0x8f, + "GATT_13_ERR": 0x13, + "GATT_12_ERR": 0x12, + "GATT_0C_ERR": 0x0C, + "GATT_16": 0x16 +} + +### Bluetooth GATT Constants End ### + +### Chameleon Constants Begin ### + +# Chameleon audio bits per sample. +audio_bits_per_sample_16 = 16 +audio_bits_per_sample_24 = 24 +audio_bits_per_sample_32 = 32 + +# Chameleon audio sample rates. +audio_sample_rate_44100 = 44100 +audio_sample_rate_48000 = 48000 +audio_sample_rate_88200 = 88200 +audio_sample_rate_96000 = 96000 + +# Chameleon audio channel modes. +audio_channel_mode_mono = 1 +audio_channel_mode_stereo = 2 +audio_channel_mode_8 = 8 + +# Chameleon time delays. +delay_after_binding_seconds = 0.5 +delay_before_record_seconds = 0.5 +silence_wait_seconds = 5 + +# Chameleon bus endpoints. +fpga_linein_bus_endpoint = 'Chameleon FPGA line-in' +headphone_bus_endpoint = 'Cros device headphone' + +### Chameleon Constants End ### + +# Begin logcat strings dict""" +logcat_strings = { + "media_playback_vol_changed": "onRouteVolumeChanged", +} + +# End logcat strings dict""" + +### Begin Service Discovery UUIDS ### +# Values match the Bluetooth SIG defined values: """ +""" https://www.bluetooth.com/specifications/assigned-numbers/service-discovery """ +sig_uuid_constants = { + "BASE_UUID": "0000{}-0000-1000-8000-00805F9B34FB", + "SDP": "0001", + "UDP": "0002", + "RFCOMM": "0003", + "TCP": "0004", + "TCS-BIN": "0005", + "TCS-AT": "0006", + "ATT": "0007", + "OBEX": "0008", + "IP": "0009", + "FTP": "000A", + "HTTP": "000C", + "WSP": "000E", + "BNEP": "000F", + "UPNP": "0010", + "HIDP": "0011", + "HardcopyControlChannel": "0012", + "HardcopyDataChannel": "0014", + "HardcopyNotification": "0016", + "AVCTP": "0017", + "AVDTP": "0019", + "CMTP": "001B", + "MCAPControlChannel": "001E", + "MCAPDataChannel": "001F", + "L2CAP": "0100", + "ServiceDiscoveryServerServiceClassID": "1000", + "BrowseGroupDescriptorServiceClassID": "1001", + "SerialPort": "1101", + "LANAccessUsingPPP": "1102", + "DialupNetworking": "1103", + "IrMCSync": "1104", + "OBEXObjectPush": "1105", + "OBEXFileTransfer": "1106", + "IrMCSyncCommand": "1107", + "Headset": "1108", + "CordlessTelephony": "1109", + "AudioSource": "110A", + "AudioSink": "110B", + "A/V_RemoteControlTarget": "110C", + "AdvancedAudioDistribution": "110D", + "A/V_RemoteControl": "110E", + "A/V_RemoteControlController": "110F", + "Intercom": "1110", + "Fax": "1111", + "Headset - Audio Gateway (AG)": "1112", + "WAP": "1113", + "WAP_CLIENT": "1114", + "PANU": "1115", + "NAP": "1116", + "GN": "1117", + "DirectPrinting": "1118", + "ReferencePrinting": "1119", + "ImagingResponder": "111B", + "ImagingAutomaticArchive": "111C", + "ImagingReferencedObjects": "111D", + "Handsfree": "111E", + "HandsfreeAudioGateway": "111F", + "DirectPrintingReferenceObjectsService": "1120", + "ReflectedUI": "1121", + "BasicPrinting": "1122", + "PrintingStatus": "1123", + "HumanInterfaceDeviceService": "1124", + "HardcopyCableReplacement": "1125", + "HCR_Print": "1126", + "HCR_Scan": "1127", + "Common_ISDN_Access": "1128", + "SIM_Access": "112D", + "Phonebook Access - PCE": "112E", + "Phonebook Access - PSE": "112F", + "Phonebook Access": "1130", + "Headset - HS": "1131", + "Message Access Server": "1132", + "Message Notification Server": "1133", + "Message Access Profile": "1134", + "GNSS": "1135", + "GNSS_Server": "1136", + "PnPInformation": "1200", + "GenericNetworking": "1201", + "GenericFileTransfer": "1202", + "GenericAudio": "1203", + "GenericTelephony": "1204", + "UPNP_Service": "1205", + "UPNP_IP_Service": "1206", + "ESDP_UPNP_IP_PAN": "1300", + "ESDP_UPNP_IP_LAP": "1301", + "ESDP_UPNP_L2CAP": "1302", + "VideoSource": "1303", + "VideoSink": "1304", + "VideoDistribution": "1305", + "HDP": "1400" +} + +### End Service Discovery UUIDS ### + +### Begin Appearance Constants ### +# https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.gap.appearance.xml +sig_appearance_constants = { + "UNKNOWN": 0, + "PHONE": 64, + "COMPUTER": 128, + "WATCH": 192, + "WATCH_SPORTS": 193, + "CLOCK": 256, + "DISPLAY": 320, + "REMOTE_CONTROL": 384, + "EYE_GLASSES": 448, + "TAG": 512, + "KEYRING": 576, + "MEDIA_PLAYER": 640, + "BARCODE_SCANNER": 704, + "THERMOMETER": 768, + "THERMOMETER_EAR": 769, + "HEART_RATE_SENSOR": 832, + "HEART_RATE_SENSOR_BELT": 833, + "BLOOD_PRESSURE": 896, + "BLOOD_PRESSURE_ARM": 897, + "BLOOD_PRESSURE_WRIST": 898, + "HID": 960, + "HID_KEYBOARD": 961, + "HID_MOUSE": 962, + "HID_JOYSTICK": 963, + "HID_GAMEPAD": 964, + "HID_DIGITIZER_TABLET": 965, + "HID_CARD_READER": 966, + "HID_DIGITAL_PEN": 967, + "HID_BARCODE_SCANNER": 968, + "GLUCOSE_METER": 1024, + "RUNNING_WALKING_SENSOR": 1088, + "RUNNING_WALKING_SENSOR_IN_SHOE": 1089, + "RUNNING_WALKING_SENSOR_ON_SHOE": 1090, + "RUNNING_WALKING_SENSOR_ON_HIP": 1091, + "CYCLING": 1152, + "CYCLING_COMPUTER": 1153, + "CYCLING_SPEED_SENSOR": 1154, + "CYCLING_CADENCE_SENSOR": 1155, + "CYCLING_POWER_SENSOR": 1156, + "CYCLING_SPEED_AND_CADENCE_SENSOR": 1157, + "PULSE_OXIMETER": 3136, + "PULSE_OXIMETER_FINGERTIP": 3137, + "PULSE_OXIMETER_WRIST": 3138, + "WEIGHT_SCALE": 3200, + "PERSONAL_MOBILITY": 3264, + "PERSONAL_MOBILITY_WHEELCHAIR": 3265, + "PERSONAL_MOBILITY_SCOOTER": 3266, + "GLUCOSE_MONITOR": 3328, + "SPORTS_ACTIVITY": 5184, + "SPORTS_ACTIVITY_LOCATION_DISPLAY": 5185, + "SPORTS_ACTIVITY_LOCATION_AND_NAV_DISPLAY": 5186, + "SPORTS_ACTIVITY_LOCATION_POD": 5187, + "SPORTS_ACTIVITY_LOCATION_AND_NAV_POD": 5188, +} + +### End Appearance Constants ### + +# Attribute Record values from the Bluetooth Specification +# Version 5, Vol 3, Part B +bt_attribute_values = { + 'ATTR_SERVICE_RECORD_HANDLE': 0x0000, + 'ATTR_SERVICE_CLASS_ID_LIST': 0x0001, + 'ATTR_SERVICE_RECORD_STATE': 0x0002, + 'ATTR_SERVICE_ID': 0x0003, + 'ATTR_PROTOCOL_DESCRIPTOR_LIST': 0x0004, + 'ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LIST': 0x000D, + 'ATTR_BROWSE_GROUP_LIST': 0x0005, + 'ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST': 0x0006, + 'ATTR_SERVICE_INFO_TIME_TO_LIVE': 0x0007, + 'ATTR_SERVICE_AVAILABILITY': 0x0008, + 'ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST': 0x0009, + 'ATTR_A2DP_SUPPORTED_FEATURES': 0x0311, +} diff --git a/system/blueberry/tests/gd_sl4a/lib/gd_sl4a_base_test.py b/system/blueberry/tests/gd_sl4a/lib/gd_sl4a_base_test.py new file mode 100644 index 0000000000..a5ae587ff9 --- /dev/null +++ b/system/blueberry/tests/gd_sl4a/lib/gd_sl4a_base_test.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python3 +# +# Copyright 2021 - 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. + +import traceback +import os +import logging + +from functools import wraps +from grpc import RpcError + +from mobly import signals +from mobly.base_test import BaseTestClass +from mobly.controllers.android_device_lib.adb import AdbError +from mobly.controllers import android_device +from mobly.controllers.android_device import MOBLY_CONTROLLER_CONFIG_NAME as ANDROID_DEVICE_COFNIG_NAME +from mobly.controllers.android_device_lib.jsonrpc_client_base import \ + AppRestoreConnectionError +from mobly.controllers.android_device_lib.services.sl4a_service import Sl4aService +import mobly.controllers.android_device_lib.sl4a_client as sl4a_client + +from blueberry.tests.gd.cert.context import get_current_context +from blueberry.tests.gd.cert.gd_device import MOBLY_CONTROLLER_CONFIG_NAME as GD_DEVICE_CONFIG_NAME +from blueberry.tests.gd_sl4a.lib.ble_lib import enable_bluetooth, disable_bluetooth, BleLib +from blueberry.facade import rootservice_pb2 as facade_rootservice +from blueberry.tests.gd.cert import gd_device + + +class GdSl4aBaseTestClass(BaseTestClass): + + SUBPROCESS_WAIT_TIMEOUT_SECONDS = 10 + + def setup_class(self, cert_module): + self.log_path_base = get_current_context().get_full_output_path() + self.verbose_mode = bool(self.user_params.get('verbose_mode', False)) + for config in self.controller_configs[GD_DEVICE_CONFIG_NAME]: + config['verbose_mode'] = self.verbose_mode + self.cert_module = cert_module + + # Parse and construct GD device objects + self.gd_devices = self.register_controller(gd_device, required=True) + self.cert = self.gd_devices[0] + + # Parse and construct Android device objects + server_port = int(self.controller_configs[ANDROID_DEVICE_COFNIG_NAME][0]['server_port']) + forwarded_port = int(self.controller_configs[ANDROID_DEVICE_COFNIG_NAME][0]['forwarded_port']) + sl4a_client._DEVICE_SIDE_PORT = server_port + sl4a_client._APP_START_WAIT_TIME = 0.5 + self.android_devices = self.register_controller(android_device, required=True) + self.dut = self.android_devices[0] + self.dut.services.register('sl4a', Sl4aService, start_service=False) + try: + self.dut.sl4a.start() + except AppRestoreConnectionError: + pass + try: + self.dut.sl4a.clear_host_port() + except AdbError: + pass + sl4a_client._APP_START_WAIT_TIME = 2 * 60 + self.dut.sl4a.restore_app_connection(port=forwarded_port) + + # Enable full btsnoop log + self.dut.adb.shell("setprop persist.bluetooth.btsnooplogmode full") + getprop_result = self.dut.adb.shell("getprop persist.bluetooth.btsnooplogmode") == "full" + if not getprop_result: + self.dut.log.warning("Failed to enable Bluetooth Hci Snoop Logging.") + + self.ble = BleLib(dut=self.dut) + + def teardown_class(self): + pass + + def setup_test(self): + self.cert.rootservice.StartStack( + facade_rootservice.StartStackRequest( + module_under_test=facade_rootservice.BluetoothModule.Value(self.cert_module),)) + self.cert.wait_channel_ready() + + self.timer_list = [] + self.dut.ed.clear_all_events() + self.dut.sl4a.setScreenTimeout(500) + self.dut.sl4a.wakeUpNow() + + # Always start tests with Bluetooth enabled and BLE disabled. + self.dut.sl4a.bluetoothDisableBLE() + disable_bluetooth(self.dut.sl4a, self.dut.ed) + # Enable full verbose logging for Bluetooth + self.dut.adb.shell("device_config put bluetooth INIT_logging_debug_enabled_for_all true") + # Then enable Bluetooth + enable_bluetooth(self.dut.sl4a, self.dut.ed) + self.dut.sl4a.bluetoothDisableBLE() + return True + + def teardown_test(self): + # Make sure BLE is disabled and Bluetooth is disabled after test + self.dut.sl4a.bluetoothDisableBLE() + disable_bluetooth(self.dut.sl4a, self.dut.ed) + self.cert.rootservice.StopStack(facade_rootservice.StopStackRequest()) + + # TODO: split cert logcat logs into individual tests + current_test_dir = get_current_context().get_full_output_path() + + # Pull DUT logs + self.pull_dut_logs(current_test_dir) + + # Pull CERT logs + self.cert.pull_logs(current_test_dir) + + def pull_dut_logs(self, base_dir): + try: + self.dut.adb.pull([ + "/data/misc/bluetooth/logs/btsnoop_hci.log", + os.path.join(base_dir, "DUT_%s_btsnoop_hci.log" % self.dut.serial) + ]) + self.dut.adb.pull([ + "/data/misc/bluedroid/bt_config.conf", + os.path.join(base_dir, "DUT_%s_bt_config.conf" % self.dut.serial) + ]) + self.dut.adb.pull([ + "/data/misc/bluedroid/bt_config.bak", + os.path.join(base_dir, "DUT_%s_bt_config.bak" % self.dut.serial) + ]) + except AdbError as error: + logging.warning("Failed to pull logs from DUT: " + str(error)) + + def __getattribute__(self, name): + attr = super().__getattribute__(name) + if not callable(attr) or not GdSl4aBaseTestClass.__is_entry_function(name): + return attr + + @wraps(attr) + def __wrapped(*args, **kwargs): + try: + return attr(*args, **kwargs) + except RpcError as e: + exception_info = "".join(traceback.format_exception(e.__class__, e, e.__traceback__)) + raise signals.TestFailure("RpcError during test\n\nRpcError:\n\n%s" % (exception_info)) + + return __wrapped + + __ENTRY_METHODS = {"setup_class", "teardown_class", "setup_test", "teardown_test"} + + @staticmethod + def __is_entry_function(name): + return name.startswith("test_") or name in GdSl4aBaseTestClass.__ENTRY_METHODS diff --git a/system/bta/Android.bp b/system/bta/Android.bp index 363541be55..03a35f9489 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -99,6 +99,8 @@ cc_library_static { "le_audio/state_machine.cc", "le_audio/client_parser.cc", "le_audio/client_audio.cc", + "le_audio/le_audio_set_configuration_provider.cc", + "le_audio/le_audio_set_configuration_provider_json.cc", "le_audio/le_audio_types.cc", "has/has_client.cc", "has/has_ctp.cc", @@ -140,13 +142,13 @@ cc_library_static { ], static_libs: [ "avrcp-target-service", + "libflatbuffers-cpp", "lib-bt-packets", "libbt-platform-protos-lite", ], shared_libs: [ "android.hardware.bluetooth.audio@2.0", "android.hardware.bluetooth.audio@2.1", - "android.hardware.bluetooth.audio@2.2", ], target: { android: { @@ -155,6 +157,9 @@ cc_library_static { ], }, }, + generated_headers: [ + "LeAudioSetConfigSchemas_h", + ], host_supported: true, } @@ -188,6 +193,12 @@ cc_test { "libosi", "libbt-common", ], + data: [ + ":audio_set_scenarios_bfbs", + ":audio_set_scenarios_json", + ":audio_set_configurations_bfbs", + ":audio_set_configurations_json", + ], } cc_test { @@ -430,6 +441,78 @@ cc_test { }, } +genrule { + name: "LeAudioSetConfigSchemas_h", + tools: [ + "flatc", + ], + cmd: "$(location flatc) -I packages/modules/Bluetooth/system/ -o $(genDir) --cpp $(in) ", + srcs: [ + "le_audio/audio_set_configurations.fbs", + "le_audio/audio_set_scenarios.fbs", + ], + out: [ + "audio_set_configurations_generated.h", + "audio_set_scenarios_generated.h", + ], +} + +genrule { + name: "LeAudioSetScenariosSchema_bfbs", + tools: [ + "flatc", + ], + cmd: "$(location flatc) -I packages/modules/Bluetooth/system/ -b --schema -o $(genDir) $(in) ", + srcs: [ + "le_audio/audio_set_scenarios.fbs", + ], + out: [ + "audio_set_scenarios.bfbs", + ], +} + +genrule { + name: "LeAudioSetConfigsSchema_bfbs", + tools: [ + "flatc", + ], + cmd: "$(location flatc) -I packages/modules/Bluetooth/system/ -b --schema -o $(genDir) $(in) ", + srcs: [ + "le_audio/audio_set_configurations.fbs", + ], + out: [ + "audio_set_configurations.bfbs", + ], +} + +prebuilt_etc { + name: "audio_set_scenarios_bfbs", + src: ":LeAudioSetScenariosSchema_bfbs", + filename: "audio_set_scenarios.bfbs", + sub_dir: "bluetooth/le_audio", +} + +prebuilt_etc { + name: "audio_set_scenarios_json", + src: "le_audio/audio_set_scenarios.json", + filename_from_src: true, + sub_dir: "bluetooth/le_audio", +} + +prebuilt_etc { + name: "audio_set_configurations_bfbs", + src: ":LeAudioSetConfigsSchema_bfbs", + filename: "audio_set_configurations.bfbs", + sub_dir: "bluetooth/le_audio", +} + +prebuilt_etc { + name: "audio_set_configurations_json", + src: "le_audio/audio_set_configurations.json", + filename_from_src: true, + sub_dir: "bluetooth/le_audio", +} + // bta unit tests for LE Audio // ======================================================== cc_test { @@ -440,6 +523,19 @@ cc_test { "clang_coverage_bin", ], host_supported: true, + target: { + darwin: { + enabled: false, + }, + android: { + cflags: [ + "-DOS_ANDROID", + ], + sanitize: { + misc_undefined: ["bounds"], + }, + }, + }, include_dirs: [ "packages/modules/Bluetooth/system", "packages/modules/Bluetooth/system/bta/include", @@ -460,6 +556,7 @@ cc_test { "le_audio/client_parser_test.cc", "le_audio/devices.cc", "le_audio/devices_test.cc", + "le_audio/le_audio_set_configuration_provider_json.cc", "le_audio/le_audio_types.cc", "le_audio/le_audio_types_test.cc", "le_audio/mock_iso_manager.cc", @@ -468,6 +565,15 @@ cc_test { "le_audio/state_machine_test.cc", "le_audio/mock_codec_manager.cc", ], + data: [ + ":audio_set_scenarios_bfbs", + ":audio_set_scenarios_json", + ":audio_set_configurations_bfbs", + ":audio_set_configurations_json" + ], + generated_headers: [ + "LeAudioSetConfigSchemas_h", + ], shared_libs: [ "libprotobuf-cpp-lite", "libcrypto", @@ -477,6 +583,7 @@ cc_test { "libgmock", "libbt-common", "libbt-protos-lite", + "libflatbuffers-cpp", "libosi", ], sanitize: { @@ -507,6 +614,7 @@ cc_test { "le_audio/client_parser.cc", "le_audio/devices.cc", "le_audio/le_audio_client_test.cc", + "le_audio/le_audio_set_configuration_provider_json.cc", "le_audio/le_audio_types.cc", "le_audio/mock_iso_manager.cc", "le_audio/mock_le_audio_client_audio.cc", @@ -523,7 +631,6 @@ cc_test { shared_libs: [ "android.hardware.bluetooth.audio@2.0", "android.hardware.bluetooth.audio@2.1", - "android.hardware.bluetooth.audio@2.2", "libprotobuf-cpp-lite", "libcrypto", "liblog", @@ -533,10 +640,19 @@ cc_test { "libgmock", "libbt-common", "libbt-protos-lite", + "libflatbuffers-cpp", "libosi", - "liblc3codec", "liblc3", ], + data: [ + ":audio_set_scenarios_bfbs", + ":audio_set_scenarios_json", + ":audio_set_configurations_bfbs", + ":audio_set_configurations_json", + ], + generated_headers: [ + "LeAudioSetConfigSchemas_h", + ], target: { android: { shared_libs: [ @@ -580,6 +696,7 @@ cc_test { "le_audio/broadcaster/state_machine_test.cc", "le_audio/le_audio_types.cc", "le_audio/mock_iso_manager.cc", + "le_audio/mock_codec_manager.cc", ], shared_libs: [ "libprotobuf-cpp-lite", @@ -631,6 +748,7 @@ cc_test { "le_audio/mock_iso_manager.cc", "le_audio/mock_le_audio_client_audio.cc", "test/common/mock_controller.cc", + "le_audio/mock_codec_manager.cc", ], shared_libs: [ "libprotobuf-cpp-lite", diff --git a/system/bta/ag/bta_ag_act.cc b/system/bta/ag/bta_ag_act.cc index adf08beafc..1ba68bcc44 100644 --- a/system/bta/ag/bta_ag_act.cc +++ b/system/bta/ag/bta_ag_act.cc @@ -373,7 +373,6 @@ void bta_ag_rfc_close(tBTA_AG_SCB* p_scb, p_scb->codec_fallback = false; p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2; p_scb->role = 0; - p_scb->post_sco = BTA_AG_POST_SCO_NONE; p_scb->svc_conn = false; p_scb->hsp_version = HSP_VERSION_1_2; bta_ag_at_reinit(&p_scb->at_cb); diff --git a/system/bta/csis/csis_client_test.cc b/system/bta/csis/csis_client_test.cc index f3aaefe098..1ad837f637 100644 --- a/system/bta/csis/csis_client_test.cc +++ b/system/bta/csis/csis_client_test.cc @@ -75,12 +75,12 @@ RawAddress GetTestAddress(int index) { class MockCsisLockCallback { public: MockCsisLockCallback() = default; + MockCsisLockCallback(const MockCsisLockCallback&) = delete; + MockCsisLockCallback& operator=(const MockCsisLockCallback&) = delete; + ~MockCsisLockCallback() = default; MOCK_METHOD((void), CsisGroupLockCb, (int group_id, bool locked, CsisGroupLockStatus status)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockCsisLockCallback); }; static MockCsisLockCallback* csis_lock_callback_mock; @@ -93,6 +93,9 @@ void SetMockCsisLockCallback(MockCsisLockCallback* mock) { class MockCsisCallbacks : public CsisClientCallbacks { public: MockCsisCallbacks() = default; + MockCsisCallbacks(const MockCsisCallbacks&) = delete; + MockCsisCallbacks& operator=(const MockCsisCallbacks&) = delete; + ~MockCsisCallbacks() override = default; MOCK_METHOD((void), OnConnectionState, @@ -110,9 +113,6 @@ class MockCsisCallbacks : public CsisClientCallbacks { MOCK_METHOD((void), OnGattCsisWriteLockRsp, (uint16_t conn_id, tGATT_STATUS status, uint16_t handle, void* data)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockCsisCallbacks); }; class CsisClientTest : public ::testing::Test { diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc index 2ecc3e906a..1ab4ca5592 100644 --- a/system/bta/dm/bta_dm_act.cc +++ b/system/bta/dm/bta_dm_act.cc @@ -264,8 +264,6 @@ void bta_dm_enable(tBTA_DM_SEC_CBACK* p_sec_cback) { previous one, it could be an error recovery mechanism */ if (p_sec_cback != NULL) bta_dm_cb.p_sec_cback = p_sec_cback; - /* notify BTA DM is now active */ - bta_dm_cb.is_bta_dm_active = true; btm_local_io_caps = btif_storage_get_local_io_caps(); } @@ -328,9 +326,6 @@ void BTA_dm_on_hw_off() { osi_free(bta_dm_search_cb.p_pending_search); fixed_queue_free(bta_dm_search_cb.pending_discovery_queue, osi_free); memset(&bta_dm_search_cb, 0, sizeof(bta_dm_search_cb)); - - /* notify BTA DM is now unactive */ - bta_dm_cb.is_bta_dm_active = false; } void BTA_dm_on_hw_on() { @@ -345,7 +340,6 @@ void BTA_dm_on_hw_on() { bta_dm_init_cb(); /* and retrieve the callback */ bta_dm_cb.p_sec_cback = temp_cback; - bta_dm_cb.is_bta_dm_active = true; /* hw is ready, go on with BTA DM initialization */ alarm_free(bta_dm_search_cb.search_timer); @@ -495,21 +489,19 @@ static void bta_dm_wait_for_acl_to_drain_cback(void* data) { const WaitForAllAclConnectionsToDrain* pass = WaitForAllAclConnectionsToDrain::FromAlarmCallbackData(data); - if (BTM_GetNumAclLinks() && + if (BTM_GetNumAclLinks() && force_disconnect_all_acl_connections() && WaitForAllAclConnectionsToDrain::IsFirstPass(pass)) { /* DISABLE_EVT still need to be sent out to avoid java layer disable timeout */ - if (force_disconnect_all_acl_connections()) { - LOG_DEBUG( - "Set timer for second pass to wait for all ACL connections to " - "close:%lu ms ", - second_pass.TimeToWaitInMs()); - alarm_set_on_mloop( - bta_dm_cb.disable_timer, second_pass.time_to_wait_in_ms, - bta_dm_wait_for_acl_to_drain_cback, second_pass.AlarmCallbackData()); - } + LOG_DEBUG( + "Set timer for second pass to wait for all ACL connections to " + "close:%lu ms ", + second_pass.TimeToWaitInMs()); + alarm_set_on_mloop(bta_dm_cb.disable_timer, second_pass.time_to_wait_in_ms, + bta_dm_wait_for_acl_to_drain_cback, + second_pass.AlarmCallbackData()); } else { - // No ACL links were up or is second pass at ACL closure + // No ACL links to close were up or is second pass at ACL closure LOG_INFO("Ensuring all ACL connections have been properly flushed"); bluetooth::shim::ACL_Shutdown(); @@ -3998,6 +3990,20 @@ void bta_dm_proc_open_evt(tBTA_GATTC_OPEN* p_data) { /******************************************************************************* * + * Function bta_dm_proc_open_evt + * + * Description process BTA_GATTC_OPEN_EVT in DM. + * + * Parameters: + * + ******************************************************************************/ +void bta_dm_clear_event_filter(void) { + VLOG(1) << "bta_dm_clear_event_filter in bta_dm_act"; + bluetooth::shim::BTM_ClearEventFilter(); +} + +/******************************************************************************* + * * Function bta_dm_gattc_callback * * Description This is GATT client callback function used in DM. diff --git a/system/bta/dm/bta_dm_api.cc b/system/bta/dm/bta_dm_api.cc index c9e5166353..5e1a8787f7 100644 --- a/system/bta/dm/bta_dm_api.cc +++ b/system/bta/dm/bta_dm_api.cc @@ -670,3 +670,17 @@ void BTA_DmBleCsisObserve(bool observe, tBTA_DM_SEARCH_CBACK* p_results_cb) { * ******************************************************************************/ void BTA_VendorInit(void) { APPL_TRACE_API("BTA_VendorInit"); } + +/******************************************************************************* + * + * Function BTA_DmClearEventFilter + * + * Description This function clears the event filter + * + * Returns void + * + ******************************************************************************/ +void BTA_DmClearEventFilter(void) { + APPL_TRACE_API("BTA_DmClearEventFilter"); + do_in_main_thread(FROM_HERE, base::Bind(bta_dm_clear_event_filter)); +} diff --git a/system/bta/dm/bta_dm_int.h b/system/bta/dm/bta_dm_int.h index 02d25eb12b..637c22aef9 100644 --- a/system/bta/dm/bta_dm_int.h +++ b/system/bta/dm/bta_dm_int.h @@ -310,22 +310,14 @@ extern tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs; /* DM control block */ typedef struct { - bool is_bta_dm_active; tBTA_DM_ACTIVE_LINK device_list; tBTA_DM_SEC_CBACK* p_sec_cback; tBTA_BLE_ENERGY_INFO_CBACK* p_energy_info_cback; - uint16_t state; bool disabling; alarm_t* disable_timer; - uint32_t wbt_sdp_handle; /* WIDCOMM Extensions SDP record handle */ - uint8_t wbt_scn; /* WIDCOMM Extensions SCN */ - uint8_t num_central_only; uint8_t pm_id; tBTA_PM_TIMER pm_timer[BTA_DM_NUM_PM_TIMER]; uint8_t cur_av_count; /* current AV connecions */ - bool disable_pair_mode; /* disable pair mode or not */ - bool conn_paired_only; /* allow connectable to paired device only or not */ - tBTA_DM_API_SEARCH search_msg; /* Storage for pin code request parameters */ RawAddress pin_bd_addr; @@ -349,7 +341,6 @@ typedef struct { tBTA_DM_ENCRYPT_CBACK* p_encrypt_cback; alarm_t* switch_delay_timer; - } tBTA_DM_CB; /* DM search control block */ @@ -553,6 +544,8 @@ extern void bta_dm_disc_rmt_name(tBTA_DM_MSG* p_data); extern tBTA_DM_PEER_DEVICE* bta_dm_find_peer_device( const RawAddress& peer_addr); +extern void bta_dm_clear_event_filter(void); + uint8_t bta_dm_search_get_state(); void bta_dm_search_set_state(uint8_t state); diff --git a/system/bta/gatt/database.cc b/system/bta/gatt/database.cc index 433fd55ac0..184ff9223f 100644 --- a/system/bta/gatt/database.cc +++ b/system/bta/gatt/database.cc @@ -20,6 +20,7 @@ #include <base/logging.h> +#include <algorithm> #include <list> #include <memory> #include <sstream> diff --git a/system/bta/groups/groups_test.cc b/system/bta/groups/groups_test.cc index 8966284df5..2299c573e3 100644 --- a/system/bta/groups/groups_test.cc +++ b/system/bta/groups/groups_test.cc @@ -52,6 +52,9 @@ RawAddress GetTestAddress(int index) { class MockGroupsCallbacks : public DeviceGroupsCallbacks { public: MockGroupsCallbacks() = default; + MockGroupsCallbacks(const MockGroupsCallbacks&) = delete; + MockGroupsCallbacks& operator=(const MockGroupsCallbacks&) = delete; + ~MockGroupsCallbacks() override = default; MOCK_METHOD((void), OnGroupAdded, @@ -69,9 +72,6 @@ class MockGroupsCallbacks : public DeviceGroupsCallbacks { (const RawAddress& address, const bluetooth::Uuid& uuid, int group_id), (override)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockGroupsCallbacks); }; class GroupsTest : public ::testing::Test { diff --git a/system/bta/has/has_client.cc b/system/bta/has/has_client.cc index 7c6bbdc3c9..044713437f 100644 --- a/system/bta/has/has_client.cc +++ b/system/bta/has/has_client.cc @@ -1044,14 +1044,14 @@ class HasClientImpl : public HasClient { /* Journal update */ device->has_journal_.Append(HasJournalRecord(features, true)); - /* When service is not yet validated, report the available device and - * notify features otherwise. + /* When service is not yet validated, report the available device with + * features. */ - if (!device->isGattServiceValid()) { + if (!device->isGattServiceValid()) callbacks_->OnDeviceAvailable(device->addr, device->GetFeatures()); - } else { - callbacks_->OnFeaturesUpdate(device->addr, device->GetFeatures()); - } + + /* Notify features */ + callbacks_->OnFeaturesUpdate(device->addr, device->GetFeatures()); MarkDeviceValidIfInInitialDiscovery(*device); } diff --git a/system/bta/has/has_client_test.cc b/system/bta/has/has_client_test.cc index c46e034de7..571686981c 100644 --- a/system/bta/has/has_client_test.cc +++ b/system/bta/has/has_client_test.cc @@ -104,6 +104,9 @@ static uint16_t GetTestConnId(const RawAddress& address) { class MockHasCallbacks : public HasClientCallbacks { public: MockHasCallbacks() = default; + MockHasCallbacks(const MockHasCallbacks&) = delete; + MockHasCallbacks& operator=(const MockHasCallbacks&) = delete; + ~MockHasCallbacks() override = default; MOCK_METHOD((void), OnConnectionState, @@ -133,9 +136,6 @@ class MockHasCallbacks : public HasClientCallbacks { ((std::variant<RawAddress, int> addr_or_group_id), uint8_t preset_index, ErrorCode error_code), (override)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockHasCallbacks); }; class HasClientTestBase : public ::testing::Test { diff --git a/system/bta/has/has_types.h b/system/bta/has/has_types.h index 89ed82a8ce..d726f07cf7 100644 --- a/system/bta/has/has_types.h +++ b/system/bta/has/has_types.h @@ -72,7 +72,7 @@ static_assert(sizeof(HasGattOpContext) <= sizeof(void*)); /* Service UUIDs */ /* FIXME: actually these were not yet assigned - using placeholders for now. */ static const bluetooth::Uuid kUuidHearingAccessService = - bluetooth::Uuid::From16Bit(0xEEEE); + bluetooth::Uuid::From16Bit(0x1854); static const bluetooth::Uuid kUuidHearingAidFeatures = bluetooth::Uuid::From16Bit(0xEEED); static const bluetooth::Uuid kUuidHearingAidPresetControlPoint = diff --git a/system/bta/hearing_aid/hearing_aid.cc b/system/bta/hearing_aid/hearing_aid.cc index b8667fef0a..3aef56e9e1 100644 --- a/system/bta/hearing_aid/hearing_aid.cc +++ b/system/bta/hearing_aid/hearing_aid.cc @@ -41,7 +41,6 @@ #include "stack/include/acl_api_types.h" // tBTM_RSSI_RESULT #include "stack/include/bt_hdr.h" #include "stack/include/bt_octets.h" -#include "stack/include/gap_api.h" #include "stack/include/l2c_api.h" // L2CAP_MIN_OFFSET #include "types/bluetooth/uuid.h" #include "types/bt_transport.h" @@ -589,9 +588,9 @@ class HearingAidImpl : public HearingAid { hearingDevice->first_connection = true; hearingDevice->service_changed_rcvd = true; BtaGattQueue::Clean(hearingDevice->conn_id); - if (hearingDevice->gap_handle) { + if (hearingDevice->gap_handle != GAP_INVALID_HANDLE) { GAP_ConnClose(hearingDevice->gap_handle); - hearingDevice->gap_handle = 0; + hearingDevice->gap_handle = GAP_INVALID_HANDLE; } } @@ -1332,9 +1331,20 @@ class HearingAidImpl : public HearingAid { case GAP_EVT_CONN_CLOSED: LOG(INFO) << __func__ << ": GAP_EVT_CONN_CLOSED: " << hearingDevice->address - << ", playback_started=" << hearingDevice->playback_started; - /* Disconnect profile when data channel is not available */ - Disconnect(hearingDevice->address); + << ", playback_started=" << hearingDevice->playback_started + << ", connecting_actively=" + << hearingDevice->connecting_actively; + if (hearingDevice->connecting_actively) { + /* Disconnect connection when data channel is not available */ + BTA_GATTC_Close(hearingDevice->conn_id); + } else { + /* Just clean data channel related parameter when data channel is + * available */ + hearingDevice->gap_handle = GAP_INVALID_HANDLE; + hearingDevice->accepting_audio = false; + hearingDevice->playback_started = false; + hearingDevice->command_acked = false; + } break; case GAP_EVT_CONN_DATA_AVAIL: { DVLOG(2) << "GAP_EVT_CONN_DATA_AVAIL"; @@ -1461,7 +1471,7 @@ class HearingAidImpl : public HearingAid { bool connected = hearingDevice->accepting_audio; bool connecting_by_user = hearingDevice->connecting_actively; - LOG(INFO) << "GAP_EVT_CONN_CLOSED: " << hearingDevice->address + LOG(INFO) << __func__ << ": " << hearingDevice->address << ", playback_started=" << hearingDevice->playback_started << ", accepting_audio=" << hearingDevice->accepting_audio; @@ -1480,17 +1490,19 @@ class HearingAidImpl : public HearingAid { DoDisconnectCleanUp(hearingDevice); - hearingDevices.Remove(address); - if (!connected) { /* In case user wanted to connect, sent DISCONNECTED state */ - if (connecting_by_user) + if (connecting_by_user) { callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address); - + } + /* Do remove device when the address is useless. */ + hearingDevices.Remove(address); return; } callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address); + /* Do remove device when the address is useless. */ + hearingDevices.Remove(address); for (const auto& device : hearingDevices.devices) { if (device.accepting_audio) return; } @@ -1549,9 +1561,9 @@ class HearingAidImpl : public HearingAid { hearingDevice->conn_id = 0; } - if (hearingDevice->gap_handle) { + if (hearingDevice->gap_handle != GAP_INVALID_HANDLE) { GAP_ConnClose(hearingDevice->gap_handle); - hearingDevice->gap_handle = 0; + hearingDevice->gap_handle = GAP_INVALID_HANDLE; } hearingDevice->accepting_audio = false; diff --git a/system/bta/include/bta_api.h b/system/bta/include/bta_api.h index 701de0aee8..3c0bd4b38a 100644 --- a/system/bta/include/bta_api.h +++ b/system/bta/include/bta_api.h @@ -1194,4 +1194,15 @@ extern void BTA_DmBleGetEnergyInfo(tBTA_BLE_ENERGY_INFO_CBACK* p_cmpl_cback); ******************************************************************************/ extern void BTA_VendorInit(void); +/******************************************************************************* + * + * Function BTA_DmClearEventFilter + * + * Description This function clears the event filter + * + * Returns void + * + ******************************************************************************/ +extern void BTA_DmClearEventFilter(void); + #endif /* BTA_API_H */ diff --git a/system/bta/include/bta_hearing_aid_api.h b/system/bta/include/bta_hearing_aid_api.h index b7ac365335..3ae46fd751 100644 --- a/system/bta/include/bta_hearing_aid_api.h +++ b/system/bta/include/bta_hearing_aid_api.h @@ -26,6 +26,7 @@ #include <functional> #include <vector> +#include "stack/include/gap_api.h" #include "types/raw_address.h" constexpr uint16_t HEARINGAID_MAX_NUM_UUIDS = 1; @@ -166,7 +167,7 @@ struct HearingDevice { connection_update_status(NONE), accepting_audio(false), conn_id(0), - gap_handle(0), + gap_handle(GAP_INVALID_HANDLE), audio_control_point_handle(audio_control_point_handle), audio_status_handle(audio_status_handle), audio_status_ccc_handle(audio_status_ccc_handle), @@ -190,7 +191,7 @@ struct HearingDevice { connection_update_status(NONE), accepting_audio(false), conn_id(0), - gap_handle(0), + gap_handle(GAP_INVALID_HANDLE), audio_status_handle(0), audio_status_ccc_handle(0), service_changed_ccc_handle(0), diff --git a/system/bta/include/bta_le_audio_api.h b/system/bta/include/bta_le_audio_api.h index ba878ebfc7..832910bcd5 100644 --- a/system/bta/include/bta_le_audio_api.h +++ b/system/bta/include/bta_le_audio_api.h @@ -28,6 +28,7 @@ class LeAudioHalVerifier { public: static bool SupportsLeAudio(); static bool SupportsLeAudioHardwareOffload(); + static bool SupportsLeAudioBroadcast(); }; /* Interface class */ @@ -35,10 +36,12 @@ class LeAudioClient { public: virtual ~LeAudioClient(void) = default; - static void Initialize(bluetooth::le_audio::LeAudioClientCallbacks* callbacks, - base::Closure initCb, - base::Callback<bool()> hal_2_1_verifier); - static void Cleanup(void); + static void Initialize( + bluetooth::le_audio::LeAudioClientCallbacks* callbacks, + base::Closure initCb, base::Callback<bool()> hal_2_1_verifier, + const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>& + offloading_preference); + static void Cleanup(base::Callback<void()> cleanupCb); static LeAudioClient* Get(void); static void DebugDump(int fd); @@ -55,4 +58,7 @@ class LeAudioClient { virtual std::vector<RawAddress> GetGroupDevices(const int group_id) = 0; static void AddFromStorage(const RawAddress& addr, bool autoconnect); static bool IsLeAudioClientRunning(); + + static void InitializeAudioSetConfigurationProvider(void); + static void CleanupAudioSetConfigurationProvider(void); }; diff --git a/system/bta/le_audio/audio_set_configurations.fbs b/system/bta/le_audio/audio_set_configurations.fbs new file mode 100644 index 0000000000..392263ad0c --- /dev/null +++ b/system/bta/le_audio/audio_set_configurations.fbs @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +namespace bluetooth.le_audio; +enum CodecSpecificLtvGenericTypes : byte { + SUPPORTED_SAMPLING_FREQUENCY = 0x01, + SUPPORTED_FRAME_DURATION = 0x02, + SUPPORTED_AUDIO_CHANNEL_ALLOCATION = 0x03, + SUPPORTED_OCTETS_PER_CODEC_FRAME = 0x04, + SUPPORTED_CODEC_FRAME_BLOCKS_PER_SDU = 0x05, +} +/// Note: Holds either a single value (when `value_width == 0`) or multiple +/// values if `value.length()` is no-remainder divisible by the non-zero +/// `value_width`. +/// Note: Consider extending it with `flags` field, to hold additional info like +/// IsBitfield, IsRange, etc. if we need these type-specific validations. +table CompoundValue { + value: [ubyte] (required); + value_width: ubyte = 0; +} +table CodecSpecificConfiguration { + name: string; + type: ubyte (key); + compound_value: CompoundValue; +} +struct CodecId { + coding_format: ubyte; + vendor_company_id : ushort; + vendor_codec_id : ushort; +} +enum AudioSetConfigurationStrategy : byte { + MONO_ONE_CIS_PER_DEVICE = 0x00, + STEREO_TWO_CISES_PER_DEVICE = 0x01, + STEREO_ONE_CIS_PER_DEVICE = 0x02, +} +enum AudioSetConfigurationDirection : byte { + SINK = 0x01, + SOURCE = 0x02, +} +table AudioSetSubConfiguration { + device_cnt: ubyte; + ase_cnt: ubyte; + direction: AudioSetConfigurationDirection = SINK; + configuration_strategy: AudioSetConfigurationStrategy; + codec_id : CodecId (required); + codec_configuration: [CodecSpecificConfiguration] (required); +} +/// Each set configration can contain multiple logical subconfigurations, which +/// all must be configurable with the current set of audio devices. For example, +/// one can define multiple output stream configurations with different +/// qualities, or assign different configurations to each stream direction. +table AudioSetConfiguration { + name: string (key, required); + subconfigurations: [AudioSetSubConfiguration] (required); +} +table AudioSetConfigurations { + _comments_: [string]; + configurations: [AudioSetConfiguration] (required); +} +root_type AudioSetConfigurations; diff --git a/system/bta/le_audio/audio_set_configurations.json b/system/bta/le_audio/audio_set_configurations.json new file mode 100644 index 0000000000..08453307a1 --- /dev/null +++ b/system/bta/le_audio/audio_set_configurations.json @@ -0,0 +1,2118 @@ +{ + "_comments_": [ + " == Audio Set Configurations == ", + " Example values which can be used as 'codec_configuration.type'", + " Codec Configuration parameter types:", + " SUPPORTED_SAMPLING_FREQUENCY = 1", + " SUPPORTED_FRAME_DURATION = 2", + " SUPPORTED_AUDIO_CHANNEL_ALLOCATION = 3", + " SUPPORTED_OCTETS_PER_CODEC_FRAME = 4", + " SUPPORTED_CODEC_FRAME_BLOCKS_PER_SDU = 5", + " Example values which can be used as 'codec_configuration.compound_value'", + " Codec Coding formats:", + " LC3 = 6", + " ASE Configuration strategies:", + " MONO_ONE_CIS_PER_DEVICE = 0", + " STEREO_TWO_CISES_PER_DEVICE = 1", + " STEREO_ONE_CIS_PER_DEVICE = 2", + " Sampling Frequencies: ", + " 8000Hz = 1", + " 11025Hz = 2", + " 16000Hz = 3", + " 22050Hz = 4", + " 24000Hz = 5", + " 32000Hz = 6", + " 44100Hz = 7", + " 48000Hz = 8", + " 88200Hz = 9", + " 96000Hz = 10", + " 176400Hz = 11", + " 192000Hz = 12", + " 384000Hz = 13", + " Frame Durations:", + " 7500us = 0", + " 10000us = 1" + ], + "configurations": [ + { + "name": "DualDev_OneChanStereoSnk_16_2", + "subconfigurations": [ + { + "device_cnt": 2, + "ase_cnt": 2, + "direction": "SINK", + "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 40, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "DualDev_OneChanStereoSnk_16_1", + "subconfigurations": [ + { + "device_cnt": 2, + "ase_cnt": 2, + "direction": "SINK", + "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 0 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 30, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "SingleDev_OneChanStereoSnk_16_2", + "subconfigurations": [ + { + "device_cnt": 1, + "ase_cnt": 2, + "direction": "SINK", + "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 40, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "SingleDev_OneChanStereoSnk_16_1", + "subconfigurations": [ + { + "device_cnt": 1, + "ase_cnt": 2, + "direction": "SINK", + "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 0 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 30, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "SingleDev_TwoChanStereoSnk_16_2", + "subconfigurations": [ + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SINK", + "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 3, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 40, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "SingleDev_TwoChanStereoSnk_16_1", + "subconfigurations": [ + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SINK", + "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 0 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 3, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 30, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "SingleDev_OneChanMonoSnk_16_2", + "subconfigurations": [ + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SINK", + "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 40, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "SingleDev_OneChanMonoSnk_16_1", + "subconfigurations": [ + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SINK", + "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 0 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 30, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2", + "subconfigurations": [ + { + "device_cnt": 2, + "ase_cnt": 2, + "direction": "SINK", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 40, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + }, + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SOURCE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 40, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1", + "subconfigurations": [ + { + "device_cnt": 2, + "ase_cnt": 2, + "direction": "SINK", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 0 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 30, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + }, + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SOURCE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 0 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 30, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2", + "subconfigurations": [ + { + "device_cnt": 2, + "ase_cnt": 4, + "direction": "SINK", + "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 40, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + }, + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SOURCE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 40, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1", + "subconfigurations": [ + { + "device_cnt": 2, + "ase_cnt": 4, + "direction": "SINK", + "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 0 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 30, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + }, + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SOURCE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 0 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 30, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2", + "subconfigurations": [ + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SINK", + "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 3, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 40, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + }, + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SOURCE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 40, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1", + "subconfigurations": [ + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SINK", + "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 0 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 3, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 30, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + }, + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SOURCE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 0 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 30, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2", + "subconfigurations": [ + { + "device_cnt": 1, + "ase_cnt": 2, + "direction": "SINK", + "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 40, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + }, + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SOURCE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 40, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1", + "subconfigurations": [ + { + "device_cnt": 1, + "ase_cnt": 2, + "direction": "SINK", + "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 0 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 30, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + }, + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SOURCE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 0 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 30, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2", + "subconfigurations": [ + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SINK", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 40, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + }, + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SOURCE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 40, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1", + "subconfigurations": [ + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SINK", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 0 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 30, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + }, + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SOURCE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 3 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 0 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 30, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "DualDev_OneChanStereoSnk_48_4", + "subconfigurations": [ + { + "device_cnt": 2, + "ase_cnt": 2, + "direction": "SINK", + "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 8 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 120, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "SingleDev_OneChanStereoSnk_48_4", + "subconfigurations": [ + { + "device_cnt": 1, + "ase_cnt": 2, + "direction": "SINK", + "configuration_strategy": "STEREO_TWO_CISES_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 8 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 120, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "SingleDev_TwoChanStereoSnk_48_4", + "subconfigurations": [ + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SINK", + "configuration_strategy": "STEREO_ONE_CIS_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 8 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 3, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 120, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + }, + { + "name": "SingleDev_OneChanMonoSnk_48_4", + "subconfigurations": [ + { + "device_cnt": 1, + "ase_cnt": 1, + "direction": "SINK", + "configuration_strategy": "MONO_ONE_CIS_PER_DEVICE", + "codec_id": { + "coding_format": 6, + "vendor_company_id": 0, + "vendor_codec_id": 0 + }, + "codec_configuration": [ + { + "name": "sampling_frequency", + "type": 1, + "compound_value": { + "value": [ + 8 + ] + } + }, + { + "name": "frame_duration", + "type": 2, + "compound_value": { + "value": [ + 1 + ] + } + }, + { + "name": "audio_channel_allocation", + "type": 3, + "compound_value": { + "value": [ + 1, + 0, + 0, + 0 + ] + } + }, + { + "name": "octets_per_codec_frame", + "type": 4, + "compound_value": { + "value": [ + 120, + 0 + ] + } + }, + { + "name": "codec_frame_blocks_per_sdu", + "type": 5, + "compound_value": { + "value": [ + 1 + ] + } + } + ] + } + ] + } + ] +}
\ No newline at end of file diff --git a/system/bta/le_audio/audio_set_scenarios.fbs b/system/bta/le_audio/audio_set_scenarios.fbs new file mode 100644 index 0000000000..301a5c1bb7 --- /dev/null +++ b/system/bta/le_audio/audio_set_scenarios.fbs @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +namespace bluetooth.le_audio; +/// Scenario represents the use case such as "Media", "Conversation", etc. +/// Each scenario can list any number of codec configurations by their names in +/// the order of preference. That means if the first entry does not meet all +/// the current requirements (such as peer device capabilities etc.) next +/// configurations are being checked. +/// +/// The referenced codec configurations are defined by the +/// audio_set_configurations.fbs schema and loaded from a different source file. +/// Multiple scenarios can reference same codec configurations. +table AudioSetScenario { + _comments_: [string]; + name: string (key, required); + configurations: [string] (required); +} +table AudioSetScenarios { + _comments_: [string]; + scenarios: [AudioSetScenario] (required); +} +root_type AudioSetScenarios; diff --git a/system/bta/le_audio/audio_set_scenarios.json b/system/bta/le_audio/audio_set_scenarios.json new file mode 100644 index 0000000000..d9f7b8fc7a --- /dev/null +++ b/system/bta/le_audio/audio_set_scenarios.json @@ -0,0 +1,63 @@ +{ + "_comments_": [ + "== Audio Set Scenarios ==", + " Each defined scenario references externally defined audio set", + " configurations, listed in the order of priority." + ], + "scenarios": [ + { + "name": "Ringtone", + "configurations": [ + "DualDev_OneChanStereoSnk_16_2", + "DualDev_OneChanStereoSnk_16_1", + "SingleDev_OneChanStereoSnk_16_2", + "SingleDev_OneChanStereoSnk_16_1", + "SingleDev_TwoChanStereoSnk_16_2", + "SingleDev_TwoChanStereoSnk_16_1", + "SingleDev_OneChanMonoSnk_16_2", + "SingleDev_OneChanMonoSnk_16_1" + ] + }, + { + "name": "Conversational", + "configurations": [ + "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2", + "DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1", + "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2", + "DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1", + "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2", + "SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1", + "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2", + "SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1", + "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2", + "SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1" + ] + }, + { + "name": "Media", + "configurations": [ + "DualDev_OneChanStereoSnk_48_4", + "DualDev_OneChanStereoSnk_16_2", + "DualDev_OneChanStereoSnk_16_1", + "SingleDev_OneChanStereoSnk_48_4", + "SingleDev_OneChanStereoSnk_16_2", + "SingleDev_OneChanStereoSnk_16_1", + "SingleDev_TwoChanStereoSnk_48_4", + "SingleDev_TwoChanStereoSnk_16_2", + "SingleDev_TwoChanStereoSnk_16_1", + "SingleDev_OneChanMonoSnk_48_4", + "SingleDev_OneChanMonoSnk_16_2", + "SingleDev_OneChanMonoSnk_16_1" + ] + }, + { + "name": "Default", + "configurations": [ + "DualDev_OneChanStereoSnk_16_2", + "SingleDev_OneChanStereoSnk_16_2", + "SingleDev_TwoChanStereoSnk_16_2", + "SingleDev_OneChanMonoSnk_16_2" + ] + } + ] +}
\ No newline at end of file diff --git a/system/bta/le_audio/broadcaster/broadcaster.cc b/system/bta/le_audio/broadcaster/broadcaster.cc index 2122fb3585..2744fe9fc9 100644 --- a/system/bta/le_audio/broadcaster/broadcaster.cc +++ b/system/bta/le_audio/broadcaster/broadcaster.cc @@ -134,7 +134,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { .vendor_codec_id = codec_id.vendor_codec_id, .codec_specific_params = std::move(codec_spec_data), }, - .metadata = metadata, + .metadata = std::move(metadata), .bis_configs = {}, }}; @@ -542,7 +542,7 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks { encoders_mem_.emplace_back(malloc(encoder_bytes), &std::free); encoders_.emplace_back( - lc3_setup_encoder(dt_us, sr_hz, encoders_mem_.back().get())); + lc3_setup_encoder(dt_us, sr_hz, 0, encoders_mem_.back().get())); } } diff --git a/system/bta/le_audio/broadcaster/mock_ble_advertising_manager.h b/system/bta/le_audio/broadcaster/mock_ble_advertising_manager.h index ee1d8749a5..eca09c87ba 100644 --- a/system/bta/le_audio/broadcaster/mock_ble_advertising_manager.h +++ b/system/bta/le_audio/broadcaster/mock_ble_advertising_manager.h @@ -27,6 +27,10 @@ class MockBleAdvertisingManager : public BleAdvertisingManager { public: MockBleAdvertisingManager() = default; + MockBleAdvertisingManager(const MockBleAdvertisingManager&) = delete; + MockBleAdvertisingManager& operator=(const MockBleAdvertisingManager&) = + delete; + ~MockBleAdvertisingManager() override = default; /* Allows getting and setting BleAdvertiserHciInterface dependency */ @@ -99,7 +103,6 @@ class MockBleAdvertisingManager : public BleAdvertisingManager { (override)); private: - DISALLOW_COPY_AND_ASSIGN(MockBleAdvertisingManager); base::WeakPtrFactory<MockBleAdvertisingManager> weak_factory_{this}; BleAdvertiserHciInterface* ble_adv_hci_interface_; }; diff --git a/system/bta/le_audio/broadcaster/state_machine_test.cc b/system/bta/le_audio/broadcaster/state_machine_test.cc index d0fc071c13..a203bcab2b 100644 --- a/system/bta/le_audio/broadcaster/state_machine_test.cc +++ b/system/bta/le_audio/broadcaster/state_machine_test.cc @@ -53,6 +53,11 @@ class MockBroadcastStatMachineCallbacks : public IBroadcastStateMachineCallbacks { public: MockBroadcastStatMachineCallbacks() = default; + MockBroadcastStatMachineCallbacks(const MockBroadcastStatMachineCallbacks&) = + delete; + MockBroadcastStatMachineCallbacks& operator=( + const MockBroadcastStatMachineCallbacks&) = delete; + ~MockBroadcastStatMachineCallbacks() override = default; MOCK_METHOD((void), OnStateMachineCreateStatus, @@ -70,9 +75,6 @@ class MockBroadcastStatMachineCallbacks MOCK_METHOD((uint32_t), GetSduItv, (uint8_t instance_id), (override)); MOCK_METHOD((uint16_t), GetMaxTransportLatency, (uint8_t instance_id), (override)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockBroadcastStatMachineCallbacks); }; class StateMachineTest : public Test { diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index 3aa605e581..71ba18b345 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -34,7 +34,6 @@ #include "common/time_util.h" #include "device/include/controller.h" #include "devices.h" -#include "embdrv/lc3_dec/Api/Lc3Decoder.hpp" #include "embdrv/lc3/include/lc3.h" #include "gatt/bta_gattc_int.h" #include "le_audio_types.h" @@ -175,6 +174,7 @@ class LeAudioClientImpl : public LeAudioClient { current_sink_codec_config({0, 0, 0, 0}), lc3_encoder_left_mem(nullptr), lc3_encoder_right_mem(nullptr), + lc3_decoder_mem(nullptr), lc3_decoder(nullptr), audio_source_instance_(nullptr), audio_sink_instance_(nullptr), @@ -671,9 +671,13 @@ class LeAudioClientImpl : public LeAudioClient { } if (active_group_id_ != bluetooth::groups::kGroupUnknown) { - LOG(WARNING) << __func__ << ", Another group already active: " - << static_cast<int>(active_group_id_); - return; + if (active_group_id_ == group_id) { + LOG(INFO) << __func__ << ", Group is already active: " + << static_cast<int>(active_group_id_); + callbacks_->OnGroupStatus(active_group_id_, GroupStatus::ACTIVE); + return; + } + LOG(INFO) << __func__ << ", switching active group to: " << group_id; } if (!audio_source_instance_) { @@ -701,21 +705,25 @@ class LeAudioClientImpl : public LeAudioClient { if (current_source_codec_config.IsInvalid() && current_sink_codec_config.IsInvalid()) { LOG(WARNING) << __func__ << ", unsupported device configurations"; - callbacks_->OnGroupStatus(active_group_id_, GroupStatus::INACTIVE); return; } - /* Expose audio sessions */ - audio_framework_source_config.data_interval_us = - current_source_codec_config.data_interval_us; - LeAudioClientAudioSource::Start(audio_framework_source_config, - audioSinkReceiver); + if (active_group_id_ == bluetooth::groups::kGroupUnknown) { + /* Expose audio sessions if there was no previous active group */ + audio_framework_source_config.data_interval_us = + current_source_codec_config.data_interval_us; + LeAudioClientAudioSource::Start(audio_framework_source_config, + audioSinkReceiver); - audio_framework_sink_config.data_interval_us = + audio_framework_sink_config.data_interval_us = current_source_codec_config.data_interval_us; - LeAudioClientAudioSink::Start(audio_framework_sink_config, - audioSourceReceiver); + LeAudioClientAudioSink::Start(audio_framework_sink_config, + audioSourceReceiver); + } else { + /* In case there was an active group. Stop the stream */ + GroupStop(active_group_id_); + } active_group_id_ = group_id; callbacks_->OnGroupStatus(active_group_id_, GroupStatus::ACTIVE); @@ -1258,6 +1266,11 @@ class LeAudioClientImpl : public LeAudioClient { group_remove_node(group, address, true); } leAudioDevices_.Remove(address); + return; + } + /* Attempt background re-connect if disconnect was not intended locally */ + if (reason != GATT_CONN_TERMINATE_LOCAL_HOST) { + BTA_GATTC_Open(gatt_if_, address, false, false); } } @@ -1815,8 +1828,8 @@ class LeAudioClientImpl : public LeAudioClient { uint16_t num_of_frames_per_ch; int dt_us = current_source_codec_config.data_interval_us; - int sr_hz = current_source_codec_config.sample_rate; - num_of_frames_per_ch = lc3_frame_samples(dt_us, sr_hz); + int af_hz = audio_framework_source_config.sample_rate; + num_of_frames_per_ch = lc3_frame_samples(dt_us, af_hz); chan_mono.reserve(num_of_frames_per_ch); for (int i = 0; i < pitch * num_of_frames_per_ch; i += pitch) { @@ -1842,8 +1855,8 @@ class LeAudioClientImpl : public LeAudioClient { uint16_t number_of_required_samples_per_channel; int dt_us = current_source_codec_config.data_interval_us; - int sr_hz = current_source_codec_config.sample_rate; - number_of_required_samples_per_channel = lc3_frame_samples(dt_us, sr_hz); + int af_hz = audio_framework_source_config.sample_rate; + number_of_required_samples_per_channel = lc3_frame_samples(dt_us, af_hz); for (auto [cis_handle, audio_location] : stream_conf->sink_streams) { if (audio_location & le_audio::codec_spec_conf::kLeAudioLocationAnyLeft) @@ -1865,22 +1878,16 @@ class LeAudioClientImpl : public LeAudioClient { bool mono = (left_cis_handle == 0) || (right_cis_handle == 0); - int af_hz = audio_framework_source_config.sample_rate; - LOG_ASSERT(af_hz >= sr_hz) << __func__ << " sample freq issue"; - - int pitch = af_hz / sr_hz; - - LOG(INFO) << __func__ << " pitch " << pitch - << " data size: " << (int)data.size() + LOG(INFO) << __func__ << " data size: " << (int)data.size() << " byte count: " << byte_count << " mono: " << mono; if (!mono) { - lc3_encode(lc3_encoder_left, (const int16_t*)data.data(), 2 * pitch, + lc3_encode(lc3_encoder_left, (const int16_t*)data.data(), 2, chan_left_enc.size(), chan_left_enc.data()); - lc3_encode(lc3_encoder_right, ((const int16_t*)data.data()) + 1, - 2 * pitch, chan_right_enc.size(), chan_right_enc.data()); + lc3_encode(lc3_encoder_right, ((const int16_t*)data.data()) + 1, 2, + chan_right_enc.size(), chan_right_enc.data()); } else { std::vector<int16_t> chan_mono; - get_mono_stream(data, chan_mono, pitch); + get_mono_stream(data, chan_mono); if (left_cis_handle) { lc3_encode(lc3_encoder_left, (const int16_t*)chan_mono.data(), 1, @@ -1914,8 +1921,8 @@ class LeAudioClientImpl : public LeAudioClient { uint16_t number_of_required_samples_per_channel; int dt_us = current_source_codec_config.data_interval_us; - int sr_hz = current_source_codec_config.sample_rate; - number_of_required_samples_per_channel = lc3_frame_samples(dt_us, sr_hz); + int af_hz = audio_framework_source_config.sample_rate; + number_of_required_samples_per_channel = lc3_frame_samples(dt_us, af_hz); if ((int)data.size() < (2 /* bytes per sample */ * num_channels * number_of_required_samples_per_channel)) { @@ -1924,24 +1931,22 @@ class LeAudioClientImpl : public LeAudioClient { } std::vector<uint8_t> chan_encoded(num_channels * byte_count, 0); - int af_hz = audio_framework_source_config.sample_rate; - LOG_ASSERT(af_hz >= sr_hz) << __func__ << " sample freq issue"; - - int pitch = af_hz / sr_hz; - if (num_channels == 1) { /* Since we always get two channels from framework, lets make it mono here */ std::vector<int16_t> chan_mono; - get_mono_stream(data, chan_mono, pitch); + get_mono_stream(data, chan_mono); - lc3_encode(lc3_encoder_left, (const int16_t*)chan_mono.data(), 1, - byte_count, chan_encoded.data()); + auto err = lc3_encode(lc3_encoder_left, (const int16_t*)chan_mono.data(), + 1, byte_count, chan_encoded.data()); + if (err < 0) { + LOG(ERROR) << " error while encoding, error code: " << +err; + } } else { - lc3_encode(lc3_encoder_left, (const int16_t*)data.data(), 2 * pitch, - byte_count, chan_encoded.data()); - lc3_encode(lc3_encoder_right, (const int16_t*)data.data() + 1, 2 * pitch, + lc3_encode(lc3_encoder_left, (const int16_t*)data.data(), 2, byte_count, + chan_encoded.data()); + lc3_encode(lc3_encoder_right, (const int16_t*)data.data() + 1, 2, byte_count, chan_encoded.data() + byte_count); } @@ -2058,8 +2063,21 @@ class LeAudioClientImpl : public LeAudioClient { void SendAudioData(uint8_t* data, uint16_t size) { /* Get only one channel for MONO microphone */ /* Gather data for channel */ + + if ((active_group_id_ == bluetooth::groups::kGroupUnknown) || + (audio_sender_state_ != AudioState::STARTED)) + return; + + LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_); + if (!group) { + LOG(ERROR) << __func__ << "There is no streaming group available"; + return; + } + + auto stream_conf = group->stream_conf; + uint16_t required_for_channel_byte_count = - lc3_decoder->lc3Config.getByteCountFromBitrate(32000); + stream_conf.source_octets_per_codec_frame; size_t required_byte_count = current_sink_codec_config.num_channels * required_for_channel_byte_count; @@ -2069,14 +2087,32 @@ class LeAudioClientImpl : public LeAudioClient { return; } - uint8_t BEC_detect = 0; - std::vector<int16_t> pcm_data_decoded(lc3_decoder->lc3Config.NF, 0); - auto err = lc3_decoder->run(data, required_for_channel_byte_count, 0, - pcm_data_decoded.data(), - pcm_data_decoded.size(), BEC_detect); + int dt_us = current_sink_codec_config.data_interval_us; + int af_hz = audio_framework_sink_config.sample_rate; + + int pcm_size; + if (dt_us == 10000) { + if (af_hz == 44100) + pcm_size = 480; + else + pcm_size = af_hz / 100; + } else if (dt_us == 7500) { + if (af_hz == 44100) + pcm_size = 360; + else + pcm_size = (af_hz * 3) / 400; + } else { + LOG(ERROR) << "BAD dt_us: " << dt_us; + return; + } + + std::vector<int16_t> pcm_data_decoded(pcm_size, 0); + + auto err = lc3_decode(lc3_decoder, data, size, pcm_data_decoded.data(), + 1 /* pitch */); /* TODO: How handle failing decoding ? */ - if (err != Lc3Decoder::ERROR_FREE) { + if (err < 0) { LOG(ERROR) << " error while decoding error code: " << static_cast<int>(err); return; @@ -2088,17 +2124,6 @@ class LeAudioClientImpl : public LeAudioClient { /* TODO: What to do if not all data sinked ? */ if (written != to_write) LOG(ERROR) << __func__ << ", not all data sinked"; - - DLOG(INFO) << __func__ - << " num of frames: " << (int)lc3_decoder->lc3Config.NF; - } - - static inline Lc3Config::FrameDuration Lc3ConfigFrameDuration( - uint32_t frame_duration_us) { - if (frame_duration_us == LeAudioCodecConfiguration::kInterval7500Us) - return Lc3Config::FrameDuration::d7p5ms; - else - return Lc3Config::FrameDuration::d10ms; } bool StartSendingAudio(int group_id) { @@ -2130,14 +2155,17 @@ class LeAudioClientImpl : public LeAudioClient { } int dt_us = current_source_codec_config.data_interval_us; int sr_hz = current_source_codec_config.sample_rate; - unsigned enc_size = lc3_encoder_size(dt_us, sr_hz); + int af_hz = audio_framework_source_config.sample_rate; + unsigned enc_size = lc3_encoder_size(dt_us, af_hz); lc3_encoder_left_mem = malloc(enc_size); lc3_encoder_right_mem = malloc(enc_size); - lc3_encoder_left = lc3_setup_encoder(dt_us, sr_hz, lc3_encoder_left_mem); + lc3_encoder_left = + lc3_setup_encoder(dt_us, sr_hz, af_hz, lc3_encoder_left_mem); lc3_encoder_right = - lc3_setup_encoder(dt_us, sr_hz, lc3_encoder_right_mem); + lc3_setup_encoder(dt_us, sr_hz, af_hz, lc3_encoder_right_mem); + } else if (CodecManager::GetInstance()->GetCodecLocation() == le_audio::types::CodecLocation::ADSP) { CodecManager::GetInstance()->UpdateActiveSourceAudioConfig( @@ -2207,12 +2235,20 @@ class LeAudioClientImpl : public LeAudioClient { if (CodecManager::GetInstance()->GetCodecLocation() == le_audio::types::CodecLocation::HOST) { - Lc3Config lc3Config( - current_sink_codec_config.sample_rate, - Lc3ConfigFrameDuration(current_sink_codec_config.data_interval_us), - 1); + if (lc3_decoder_mem) { + LOG(WARNING) + << " The decoder instance should have been already released."; + free(lc3_decoder_mem); + lc3_decoder_mem = nullptr; + } + + int dt_us = current_sink_codec_config.data_interval_us; + int sr_hz = current_sink_codec_config.sample_rate; + int af_hz = audio_framework_sink_config.sample_rate; + unsigned dec_size = lc3_decoder_size(dt_us, af_hz); + lc3_decoder_mem = malloc(dec_size); - lc3_decoder = new Lc3Decoder(lc3Config); + lc3_decoder = lc3_setup_decoder(dt_us, sr_hz, af_hz, lc3_decoder_mem); } else if (CodecManager::GetInstance()->GetCodecLocation() == le_audio::types::CodecLocation::ADSP) { CodecManager::GetInstance()->UpdateActiveSinkAudioConfig(*stream_conf, @@ -2235,11 +2271,10 @@ class LeAudioClientImpl : public LeAudioClient { lc3_encoder_right_mem = nullptr; } - if (lc3_decoder) { + if (lc3_decoder_mem) { LOG(INFO) << __func__ << " stopping sink"; - - delete lc3_decoder; - lc3_decoder = nullptr; + free(lc3_decoder_mem); + lc3_decoder_mem = nullptr; } } @@ -2305,12 +2340,15 @@ class LeAudioClientImpl : public LeAudioClient { leAudioDevices_.Dump(fd, bluetooth::groups::kGroupUnknown); } - void Cleanup(void) { + void Cleanup(base::Callback<void()> cleanupCb) { if (alarm_is_scheduled(suspend_timeout_)) alarm_cancel(suspend_timeout_); + groupStateMachine_->Cleanup(); leAudioDevices_.Cleanup(); aseGroups_.Cleanup(); StopAudio(); if (gatt_if_) BTA_GATTC_AppDeregister(gatt_if_); + + std::move(cleanupCb).Run(); } bool UpdateConfigAndCheckIfReconfigurationIsNeeded( @@ -3090,7 +3128,9 @@ class LeAudioClientImpl : public LeAudioClient { lc3_encoder_t lc3_encoder_left; lc3_encoder_t lc3_encoder_right; - Lc3Decoder* lc3_decoder; + void* lc3_decoder_mem; + lc3_decoder_t lc3_decoder; + std::vector<uint8_t> encoded_data; const void* audio_source_instance_; const void* audio_sink_instance_; @@ -3303,7 +3343,9 @@ LeAudioClient* LeAudioClient::Get() { /* Initializer of main le audio implementation class and its instance */ void LeAudioClient::Initialize( bluetooth::le_audio::LeAudioClientCallbacks* callbacks_, - base::Closure initCb, base::Callback<bool()> hal_2_1_verifier) { + base::Closure initCb, base::Callback<bool()> hal_2_1_verifier, + const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>& + offloading_preference) { if (instance) { LOG(ERROR) << "Already initialized"; return; @@ -3337,7 +3379,7 @@ void LeAudioClient::Initialize( instance = new LeAudioClientImpl(callbacks_, stateMachineCallbacks, initCb); IsoManager::GetInstance()->RegisterCigCallbacks(stateMachineHciCallbacks); - CodecManager::GetInstance()->Start(); + CodecManager::GetInstance()->Start(offloading_preference, capabilities); } void LeAudioClient::DebugDump(int fd) { @@ -3354,7 +3396,7 @@ void LeAudioClient::DebugDump(int fd) { dprintf(fd, "\n"); } -void LeAudioClient::Cleanup(void) { +void LeAudioClient::Cleanup(base::Callback<void()> cleanupCb) { if (!instance) { LOG(ERROR) << "Not initialized"; return; @@ -3362,7 +3404,7 @@ void LeAudioClient::Cleanup(void) { LeAudioClientImpl* ptr = instance; instance = nullptr; - ptr->Cleanup(); + ptr->Cleanup(cleanupCb); delete ptr; CodecManager::GetInstance()->Stop(); diff --git a/system/bta/le_audio/client_linux.cc b/system/bta/le_audio/client_linux.cc index 309a8fee2e..9644bfdc73 100644 --- a/system/bta/le_audio/client_linux.cc +++ b/system/bta/le_audio/client_linux.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include <base/callback.h> + #include "bta_le_audio_api.h" class LeAudioClientImpl : public LeAudioClient { @@ -38,9 +40,13 @@ class LeAudioClientImpl : public LeAudioClient { void LeAudioClient::Initialize( bluetooth::le_audio::LeAudioClientCallbacks* callbacks, - base::Closure initCb, base::Callback<bool()> hal_2_1_verifier) {} -void LeAudioClient::Cleanup(void) {} + base::Closure initCb, base::Callback<bool()> hal_2_1_verifier, + const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>& + offloading_preference) {} +void LeAudioClient::Cleanup(base::Callback<void()> cleanupCb) {} LeAudioClient* LeAudioClient::Get(void) { return nullptr; } void LeAudioClient::DebugDump(int fd) {} void LeAudioClient::AddFromStorage(const RawAddress& addr, bool autoconnect) {} bool LeAudioClient::IsLeAudioClientRunning() { return false; } +void LeAudioClient::InitializeAudioSetConfigurationProvider(void) {} +void LeAudioClient::CleanupAudioSetConfigurationProvider(void) {} diff --git a/system/bta/le_audio/codec_manager.cc b/system/bta/le_audio/codec_manager.cc index 3063d0c055..55db54430c 100644 --- a/system/bta/le_audio/codec_manager.cc +++ b/system/bta/le_audio/codec_manager.cc @@ -22,6 +22,7 @@ #include "osi/include/properties.h" #include "stack/acl/acl.h" #include "stack/include/acl_api.h" +#include "le_audio_set_configuration_provider.h" namespace { @@ -29,13 +30,23 @@ using bluetooth::hci::iso_manager::kIsoDataPathHci; using bluetooth::hci::iso_manager::kIsoDataPathPlatformDefault; using le_audio::CodecManager; using le_audio::types::CodecLocation; + +using bluetooth::le_audio::btle_audio_codec_config_t; +using bluetooth::le_audio::btle_audio_codec_index_t; +using le_audio::AudioSetConfigurationProvider; +using le_audio::set_configurations::AudioSetConfiguration; +using le_audio::set_configurations::AudioSetConfigurations; +using le_audio::set_configurations::SetConfiguration; + } // namespace namespace le_audio { struct codec_manager_impl { public: - codec_manager_impl() { + codec_manager_impl( + const std::vector<btle_audio_codec_config_t>& offloading_preference, + const std::vector<AudioSetConfiguration>& adsp_capabilities) { offload_enable_ = osi_property_get_bool( "ro.bluetooth.leaudio_offload.supported", false) && osi_property_get_bool( @@ -60,6 +71,7 @@ struct codec_manager_impl { kIsoDataPathPlatformDefault, {}); btm_configure_data_path(btm_data_direction::CONTROLLER_TO_HOST, kIsoDataPathPlatformDefault, {}); + UpdateOffloadCapability(offloading_preference, adsp_capabilities); SetCodecLocation(CodecLocation::ADSP); } ~codec_manager_impl() { @@ -73,7 +85,7 @@ struct codec_manager_impl { CodecLocation GetCodecLocation(void) const { return codec_location_; } void UpdateActiveSourceAudioConfig( - const le_audio::stream_configuration& stream_conf, uint16_t delay) { + const le_audio::stream_configuration& stream_conf, uint16_t delay_ms) { if (stream_conf.sink_streams.empty()) return; sink_config.stream_map = std::move(stream_conf.sink_streams); @@ -86,12 +98,12 @@ struct codec_manager_impl { // TODO: set the default value 1 for now, would change it if we need more // configuration sink_config.blocks_per_sdu = 1; - sink_config.peer_delay = delay; + sink_config.peer_delay_ms = delay_ms; LeAudioClientAudioSource::UpdateAudioConfigToHal(sink_config); } void UpdateActiveSinkAudioConfig( - const le_audio::stream_configuration& stream_conf, uint16_t delay) { + const le_audio::stream_configuration& stream_conf, uint16_t delay_ms) { if (stream_conf.source_streams.empty()) return; source_config.stream_map = std::move(stream_conf.source_streams); @@ -104,27 +116,167 @@ struct codec_manager_impl { // TODO: set the default value 1 for now, would change it if we need more // configuration source_config.blocks_per_sdu = 1; - source_config.peer_delay = delay; + source_config.peer_delay_ms = delay_ms; LeAudioClientAudioSink::UpdateAudioConfigToHal(source_config); } + const AudioSetConfigurations* GetOffloadCodecConfig( + types::LeAudioContextType ctx_type) { + return &context_type_offload_config_map_[ctx_type]; + } + private: void SetCodecLocation(CodecLocation location) { if (offload_enable_ == false) return; codec_location_ = location; } + + bool IsLc3ConfigMatched( + const set_configurations::CodecCapabilitySetting& adsp_config, + const set_configurations::CodecCapabilitySetting& target_config) { + if (adsp_config.id.coding_format != types::kLeAudioCodingFormatLC3 || + target_config.id.coding_format != types::kLeAudioCodingFormatLC3) { + return false; + } + + const types::LeAudioLc3Config adsp_lc3_config = + std::get<types::LeAudioLc3Config>(adsp_config.config); + const types::LeAudioLc3Config target_lc3_config = + std::get<types::LeAudioLc3Config>(target_config.config); + + if (adsp_lc3_config.sampling_frequency != + target_lc3_config.sampling_frequency || + adsp_lc3_config.frame_duration != target_lc3_config.frame_duration || + adsp_lc3_config.channel_count != target_lc3_config.channel_count || + adsp_lc3_config.octets_per_codec_frame != + target_lc3_config.octets_per_codec_frame) { + return false; + } + + return true; + } + + bool IsSetConfigurationMatched(const SetConfiguration& software_set_config, + const SetConfiguration& adsp_set_config) { + // Skip the check of stategry and ase_cnt due to ADSP doesn't have the info + return ( + software_set_config.direction == adsp_set_config.direction && + software_set_config.device_cnt == adsp_set_config.device_cnt && + IsLc3ConfigMatched(software_set_config.codec, adsp_set_config.codec)); + } + + bool IsAudioSetConfigurationMatched( + const AudioSetConfiguration* software_audio_set_conf, + std::unordered_set<uint8_t>& offload_preference_set, + const std::vector<AudioSetConfiguration>& adsp_capabilities) { + if (software_audio_set_conf->confs.empty()) { + return false; + } + + std::unordered_map<uint8_t, const SetConfiguration&> + software_set_conf_direction_map; + + for (auto& software_set_conf : software_audio_set_conf->confs) { + // Checks offload preference supports the codec + if (offload_preference_set.find( + software_set_conf.codec.id.coding_format) == + offload_preference_set.end()) { + return false; + } + software_set_conf_direction_map.emplace(software_set_conf.direction, + software_set_conf); + } + + // Checks any of offload config matches the input audio set config + for (const auto& adsp_audio_set_conf : adsp_capabilities) { + if (adsp_audio_set_conf.confs.size() != + software_audio_set_conf->confs.size()) { + continue; + } + + size_t match_cnt = 0; + + for (auto& adsp_set_conf : adsp_audio_set_conf.confs) { + auto it = software_set_conf_direction_map.find(adsp_set_conf.direction); + + if (it == software_set_conf_direction_map.end()) { + continue; + } + + if (IsSetConfigurationMatched(it->second, adsp_set_conf)) { + match_cnt++; + } + } + + if (match_cnt == software_set_conf_direction_map.size()) { + return true; + } + } + + return false; + } + + void UpdateOffloadCapability( + const std::vector<btle_audio_codec_config_t>& offloading_preference, + const std::vector<AudioSetConfiguration>& adsp_capabilities) { + LOG(INFO) << __func__; + std::unordered_set<uint8_t> offload_preference_set; + + if (AudioSetConfigurationProvider::Get() == nullptr) { + LOG(ERROR) << __func__ << " Audio set configuration provider is not available."; + return; + } + + for (auto codec : offloading_preference) { + auto it = btle_audio_codec_type_map_.find(codec.codec_type); + + if (it != btle_audio_codec_type_map_.end()) { + offload_preference_set.insert(it->second); + } + } + + for (types::LeAudioContextType ctx_type : + types::kLeAudioContextAllTypesArray) { + // Gets the software supported context type and the corresponding config + // priority + const AudioSetConfigurations* software_audio_set_confs = + AudioSetConfigurationProvider::Get()->GetConfigurations(ctx_type); + + for (const auto& software_audio_set_conf : *software_audio_set_confs) { + if (IsAudioSetConfigurationMatched(software_audio_set_conf, + offload_preference_set, + adsp_capabilities)) { + LOG(INFO) << "Offload supported conf, context type: " << (int)ctx_type + << ", settings -> " << software_audio_set_conf->name; + context_type_offload_config_map_[ctx_type].push_back( + software_audio_set_conf); + } + } + } + } + CodecLocation codec_location_ = CodecLocation::HOST; bool offload_enable_ = false; le_audio::offload_config sink_config; le_audio::offload_config source_config; + std::unordered_map<types::LeAudioContextType, AudioSetConfigurations> + context_type_offload_config_map_; + std::unordered_map<btle_audio_codec_index_t, uint8_t> + btle_audio_codec_type_map_ = { + {::bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3, + types::kLeAudioCodingFormatLC3}}; }; struct CodecManager::impl { impl(const CodecManager& codec_manager) : codec_manager_(codec_manager) {} - void Start() { + void Start( + const std::vector<btle_audio_codec_config_t>& offloading_preference, + const std::vector<set_configurations::AudioSetConfiguration>& + adsp_capabilities) { LOG_ASSERT(!codec_manager_impl_); - codec_manager_impl_ = std::make_unique<codec_manager_impl>(); + codec_manager_impl_ = std::make_unique<codec_manager_impl>( + offloading_preference, adsp_capabilities); } void Stop() { @@ -140,8 +292,12 @@ struct CodecManager::impl { CodecManager::CodecManager() : pimpl_(std::make_unique<impl>(*this)) {} -void CodecManager::Start() { - if (!pimpl_->IsRunning()) pimpl_->Start(); +void CodecManager::Start( + const std::vector<btle_audio_codec_config_t>& offloading_preference, + const std::vector<set_configurations::AudioSetConfiguration>& + adsp_capabilities) { + if (!pimpl_->IsRunning()) + pimpl_->Start(offloading_preference, adsp_capabilities); } void CodecManager::Stop() { @@ -157,17 +313,26 @@ types::CodecLocation CodecManager::GetCodecLocation(void) const { } void CodecManager::UpdateActiveSourceAudioConfig( - const stream_configuration& stream_conf, uint16_t delay) { + const stream_configuration& stream_conf, uint16_t delay_ms) { if (pimpl_->IsRunning()) pimpl_->codec_manager_impl_->UpdateActiveSourceAudioConfig(stream_conf, - delay); + delay_ms); } void CodecManager::UpdateActiveSinkAudioConfig( - const stream_configuration& stream_conf, uint16_t delay) { + const stream_configuration& stream_conf, uint16_t delay_ms) { if (pimpl_->IsRunning()) pimpl_->codec_manager_impl_->UpdateActiveSinkAudioConfig(stream_conf, - delay); + delay_ms); +} + +const AudioSetConfigurations* CodecManager::GetOffloadCodecConfig( + types::LeAudioContextType ctx_type) { + if (pimpl_->IsRunning()) { + return pimpl_->codec_manager_impl_->GetOffloadCodecConfig(ctx_type); + } + + return nullptr; } } // namespace le_audio diff --git a/system/bta/le_audio/codec_manager.h b/system/bta/le_audio/codec_manager.h index 84e2948aa9..4c02563b34 100644 --- a/system/bta/le_audio/codec_manager.h +++ b/system/bta/le_audio/codec_manager.h @@ -27,7 +27,7 @@ struct offload_config { uint32_t frame_duration; uint16_t octets_per_frame; uint8_t blocks_per_sdu; - uint16_t peer_delay; + uint16_t peer_delay_ms; }; class CodecManager { @@ -38,13 +38,19 @@ class CodecManager { static CodecManager* instance = new CodecManager(); return instance; } - void Start(void); + void Start( + const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>& + offloading_preference, + const std::vector<::le_audio::set_configurations::AudioSetConfiguration>& + adsp_capabilities); void Stop(void); virtual types::CodecLocation GetCodecLocation(void) const; virtual void UpdateActiveSourceAudioConfig( - const stream_configuration& stream_conf, uint16_t delay); + const stream_configuration& stream_conf, uint16_t delay_ms); virtual void UpdateActiveSinkAudioConfig( - const stream_configuration& stream_conf, uint16_t delay); + const stream_configuration& stream_conf, uint16_t delay_ms); + const ::le_audio::set_configurations::AudioSetConfigurations* + GetOffloadCodecConfig(::le_audio::types::LeAudioContextType ctx_type); private: struct impl; diff --git a/system/bta/le_audio/devices.cc b/system/bta/le_audio/devices.cc index 40588f6f45..7ebae5e26f 100644 --- a/system/bta/le_audio/devices.cc +++ b/system/bta/le_audio/devices.cc @@ -28,6 +28,7 @@ #include "btm_iso_api_types.h" #include "client_audio.h" #include "device/include/controller.h" +#include "le_audio_set_configuration_provider.h" using bluetooth::hci::kIsoCigFramingFramed; using bluetooth::hci::kIsoCigFramingUnframed; @@ -35,6 +36,7 @@ using bluetooth::hci::kIsoCigPackingSequential; using bluetooth::hci::kIsoCigPhy1M; using bluetooth::hci::kIsoCigPhy2M; using bluetooth::hci::iso_manager::kIsoSca0To20Ppm; +using le_audio::AudioSetConfigurationProvider; using le_audio::set_configurations::CodecCapabilitySetting; using le_audio::types::ase; using le_audio::types::AseState; @@ -104,7 +106,10 @@ void LeAudioDeviceGroup::Deactivate(void) { } LeAudioDevice* LeAudioDeviceGroup::GetFirstDevice(void) { - return (leAudioDevices_.front().lock()).get(); + auto d = leAudioDevices_.front(); + if (d.expired()) return nullptr; + + return (d.lock()).get(); } LeAudioDevice* LeAudioDeviceGroup::GetFirstDeviceWithActiveContext( @@ -1114,7 +1119,7 @@ const set_configurations::AudioSetConfiguration* LeAudioDeviceGroup::FindFirstSupportedConfiguration( LeAudioContextType context_type) { const set_configurations::AudioSetConfigurations* confs = - set_configurations::get_confs_by_type(context_type); + AudioSetConfigurationProvider::Get()->GetConfigurations(context_type); DLOG(INFO) << __func__ << " context type: " << (int)context_type << " number of connected devices: " << NumOfConnected(); diff --git a/system/bta/le_audio/devices_test.cc b/system/bta/le_audio/devices_test.cc index 888fad83b9..bb8a939091 100644 --- a/system/bta/le_audio/devices_test.cc +++ b/system/bta/le_audio/devices_test.cc @@ -21,6 +21,7 @@ #include <gtest/gtest.h> #include "btm_api_mock.h" +#include "le_audio_set_configuration_provider.h" #include "le_audio_types.h" #include "mock_controller.h" #include "stack/btm/btm_int_types.h" @@ -380,6 +381,7 @@ class LeAudioAseConfigurationTest : public Test { group_ = new LeAudioDeviceGroup(group_id_); bluetooth::manager::SetMockBtmInterface(&btm_interface_); controller::SetMockControllerInterface(&controller_interface_); + ::le_audio::AudioSetConfigurationProvider::Initialize(); } void TearDown() override { @@ -387,6 +389,7 @@ class LeAudioAseConfigurationTest : public Test { bluetooth::manager::SetMockBtmInterface(nullptr); devices_.clear(); delete group_; + ::le_audio::AudioSetConfigurationProvider::Cleanup(); } LeAudioDevice* AddTestDevice(int snk_ase_num, int src_ase_num, @@ -505,7 +508,9 @@ class LeAudioAseConfigurationTest : public Test { void TestGroupAseConfiguration(LeAudioContextType context_type, TestGroupAseConfigurationData* data, uint8_t data_size) { - const auto* configurations = get_confs_by_type(context_type); + const auto* configurations = + ::le_audio::AudioSetConfigurationProvider::Get()->GetConfigurations( + context_type); for (const auto& audio_set_conf : *configurations) { // the configuration should fail if there are no active ases expected bool success_expected = data_size > 0; @@ -854,8 +859,14 @@ TEST_F(LeAudioAseConfigurationTest, test_reconnection_media) { {right, kLeAudioCodecLC3ChannelCountSingleChannel, kLeAudioCodecLC3ChannelCountSingleChannel, 1, 0}}; - TestSingleAseConfiguration(LeAudioContextType::MEDIA, data, 2, - &kDualDev_OneChanStereoSnk_48_4); + auto all_configurations = + ::le_audio::AudioSetConfigurationProvider::Get()->GetConfigurations( + LeAudioContextType::MEDIA); + ASSERT_NE(nullptr, all_configurations); + ASSERT_NE(all_configurations->end(), all_configurations->begin()); + auto configuration = *all_configurations->begin(); + + TestSingleAseConfiguration(LeAudioContextType::MEDIA, data, 2, configuration); SetCisInformationToActiveAse(); @@ -871,9 +882,6 @@ TEST_F(LeAudioAseConfigurationTest, test_reconnection_media) { ::le_audio::types::AudioLocations group_src_audio_location = *ase->codec_config.audio_channel_allocation; - /* Get known requirement*/ - auto* configuration = &kDualDev_OneChanStereoSnk_48_4; - /* Get entry for the sink direction and use it to set configuration */ for (auto& ent : configuration->confs) { if (ent.direction == ::le_audio::types::kLeAudioDirectionSink) { diff --git a/system/bta/le_audio/hal_verifier.cc b/system/bta/le_audio/hal_verifier.cc index 5eb6b8004a..2367593a45 100644 --- a/system/bta/le_audio/hal_verifier.cc +++ b/system/bta/le_audio/hal_verifier.cc @@ -23,6 +23,11 @@ bool LeAudioHalVerifier::SupportsLeAudio() { } bool LeAudioHalVerifier::SupportsLeAudioHardwareOffload() { - return bluetooth::audio::HalVersionManager::GetHalVersion() > - bluetooth::audio::BluetoothAudioHalVersion::VERSION_2_1; + return bluetooth::audio::HalVersionManager::GetHalTransport() == + bluetooth::audio::BluetoothAudioHalTransport::AIDL; +} + +bool LeAudioHalVerifier::SupportsLeAudioBroadcast() { + return bluetooth::audio::HalVersionManager::GetHalTransport() == + bluetooth::audio::BluetoothAudioHalTransport::AIDL; } diff --git a/system/bta/le_audio/hal_verifier_linux.cc b/system/bta/le_audio/hal_verifier_linux.cc index 2da71ef329..3318291eb9 100644 --- a/system/bta/le_audio/hal_verifier_linux.cc +++ b/system/bta/le_audio/hal_verifier_linux.cc @@ -18,3 +18,4 @@ bool LeAudioHalVerifier::SupportsLeAudio() { return false; } bool LeAudioHalVerifier::SupportsLeAudioHardwareOffload() { return false; } +bool LeAudioHalVerifier::SupportsLeAudioBroadcast() { return false; } diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc index 13f8067ad9..4aae9493fc 100644 --- a/system/bta/le_audio/le_audio_client_test.cc +++ b/system/bta/le_audio/le_audio_client_test.cc @@ -33,6 +33,7 @@ #include "fake_osi.h" #include "gatt/database_builder.h" #include "hardware/bt_gatt_types.h" +#include "le_audio_set_configuration_provider.h" #include "le_audio_types.h" #include "mock_controller.h" #include "mock_csis_client.h" @@ -264,7 +265,9 @@ class UnicastTestNoInit : public Test { base::Unretained(this->gatt_callback), event_data)); } - void InjectDisconnectedEvent(uint16_t conn_id) { + void InjectDisconnectedEvent( + uint16_t conn_id, + tGATT_DISCONN_REASON reason = GATT_CONN_TERMINATE_LOCAL_HOST) { ASSERT_NE(conn_id, GATT_INVALID_CONN_ID); ASSERT_NE(peer_devices.count(conn_id), 0u); @@ -273,7 +276,7 @@ class UnicastTestNoInit : public Test { .conn_id = conn_id, .client_if = gatt_if, .remote_bda = peer_devices.at(conn_id)->addr, - .reason = GATT_CONN_TERMINATE_PEER_USER, + .reason = reason, }; peer_devices.at(conn_id)->connected = false; @@ -715,6 +718,7 @@ class UnicastTestNoInit : public Test { SetUpMockGroups(); SetUpMockGatt(); + le_audio::AudioSetConfigurationProvider::Initialize(); ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning()); } @@ -730,10 +734,13 @@ class UnicastTestNoInit : public Test { if (LeAudioClient::IsLeAudioClientRunning()) { EXPECT_CALL(mock_gatt_interface_, AppDeregister(gatt_if)).Times(1); - LeAudioClient::Cleanup(); + LeAudioClient::Cleanup(base::DoNothing()); ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning()); } + if (le_audio::AudioSetConfigurationProvider::Get()) + le_audio::AudioSetConfigurationProvider::Cleanup(); + iso_manager_->Stop(); } @@ -1627,6 +1634,8 @@ class UnicastTest : public UnicastTestNoInit { EXPECT_CALL(mock_hal_2_1_verifier, Call()).Times(1); EXPECT_CALL(mock_storage_load, Call()).Times(1); + std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> + framework_encode_preference; BtaAppRegisterCallback app_register_callback; EXPECT_CALL(mock_gatt_interface_, AppRegister(_, _, _)) .WillOnce(DoAll(SaveArg<0>(&gatt_callback), @@ -1636,7 +1645,8 @@ class UnicastTest : public UnicastTestNoInit { base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load), base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, - &mock_hal_2_1_verifier)); + &mock_hal_2_1_verifier), + framework_encode_preference); SyncOnMainLoop(); ASSERT_TRUE(gatt_callback); @@ -1675,6 +1685,8 @@ TEST_F(UnicastTestNoInit, InitializeNoHal_2_1) { ON_CALL(mock_gatt_interface_, AppRegister(_, _, _)) .WillByDefault(DoAll(SaveArg<0>(&gatt_callback), SaveArg<1>(&app_register_callback))); + std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> + framework_encode_preference; EXPECT_DEATH( LeAudioClient::Initialize( @@ -1682,7 +1694,8 @@ TEST_F(UnicastTestNoInit, InitializeNoHal_2_1) { base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load), base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, - &mock_hal_2_1_verifier)), + &mock_hal_2_1_verifier), + framework_encode_preference), ", LE Audio Client requires Bluetooth Audio HAL V2.1 at least. Either " "disable LE Audio Profile, or update your HAL"); } @@ -1769,6 +1782,29 @@ TEST_F(UnicastTest, ConnectDisconnectOneEarbud) { DisconnectLeAudio(test_address0, 1); } +/* same as above case except the disconnect is initiated by remote */ +TEST_F(UnicastTest, ConnectRemoteDisconnectOneEarbud) { + const RawAddress test_address0 = GetTestAddress(0); + SetSampleDatabaseEarbudsValid(1, test_address0, + codec_spec_conf::kLeAudioLocationStereo, + codec_spec_conf::kLeAudioLocationStereo); + EXPECT_CALL(mock_client_callbacks_, + OnConnectionState(ConnectionState::CONNECTED, test_address0)) + .Times(1); + ConnectLeAudio(test_address0); + EXPECT_CALL(mock_client_callbacks_, + OnConnectionState(ConnectionState::DISCONNECTED, test_address0)) + .Times(1); + /* For remote disconnection, expect stack to try background re-connect */ + EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, false, _)) + .Times(1); + global_conn_id = 1; /* Reset to keep conn_id same during re-connect */ + EXPECT_CALL(mock_client_callbacks_, + OnConnectionState(ConnectionState::CONNECTED, test_address0)) + .Times(1); + InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER); +} + TEST_F(UnicastTest, ConnectTwoEarbudsCsisGrouped) { uint8_t group_size = 2; int group_id = 2; @@ -1899,6 +1935,9 @@ TEST_F(UnicastTestNoInit, LoadStoredEarbudsCsisGrouped) { .WillByDefault( DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true))); + std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> + framework_encode_preference; + // Initialize BtaAppRegisterCallback app_register_callback; ON_CALL(mock_gatt_interface_, AppRegister(_, _, _)) @@ -1909,7 +1948,8 @@ TEST_F(UnicastTestNoInit, LoadStoredEarbudsCsisGrouped) { base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load), base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, - &mock_hal_2_1_verifier)); + &mock_hal_2_1_verifier), + framework_encode_preference); if (app_register_callback) app_register_callback.Run(gatt_if, GATT_SUCCESS); // We need to wait for the storage callback before verifying stuff @@ -1991,12 +2031,15 @@ TEST_F(UnicastTestNoInit, LoadStoredEarbudsCsisGroupedDifferently) { ON_CALL(mock_gatt_interface_, AppRegister(_, _, _)) .WillByDefault(DoAll(SaveArg<0>(&gatt_callback), SaveArg<1>(&app_register_callback))); + std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> + framework_encode_preference; LeAudioClient::Initialize( &mock_client_callbacks_, base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load), base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, - &mock_hal_2_1_verifier)); + &mock_hal_2_1_verifier), + framework_encode_preference); if (app_register_callback) app_register_callback.Run(gatt_if, GATT_SUCCESS); // We need to wait for the storage callback before verifying stuff diff --git a/system/bta/le_audio/le_audio_set_configuration_provider.cc b/system/bta/le_audio/le_audio_set_configuration_provider.cc new file mode 100644 index 0000000000..1ffc042530 --- /dev/null +++ b/system/bta/le_audio/le_audio_set_configuration_provider.cc @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "le_audio_set_configuration_provider.h" + +#include "bta_le_audio_api.h" + +void LeAudioClient::InitializeAudioSetConfigurationProvider(void) { + le_audio::AudioSetConfigurationProvider::Initialize(); +} + +void LeAudioClient::CleanupAudioSetConfigurationProvider(void) { + le_audio::AudioSetConfigurationProvider::Cleanup(); +} diff --git a/system/bta/le_audio/le_audio_set_configuration_provider.h b/system/bta/le_audio/le_audio_set_configuration_provider.h new file mode 100644 index 0000000000..679135942e --- /dev/null +++ b/system/bta/le_audio/le_audio_set_configuration_provider.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#pragma once + +#include "le_audio_types.h" + +namespace le_audio { + +/* Audio set configurations provider interface. */ +class AudioSetConfigurationProvider { + public: + AudioSetConfigurationProvider(); + virtual ~AudioSetConfigurationProvider() = default; + static AudioSetConfigurationProvider* Get(); + static void Initialize(); + static void Cleanup(); + virtual const set_configurations::AudioSetConfigurations* GetConfigurations( + ::le_audio::types::LeAudioContextType content_type) const; + + private: + struct impl; + std::unique_ptr<impl> pimpl_; +}; + +} // namespace le_audio diff --git a/system/bta/le_audio/le_audio_set_configuration_provider_json.cc b/system/bta/le_audio/le_audio_set_configuration_provider_json.cc new file mode 100644 index 0000000000..b5d55b98b9 --- /dev/null +++ b/system/bta/le_audio/le_audio_set_configuration_provider_json.cc @@ -0,0 +1,452 @@ +/* + * Copyright (c) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "audio_set_configurations_generated.h" +#include "audio_set_scenarios_generated.h" +#include "codec_manager.h" +#include "flatbuffers/idl.h" +#include "flatbuffers/util.h" +#include "le_audio_set_configuration_provider.h" +#include "osi/include/log.h" + +using le_audio::set_configurations::AudioSetConfiguration; +using le_audio::set_configurations::AudioSetConfigurations; +using le_audio::set_configurations::CodecCapabilitySetting; +using le_audio::set_configurations::LeAudioCodecIdLc3; +using le_audio::set_configurations::SetConfiguration; +using le_audio::types::LeAudioContextType; + +namespace le_audio { +using ::le_audio::CodecManager; + +#ifdef OS_ANDROID +static const std::vector< + std::pair<const char* /*schema*/, const char* /*content*/>> + kLeAudioSetConfigs = { + {"/system/etc/bluetooth/le_audio/audio_set_configurations.bfbs", + "/system/etc/bluetooth/le_audio/audio_set_configurations.json"}}; +static const std::vector< + std::pair<const char* /*schema*/, const char* /*content*/>> + kLeAudioSetScenarios = { + {"/system/etc/bluetooth/le_audio/audio_set_scenarios.bfbs", + "/system/etc/bluetooth/le_audio/audio_set_scenarios.json"}}; +#else +static const std::vector< + std::pair<const char* /*schema*/, const char* /*content*/>> + kLeAudioSetConfigs = { + {"audio_set_configurations.bfbs", "audio_set_configurations.json"}}; +static const std::vector< + std::pair<const char* /*schema*/, const char* /*content*/>> + kLeAudioSetScenarios = { + {"audio_set_scenarios.bfbs", "audio_set_scenarios.json"}}; +#endif + +/** Provides a set configurations for the given context type */ +struct AudioSetConfigurationProviderJson { + AudioSetConfigurationProviderJson() { + ASSERT_LOG(LoadContent(kLeAudioSetConfigs, kLeAudioSetScenarios), + ": Unable to load le audio set configuration files."); + } + + const AudioSetConfigurations* GetConfigurationsByContextType( + LeAudioContextType context_type) const { + if (context_configurations_.count(context_type)) + return &context_configurations_.at(context_type); + + LOG_WARN(": No predefined scenario for the context %d was found.", + (int)context_type); + + auto fallback_scenario = "Default"; + context_type = ScenarioToContextType(fallback_scenario); + + if (context_configurations_.count(context_type)) { + LOG_WARN(": Using %s scenario by default.", fallback_scenario); + return &context_configurations_.at(context_type); + } + + LOG_ERROR( + ": No fallback configuration for the 'Default' scenario or" + " no valid audio set configurations loaded at all."); + return nullptr; + }; + + private: + /* Codec configurations */ + std::map<std::string, const AudioSetConfiguration> configurations_; + + /* Maps of context types to a set of configuration structs */ + std::map<::le_audio::types::LeAudioContextType, AudioSetConfigurations> + context_configurations_; + + static const bluetooth::le_audio::CodecSpecificConfiguration* + LookupCodecSpecificParam( + const flatbuffers::Vector< + flatbuffers::Offset<bluetooth::le_audio::CodecSpecificConfiguration>>* + flat_codec_specific_params, + bluetooth::le_audio::CodecSpecificLtvGenericTypes type) { + auto it = std::find_if( + flat_codec_specific_params->cbegin(), + flat_codec_specific_params->cend(), + [&type](const auto& csc) { return (csc->type() == type); }); + return (it != flat_codec_specific_params->cend()) ? *it : nullptr; + } + + static CodecCapabilitySetting CodecCapabilitySettingFromFlat( + const bluetooth::le_audio::CodecId* flat_codec_id, + const flatbuffers::Vector< + flatbuffers::Offset<bluetooth::le_audio::CodecSpecificConfiguration>>* + flat_codec_specific_params) { + CodecCapabilitySetting codec; + + /* Cache the le_audio::types::CodecId type value */ + codec.id = types::LeAudioCodecId({ + .coding_format = flat_codec_id->coding_format(), + .vendor_company_id = flat_codec_id->vendor_company_id(), + .vendor_codec_id = flat_codec_id->vendor_codec_id(), + }); + + /* Cache the types::LeAudioLc3Config type value */ + uint8_t sampling_frequency = 0; + uint8_t frame_duration = 0; + uint32_t audio_channel_allocation = 0; + uint16_t octets_per_codec_frame = 0; + uint8_t codec_frames_blocks_per_sdu = 0; + + auto param = LookupCodecSpecificParam( + flat_codec_specific_params, + bluetooth::le_audio:: + CodecSpecificLtvGenericTypes_SUPPORTED_SAMPLING_FREQUENCY); + if (param) { + ASSERT_LOG((param->compound_value()->value()->size() == 1), + " Invalid compound value length: %d", + param->compound_value()->value()->size()); + auto ptr = param->compound_value()->value()->data(); + STREAM_TO_UINT8(sampling_frequency, ptr); + } + + param = LookupCodecSpecificParam( + flat_codec_specific_params, + bluetooth::le_audio:: + CodecSpecificLtvGenericTypes_SUPPORTED_FRAME_DURATION); + if (param) { + LOG_ASSERT(param->compound_value()->value()->size() == 1) + << " Invalid compound value length: " + << param->compound_value()->value()->size(); + auto ptr = param->compound_value()->value()->data(); + STREAM_TO_UINT8(frame_duration, ptr); + } + + param = LookupCodecSpecificParam( + flat_codec_specific_params, + bluetooth::le_audio:: + CodecSpecificLtvGenericTypes_SUPPORTED_AUDIO_CHANNEL_ALLOCATION); + if (param) { + ASSERT_LOG((param->compound_value()->value()->size() == 4), + " Invalid compound value length %d", + param->compound_value()->value()->size()); + auto ptr = param->compound_value()->value()->data(); + STREAM_TO_UINT32(audio_channel_allocation, ptr); + } + + param = LookupCodecSpecificParam( + flat_codec_specific_params, + bluetooth::le_audio:: + CodecSpecificLtvGenericTypes_SUPPORTED_OCTETS_PER_CODEC_FRAME); + if (param) { + ASSERT_LOG((param->compound_value()->value()->size() == 2), + " Invalid compound value length %d", + param->compound_value()->value()->size()); + auto ptr = param->compound_value()->value()->data(); + STREAM_TO_UINT16(octets_per_codec_frame, ptr); + } + + param = LookupCodecSpecificParam( + flat_codec_specific_params, + bluetooth::le_audio:: + CodecSpecificLtvGenericTypes_SUPPORTED_CODEC_FRAME_BLOCKS_PER_SDU); + if (param) { + ASSERT_LOG((param->compound_value()->value()->size() == 1), + " Invalid compound value length %d", + param->compound_value()->value()->size()); + auto ptr = param->compound_value()->value()->data(); + STREAM_TO_UINT8(codec_frames_blocks_per_sdu, ptr); + } + + codec.config = types::LeAudioLc3Config({ + .sampling_frequency = sampling_frequency, + .frame_duration = frame_duration, + .octets_per_codec_frame = octets_per_codec_frame, + .codec_frames_blocks_per_sdu = codec_frames_blocks_per_sdu, + .channel_count = + (uint8_t)std::bitset<32>(audio_channel_allocation).count(), + .audio_channel_allocation = audio_channel_allocation, + }); + return codec; + } + + SetConfiguration SetConfigurationFromFlatSubconfig( + const bluetooth::le_audio::AudioSetSubConfiguration* flat_subconfig) { + auto strategy_int = + static_cast<int>(flat_subconfig->configuration_strategy()); + + bool valid_strategy = + (strategy_int >= + (int)types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE) && + strategy_int < (int)types::LeAudioConfigurationStrategy::RFU; + + types::LeAudioConfigurationStrategy strategy = + valid_strategy + ? static_cast<types::LeAudioConfigurationStrategy>(strategy_int) + : types::LeAudioConfigurationStrategy::RFU; + + return SetConfiguration( + flat_subconfig->direction(), flat_subconfig->device_cnt(), + flat_subconfig->ase_cnt(), + CodecCapabilitySettingFromFlat(flat_subconfig->codec_id(), + flat_subconfig->codec_configuration()), + strategy); + } + + AudioSetConfiguration AudioSetConfigurationFromFlat( + const bluetooth::le_audio::AudioSetConfiguration* flat_cfg) { + std::vector<SetConfiguration> subconfigs; + if (flat_cfg->subconfigurations()) { + /* Load subconfigurations */ + for (auto subconfig : *flat_cfg->subconfigurations()) { + subconfigs.push_back(SetConfigurationFromFlatSubconfig(subconfig)); + } + + } else { + LOG_ERROR("Configuration '%s' has no valid subconfigurations.", + flat_cfg->name()->c_str()); + } + + return AudioSetConfiguration({flat_cfg->name()->c_str(), subconfigs}); + } + + bool LoadConfigurationsFromFiles(const char* schema_file, + const char* content_file) { + flatbuffers::Parser configurations_parser_; + std::string configurations_schema_binary_content; + bool ok = flatbuffers::LoadFile(schema_file, true, + &configurations_schema_binary_content); + if (!ok) return ok; + + /* Load the binary schema */ + ok = configurations_parser_.Deserialize( + (uint8_t*)configurations_schema_binary_content.c_str(), + configurations_schema_binary_content.length()); + if (!ok) return ok; + + /* Load the content from JSON */ + std::string configurations_json_content; + ok = flatbuffers::LoadFile(content_file, false, + &configurations_json_content); + if (!ok) return ok; + + /* Parse */ + ok = configurations_parser_.Parse(configurations_json_content.c_str()); + if (!ok) return ok; + + /* Import from flatbuffers */ + auto configurations_root = bluetooth::le_audio::GetAudioSetConfigurations( + configurations_parser_.builder_.GetBufferPointer()); + if (!configurations_root) return false; + + auto flat_configs = configurations_root->configurations(); + if ((flat_configs == nullptr) || (flat_configs->size() == 0)) return false; + + LOG_DEBUG(": Updating %d config entries.", flat_configs->size()); + for (auto const& flat_cfg : *flat_configs) { + configurations_.insert( + {flat_cfg->name()->str(), AudioSetConfigurationFromFlat(flat_cfg)}); + } + + return true; + } + + AudioSetConfigurations AudioSetConfigurationsFromFlatScenario( + const bluetooth::le_audio::AudioSetScenario* const flat_scenario) { + AudioSetConfigurations items; + if (!flat_scenario->configurations()) return items; + + for (auto config_name : *flat_scenario->configurations()) { + if (configurations_.count(config_name->str()) == 0) continue; + + auto& cfg = configurations_.at(config_name->str()); + items.push_back(&cfg); + } + + return items; + } + + bool LoadScenariosFromFiles(const char* schema_file, + const char* content_file) { + flatbuffers::Parser scenarios_parser_; + std::string scenarios_schema_binary_content; + bool ok = flatbuffers::LoadFile(schema_file, true, + &scenarios_schema_binary_content); + if (!ok) return ok; + + /* Load the binary schema */ + ok = scenarios_parser_.Deserialize( + (uint8_t*)scenarios_schema_binary_content.c_str(), + scenarios_schema_binary_content.length()); + if (!ok) return ok; + + /* Load the content from JSON */ + std::string scenarios_json_content; + ok = flatbuffers::LoadFile(content_file, false, &scenarios_json_content); + if (!ok) return ok; + + /* Parse */ + ok = scenarios_parser_.Parse(scenarios_json_content.c_str()); + if (!ok) return ok; + + /* Import from flatbuffers */ + auto scenarios_root = bluetooth::le_audio::GetAudioSetScenarios( + scenarios_parser_.builder_.GetBufferPointer()); + if (!scenarios_root) return false; + + auto flat_scenarios = scenarios_root->scenarios(); + if ((flat_scenarios == nullptr) || (flat_scenarios->size() == 0)) + return false; + + LOG_DEBUG(": Updating %d scenarios.", flat_scenarios->size()); + for (auto const& scenario : *flat_scenarios) { + context_configurations_.insert_or_assign( + ScenarioToContextType(scenario->name()->c_str()), + AudioSetConfigurationsFromFlatScenario(scenario)); + } + + return true; + } + + bool LoadContent( + std::vector<std::pair<const char* /*schema*/, const char* /*content*/>> + config_files, + std::vector<std::pair<const char* /*schema*/, const char* /*content*/>> + scenario_files) { + for (auto [schema, content] : config_files) { + if (!LoadConfigurationsFromFiles(schema, content)) return false; + } + + for (auto [schema, content] : scenario_files) { + if (!LoadScenariosFromFiles(schema, content)) return false; + } + return true; + } + + std::string ContextTypeToScenario( + ::le_audio::types::LeAudioContextType context_type) { + switch (context_type) { + case types::LeAudioContextType::MEDIA: + return "Media"; + case types::LeAudioContextType::CONVERSATIONAL: + return "Conversational"; + case types::LeAudioContextType::RINGTONE: + return "Ringtone"; + default: + return "Default"; + } + } + + static ::le_audio::types::LeAudioContextType ScenarioToContextType( + std::string scenario) { + static const std::map<std::string, ::le_audio::types::LeAudioContextType> + scenarios = { + {"Media", types::LeAudioContextType::MEDIA}, + {"Conversational", types::LeAudioContextType::CONVERSATIONAL}, + {"Ringtone", types::LeAudioContextType::RINGTONE}, + {"Default", types::LeAudioContextType::UNSPECIFIED}, + }; + return scenarios.count(scenario) ? scenarios.at(scenario) + : types::LeAudioContextType::RFU; + } +}; + +struct AudioSetConfigurationProvider::impl { + impl(const AudioSetConfigurationProvider& config_provider) + : config_provider_(config_provider) {} + + void Initialize() { + ASSERT_LOG(!config_provider_impl_, " Config provider not available."); + config_provider_impl_ = + std::make_unique<AudioSetConfigurationProviderJson>(); + } + + void Cleanup() { + ASSERT_LOG(config_provider_impl_, " Config provider not available."); + config_provider_impl_.reset(); + } + + bool IsRunning() { return config_provider_impl_ ? true : false; } + + const AudioSetConfigurationProvider& config_provider_; + std::unique_ptr<AudioSetConfigurationProviderJson> config_provider_impl_; +}; + +static std::unique_ptr<AudioSetConfigurationProvider> config_provider; + +AudioSetConfigurationProvider::AudioSetConfigurationProvider() + : pimpl_(std::make_unique<AudioSetConfigurationProvider::impl>(*this)) {} + +void AudioSetConfigurationProvider::Initialize() { + if (!config_provider) + config_provider = std::make_unique<AudioSetConfigurationProvider>(); + + if (!config_provider->pimpl_->IsRunning()) + config_provider->pimpl_->Initialize(); +} + +void AudioSetConfigurationProvider::Cleanup() { + if (!config_provider) return; + if (config_provider->pimpl_->IsRunning()) config_provider->pimpl_->Cleanup(); + config_provider.reset(); +} + +AudioSetConfigurationProvider* AudioSetConfigurationProvider::Get() { + return config_provider.get(); +} + +const set_configurations::AudioSetConfigurations* +AudioSetConfigurationProvider::GetConfigurations( + ::le_audio::types::LeAudioContextType content_type) const { + if (CodecManager::GetInstance()->GetCodecLocation() == + types::CodecLocation::ADSP) { + LOG_DEBUG("Get offload config for the context type: %d", (int)content_type); + const AudioSetConfigurations* offload_confs = + CodecManager::GetInstance()->GetOffloadCodecConfig(content_type); + + if (offload_confs != nullptr && !(*offload_confs).empty()) { + return offload_confs; + } + + // TODO: Need to have a mechanism to switch to software session if offload + // doesn't support. + } + + LOG_DEBUG("Get software config for the context type: %d", (int)content_type); + + if (pimpl_->IsRunning()) + return pimpl_->config_provider_impl_->GetConfigurationsByContextType( + content_type); + + return nullptr; +} + +} // namespace le_audio diff --git a/system/bta/le_audio/le_audio_types.cc b/system/bta/le_audio/le_audio_types.cc index c74e8ecbc7..3c082fb338 100644 --- a/system/bta/le_audio/le_audio_types.cc +++ b/system/bta/le_audio/le_audio_types.cc @@ -36,6 +36,7 @@ using types::LeAudioContextType; namespace set_configurations { using set_configurations::CodecCapabilitySetting; +using types::CodecLocation; using types::kLeAudioCodingFormatLC3; using types::kLeAudioDirectionSink; using types::kLeAudioDirectionSource; @@ -225,18 +226,6 @@ bool IsCodecCapabilitySettingSupported( } } -const AudioSetConfigurations* get_confs_by_type(LeAudioContextType type) { - switch (type) { - case LeAudioContextType::MEDIA: - return &audio_set_conf_media; - case LeAudioContextType::CONVERSATIONAL: - return &audio_set_conf_conversational; - case LeAudioContextType::RINGTONE: - return &audio_set_conf_ringtone; - default: - return &audio_set_conf_default; - } -} uint32_t CodecCapabilitySetting::GetConfigSamplingFrequency() const { switch (id.coding_format) { case kLeAudioCodingFormatLC3: diff --git a/system/bta/le_audio/le_audio_types.h b/system/bta/le_audio/le_audio_types.h index 382683ad3c..5bd655c806 100644 --- a/system/bta/le_audio/le_audio_types.h +++ b/system/bta/le_audio/le_audio_types.h @@ -268,7 +268,9 @@ constexpr uint16_t kLeAudioVendorCodecIdUndefined = 0x00; /* Metadata types from Assigned Numbers */ constexpr uint8_t kLeAudioMetadataTypePreferredAudioContext = 0x01; constexpr uint8_t kLeAudioMetadataTypeStreamingAudioContext = 0x02; -constexpr uint8_t kLeAudioMetadataTypeCcidList = 0x03; +constexpr uint8_t kLeAudioMetadataTypeProgramInfo = 0x03; +constexpr uint8_t kLeAudioMetadataTypeLanguage = 0x04; +constexpr uint8_t kLeAudioMetadataTypeCcidList = 0x05; constexpr uint8_t kLeAudioMetadataTypeLen = 1; constexpr uint8_t kLeAudioMetadataLenLen = 1; @@ -629,321 +631,6 @@ static constexpr uint32_t kChannelAllocationStereo = codec_spec_conf::kLeAudioLocationFrontLeft | codec_spec_conf::kLeAudioLocationFrontRight; -/** - * Supported audio codec capability settings - * - * The subset of capabilities defined in BAP_Validation_r13 Table 3.6. - */ -constexpr CodecCapabilitySetting codec_lc3_16_1(uint8_t channel_count) { - return CodecCapabilitySetting{ - .id = LeAudioCodecIdLc3, - .config = types::LeAudioLc3Config({ - .sampling_frequency = codec_spec_conf::kLeAudioSamplingFreq16000Hz, - .frame_duration = codec_spec_conf::kLeAudioCodecLC3FrameDur7500us, - .octets_per_codec_frame = codec_spec_conf::kLeAudioCodecLC3FrameLen30, - .channel_count = channel_count, - .audio_channel_allocation = 0, - })}; -} - -constexpr CodecCapabilitySetting codec_lc3_16_2(uint8_t channel_count) { - return CodecCapabilitySetting{ - .id = LeAudioCodecIdLc3, - .config = types::LeAudioLc3Config({ - .sampling_frequency = codec_spec_conf::kLeAudioSamplingFreq16000Hz, - .frame_duration = codec_spec_conf::kLeAudioCodecLC3FrameDur10000us, - .octets_per_codec_frame = codec_spec_conf::kLeAudioCodecLC3FrameLen40, - .channel_count = channel_count, - .audio_channel_allocation = 0, - })}; -} - -constexpr CodecCapabilitySetting codec_lc3_48_4(uint8_t channel_count) { - return CodecCapabilitySetting{ - .id = LeAudioCodecIdLc3, - .config = types::LeAudioLc3Config({ - .sampling_frequency = codec_spec_conf::kLeAudioSamplingFreq48000Hz, - .frame_duration = codec_spec_conf::kLeAudioCodecLC3FrameDur10000us, - .octets_per_codec_frame = - codec_spec_conf::kLeAudioCodecLC3FrameLen120, - .channel_count = channel_count, - .audio_channel_allocation = 0, - })}; -} - -/* - * AudioSetConfiguration defines the audio set configuration and codec settings - * to to be used by le audio policy to match the required configuration with - * audio server capabilities. The codec settings are defined with respect to - * "Broadcast Source audio capability configuration support requirements" - * defined in BAP d09r06 - */ -const AudioSetConfiguration kSingleDev_OneChanMonoSnk_16_2 = { - .name = "kSingleDev_OneChanMonoSnk_16_2", - .confs = {SetConfiguration( - types::kLeAudioDirectionSink, 1, 1, - codec_lc3_16_2( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel))}}; - -const AudioSetConfiguration kSingleDev_OneChanMonoSnk_16_1 = { - .name = "kSingleDev_OneChanMonoSnk_16_1", - .confs = {SetConfiguration( - types::kLeAudioDirectionSink, 1, 1, - codec_lc3_16_1( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel))}}; - -const AudioSetConfiguration kSingleDev_TwoChanStereoSnk_16_1 = { - .name = "kSingleDev_TwoChanStereoSnk_16_1", - .confs = {SetConfiguration( - types::kLeAudioDirectionSink, 1, 1, - codec_lc3_16_1(codec_spec_caps::kLeAudioCodecLC3ChannelCountTwoChannel), - le_audio::types::LeAudioConfigurationStrategy:: - STEREO_ONE_CIS_PER_DEVICE)}}; - -const AudioSetConfiguration kSingleDev_OneChanStereoSnk_16_1 = { - .name = "kSingleDev_OneChanStereoSnk_16_1", - .confs = {SetConfiguration( - types::kLeAudioDirectionSink, 1, 2, - codec_lc3_16_1( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel), - le_audio::types::LeAudioConfigurationStrategy:: - STEREO_TWO_CISES_PER_DEVICE)}}; - -const AudioSetConfiguration kDualDev_OneChanStereoSnk_16_1 = { - .name = "kDualDev_OneChanStereoSnk_16_1", - .confs = {SetConfiguration( - types::kLeAudioDirectionSink, 2, 2, - codec_lc3_16_1( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel))}}; - -const AudioSetConfiguration kSingleDev_TwoChanStereoSnk_48_4 = { - .name = "kSingleDev_TwoChanStereoSnk_48_4", - .confs = {SetConfiguration( - types::kLeAudioDirectionSink, 1, 1, - codec_lc3_48_4(codec_spec_caps::kLeAudioCodecLC3ChannelCountTwoChannel), - le_audio::types::LeAudioConfigurationStrategy:: - STEREO_ONE_CIS_PER_DEVICE)}}; - -const AudioSetConfiguration kDualDev_OneChanStereoSnk_48_4 = { - .name = "kDualDev_OneChanStereoSnk_48_4", - .confs = {SetConfiguration( - types::kLeAudioDirectionSink, 2, 2, - codec_lc3_48_4( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel))}}; - -const AudioSetConfiguration kSingleDev_OneChanStereoSnk_48_4 = { - .name = "kSingleDev_OneChanStereoSnk_48_4", - .confs = {SetConfiguration( - types::kLeAudioDirectionSink, 1, 2, - codec_lc3_48_4( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel), - le_audio::types::LeAudioConfigurationStrategy:: - STEREO_TWO_CISES_PER_DEVICE)}}; - -const AudioSetConfiguration kSingleDev_OneChanMonoSnk_48_4 = { - .name = "kSingleDev_OneChanMonoSnk_48_4", - .confs = {SetConfiguration( - types::kLeAudioDirectionSink, 1, 1, - codec_lc3_48_4( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel))}}; - -const AudioSetConfiguration kSingleDev_TwoChanStereoSnk_16_2 = { - .name = "kSingleDev_TwoChanStereoSnk_16_2", - .confs = {SetConfiguration( - types::kLeAudioDirectionSink, 1, 1, - codec_lc3_16_2(codec_spec_caps::kLeAudioCodecLC3ChannelCountTwoChannel), - le_audio::types::LeAudioConfigurationStrategy:: - STEREO_ONE_CIS_PER_DEVICE)}}; - -const AudioSetConfiguration kSingleDev_OneChanStereoSnk_16_2 = { - .name = "kSingleDev_OneChanStereoSnk_16_2", - .confs = {SetConfiguration( - types::kLeAudioDirectionSink, 1, 2, - codec_lc3_16_2( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel), - le_audio::types::LeAudioConfigurationStrategy:: - STEREO_TWO_CISES_PER_DEVICE)}}; - -const AudioSetConfiguration kDualDev_OneChanStereoSnk_16_2 = { - .name = "kDualDev_OneChanStereoSnk_16_2", - .confs = {SetConfiguration( - types::kLeAudioDirectionSink, 2, 2, - codec_lc3_16_2( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel))}}; - -const AudioSetConfiguration kSingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1 = { - .name = "kSingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1", - .confs = { - SetConfiguration( - types::kLeAudioDirectionSink, 1, 1, - codec_lc3_16_1( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel)), - SetConfiguration( - types::kLeAudioDirectionSource, 1, 1, - codec_lc3_16_1( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel))}}; - -const AudioSetConfiguration kSingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2 = { - .name = "kSingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2", - .confs = { - SetConfiguration( - types::kLeAudioDirectionSink, 1, 1, - codec_lc3_16_2( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel)), - SetConfiguration( - types::kLeAudioDirectionSource, 1, 1, - codec_lc3_16_2( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel))}}; - -const AudioSetConfiguration kSingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2 = { - .name = "kSingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2", - .confs = { - SetConfiguration( - types::kLeAudioDirectionSink, 1, 1, - codec_lc3_16_2( - codec_spec_caps::kLeAudioCodecLC3ChannelCountTwoChannel), - le_audio::types::LeAudioConfigurationStrategy:: - STEREO_ONE_CIS_PER_DEVICE), - SetConfiguration( - types::kLeAudioDirectionSource, 1, 1, - codec_lc3_16_2( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel))}}; - -const AudioSetConfiguration - kDualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2 = { - .name = "kDualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2", - .confs = { - SetConfiguration( - types::kLeAudioDirectionSink, 2, 4, - codec_lc3_16_2( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel), - le_audio::types::LeAudioConfigurationStrategy:: - STEREO_TWO_CISES_PER_DEVICE), - SetConfiguration( - types::kLeAudioDirectionSource, 1, 1, - codec_lc3_16_2( - codec_spec_caps:: - kLeAudioCodecLC3ChannelCountSingleChannel))}}; - -const AudioSetConfiguration kSingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2 = { - .name = "kSingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2", - .confs = { - SetConfiguration( - types::kLeAudioDirectionSink, 1, 2, - codec_lc3_16_2( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel), - le_audio::types::LeAudioConfigurationStrategy:: - STEREO_TWO_CISES_PER_DEVICE), - SetConfiguration( - types::kLeAudioDirectionSource, 1, 1, - codec_lc3_16_2( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel))}}; - -const AudioSetConfiguration kDualDev_OneChanStereoSnk_OneChanMonoSrc_16_2 = { - .name = "kDualDev_OneChanStereoSnk_OneChanMonoSrc_16_2", - .confs = { - SetConfiguration( - types::kLeAudioDirectionSink, 2, 2, - codec_lc3_16_2( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel)), - SetConfiguration( - types::kLeAudioDirectionSource, 1, 1, - codec_lc3_16_2( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel))}}; - -const AudioSetConfiguration kSingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1 = { - .name = "kSingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1", - .confs = { - SetConfiguration( - types::kLeAudioDirectionSink, 1, 1, - codec_lc3_16_1( - codec_spec_caps::kLeAudioCodecLC3ChannelCountTwoChannel), - le_audio::types::LeAudioConfigurationStrategy:: - STEREO_ONE_CIS_PER_DEVICE), - SetConfiguration( - types::kLeAudioDirectionSource, 1, 1, - codec_lc3_16_1( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel))}}; - -const AudioSetConfiguration kSingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1 = { - .name = "kSingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1", - .confs = { - SetConfiguration( - types::kLeAudioDirectionSink, 1, 2, - codec_lc3_16_1( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel), - le_audio::types::LeAudioConfigurationStrategy:: - STEREO_TWO_CISES_PER_DEVICE), - SetConfiguration( - types::kLeAudioDirectionSource, 1, 1, - codec_lc3_16_1( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel))}}; - -const AudioSetConfiguration kDualDev_OneChanStereoSnk_OneChanMonoSrc_16_1 = { - .name = "kDualDev_OneChanStereoSnk_OneChanMonoSrc_16_1", - .confs = { - SetConfiguration( - types::kLeAudioDirectionSink, 2, 2, - codec_lc3_16_1( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel)), - SetConfiguration( - types::kLeAudioDirectionSource, 1, 1, - codec_lc3_16_1( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel))}}; - -const AudioSetConfiguration - kDualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1 = { - .name = "kDualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1", - .confs = { - SetConfiguration( - types::kLeAudioDirectionSink, 2, 4, - codec_lc3_16_1( - codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel), - le_audio::types::LeAudioConfigurationStrategy:: - STEREO_TWO_CISES_PER_DEVICE), - SetConfiguration( - types::kLeAudioDirectionSource, 1, 1, - codec_lc3_16_1( - codec_spec_caps:: - kLeAudioCodecLC3ChannelCountSingleChannel))}}; - -/* Defined audio scenario linked with context type, priority sorted */ -const AudioSetConfigurations audio_set_conf_ringtone = { - &kDualDev_OneChanStereoSnk_16_2, &kDualDev_OneChanStereoSnk_16_1, - &kSingleDev_OneChanStereoSnk_16_2, &kSingleDev_OneChanStereoSnk_16_1, - &kSingleDev_TwoChanStereoSnk_16_2, &kSingleDev_TwoChanStereoSnk_16_1, - &kSingleDev_OneChanMonoSnk_16_2, &kSingleDev_OneChanMonoSnk_16_1, -}; - -const AudioSetConfigurations audio_set_conf_conversational = { - &kDualDev_OneChanStereoSnk_OneChanMonoSrc_16_2, - &kDualDev_OneChanStereoSnk_OneChanMonoSrc_16_1, - &kDualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2, - &kDualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1, - &kSingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2, - &kSingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1, - &kSingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2, - &kSingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1, - &kSingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2, - &kSingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1, -}; - -const AudioSetConfigurations audio_set_conf_media = { - &kDualDev_OneChanStereoSnk_48_4, &kDualDev_OneChanStereoSnk_16_2, - &kDualDev_OneChanStereoSnk_16_1, &kSingleDev_OneChanStereoSnk_48_4, - &kSingleDev_OneChanStereoSnk_16_2, &kSingleDev_OneChanStereoSnk_16_1, - &kSingleDev_TwoChanStereoSnk_48_4, &kSingleDev_TwoChanStereoSnk_16_2, - &kSingleDev_TwoChanStereoSnk_16_1, &kSingleDev_OneChanMonoSnk_48_4, - &kSingleDev_OneChanMonoSnk_16_2, &kSingleDev_OneChanMonoSnk_16_1, -}; - -const AudioSetConfigurations audio_set_conf_default = { - &kDualDev_OneChanStereoSnk_16_2, - &kSingleDev_OneChanStereoSnk_16_2, - &kSingleDev_TwoChanStereoSnk_16_2, - &kSingleDev_OneChanMonoSnk_16_2, -}; - /* Declarations */ bool check_if_may_cover_scenario( const AudioSetConfigurations* audio_set_configurations, uint8_t group_size); @@ -952,7 +639,6 @@ bool check_if_may_cover_scenario( bool IsCodecCapabilitySettingSupported( const types::acs_ac_record& pac_record, const CodecCapabilitySetting& codec_capability_setting); -const AudioSetConfigurations* get_confs_by_type(types::LeAudioContextType type); uint8_t get_num_of_devices_in_configuration( const AudioSetConfiguration* audio_set_configuration); } // namespace set_configurations diff --git a/system/bta/le_audio/mock_codec_manager.cc b/system/bta/le_audio/mock_codec_manager.cc index 15c952a323..eaacf4bd51 100644 --- a/system/bta/le_audio/mock_codec_manager.cc +++ b/system/bta/le_audio/mock_codec_manager.cc @@ -38,16 +38,27 @@ types::CodecLocation CodecManager::GetCodecLocation() const { } void CodecManager::UpdateActiveSourceAudioConfig( - const stream_configuration& stream_conf, uint16_t delay) { - if (pimpl_) return pimpl_->UpdateActiveSourceAudioConfig(stream_conf, delay); + const stream_configuration& stream_conf, uint16_t delay_ms) { + if (pimpl_) + return pimpl_->UpdateActiveSourceAudioConfig(stream_conf, delay_ms); } void CodecManager::UpdateActiveSinkAudioConfig( - const stream_configuration& stream_conf, uint16_t delay) { - if (pimpl_) return pimpl_->UpdateActiveSinkAudioConfig(stream_conf, delay); + const stream_configuration& stream_conf, uint16_t delay_ms) { + if (pimpl_) return pimpl_->UpdateActiveSinkAudioConfig(stream_conf, delay_ms); } -void CodecManager::Start() { +const set_configurations::AudioSetConfigurations* +CodecManager::GetOffloadCodecConfig(types::LeAudioContextType ctx_type) { + if (!pimpl_) return nullptr; + return pimpl_->GetOffloadCodecConfig(ctx_type); +} + +void CodecManager::Start( + const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>& + offloading_preference, + const std::vector<set_configurations::AudioSetConfiguration>& + adsp_capabilities) { // It is needed here as CodecManager which is a singleton creates it, but in // this mock we want to destroy and recreate the mock on each test case. if (!pimpl_) { diff --git a/system/bta/le_audio/mock_codec_manager.h b/system/bta/le_audio/mock_codec_manager.h index ef020a6a86..d191a5fd04 100644 --- a/system/bta/le_audio/mock_codec_manager.h +++ b/system/bta/le_audio/mock_codec_manager.h @@ -25,6 +25,9 @@ class MockCodecManager { static MockCodecManager* GetInstance(); MockCodecManager() = default; + MockCodecManager(const MockCodecManager&) = delete; + MockCodecManager& operator=(const MockCodecManager&) = delete; + virtual ~MockCodecManager() = default; MOCK_METHOD((le_audio::types::CodecLocation), GetCodecLocation, (), (const)); @@ -34,10 +37,10 @@ class MockCodecManager { MOCK_METHOD((void), UpdateActiveSinkAudioConfig, (const le_audio::stream_configuration& stream_conf, uint16_t delay)); + MOCK_METHOD((le_audio::set_configurations::AudioSetConfigurations*), + GetOffloadCodecConfig, + (le_audio::types::LeAudioContextType ctx_type), (const)); MOCK_METHOD((void), Start, ()); MOCK_METHOD((void), Stop, ()); - - private: - DISALLOW_COPY_AND_ASSIGN(MockCodecManager); }; diff --git a/system/bta/le_audio/mock_iso_manager.h b/system/bta/le_audio/mock_iso_manager.h index e4a10abccb..8db3ade2a5 100644 --- a/system/bta/le_audio/mock_iso_manager.h +++ b/system/bta/le_audio/mock_iso_manager.h @@ -26,6 +26,9 @@ struct MockIsoManager { static MockIsoManager* GetInstance(); MockIsoManager() = default; + MockIsoManager(const MockIsoManager&) = delete; + MockIsoManager& operator=(const MockIsoManager&) = delete; + virtual ~MockIsoManager() = default; MOCK_METHOD((void), RegisterCigCallbacks, @@ -68,7 +71,4 @@ struct MockIsoManager { MOCK_METHOD((void), Start, ()); MOCK_METHOD((void), Stop, ()); - - private: - DISALLOW_COPY_AND_ASSIGN(MockIsoManager); }; diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc index 3eb38ae644..e71af9516c 100644 --- a/system/bta/le_audio/state_machine.cc +++ b/system/bta/le_audio/state_machine.cc @@ -211,7 +211,8 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { void StopStream(LeAudioDeviceGroup* group) override { if (group->IsReleasing()) { - LOG(INFO) << __func__ << ", group already in releasing process"; + LOG(INFO) << __func__ << ", group: " << group->group_id_ + << " already in releasing process"; return; } @@ -499,6 +500,13 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { return; } + /* If group is in Idle there is nothing to do here */ + if ((group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) && + (group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE)) { + LOG(INFO) << __func__ << " group: " << group->group_id_ << " is in IDLE"; + return; + } + auto* stream_conf = &group->stream_conf; if (!stream_conf->sink_streams.empty() || !stream_conf->source_streams.empty()) { @@ -544,13 +552,8 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { } /* Group is not connected and all the CISes are down. - * If group is in Idle there is nothing to do here */ - if (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) { - LOG(INFO) << __func__ << " group: " << group->group_id_ << " is in IDLE"; - return; - } - - /* Clean states and destroy HCI group */ + * Clean states and destroy HCI group + */ group->SetState(AseState::BTA_LE_AUDIO_ASE_STATE_IDLE); group->SetTargetState(AseState::BTA_LE_AUDIO_ASE_STATE_IDLE); if (alarm_is_scheduled(watchdog_)) alarm_cancel(watchdog_); @@ -594,7 +597,9 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine { } if (group->GetTargetState() != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) { - LOG(ERROR) << __func__ << ", Unintended CIS establishement event came"; + LOG(ERROR) << __func__ + << ", Unintended CIS establishement event came for group id:" + << group->group_id_; StopStream(group); return; } diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc index c11fab8f30..aa700730e5 100644 --- a/system/bta/le_audio/state_machine_test.cc +++ b/system/bta/le_audio/state_machine_test.cc @@ -27,6 +27,7 @@ #include "btm_api_mock.h" #include "client_parser.h" #include "fake_osi.h" +#include "le_audio_set_configuration_provider.h" #include "mock_codec_manager.h" #include "mock_controller.h" #include "mock_iso_manager.h" @@ -136,14 +137,16 @@ class MockLeAudioGroupStateMachineCallbacks : public LeAudioGroupStateMachine::Callbacks { public: MockLeAudioGroupStateMachineCallbacks() = default; + MockLeAudioGroupStateMachineCallbacks( + const MockLeAudioGroupStateMachineCallbacks&) = delete; + MockLeAudioGroupStateMachineCallbacks& operator=( + const MockLeAudioGroupStateMachineCallbacks&) = delete; + ~MockLeAudioGroupStateMachineCallbacks() override = default; MOCK_METHOD((void), StatusReportCb, (int group_id, bluetooth::le_audio::GroupStreamStatus status), (override)); MOCK_METHOD((void), OnStateTransitionTimeout, (int group_id), (override)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockLeAudioGroupStateMachineCallbacks); }; class StateMachineTest : public Test { @@ -156,6 +159,7 @@ class StateMachineTest : public Test { gatt::SetMockBtaGattQueue(&gatt_queue); ase_id_last_assigned = types::ase::kAseIdInvalid; + ::le_audio::AudioSetConfigurationProvider::Initialize(); LeAudioGroupStateMachine::Initialize(&mock_callbacks_); // Support 2M Phy @@ -384,7 +388,11 @@ class StateMachineTest : public Test { void ConfigCodecManagerMock() { codec_manager_ = le_audio::CodecManager::GetInstance(); ASSERT_NE(codec_manager_, nullptr); - codec_manager_->Start(); + std::vector<bluetooth::le_audio::btle_audio_codec_config_t> + mock_offloading_preference(0); + std::vector<set_configurations::AudioSetConfiguration> + mock_adsp_capabilities(0); + codec_manager_->Start(mock_offloading_preference, mock_adsp_capabilities); mock_codec_manager_ = MockCodecManager::GetInstance(); ASSERT_NE(mock_codec_manager_, nullptr); ON_CALL(*mock_codec_manager_, GetCodecLocation()) @@ -408,6 +416,7 @@ class StateMachineTest : public Test { le_audio_devices_.clear(); cached_codec_configuration_map_.clear(); LeAudioGroupStateMachine::Cleanup(); + ::le_audio::AudioSetConfigurationProvider::Cleanup(); } std::shared_ptr<LeAudioDevice> PrepareConnectedDevice(uint8_t id, @@ -2116,6 +2125,31 @@ TEST_F(StateMachineTest, testAseAutonomousRelease) { } } +TEST_F(StateMachineTest, testStateTransitionTimeoutOnIdleState) { + const auto context_type = kContextTypeRingtone; + const int leaudio_group_id = 4; + + // Prepare fake connected device group + auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type); + + auto* leAudioDevice = group->GetFirstDevice(); + EXPECT_CALL(gatt_queue, + WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _, + GATT_WRITE_NO_RSP, _, _)) + .Times(1); + + // Start the configuration and stream Media content + ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream( + group, static_cast<types::LeAudioContextType>(context_type))); + + // Disconnect device + LeAudioGroupStateMachine::Get()->ProcessHciNotifAclDisconnected( + group, leAudioDevice); + + // Make sure timeout is cleared + ASSERT_TRUE(fake_osi_alarm_set_on_mloop_.cb == nullptr); +} + TEST_F(StateMachineTest, testStateTransitionTimeout) { const auto context_type = kContextTypeRingtone; const int leaudio_group_id = 4; diff --git a/system/bta/vc/devices.h b/system/bta/vc/devices.h index 71dc6c9e00..f2ce3014ba 100644 --- a/system/bta/vc/devices.h +++ b/system/bta/vc/devices.h @@ -17,6 +17,7 @@ #pragma once +#include <algorithm> #include <cstdint> #include <unordered_set> #include <vector> diff --git a/system/bta/vc/types.h b/system/bta/vc/types.h index 4461d65c92..a8a4b252c8 100644 --- a/system/bta/vc/types.h +++ b/system/bta/vc/types.h @@ -50,6 +50,7 @@ struct VolumeOperation { int group_id_; bool started_; + bool is_autonomous_; uint8_t opcode_; std::vector<uint8_t> arguments_; @@ -57,11 +58,12 @@ struct VolumeOperation { std::vector<RawAddress> devices_; alarm_t* operation_timeout_; - VolumeOperation(int operation_id, int group_id, uint8_t opcode, + VolumeOperation(int operation_id, int group_id, bool is_autonomous, uint8_t opcode, std::vector<uint8_t> arguments, std::vector<RawAddress> devices) : operation_id_(operation_id), group_id_(group_id), + is_autonomous_(is_autonomous), opcode_(opcode), arguments_(arguments), devices_(devices) { diff --git a/system/bta/vc/vc.cc b/system/bta/vc/vc.cc index 08f61e8774..23a20bf8c8 100644 --- a/system/bta/vc/vc.cc +++ b/system/bta/vc/vc.cc @@ -285,7 +285,7 @@ class VolumeControlImpl : public VolumeControl { if (!csis_api) { DLOG(INFO) << __func__ << " Csis is not available"; callbacks_->OnVolumeStateChanged(device->address, device->volume, - device->mute); + device->mute, true); return; } @@ -294,7 +294,7 @@ class VolumeControlImpl : public VolumeControl { if (group_id == bluetooth::groups::kGroupUnknown) { DLOG(INFO) << __func__ << " No group for device " << device->address; callbacks_->OnVolumeStateChanged(device->address, device->volume, - device->mute); + device->mute, true); return; } @@ -310,7 +310,7 @@ class VolumeControlImpl : public VolumeControl { if (is_volume_change) { std::vector<uint8_t> arg({device->volume}); - PrepareVolumeControlOperation(devices, group_id, + PrepareVolumeControlOperation(devices, group_id, true, kControlPointOpcodeSetAbsoluteVolume, arg); } @@ -318,7 +318,7 @@ class VolumeControlImpl : public VolumeControl { std::vector<uint8_t> arg; uint8_t opcode = device->mute ? kControlPointOpcodeMute : kControlPointOpcodeUnmute; - PrepareVolumeControlOperation(devices, group_id, opcode, arg); + PrepareVolumeControlOperation(devices, group_id, true, opcode, arg); } StartQueueOperation(); @@ -354,7 +354,7 @@ class VolumeControlImpl : public VolumeControl { /* This is just a read, send single notification */ if (!is_notification) { callbacks_->OnVolumeStateChanged(device->address, device->volume, - device->mute); + device->mute, false); return; } @@ -384,12 +384,15 @@ class VolumeControlImpl : public VolumeControl { return; } - if (op->IsGroupOperation()) + if (op->IsGroupOperation()) { callbacks_->OnGroupVolumeStateChanged(op->group_id_, device->volume, - device->mute); - else + device->mute, op->is_autonomous_); + } else { + /* op->is_autonomous_ will always be false, + since we only make it true for group operations */ callbacks_->OnVolumeStateChanged(device->address, device->volume, - device->mute); + device->mute, false); + } ongoing_operations_.erase(op); StartQueueOperation(); @@ -591,14 +594,16 @@ class VolumeControlImpl : public VolumeControl { } void PrepareVolumeControlOperation(std::vector<RawAddress>& devices, - int group_id, uint8_t opcode, + int group_id, bool is_autonomous, + uint8_t opcode, std::vector<uint8_t>& arguments) { DLOG(INFO) << __func__ << " num of devices: " << devices.size() - << " group_id: " << group_id << " opcode: " << +opcode + << " group_id: " << group_id << " is_autonomous: " << is_autonomous + << " opcode: " << +opcode << " arg size: " << arguments.size(); - ongoing_operations_.emplace_back(latest_operation_id_++, group_id, opcode, - arguments, devices); + ongoing_operations_.emplace_back(latest_operation_id_++, group_id, is_autonomous, + opcode, arguments, devices); } void SetVolume(std::variant<RawAddress, int> addr_or_group_id, @@ -613,7 +618,7 @@ class VolumeControlImpl : public VolumeControl { std::vector<RawAddress> devices = { std::get<RawAddress>(addr_or_group_id)}; - PrepareVolumeControlOperation(devices, bluetooth::groups::kGroupUnknown, + PrepareVolumeControlOperation(devices, bluetooth::groups::kGroupUnknown, false, opcode, arg); } else { /* Handle group change */ @@ -641,7 +646,7 @@ class VolumeControlImpl : public VolumeControl { return; } - PrepareVolumeControlOperation(devices, group_id, opcode, arg); + PrepareVolumeControlOperation(devices, group_id, false, opcode, arg); } StartQueueOperation(); @@ -681,7 +686,7 @@ class VolumeControlImpl : public VolumeControl { // once profile connected we can notify current states callbacks_->OnVolumeStateChanged(device->address, device->volume, - device->mute); + device->mute, false); device->EnqueueRemainingRequests(gatt_if_, chrc_read_callback_static, OnGattWriteCccStatic); diff --git a/system/bta/vc/vc_test.cc b/system/bta/vc/vc_test.cc index 41d4f20117..0e52d4a1be 100644 --- a/system/bta/vc/vc_test.cc +++ b/system/bta/vc/vc_test.cc @@ -66,18 +66,19 @@ RawAddress GetTestAddress(int index) { class MockVolumeControlCallbacks : public VolumeControlCallbacks { public: MockVolumeControlCallbacks() = default; + MockVolumeControlCallbacks(const MockVolumeControlCallbacks&) = delete; + MockVolumeControlCallbacks& operator=(const MockVolumeControlCallbacks&) = + delete; + ~MockVolumeControlCallbacks() override = default; MOCK_METHOD((void), OnConnectionState, (ConnectionState state, const RawAddress& address), (override)); MOCK_METHOD((void), OnVolumeStateChanged, - (const RawAddress& address, uint8_t volume, bool mute), + (const RawAddress& address, uint8_t volume, bool mute, bool isAutonomous), (override)); MOCK_METHOD((void), OnGroupVolumeStateChanged, - (int group_id, uint8_t volume, bool mute), (override)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockVolumeControlCallbacks); + (int group_id, uint8_t volume, bool mute, bool isAutonomous), (override)); }; class VolumeControlTest : public ::testing::Test { @@ -560,7 +561,7 @@ TEST_F(VolumeControlTest, test_subscribe_vcs_volume_state) { TEST_F(VolumeControlTest, test_read_vcs_volume_state) { const RawAddress test_address = GetTestAddress(0); - EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _)); + EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _, false)); std::vector<uint16_t> handles({0x0021}); TestReadCharacteristic(test_address, 1, handles); } @@ -605,12 +606,12 @@ class VolumeControlCallbackTest : public VolumeControlTest { TEST_F(VolumeControlCallbackTest, test_volume_state_changed) { std::vector<uint8_t> value({0x03, 0x01, 0x02}); - EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, 0x03, true)); + EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, 0x03, true, true)); GetNotificationEvent(0x0021, value); } TEST_F(VolumeControlCallbackTest, test_volume_state_changed_malformed) { - EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _)).Times(0); + EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _, _)).Times(0); std::vector<uint8_t> too_short({0x03, 0x01}); GetNotificationEvent(0x0021, too_short); std::vector<uint8_t> too_long({0x03, 0x01, 0x02, 0x03}); @@ -726,7 +727,7 @@ TEST_F(VolumeControlCsis, test_set_volume) { VolumeControl::Get()->SetVolume(group_id, 10); /* Now inject notification and make sure callback is sent up to Java layer */ - EXPECT_CALL(*callbacks, OnGroupVolumeStateChanged(group_id, 0x03, true)); + EXPECT_CALL(*callbacks, OnGroupVolumeStateChanged(group_id, 0x03, true, false)); std::vector<uint8_t> value({0x03, 0x01, 0x02}); GetNotificationEvent(conn_id_1, test_address_1, 0x0021, value); @@ -735,7 +736,7 @@ TEST_F(VolumeControlCsis, test_set_volume) { TEST_F(VolumeControlCsis, autonomus_test_set_volume) { /* Now inject notification and make sure callback is sent up to Java layer */ - EXPECT_CALL(*callbacks, OnGroupVolumeStateChanged(group_id, 0x03, false)); + EXPECT_CALL(*callbacks, OnGroupVolumeStateChanged(group_id, 0x03, false, true)); std::vector<uint8_t> value({0x03, 0x00, 0x02}); GetNotificationEvent(conn_id_1, test_address_1, 0x0021, value); diff --git a/system/btcore/fuzzer/btcore_property_fuzzer.cpp b/system/btcore/fuzzer/btcore_property_fuzzer.cpp index 0bb0c019c1..c6bfd445ba 100644 --- a/system/btcore/fuzzer/btcore_property_fuzzer.cpp +++ b/system/btcore/fuzzer/btcore_property_fuzzer.cpp @@ -58,8 +58,8 @@ void BTCorePropertyFuzzer::process(const uint8_t* data, size_t size) { property_free(property); uint32_t timeout = mFdp->ConsumeIntegral<uint32_t>(); - property = property_new_discovery_timeout(timeout); - (void)property_as_discovery_timeout(property); + property = property_new_discoverable_timeout(timeout); + (void)property_as_discoverable_timeout(property); property_free(property); std::string name = mFdp->ConsumeRandomLengthString(kRandomStringLength); diff --git a/system/btcore/include/property.h b/system/btcore/include/property.h index 73d4d41e7c..2ef94e73a0 100644 --- a/system/btcore/include/property.h +++ b/system/btcore/include/property.h @@ -46,7 +46,7 @@ bool property_equals(const bt_property_t* p1, const bt_property_t* p2); bt_property_t* property_new_addr(const RawAddress* addr); bt_property_t* property_new_device_class(const bt_device_class_t* dc); bt_property_t* property_new_device_type(bt_device_type_t device_type); -bt_property_t* property_new_discovery_timeout(const uint32_t timeout); +bt_property_t* property_new_discoverable_timeout(const uint32_t timeout); bt_property_t* property_new_name(const char* name); bt_property_t* property_new_rssi(const int8_t rssi); bt_property_t* property_new_scan_mode(bt_scan_mode_t scan_mode); @@ -62,7 +62,7 @@ void property_free_array(bt_property_t* properties, size_t count); bool property_is_addr(const bt_property_t* property); bool property_is_device_class(const bt_property_t* property); bool property_is_device_type(const bt_property_t* property); -bool property_is_discovery_timeout(const bt_property_t* property); +bool property_is_discoverable_timeout(const bt_property_t* property); bool property_is_name(const bt_property_t* property); bool property_is_rssi(const bt_property_t* property); bool property_is_scan_mode(const bt_property_t* property); @@ -74,7 +74,7 @@ const RawAddress* property_as_addr(const bt_property_t* property); const bt_device_class_t* property_as_device_class( const bt_property_t* property); bt_device_type_t property_as_device_type(const bt_property_t* property); -uint32_t property_as_discovery_timeout(const bt_property_t* property); +uint32_t property_as_discoverable_timeout(const bt_property_t* property); const bt_bdname_t* property_as_name(const bt_property_t* property); int8_t property_as_rssi(const bt_property_t* property); bt_scan_mode_t property_as_scan_mode(const bt_property_t* property); diff --git a/system/btcore/src/property.cc b/system/btcore/src/property.cc index 7b5a3033ff..94679e9961 100644 --- a/system/btcore/src/property.cc +++ b/system/btcore/src/property.cc @@ -98,9 +98,9 @@ bt_property_t* property_new_device_type(bt_device_type_t type) { BT_PROPERTY_TYPE_OF_DEVICE); } -bt_property_t* property_new_discovery_timeout(const uint32_t timeout) { +bt_property_t* property_new_discoverable_timeout(const uint32_t timeout) { return property_new_((void*)&timeout, sizeof(uint32_t), - BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT); + BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT); } bt_property_t* property_new_name(const char* name) { @@ -151,9 +151,9 @@ bool property_is_device_type(const bt_property_t* property) { return property->type == BT_PROPERTY_TYPE_OF_DEVICE; } -bool property_is_discovery_timeout(const bt_property_t* property) { +bool property_is_discoverable_timeout(const bt_property_t* property) { CHECK(property != NULL); - return property->type == BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT; + return property->type == BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT; } bool property_is_name(const bt_property_t* property) { @@ -193,8 +193,8 @@ bt_device_type_t property_as_device_type(const bt_property_t* property) { return *(const bt_device_type_t*)property->val; } -uint32_t property_as_discovery_timeout(const bt_property_t* property) { - CHECK(property_is_discovery_timeout(property)); +uint32_t property_as_discoverable_timeout(const bt_property_t* property) { + CHECK(property_is_discoverable_timeout(property)); return *(const uint32_t*)property->val; } diff --git a/system/btcore/test/property_test.cc b/system/btcore/test/property_test.cc index ee8ed22666..4e24e0d0a1 100644 --- a/system/btcore/test/property_test.cc +++ b/system/btcore/test/property_test.cc @@ -81,13 +81,13 @@ TEST_F(PropertyTest, device_type) { TEST_F(PropertyTest, discovery_timeout) { uint32_t timeout0 = 12345; - bt_property_t* property = property_new_discovery_timeout(timeout0); + bt_property_t* property = property_new_discoverable_timeout(timeout0); EXPECT_EQ(timeout0, *(uint32_t*)property->val); - EXPECT_EQ(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT, property->type); + EXPECT_EQ(BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT, property->type); EXPECT_EQ((int)sizeof(uint32_t), property->len); - uint32_t timeout1 = property_as_discovery_timeout(property); + uint32_t timeout1 = property_as_discoverable_timeout(property); EXPECT_EQ(timeout0, timeout1); property_free(property); diff --git a/system/btif/Android.bp b/system/btif/Android.bp index 92f14ea6e5..c31250d800 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -164,7 +164,6 @@ cc_defaults { "android.hardware.bluetooth.a2dp@1.0", "android.hardware.bluetooth.audio@2.0", "android.hardware.bluetooth.audio@2.1", - "android.hardware.bluetooth.audio@2.2", "libcrypto", "libflatbuffers-cpp", "libhidlbase", @@ -228,7 +227,6 @@ cc_test { "android.hardware.bluetooth.a2dp@1.0", "android.hardware.bluetooth.audio@2.0", "android.hardware.bluetooth.audio@2.1", - "android.hardware.bluetooth.audio@2.2", "android.system.suspend.control-V1-ndk", "libbinder_ndk", "libfmq", @@ -247,7 +245,6 @@ cc_test { "libbt-utils", "libFraunhoferAAC", "libg722codec", - "liblc3codec", "liblc3", "libbtdevice", "libbt-hci", @@ -470,7 +467,6 @@ cc_test { "android.hardware.bluetooth.a2dp@1.0", "android.hardware.bluetooth.audio@2.0", "android.hardware.bluetooth.audio@2.1", - "android.hardware.bluetooth.audio@2.2", "libcrypto", "libcutils", "libflatbuffers-cpp", diff --git a/system/btif/include/btif_common.h b/system/btif/include/btif_common.h index 3782b506b1..434950988f 100644 --- a/system/btif/include/btif_common.h +++ b/system/btif/include/btif_common.h @@ -232,7 +232,6 @@ void invoke_link_quality_report_cb( int retransmission_count, int packets_not_receive_count, int negative_acknowledgement_count); -void invoke_switch_buffer_size_cb(RawAddress remote_addr, - bool is_low_latency_buffer_size); +void invoke_switch_buffer_size_cb(bool is_low_latency_buffer_size); #endif /* BTIF_COMMON_H */ diff --git a/system/btif/include/btif_dm.h b/system/btif/include/btif_dm.h index dbf047670c..b3f70217a3 100644 --- a/system/btif/include/btif_dm.h +++ b/system/btif/include/btif_dm.h @@ -67,6 +67,8 @@ bool btif_dm_proc_rmt_oob(const RawAddress& bd_addr, Octet16* p_c, void btif_dm_generate_local_oob_data(tBT_TRANSPORT transport); #endif /* BTIF_DM_OOB_TEST */ +void btif_dm_clear_event_filter(); + /*callout for reading SMP properties from Text file*/ bool btif_dm_get_smp_config(tBTE_APPL_CFG* p_cfg); diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index b44d593e29..e76c617fed 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -262,7 +262,7 @@ static int set_adapter_property(const bt_property_t* property) { switch (property->type) { case BT_PROPERTY_BDNAME: case BT_PROPERTY_ADAPTER_SCAN_MODE: - case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT: + case BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT: case BT_PROPERTY_CLASS_OF_DEVICE: case BT_PROPERTY_LOCAL_IO_CAPS: case BT_PROPERTY_LOCAL_IO_CAPS_BLE: @@ -412,6 +412,14 @@ static int read_energy_info() { return BT_STATUS_SUCCESS; } +static int clear_event_filter() { + LOG_VERBOSE("%s", __func__); + if (!interface_ready()) return BT_STATUS_NOT_READY; + + do_in_main_thread(FROM_HERE, base::BindOnce(btif_dm_clear_event_filter)); + return BT_STATUS_SUCCESS; +} + static void dump(int fd, const char** arguments) { btif_debug_conn_dump(fd); btif_debug_bond_event_dump(fd); @@ -620,7 +628,8 @@ static int set_dynamic_audio_buffer_size(int codec, int size) { static bool allow_low_latency_audio(bool allowed, const RawAddress& address) { LOG_INFO("%s %s", __func__, allowed ? "true" : "false"); - return bluetooth::audio::a2dp::set_audio_low_latency_mode_allowed(allowed); + bluetooth::audio::a2dp::set_audio_low_latency_mode_allowed(allowed); + return true; } EXPORT_SYMBOL bt_interface_t bluetoothInterface = { @@ -662,7 +671,8 @@ EXPORT_SYMBOL bt_interface_t bluetoothInterface = { get_metric_id, set_dynamic_audio_buffer_size, generate_local_oob_data, - allow_low_latency_audio}; + allow_low_latency_audio, + clear_event_filter}; // callback reporting helpers @@ -924,14 +934,13 @@ void invoke_link_quality_report_cb( packets_not_receive_count, negative_acknowledgement_count)); } -void invoke_switch_buffer_size_cb(RawAddress remote_addr, - bool is_low_latency_buffer_size) { +void invoke_switch_buffer_size_cb(bool is_low_latency_buffer_size) { do_in_jni_thread( FROM_HERE, base::BindOnce( - [](RawAddress remote_addr, bool is_low_latency_buffer_size) { - HAL_CBACK(bt_hal_cbacks, switch_buffer_size_cb, &remote_addr, + [](bool is_low_latency_buffer_size) { + HAL_CBACK(bt_hal_cbacks, switch_buffer_size_cb, is_low_latency_buffer_size); }, - remote_addr, is_low_latency_buffer_size)); + is_low_latency_buffer_size)); } diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc index b2fc783c32..e67722156f 100644 --- a/system/btif/src/btif_av.cc +++ b/system/btif/src/btif_av.cc @@ -2320,6 +2320,15 @@ bool BtifAvStateMachine::StateClosing::ProcessEvent(uint32_t event, btif_a2dp_on_offload_started(peer_.PeerAddress(), BTA_AV_FAIL); break; + case BTIF_AV_CONNECT_REQ_EVT: + BTIF_TRACE_WARNING("%s: Peer %s : Ignore %s in StateClosing", + __PRETTY_FUNCTION__, + peer_.PeerAddress().ToString().c_str(), + BtifAvEvent::EventName(event).c_str()); + btif_queue_advance(); + peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle); + break; + default: BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s", __PRETTY_FUNCTION__, diff --git a/system/btif/src/btif_core.cc b/system/btif/src/btif_core.cc index 87dd06bae7..bdcf66ee25 100644 --- a/system/btif/src/btif_core.cc +++ b/system/btif/src/btif_core.cc @@ -439,7 +439,7 @@ static bt_status_t btif_in_get_adapter_properties(void) { /* DISC_TIMEOUT */ BTIF_STORAGE_FILL_PROPERTY(&properties[num_props], - BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT, + BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT, sizeof(disc_timeout), &disc_timeout); btif_storage_get_adapter_property(&properties[num_props]); num_props++; @@ -721,7 +721,7 @@ void btif_set_adapter_property(bt_property_t* property) { btif_core_storage_adapter_write(property); } } break; - case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT: { + case BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT: { /* Nothing to do beside store the value in NV. Java will change the SCAN_MODE property after setting timeout, if required */ diff --git a/system/btif/src/btif_debug_btsnoop.cc b/system/btif/src/btif_debug_btsnoop.cc index 1c13590170..11e783d2b9 100644 --- a/system/btif/src/btif_debug_btsnoop.cc +++ b/system/btif/src/btif_debug_btsnoop.cc @@ -23,214 +23,15 @@ #include <zlib.h> #include "internal_include/bt_target.h" +#include "osi/include/properties.h" #include "osi/include/ringbuffer.h" #define REDUCE_HCI_TYPE_TO_SIGNIFICANT_BITS(type) ((type) >> 8) // Total btsnoop memory log buffer size #ifndef BTSNOOP_MEM_BUFFER_SIZE -static const size_t BTSNOOP_MEM_BUFFER_SIZE = (256 * 1024); #endif -static std::mutex buffer_mutex; -static ringbuffer_t* buffer = NULL; -static uint64_t last_timestamp_ms = 0; - -static size_t btsnoop_calculate_packet_length(uint16_t type, - const uint8_t* data, - size_t length); - -static void btsnoop_cb(const uint16_t type, const uint8_t* data, - const size_t length, const uint64_t timestamp_us) { - btsnooz_header_t header; - - size_t included_length = btsnoop_calculate_packet_length(type, data, length); - if (included_length == 0) return; - - std::lock_guard<std::mutex> lock(buffer_mutex); - - // Make room in the ring buffer - - while (ringbuffer_available(buffer) < - (included_length + sizeof(btsnooz_header_t))) { - ringbuffer_pop(buffer, (uint8_t*)&header, sizeof(btsnooz_header_t)); - ringbuffer_delete(buffer, header.length - 1); - } - - // Insert data - header.type = REDUCE_HCI_TYPE_TO_SIGNIFICANT_BITS(type); - header.length = included_length + 1; // +1 for type byte - header.packet_length = length + 1; // +1 for type byte. - header.delta_time_ms = - last_timestamp_ms ? timestamp_us - last_timestamp_ms : 0; - last_timestamp_ms = timestamp_us; - - ringbuffer_insert(buffer, (uint8_t*)&header, sizeof(btsnooz_header_t)); - ringbuffer_insert(buffer, data, included_length); -} - -static size_t btsnoop_calculate_packet_length(uint16_t type, - const uint8_t* data, - size_t length) { - static const size_t HCI_ACL_HEADER_SIZE = 4; - static const size_t L2CAP_HEADER_SIZE = 4; - static const size_t L2CAP_CID_OFFSET = (HCI_ACL_HEADER_SIZE + 2); - static const uint16_t L2CAP_SIGNALING_CID = 0x0001; - - // Maximum amount of ACL data to log. - // Enough for an RFCOMM frame up to the frame check; - // not enough for a HID report or audio data. - static const size_t MAX_HCI_ACL_LEN = 14; - - // Calculate packet length to be included - - switch (type) { - case BT_EVT_TO_LM_HCI_CMD: - return length; - - case BT_EVT_TO_BTU_HCI_EVT: - return length; - - case BT_EVT_TO_LM_HCI_ACL: - case BT_EVT_TO_BTU_HCI_ACL: { - size_t len_hci_acl = HCI_ACL_HEADER_SIZE + L2CAP_HEADER_SIZE; - // Check if we have enough data for an L2CAP header - if (length > len_hci_acl) { - uint16_t l2cap_cid = - data[L2CAP_CID_OFFSET] | (data[L2CAP_CID_OFFSET + 1] << 8); - if (l2cap_cid == L2CAP_SIGNALING_CID) { - // For the signaling CID, take the full packet. - // That way, the PSM setup is captured, allowing decoding of PSMs down - // the road. - return length; - } else { - // Otherwise, return as much as we reasonably can - len_hci_acl = MAX_HCI_ACL_LEN; - } - } - return len_hci_acl < length ? len_hci_acl : length; - } - - case BT_EVT_TO_LM_HCI_ISO: - case BT_EVT_TO_BTU_HCI_ISO: - return length; - - case BT_EVT_TO_LM_HCI_SCO: - case BT_EVT_TO_BTU_HCI_SCO: - // We're not logging SCO packets at this time since they are not currently - // used. - FALLTHROUGH_INTENDED; /* FALLTHROUGH */ - default: - return 0; - } -} - -void btif_debug_btsnoop_init(void) { - if (buffer == NULL) buffer = ringbuffer_init(BTSNOOP_MEM_BUFFER_SIZE); - btsnoop_mem_set_callback(btsnoop_cb); -} - #ifndef OS_ANDROID -void btif_debug_btsnoop_dump(int fd) {} #else - -// Block size for copying buffers (for compression/encoding etc.) -static constexpr size_t BLOCK_SIZE = 16384; - -static bool btsnoop_compress(ringbuffer_t* rb_dst, ringbuffer_t* rb_src) { - CHECK(rb_dst != NULL); - CHECK(rb_src != NULL); - - z_stream zs; - zs.zalloc = Z_NULL; - zs.zfree = Z_NULL; - zs.opaque = Z_NULL; - - if (deflateInit(&zs, Z_DEFAULT_COMPRESSION) != Z_OK) return false; - - bool rc = true; - uint8_t block_src[BLOCK_SIZE]; - uint8_t block_dst[BLOCK_SIZE]; - - const size_t num_blocks = - (ringbuffer_size(rb_src) + BLOCK_SIZE - 1) / BLOCK_SIZE; - for (size_t i = 0; i < num_blocks; ++i) { - zs.avail_in = - ringbuffer_peek(rb_src, i * BLOCK_SIZE, block_src, BLOCK_SIZE); - zs.next_in = block_src; - - do { - zs.avail_out = BLOCK_SIZE; - zs.next_out = block_dst; - - int err = deflate(&zs, (i == num_blocks - 1) ? Z_FINISH : Z_NO_FLUSH); - if (err == Z_STREAM_ERROR) { - rc = false; - break; - } - - const size_t length = BLOCK_SIZE - zs.avail_out; - ringbuffer_insert(rb_dst, block_dst, length); - } while (zs.avail_out == 0); - } - - deflateEnd(&zs); - return rc; -} - -void btif_debug_btsnoop_dump(int fd) { - ringbuffer_t* ringbuffer = ringbuffer_init(BTSNOOP_MEM_BUFFER_SIZE); - if (ringbuffer == NULL) { - dprintf(fd, "%s Unable to allocate memory for compression", __func__); - return; - } - - // Prepend preamble - - btsnooz_preamble_t preamble; - preamble.version = BTSNOOZ_CURRENT_VERSION; - preamble.last_timestamp_ms = last_timestamp_ms; - ringbuffer_insert(ringbuffer, (uint8_t*)&preamble, - sizeof(btsnooz_preamble_t)); - - // Compress data - - uint8_t b64_in[3] = {0}; - char b64_out[5] = {0}; - - size_t line_length = 0; - - bool rc; - { - std::lock_guard<std::mutex> lock(buffer_mutex); - dprintf(fd, "--- BEGIN:BTSNOOP_LOG_SUMMARY (%zu bytes in) ---\n", - ringbuffer_size(buffer)); - rc = btsnoop_compress(ringbuffer, buffer); - } - - if (!rc) { - dprintf(fd, "%s Log compression failed", __func__); - goto error; - } - - // Base64 encode & output - - while (ringbuffer_size(ringbuffer) > 0) { - size_t read = ringbuffer_pop(ringbuffer, b64_in, 3); - // Maximum line length in bugreport (should be multiple of 4 for base64 - // output) - constexpr uint8_t MAX_LINE_LENGTH = 128; - if (line_length >= MAX_LINE_LENGTH) { - dprintf(fd, "\n"); - line_length = 0; - } - line_length += b64_ntop(b64_in, read, b64_out, 5); - dprintf(fd, "%s", b64_out); - } - - dprintf(fd, "\n--- END:BTSNOOP_LOG_SUMMARY ---\n"); - -error: - ringbuffer_free(ringbuffer); -} #endif diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index 989f7399a2..28abdabf5e 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -95,9 +95,8 @@ const Uuid UUID_VC = Uuid::FromString("1844"); const Uuid UUID_CSIS = Uuid::FromString("1846"); const Uuid UUID_LE_AUDIO = Uuid::FromString("184E"); const Uuid UUID_LE_MIDI = Uuid::FromString("03B80E5A-EDE8-4B33-A751-6CE34EC4C700"); -/* FIXME: Not known yet, using a placeholder instead. */ -const Uuid UUID_HAS = Uuid::FromString("EEEEEEEE-EEEE-EEEE-EEEE-EEEEEEEEEEEE"); -const bool enable_address_consolidate = false; // TODO remove +const Uuid UUID_HAS = Uuid::FromString("1854"); +const bool enable_address_consolidate = true; // TODO remove #define COD_MASK 0x07FF @@ -2180,7 +2179,7 @@ bt_status_t btif_dm_get_adapter_property(bt_property_t* prop) { prop->len = sizeof(bt_scan_mode_t); } break; - case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT: { + case BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT: { uint32_t* tmt = (uint32_t*)prop->val; *tmt = 120; /* default to 120s, if not found in NV */ prop->len = sizeof(uint32_t); @@ -3206,3 +3205,8 @@ bool btif_get_address_type(const RawAddress& bda, tBLE_ADDR_TYPE* p_addr_type) { AddressTypeText(*p_addr_type).c_str()); return true; } + +void btif_dm_clear_event_filter() { + LOG_VERBOSE("%s: called", __func__); + bta_dm_clear_event_filter(); +} diff --git a/system/btif/src/btif_hh.cc b/system/btif/src/btif_hh.cc index ae4ee067cf..bff20a0686 100644 --- a/system/btif/src/btif_hh.cc +++ b/system/btif/src/btif_hh.cc @@ -905,6 +905,12 @@ static void btif_hh_upstreams_evt(uint16_t event, char* p_param) { case BTA_HH_GET_PROTO_EVT: p_dev = btif_hh_find_connected_dev_by_handle(p_data->hs_data.handle); + if (p_dev == NULL) { + BTIF_TRACE_WARNING( + "BTA_HH_GET_PROTO_EVT: Error, cannot find device with handle %d", + p_data->hs_data.handle); + return; + } BTIF_TRACE_WARNING( "BTA_HH_GET_PROTO_EVT: status = %d, handle = %d, proto = [%d], %s", p_data->hs_data.status, p_data->hs_data.handle, @@ -941,9 +947,11 @@ static void btif_hh_upstreams_evt(uint16_t event, char* p_param) { p_data->hs_data.handle, p_data->hs_data.status, p_data->hs_data.rsp_data.idle_rate); p_dev = btif_hh_find_connected_dev_by_handle(p_data->hs_data.handle); - HAL_CBACK(bt_hh_callbacks, idle_time_cb, (RawAddress*)&(p_dev->bd_addr), - (bthh_status_t)p_data->hs_data.status, - p_data->hs_data.rsp_data.idle_rate); + if (p_dev) { + HAL_CBACK(bt_hh_callbacks, idle_time_cb, (RawAddress*)&(p_dev->bd_addr), + (bthh_status_t)p_data->hs_data.status, + p_data->hs_data.rsp_data.idle_rate); + } break; case BTA_HH_SET_IDLE_EVT: diff --git a/system/btif/src/btif_le_audio.cc b/system/btif/src/btif_le_audio.cc index 4660a2ccc5..acb7ed703f 100644 --- a/system/btif/src/btif_le_audio.cc +++ b/system/btif/src/btif_le_audio.cc @@ -79,18 +79,27 @@ class LeAudioClientInterfaceImpl : public LeAudioClientInterface, LOG_INFO("supported codec: %s", codec.ToString().c_str()); } + LeAudioClient::InitializeAudioSetConfigurationProvider(); do_in_main_thread( FROM_HERE, Bind(&LeAudioClient::Initialize, this, jni_thread_wrapper( FROM_HERE, Bind(&btif_storage_load_bonded_leaudio)), base::Bind([]() -> bool { return LeAudioHalVerifier::SupportsLeAudio(); - }))); + }), + offloading_preference)); } void Cleanup(void) override { DVLOG(2) << __func__; - do_in_main_thread(FROM_HERE, Bind(&LeAudioClient::Cleanup)); + do_in_main_thread( + FROM_HERE, + Bind( + &LeAudioClient::Cleanup, + jni_thread_wrapper( + FROM_HERE, + Bind( + &LeAudioClient::CleanupAudioSetConfigurationProvider)))); } void RemoveDevice(const RawAddress& address) override { diff --git a/system/btif/src/btif_le_audio_broadcaster.cc b/system/btif/src/btif_le_audio_broadcaster.cc index be55da65a2..57d14f93fc 100644 --- a/system/btif/src/btif_le_audio_broadcaster.cc +++ b/system/btif/src/btif_le_audio_broadcaster.cc @@ -21,6 +21,7 @@ #include <hardware/bt_le_audio.h> #include "audio_hal_interface/hal_version_manager.h" +#include "bta_le_audio_api.h" #include "bta_le_audio_broadcaster_api.h" #include "btif_common.h" #include "stack/include/btu.h" @@ -46,8 +47,7 @@ class LeAudioBroadcasterInterfaceImpl : public LeAudioBroadcasterInterface, do_in_main_thread( FROM_HERE, Bind(&LeAudioBroadcaster::Initialize, this, base::Bind([]() -> bool { - return bluetooth::audio::HalVersionManager::GetHalVersion() == - bluetooth::audio::BluetoothAudioHalVersion::VERSION_2_1; + return LeAudioHalVerifier::SupportsLeAudioBroadcast(); }))); } diff --git a/system/btif/src/btif_sock_thread.cc b/system/btif/src/btif_sock_thread.cc index 88f40e75cc..6744d3d10c 100644 --- a/system/btif/src/btif_sock_thread.cc +++ b/system/btif/src/btif_sock_thread.cc @@ -448,6 +448,10 @@ static void process_data_sock(int h, struct pollfd* pfds, int count) { for (i = 1; i < ts[h].poll_count; i++) { if (pfds[i].revents) { int ps_i = ts[h].psi[i]; + if (ts[h].ps[ps_i].pfd.fd == -1) { + LOG_INFO("Socket has been removed from poll set"); + continue; + } asrt(pfds[i].fd == ts[h].ps[ps_i].pfd.fd); uint32_t user_id = ts[h].ps[ps_i].user_id; int type = ts[h].ps[ps_i].type; diff --git a/system/btif/src/btif_storage.cc b/system/btif/src/btif_storage.cc index 7838f9e6d6..1f130d726f 100644 --- a/system/btif/src/btif_storage.cc +++ b/system/btif/src/btif_storage.cc @@ -248,7 +248,7 @@ static int prop2cfg(const RawAddress* remote_bd_addr, bt_property_t* prop) { btif_config_set_int("Adapter", BTIF_STORAGE_KEY_LOCAL_IO_CAPS_BLE, *(int*)prop->val); break; - case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT: + case BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT: btif_config_set_int("Adapter", BTIF_STORAGE_KEY_ADAPTER_DISC_TIMEOUT, *(int*)prop->val); break; @@ -358,7 +358,7 @@ static int cfg2prop(const RawAddress* remote_bd_addr, bt_property_t* prop) { (int*)prop->val); break; - case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT: + case BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT: if (prop->len >= (int)sizeof(int)) ret = btif_config_get_int( "Adapter", BTIF_STORAGE_KEY_ADAPTER_DISC_TIMEOUT, (int*)prop->val); @@ -1040,9 +1040,9 @@ bt_status_t btif_storage_load_bonded_devices(void) { num_props++; /* DISC_TIMEOUT */ - BTIF_STORAGE_GET_ADAPTER_PROP(status, BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT, - &disc_timeout, sizeof(disc_timeout), - adapter_props[num_props]); + BTIF_STORAGE_GET_ADAPTER_PROP( + status, BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT, &disc_timeout, + sizeof(disc_timeout), adapter_props[num_props]); num_props++; /* BONDED_DEVICES */ diff --git a/system/btif/src/btif_util.cc b/system/btif/src/btif_util.cc index 86307bc881..bcd0ef96fc 100644 --- a/system/btif/src/btif_util.cc +++ b/system/btif/src/btif_util.cc @@ -129,7 +129,7 @@ const char* dump_property_type(bt_property_type_t type) { CASE_RETURN_STR(BT_PROPERTY_CLASS_OF_DEVICE) CASE_RETURN_STR(BT_PROPERTY_TYPE_OF_DEVICE) CASE_RETURN_STR(BT_PROPERTY_REMOTE_RSSI) - CASE_RETURN_STR(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT) + CASE_RETURN_STR(BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT) CASE_RETURN_STR(BT_PROPERTY_ADAPTER_BONDED_DEVICES) CASE_RETURN_STR(BT_PROPERTY_ADAPTER_SCAN_MODE) CASE_RETURN_STR(BT_PROPERTY_REMOTE_FRIENDLY_NAME) diff --git a/system/btif/src/btif_vc.cc b/system/btif/src/btif_vc.cc index 66374e215e..61ecb20172 100644 --- a/system/btif/src/btif_vc.cc +++ b/system/btif/src/btif_vc.cc @@ -55,21 +55,21 @@ class VolumeControlInterfaceImpl : public VolumeControlInterface, } void OnVolumeStateChanged(const RawAddress& address, uint8_t volume, - bool mute) override { - DVLOG(2) << __func__ << " address: " << address << "volume: " << volume - << "mute: " << mute; + bool mute, bool isAutonomous) override { + DVLOG(2) << __func__ << " address: " << address << " volume: " << volume + << " mute: " << mute << " isAutonomous: " << isAutonomous; do_in_jni_thread(FROM_HERE, Bind(&VolumeControlCallbacks::OnVolumeStateChanged, - Unretained(callbacks_), address, volume, mute)); + Unretained(callbacks_), address, volume, mute, isAutonomous)); } void OnGroupVolumeStateChanged(int group_id, uint8_t volume, - bool mute) override { - DVLOG(2) << __func__ << "group_id: " << group_id << "volume: " << volume - << "mute: " << mute; + bool mute, bool isAutonomous) override { + DVLOG(2) << __func__ << " group_id: " << group_id << " volume: " << volume + << " mute: " << mute << " isAutonomous: " << isAutonomous; do_in_jni_thread(FROM_HERE, Bind(&VolumeControlCallbacks::OnGroupVolumeStateChanged, - Unretained(callbacks_), group_id, volume, mute)); + Unretained(callbacks_), group_id, volume, mute, isAutonomous)); } void Connect(const RawAddress& address) override { diff --git a/system/btif/src/stack_manager.cc b/system/btif/src/stack_manager.cc index fe730e7d6e..d7cc4931b6 100644 --- a/system/btif/src/stack_manager.cc +++ b/system/btif/src/stack_manager.cc @@ -191,16 +191,13 @@ static void clean_up_stack() { static bool get_stack_is_running() { return stack_is_running; } // Internal functions - extern const module_t bt_utils_module; extern const module_t bte_logmsg_module; extern const module_t btif_config_module; -extern const module_t btsnoop_module; extern const module_t bt_utils_module; extern const module_t gd_controller_module; extern const module_t gd_idle_module; extern const module_t gd_shim_module; -extern const module_t hci_module; extern const module_t interop_module; extern const module_t osi_module; extern const module_t stack_config_module; diff --git a/system/btif/test/btif_core_test.cc b/system/btif/test/btif_core_test.cc index 50fd519e98..28d9cccdb7 100644 --- a/system/btif/test/btif_core_test.cc +++ b/system/btif/test/btif_core_test.cc @@ -79,6 +79,7 @@ void energy_info_callback(bt_activity_energy_info* energy_info, bt_uid_traffic_t* uid_data) {} void generate_local_oob_data_callback(tBT_TRANSPORT transport, bt_oob_data_t oob_data) {} +void switch_buffer_size_callback(bool is_low_latency_buffer_size) {} #undef TESTCB bt_callbacks_t callbacks = { @@ -99,6 +100,7 @@ bt_callbacks_t callbacks = { .energy_info_cb = energy_info_callback, .link_quality_report_cb = link_quality_report_callback, .generate_local_oob_data_cb = generate_local_oob_data_callback, + .switch_buffer_size_cb = switch_buffer_size_callback, }; } // namespace diff --git a/system/build/Android.bp b/system/build/Android.bp index f0f2a3b7c8..70c509957f 100644 --- a/system/build/Android.bp +++ b/system/build/Android.bp @@ -120,8 +120,6 @@ fluoride_defaults { "android.hardware.bluetooth@1.0", "android.hardware.bluetooth@1.1", "libcutils", - "libgrpc++", - "libgrpc_wrap", "libhidlbase", "libstatslog_bt", "libutils", diff --git a/system/build/dpkg/libchrome-822064/debian/README.Debian b/system/build/dpkg/libchrome-822064/debian/README.Debian deleted file mode 100644 index 773bbf318e..0000000000 --- a/system/build/dpkg/libchrome-822064/debian/README.Debian +++ /dev/null @@ -1 +0,0 @@ -libchrome for Debian diff --git a/system/build/dpkg/libchrome-822064/debian/changelog b/system/build/dpkg/libchrome-822064/debian/changelog deleted file mode 100644 index 113a5e756a..0000000000 --- a/system/build/dpkg/libchrome-822064/debian/changelog +++ /dev/null @@ -1,5 +0,0 @@ -libchrome (822064-1) buster; urgency=low - - * Initial release. - - -- Sonny Sasaka <sonnysasaka@chromium.org> Fri, 30 Apr 2021 19:41:40 +0000 diff --git a/system/build/dpkg/libchrome-822064/debian/compat b/system/build/dpkg/libchrome-822064/debian/compat deleted file mode 100644 index f599e28b8a..0000000000 --- a/system/build/dpkg/libchrome-822064/debian/compat +++ /dev/null @@ -1 +0,0 @@ -10 diff --git a/system/build/dpkg/libchrome-822064/debian/control b/system/build/dpkg/libchrome-822064/debian/control deleted file mode 100644 index b11c23fbc2..0000000000 --- a/system/build/dpkg/libchrome-822064/debian/control +++ /dev/null @@ -1,28 +0,0 @@ -Source: libchrome -Section: libs -Priority: optional -Maintainer: Sonny Sasaka <sonnysasaka@chromium.org> -Standards-Version: 4.1.4 -Homepage: https://chromium.googlesource.com/aosp/platform/external/libchrome/ -Build-Depends: - debhelper (>=11~), - clang, - python3, - pkg-config, - ninja-build, - libglib2.0-dev, - libevent-dev, - libnss3-dev, - libdbus-1-dev, - libprotobuf-dev, - googletest, - libre2-dev, - libdouble-conversion-dev, - libssl-dev, - libabsl-dev - -Package: libchrome -Architecture: any -Multi-Arch: foreign -Depends: ${misc:Depends}, ${shlibs:Depends} -Description: Chromium's base library diff --git a/system/build/dpkg/libchrome-822064/debian/install_headers.sh b/system/build/dpkg/libchrome-822064/debian/install_headers.sh deleted file mode 100755 index 7157b1499d..0000000000 --- a/system/build/dpkg/libchrome-822064/debian/install_headers.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -destdir="$1" - -header_dirs=( - base - base/allocator - base/containers - base/debug - base/files - base/hash - base/i18n - base/json - base/memory - base/message_loop - base/metrics - base/numerics - base/posix - base/process - base/ranges - base/strings - base/synchronization - base/system - base/task - base/task/common - base/task/sequence_manager - base/task/thread_pool - base/test - base/third_party/icu - base/third_party/nspr - base/third_party/valgrind - base/threading - base/time - base/timer - base/trace_event - base/trace_event/common - build - components/policy - components/policy/core/common - testing/gmock/include/gmock - testing/gtest/include/gtest - dbus - third_party/abseil-cpp/absl/types - ) - -# Install header files. -for d in "${header_dirs[@]}" ; do - mkdir -p "${destdir}/usr/include/libchrome/${d}" - cp libchrome/"${d}"/*.h "${destdir}/usr/include/libchrome/${d}" -done diff --git a/system/build/dpkg/libchrome-822064/debian/libchrome.install b/system/build/dpkg/libchrome-822064/debian/libchrome.install deleted file mode 100644 index 9d381c1e2b..0000000000 --- a/system/build/dpkg/libchrome-822064/debian/libchrome.install +++ /dev/null @@ -1,4 +0,0 @@ -out/Release/lib/libbase*.so /usr/lib -out/Release/libbase*.a /usr/lib -out/Release/obj/libchrome/libchrome*.pc /usr/lib/pkgconfig -usr/include /usr diff --git a/system/build/dpkg/libchrome-822064/debian/patches/0001-Add-missing-includes.patch b/system/build/dpkg/libchrome-822064/debian/patches/0001-Add-missing-includes.patch deleted file mode 100644 index a2f2b4b9ad..0000000000 --- a/system/build/dpkg/libchrome-822064/debian/patches/0001-Add-missing-includes.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 50a4636886c958717213856132fcbb57c3b8ea2a Mon Sep 17 00:00:00 2001 -From: Sonny Sasaka <sonnysasaka@chromium.org> -Date: Fri, 19 Mar 2021 16:18:07 -0700 -Subject: [PATCH] Add missing includes - ---- - base/hash/md5.cc | 1 + - crypto/p224_spake.cc | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/libchrome/base/hash/md5.cc b/libchrome/base/hash/md5.cc -index bdb9990a9..ef8954eaf 100644 ---- a/libchrome/base/hash/md5.cc -+++ b/libchrome/base/hash/md5.cc -@@ -24,6 +24,7 @@ - #include "base/hash/md5.h" - - #include <stddef.h> -+#include <string.h> - - namespace { - -diff --git a/libchrome/crypto/p224_spake.cc b/libchrome/crypto/p224_spake.cc -index 157410537..de0af5466 100644 ---- a/libchrome/crypto/p224_spake.cc -+++ b/libchrome/crypto/p224_spake.cc -@@ -8,6 +8,7 @@ - #include <crypto/p224_spake.h> - - #include <algorithm> -+#include <string.h> - - #include <base/logging.h> - #include <crypto/p224.h> --- -2.20.1 - diff --git a/system/build/dpkg/libchrome-822064/debian/patches/0001-rebase_path-for-write_args.patch b/system/build/dpkg/libchrome-822064/debian/patches/0001-rebase_path-for-write_args.patch deleted file mode 100644 index 9b359c0e8d..0000000000 --- a/system/build/dpkg/libchrome-822064/debian/patches/0001-rebase_path-for-write_args.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 6875449497baf026fb8228668930a715ffcc7082 Mon Sep 17 00:00:00 2001 -From: Sonny Sasaka <sonnysasaka@chromium.org> -Date: Fri, 19 Mar 2021 16:56:59 -0700 -Subject: [PATCH] rebase_path for write_args - ---- - BUILD.gn | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/libchrome/BUILD.gn b/libchrome/BUILD.gn -index a846d8f52..66ac10a55 100644 ---- a/libchrome/BUILD.gn -+++ b/libchrome/BUILD.gn -@@ -556,7 +556,7 @@ action("base") { - - script = "//common-mk/write_args.py" - outputs = [ "${root_out_dir}/lib/lib${target_name}.so" ] -- args = [ "--output" ] + outputs + [ "--" ] + [ -+ args = [ "--output" ] + rebase_path(outputs) + [ "--" ] + [ - "GROUP", - "(", - "AS_NEEDED", -@@ -618,7 +618,7 @@ action("base-test") { - - script = "//common-mk/write_args.py" - outputs = [ "${root_out_dir}/lib${target_name}.a" ] -- args = [ "--output" ] + outputs + [ "--" ] + [ -+ args = [ "--output" ] + rebase_path(outputs) + [ "--" ] + [ - "GROUP", - "(", - "AS_NEEDED", --- -2.20.1 - diff --git a/system/build/dpkg/libchrome-822064/debian/patches/series b/system/build/dpkg/libchrome-822064/debian/patches/series deleted file mode 100644 index 9128588280..0000000000 --- a/system/build/dpkg/libchrome-822064/debian/patches/series +++ /dev/null @@ -1,3 +0,0 @@ -0001-Add-missing-includes.patch -0001-rebase_path-for-write_args.patch -0001-Remove-absl-from-pkgconfig.patch diff --git a/system/build/dpkg/libchrome-822064/debian/rules b/system/build/dpkg/libchrome-822064/debian/rules deleted file mode 100755 index 60b6792048..0000000000 --- a/system/build/dpkg/libchrome-822064/debian/rules +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/make -f - -# gn args -defines = -defines += pkg_config=\"pkg-config\" -defines += libbase_ver=\"822064\" -defines += platform2_root=\"$(shell pwd)/\" -defines += platform_subdir=\"libchrome\" -defines += cxx=\"clang++\" -defines += cc=\"clang\" -defines += ar=\"ar\" -defines += external_cxxflags=[\"-DNDEBUG\", \"-I/usr/src/googletest/googletest/include\", \"-I/usr/src/googletest/googlemock/include\", \"-Wno-unknown-warning-option\", \"-Wno-unused-command-line-argument\"] -defines += external_ldflags=[\"-latomic\", \"-labsl_base\", \"-labsl_bad_variant_access\"] -defines += enable_werror=false -defines += libdir=\"/usr/lib\" -defines += use={mojo=false asan=false coverage=false crypto=true dbus=true fuzzer=false timers=true cros_host=false profiling=false tcmalloc=false} - -# handle parallel build options -njobs=1 -ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) -njobs=$(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) -endif - -%: - dh $@ --parallel - -override_dh_auto_build-arch: - gn gen out/Release --args="$(defines)" - ninja -j$(njobs) -C out/Release - -override_dh_auto_clean: - rm -rf out - find . -name \*.pyc -execdir rm -f {} \; - dh_auto_clean - -override_dh_auto_install-arch: - dh_auto_install - debian/install_headers.sh debian/tmp diff --git a/system/build/dpkg/libchrome-822064/gen-src-pkg.sh b/system/build/dpkg/libchrome-822064/gen-src-pkg.sh deleted file mode 100755 index cbb5dce54a..0000000000 --- a/system/build/dpkg/libchrome-822064/gen-src-pkg.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash -# Generates Debian source and binary packages of libchrome. - -if [ -z "$1" ]; then - echo "Usage: gen-src-pkg.sh <output-dir>" - exit 1 -fi - -outdir="$1" -pkgdir=libchrome-822064 -origtar=libchrome_822064.orig.tar.gz -scriptdir="$( cd "$( dirname "$0" )" && pwd )" -branch=release-R91-13904.B - -tmpdir=$(mktemp -d) -echo Generating source package in "${tmpdir}". - -# Download platform2 source. -cd "${tmpdir}" -git clone --branch "${branch}" https://chromium.googlesource.com/chromiumos/platform2 || exit 1 -mkdir "${pkgdir}" -cd "${pkgdir}" -# Trim platform2, only common-mk is needed. -cp -a ../platform2/{common-mk,.gn} . - -# Download libchrome source and apply Chrome OS's patches. -git clone --branch "${branch}" https://chromium.googlesource.com/aosp/platform/external/libchrome || exit 1 -cd libchrome -rm -rf .git -while read -r patch; do - patch -p1 < "libchrome_tools/patches/${patch}" -done < <(grep -E '^[^#]' "libchrome_tools/patches/patches") - -# Clean up temporary platform2 checkout. -cd ../.. -rm -rf platform2 - -# Debian requires creating .orig.tar.gz. -tar czf "${origtar}" "${pkgdir}" - -# Debianize the source. -cd "${pkgdir}" -yes | debmake || exit 1 -cp -aT "${scriptdir}/debian/" "${tmpdir}/${pkgdir}/debian/" - -# Build source package and binary package. -cd "${tmpdir}/${pkgdir}" -dpkg-buildpackage --no-sign || exit 1 - -# Copy the results to output dir. -cd "${tmpdir}" -mkdir -p "${outdir}/src" -cp *.dsc *.orig.tar.gz *.debian.tar.xz "${outdir}/src" -cp *.deb "${outdir}" -cd / - -echo Removing temporary directory "${tmpdir}". -rm -rf "${tmpdir}" - -echo Done. Check out Debian source package in "${outdir}". diff --git a/system/build/dpkg/libchrome/debian/changelog b/system/build/dpkg/libchrome/debian/changelog index 3cdedf6890..e8985eae22 100644 --- a/system/build/dpkg/libchrome/debian/changelog +++ b/system/build/dpkg/libchrome/debian/changelog @@ -1,5 +1,5 @@ -libchrome (780652-1) buster; urgency=low +libchrome (930012-1) bullseye; urgency=low - * Initial release. + * Upgrade to BASE_VER = 930012 - -- Sonny Sasaka <sonnysasaka@chromium.org> Fri, 19 Mar 2021 19:41:40 +0000 + -- Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Fri, 11 Feb 2022 14:56:00 +0000 diff --git a/system/build/dpkg/libchrome/debian/control b/system/build/dpkg/libchrome/debian/control index d804b4d88d..b11c23fbc2 100644 --- a/system/build/dpkg/libchrome/debian/control +++ b/system/build/dpkg/libchrome/debian/control @@ -18,7 +18,8 @@ Build-Depends: googletest, libre2-dev, libdouble-conversion-dev, - libssl-dev + libssl-dev, + libabsl-dev Package: libchrome Architecture: any diff --git a/system/build/dpkg/libchrome/debian/install_headers.sh b/system/build/dpkg/libchrome/debian/install_headers.sh index 19cb5efa80..817f1a6efc 100755 --- a/system/build/dpkg/libchrome/debian/install_headers.sh +++ b/system/build/dpkg/libchrome/debian/install_headers.sh @@ -5,9 +5,12 @@ destdir="$1" header_dirs=( base base/allocator + base/allocator/partition_allocator + base/allocator/partition_allocator/starscan base/containers base/debug base/files + base/functional base/hash base/i18n base/json @@ -17,6 +20,7 @@ header_dirs=( base/numerics base/posix base/process + base/ranges base/strings base/synchronization base/system @@ -33,13 +37,18 @@ header_dirs=( base/timer base/trace_event base/trace_event/common + base/types build components/policy components/policy/core/common testing/gmock/include/gmock testing/gtest/include/gtest dbus - ) + third_party/abseil-cpp/absl/types + third_party/perfetto/include/perfetto/tracing/ + third_party/perfetto/include/perfetto/protozero/ + third_party/perfetto/protos/perfetto/trace/track_event/ +) # Install header files. for d in "${header_dirs[@]}" ; do diff --git a/system/build/dpkg/libchrome/debian/libchrome.install.docker b/system/build/dpkg/libchrome/debian/libchrome.install.docker new file mode 100644 index 0000000000..b4034e7457 --- /dev/null +++ b/system/build/dpkg/libchrome/debian/libchrome.install.docker @@ -0,0 +1,5 @@ +out/Release/lib/libbase*.so /usr/lib/x86_64-linux-gnu +out/Release/libbase*.a /usr/lib/x86_64-linux-gnu +out/Release/obj/libchrome/libchrome*.pc /usr/lib/x86_64-linux-gnu/pkgconfig +usr/include /usr + diff --git a/system/build/dpkg/libchrome/debian/patches/0001-Fix-build-issues-on-930012.patch b/system/build/dpkg/libchrome/debian/patches/0001-Fix-build-issues-on-930012.patch new file mode 100644 index 0000000000..61d044b4fb --- /dev/null +++ b/system/build/dpkg/libchrome/debian/patches/0001-Fix-build-issues-on-930012.patch @@ -0,0 +1,37 @@ +From 1153211a5615156f450a4f521da284a7df4d4e5f Mon Sep 17 00:00:00 2001 +From: Abhishek Pandit-Subedi <abhishekpandit@google.com> +Date: Mon, 14 Feb 2022 14:40:41 -0800 +Subject: [PATCH] Fix build issues on 930012 + +--- + BUILD.gn | 1 + + base/command_line.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/libchrome/BUILD.gn b/libchrome/BUILD.gn +index 292c08565a..dbe3fb0981 100644 +--- a/libchrome/BUILD.gn ++++ b/libchrome/BUILD.gn +@@ -42,6 +42,7 @@ config("libchrome_config") { + "-Wno-unreachable-code-return", + "-Wno-unused-local-typedefs", + "-Xclang-only=-Wno-char-subscripts", ++ "-Wno-implicit-int-float-conversion", + ] + + # Address sanitizer + coverage builds do not support -z,defs. +diff --git a/libchrome/base/command_line.h b/libchrome/base/command_line.h +index 706726a73e..ad0281283a 100644 +--- a/libchrome/base/command_line.h ++++ b/libchrome/base/command_line.h +@@ -19,6 +19,7 @@ + #include <stddef.h> + #include <functional> + #include <map> ++#include <memory> + #include <string> + #include <vector> + +-- +2.35.1.265.g69c8d7142f-goog + diff --git a/system/build/dpkg/libchrome-822064/debian/patches/0001-Remove-absl-from-pkgconfig.patch b/system/build/dpkg/libchrome/debian/patches/0001-Remove-absl-from-pkgconfig.patch index 73b8c48cd6..73b8c48cd6 100644 --- a/system/build/dpkg/libchrome-822064/debian/patches/0001-Remove-absl-from-pkgconfig.patch +++ b/system/build/dpkg/libchrome/debian/patches/0001-Remove-absl-from-pkgconfig.patch diff --git a/system/build/dpkg/libchrome/debian/patches/0001-common-mk-rebase_path-output-location-of-generate-pc.patch b/system/build/dpkg/libchrome/debian/patches/0001-common-mk-rebase_path-output-location-of-generate-pc.patch deleted file mode 100644 index 418efcc475..0000000000 --- a/system/build/dpkg/libchrome/debian/patches/0001-common-mk-rebase_path-output-location-of-generate-pc.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 04fa5e1ade08696b5a2cc3b65bf0fd26c43251c7 Mon Sep 17 00:00:00 2001 -From: Sonny Sasaka <sonnysasaka@chromium.org> -Date: Fri, 19 Mar 2021 11:17:43 -0700 -Subject: [PATCH] common-mk: rebase_path output location of generate-pc.py - -Without rebase_path, the generate-pc.py would be called like -`generate-pc.py --output //out/Release` if the output is inside the -source directory and this gn path isn't recognized as a generic -filesystem path. - -BUG=b:183216216 -TEST=with modp_b64, call -$ gn gen out/Release --args=... -$ ninja - -Change-Id: Ic9d9b3d01d52d483e3d81ca2e8d514b47900f5bb ---- - common-mk/pkg_config.gni | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/common-mk/pkg_config.gni b/common-mk/pkg_config.gni -index 24e2cf1401..b2c58845d4 100644 ---- a/common-mk/pkg_config.gni -+++ b/common-mk/pkg_config.gni -@@ -84,7 +84,7 @@ template("generate_pkg_config") { - outputs = [ "${target_out_dir}/${output_name}.pc" ] - - script = "//common-mk/generate-pc.py" -- args = [ "--output" ] + outputs + [ "--name=" + name ] -+ args = [ "--output" ] + rebase_path(outputs) + [ "--name=" + name ] - if (defined(description)) { - args += [ "--description=" + description ] - } --- -2.29.2 - diff --git a/system/build/dpkg/libchrome/debian/patches/series b/system/build/dpkg/libchrome/debian/patches/series index 5a26f7be70..de8be97780 100644 --- a/system/build/dpkg/libchrome/debian/patches/series +++ b/system/build/dpkg/libchrome/debian/patches/series @@ -1,3 +1,4 @@ -0001-common-mk-rebase_path-output-location-of-generate-pc.patch 0001-Add-missing-includes.patch 0001-rebase_path-for-write_args.patch +0001-Remove-absl-from-pkgconfig.patch +0001-Fix-build-issues-on-930012.patch diff --git a/system/build/dpkg/libchrome/debian/rules b/system/build/dpkg/libchrome/debian/rules index 6ac17835c4..3374099c98 100755 --- a/system/build/dpkg/libchrome/debian/rules +++ b/system/build/dpkg/libchrome/debian/rules @@ -3,17 +3,17 @@ # gn args defines = defines += pkg_config=\"pkg-config\" -defines += libbase_ver=\"780652\" +defines += libbase_ver=\"930012\" defines += platform2_root=\"$(shell pwd)/\" defines += platform_subdir=\"libchrome\" defines += cxx=\"clang++\" defines += cc=\"clang\" defines += ar=\"ar\" -defines += external_cxxflags=[\"-I/usr/src/googletest/googletest/include\", \"-I/usr/src/googletest/googlemock/include\"] -defines += external_ldflags=[\"-latomic\"] +defines += external_cxxflags=[\"-DNDEBUG\", \"-I/usr/src/googletest/googletest/include\", \"-I/usr/src/googletest/googlemock/include\", \"-Wno-unknown-warning-option\", \"-Wno-unused-command-line-argument\", \"-Wno-implicit-int-float-conversion\"] +defines += external_ldflags=[\"-latomic\", \"-labsl_base\", \"-labsl_bad_variant_access\", \"-labsl_bad_optional_access\"] defines += enable_werror=false defines += libdir=\"/usr/lib\" -defines += use={mojo=false asan=false coverage=false crypto=true dbus=true fuzzer=false timers=true cros_host=false profiling=false tcmalloc=false} +defines += use={mojo=false asan=false coverage=false crypto=true dbus=true fuzzer=false timers=true cros_host=false profiling=false tcmalloc=false test=false} # handle parallel build options njobs=1 diff --git a/system/build/dpkg/libchrome/gen-src-pkg.sh b/system/build/dpkg/libchrome/gen-src-pkg.sh index 3cee0e4612..01390f126d 100755 --- a/system/build/dpkg/libchrome/gen-src-pkg.sh +++ b/system/build/dpkg/libchrome/gen-src-pkg.sh @@ -7,25 +7,34 @@ if [ -z "$1" ]; then fi outdir="$1" -pkgdir=libchrome-780652 -origtar=libchrome_780652.orig.tar.gz +pkgdir=libchrome-930012 +origtar=libchrome_930012.orig.tar.gz scriptdir="$( cd "$( dirname "$0" )" && pwd )" -branch=release-R90-13816.B + +# Pin the libchrome branch + commit +libchrome_branch=master +libchrome_commit=4b86c42f09b7c8d88b0233c60f59bafeb4d8df19 + +# Pin the platform2 branch + commit +platform2_branch=main +platform2_commit=4567e833015453b3ea322eec1201cc41ecdfdec0 tmpdir=$(mktemp -d) echo Generating source package in "${tmpdir}". # Download platform2 source. cd "${tmpdir}" -git clone --branch "${branch}" https://chromium.googlesource.com/chromiumos/platform2 || exit 1 +git clone --branch "${platform2_branch}" https://chromium.googlesource.com/chromiumos/platform2 || exit 1 +(cd platform2 && git checkout "${platform2_commit}") mkdir "${pkgdir}" cd "${pkgdir}" # Trim platform2, only common-mk is needed. cp -a ../platform2/{common-mk,.gn} . # Download libchrome source and apply Chrome OS's patches. -git clone --branch "${branch}" https://chromium.googlesource.com/aosp/platform/external/libchrome || exit 1 +git clone --branch "${libchrome_branch}" https://chromium.googlesource.com/aosp/platform/external/libchrome || exit 1 cd libchrome +git checkout "${libchrome_commit}" rm -rf .git while read -r patch; do patch -p1 < "libchrome_tools/patches/${patch}" @@ -43,6 +52,14 @@ cd "${pkgdir}" yes | debmake || exit 1 cp -aT "${scriptdir}/debian/" "${tmpdir}/${pkgdir}/debian/" +# If building for docker, use the right install script. +if [ ! -z "${LIBCHROME_DOCKER}" ]; then + mv "${tmpdir}/${pkgdir}/debian/libchrome.install.docker" \ + "${tmpdir}/${pkgdir}/debian/libchrome.install" +else + rm -f "${tmpdir}/${pkgdir}/debian/libchrome.install.docker" +fi + # Build source package and binary package. cd "${tmpdir}/${pkgdir}" dpkg-buildpackage --no-sign || exit 1 diff --git a/system/build/dpkg/modp_b64/debian/modp-b64.install.docker b/system/build/dpkg/modp_b64/debian/modp-b64.install.docker new file mode 100644 index 0000000000..a028ca4955 --- /dev/null +++ b/system/build/dpkg/modp_b64/debian/modp-b64.install.docker @@ -0,0 +1,3 @@ +modp_b64/modp_b64 /usr/include +out/Release/libmodp_b64.a /usr/lib/x86_64-linux-gnu +out/Release/obj/modp_b64/libmodp_b64.pc /usr/lib/x86_64-linux-gnu/pkgconfig diff --git a/system/build/dpkg/modp_b64/gen-src-pkg.sh b/system/build/dpkg/modp_b64/gen-src-pkg.sh index cc22f678f2..5e62160159 100755 --- a/system/build/dpkg/modp_b64/gen-src-pkg.sh +++ b/system/build/dpkg/modp_b64/gen-src-pkg.sh @@ -40,6 +40,15 @@ cd "${pkgdir}" yes | debmake || exit 1 cp -aT "${scriptdir}/debian/" "${tmpdir}/${pkgdir}/debian/" +# If building for docker, use the right install script. +if [ ! -z "${MODP_DOCKER}" ]; then + mv "${tmpdir}/${pkgdir}/debian/modp-b64.install.docker" \ + "${tmpdir}/${pkgdir}/debian/modp-b64.install" +else + rm -f "${tmpdir}/${pkgdir}/debian/modp-b64.install.docker" +fi + + # Build source package and binary package. cd "${tmpdir}/${pkgdir}" dpkg-buildpackage --no-sign || exit 1 diff --git a/system/common/message_loop_thread.h b/system/common/message_loop_thread.h index 7420dbcb26..ece1d0ffbc 100644 --- a/system/common/message_loop_thread.h +++ b/system/common/message_loop_thread.h @@ -48,6 +48,9 @@ class MessageLoopThread final { explicit MessageLoopThread(const std::string& thread_name); explicit MessageLoopThread(const std::string& thread_name, bool is_main); + MessageLoopThread(const MessageLoopThread&) = delete; + MessageLoopThread& operator=(const MessageLoopThread&) = delete; + /** * Destroys the message loop thread automatically when it goes out of scope */ @@ -199,8 +202,6 @@ class MessageLoopThread final { bool shutting_down_; bool is_main_; ::rust::Box<shim::rust::MessageLoopThread>* rust_thread_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(MessageLoopThread); }; inline std::ostream& operator<<(std::ostream& os, diff --git a/system/common/once_timer.h b/system/common/once_timer.h index ca7185d001..d708ed97d6 100644 --- a/system/common/once_timer.h +++ b/system/common/once_timer.h @@ -39,6 +39,9 @@ class MessageLoopThread; class OnceTimer final { public: OnceTimer() {} + OnceTimer(const OnceTimer&) = delete; + OnceTimer& operator=(const OnceTimer&) = delete; + ~OnceTimer(); /** @@ -84,8 +87,6 @@ class OnceTimer final { void CancelClosure(std::promise<void> promise); void RunTask(); - - DISALLOW_COPY_AND_ASSIGN(OnceTimer); }; } // namespace common diff --git a/system/common/repeating_timer.h b/system/common/repeating_timer.h index 24eae67d09..5c2c9e3169 100644 --- a/system/common/repeating_timer.h +++ b/system/common/repeating_timer.h @@ -39,6 +39,9 @@ class MessageLoopThread; class RepeatingTimer final { public: RepeatingTimer() : expected_time_next_task_us_(0) {} + RepeatingTimer(const RepeatingTimer&) = delete; + RepeatingTimer& operator=(const RepeatingTimer&) = delete; + ~RepeatingTimer(); /** @@ -85,8 +88,6 @@ class RepeatingTimer final { void CancelClosure(std::promise<void> promise); void RunTask(); - - DISALLOW_COPY_AND_ASSIGN(RepeatingTimer); }; } // namespace common diff --git a/system/device/include/controller.h b/system/device/include/controller.h index d65ab32d90..d2ee43833e 100644 --- a/system/device/include/controller.h +++ b/system/device/include/controller.h @@ -114,6 +114,7 @@ typedef struct controller_t { void (*set_ble_resolving_list_max_size)(int resolving_list_max_size); uint8_t* (*get_local_supported_codecs)(uint8_t* number_of_codecs); uint8_t (*get_le_all_initiating_phys)(void); + uint8_t (*clear_event_filter)(void); } controller_t; diff --git a/system/embdrv/lc3/fuzzer/liblc3encoder_fuzzer.cpp b/system/embdrv/lc3/fuzzer/liblc3encoder_fuzzer.cpp index 7979bc7047..767dba495e 100644 --- a/system/embdrv/lc3/fuzzer/liblc3encoder_fuzzer.cpp +++ b/system/embdrv/lc3/fuzzer/liblc3encoder_fuzzer.cpp @@ -37,7 +37,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { void* lc3_encoder_mem = nullptr; lc3_encoder_mem = malloc(enc_size); - lc3_encoder_t lc3_encoder = lc3_setup_encoder(dt_us, sr_hz, lc3_encoder_mem); + lc3_encoder_t lc3_encoder = + lc3_setup_encoder(dt_us, sr_hz, 0, lc3_encoder_mem); std::vector<uint8_t> output(output_byte_count); lc3_encode(lc3_encoder, (const int16_t*)input_frames.data(), 1, diff --git a/system/embdrv/lc3/include/lc3.h b/system/embdrv/lc3/include/lc3.h index ec53f2b162..f8dc8b3492 100644 --- a/system/embdrv/lc3/include/lc3.h +++ b/system/embdrv/lc3/include/lc3.h @@ -205,6 +205,9 @@ int lc3_delay_samples(int dt_us, int sr_hz); * dt_us Frame duration in us, 7500 or 10000 * sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000 * return Size of then encoder in bytes, 0 on bad parameters + * + * The `sr_hz` parameter is the samplerate of the PCM input stream, + * and will match `sr_pcm_hz` of `lc3_setup_encoder()`. */ unsigned lc3_encoder_size(int dt_us, int sr_hz); @@ -212,10 +215,18 @@ unsigned lc3_encoder_size(int dt_us, int sr_hz); * Setup encoder * dt_us Frame duration in us, 7500 or 10000 * sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000 + * sr_pcm_hz Input samplerate, downsampling option of input, or 0 * mem Encoder memory space, aligned to pointer type * return Encoder as an handle, NULL on bad parameters + * + * The `sr_pcm_hz` parameter is a downsampling option of PCM input, + * the value `0` fallback to the samplerate of the encoded stream `sr_hz`. + * When used, `sr_pcm_hz` is intended to be higher or equal to the encoder + * samplerate `sr_hz`. The size of the context needed, given by + * `lc3_encoder_size()` will be set accordingly to `sr_pcm_hz`. */ -lc3_encoder_t lc3_setup_encoder(int dt_us, int sr_hz, void *mem); +lc3_encoder_t lc3_setup_encoder( + int dt_us, int sr_hz, int sr_pcm_hz, void *mem); /** * Encode a frame @@ -233,6 +244,9 @@ int lc3_encode(lc3_encoder_t encoder, * dt_us Frame duration in us, 7500 or 10000 * sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000 * return Size of then decoder in bytes, 0 on bad parameters + * + * The `sr_hz` parameter is the samplerate of the PCM output stream, + * and will match `sr_pcm_hz` of `lc3_setup_decoder()`. */ unsigned lc3_decoder_size(int dt_us, int sr_hz); @@ -240,10 +254,18 @@ unsigned lc3_decoder_size(int dt_us, int sr_hz); * Setup decoder * dt_us Frame duration in us, 7500 or 10000 * sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000 + * sr_pcm_hz Output samplerate, upsampling option of output (or 0) * mem Decoder memory space, aligned to pointer type * return Decoder as an handle, NULL on bad parameters + * + * The `sr_pcm_hz` parameter is an upsampling option of PCM output, + * the value `0` fallback to the samplerate of the decoded stream `sr_hz`. + * When used, `sr_pcm_hz` is intended to be higher or equal to the decoder + * samplerate `sr_hz`. The size of the context needed, given by + * `lc3_decoder_size()` will be set accordingly to `sr_pcm_hz`. */ -lc3_decoder_t lc3_setup_decoder(int dt_us, int sr_hz, void *mem); +lc3_decoder_t lc3_setup_decoder( + int dt_us, int sr_hz, int sr_pcm_hz, void *mem); /** * Decode a frame diff --git a/system/embdrv/lc3/include/lc3_private.h b/system/embdrv/lc3/include/lc3_private.h index d6037d57e4..c59ff53d46 100644 --- a/system/embdrv/lc3/include/lc3_private.h +++ b/system/embdrv/lc3/include/lc3_private.h @@ -97,7 +97,7 @@ typedef struct lc3_spec_analysis { struct lc3_encoder { enum lc3_dt dt; - enum lc3_srate sr; + enum lc3_srate sr, sr_pcm; lc3_attdet_analysis_t attdet; lc3_ltpf_analysis_t ltpf; @@ -134,7 +134,7 @@ typedef struct lc3_plc_state { struct lc3_decoder { enum lc3_dt dt; - enum lc3_srate sr; + enum lc3_srate sr, sr_pcm; lc3_ltpf_synthesis_t ltpf; lc3_plc_state_t plc; diff --git a/system/embdrv/lc3/src/bits.h b/system/embdrv/lc3/src/bits.h index d1fc45033d..388bba1611 100644 --- a/system/embdrv/lc3/src/bits.h +++ b/system/embdrv/lc3/src/bits.h @@ -292,7 +292,7 @@ static inline unsigned lc3_get_symbol( if (ac->error) ac->low = 0; - unsigned s = 16; + int s = 16; if (ac->low < range * symbols[s].low) { s >>= 1; diff --git a/system/embdrv/lc3/src/lc3.c b/system/embdrv/lc3/src/lc3.c index bff7dc30c9..6fd7575014 100644 --- a/system/embdrv/lc3/src/lc3.c +++ b/system/embdrv/lc3/src/lc3.c @@ -153,7 +153,7 @@ static void load_s16( struct lc3_encoder *encoder, const int16_t *pcm, int pitch) { enum lc3_dt dt = encoder->dt; - enum lc3_srate sr = encoder->sr; + enum lc3_srate sr = encoder->sr_pcm; float *xs = encoder->xs; int ns = LC3_NS(dt, sr); @@ -172,23 +172,25 @@ static void analyze(struct lc3_encoder *encoder, { enum lc3_dt dt = encoder->dt; enum lc3_srate sr = encoder->sr; + enum lc3_srate sr_pcm = encoder->sr_pcm; + int ns = LC3_NS(dt, sr_pcm); + int nd = LC3_ND(dt, sr_pcm); + float *xs = encoder->xs; float *xf = encoder->xf; - int ns = LC3_NS(dt, sr); - int nd = LC3_ND(dt, sr); /* --- Temporal --- */ - bool att = lc3_attdet_run(dt, sr, nbytes, &encoder->attdet, xs); + bool att = lc3_attdet_run(dt, sr_pcm, nbytes, &encoder->attdet, xs); side->pitch_present = - lc3_ltpf_analyse(dt, sr, &encoder->ltpf, xs, &side->ltpf); + lc3_ltpf_analyse(dt, sr_pcm, &encoder->ltpf, xs, &side->ltpf); /* --- Spectral --- */ float e[LC3_NUM_BANDS]; - lc3_mdct_forward(dt, sr, xs, xf); + lc3_mdct_forward(dt, sr_pcm, sr, xs, xf); memmove(xs - nd, xs + ns-nd, nd * sizeof(float)); bool nn_flag = lc3_energy_compute(dt, sr, xf, e); @@ -260,26 +262,32 @@ unsigned lc3_encoder_size(int dt_us, int sr_hz) /** * Setup encoder */ -struct lc3_encoder *lc3_setup_encoder(int dt_us, int sr_hz, void *mem) +struct lc3_encoder *lc3_setup_encoder( + int dt_us, int sr_hz, int sr_pcm_hz, void *mem) { + if (sr_pcm_hz <= 0) + sr_pcm_hz = sr_hz; + enum lc3_dt dt = resolve_dt(dt_us); enum lc3_srate sr = resolve_sr(sr_hz); + enum lc3_srate sr_pcm = resolve_sr(sr_pcm_hz); - if (dt >= LC3_NUM_DT || sr >= LC3_NUM_SRATE || !mem) + if (dt >= LC3_NUM_DT || sr_pcm >= LC3_NUM_SRATE || sr > sr_pcm || !mem) return NULL; struct lc3_encoder *encoder = mem; - int ns = LC3_NS(dt, sr); - int nd = LC3_ND(dt, sr); + int ns = LC3_NS(dt, sr_pcm); + int nd = LC3_ND(dt, sr_pcm); *encoder = (struct lc3_encoder){ .dt = dt, .sr = sr, + .sr_pcm = sr_pcm, .xs = encoder->s + nd, .xf = encoder->s + nd+ns, }; memset(encoder->s, 0, - LC3_ENCODER_BUFFER_COUNT(dt_us, sr_hz) * sizeof(float)); + LC3_ENCODER_BUFFER_COUNT(dt_us, sr_pcm_hz) * sizeof(float)); return encoder; } @@ -324,7 +332,7 @@ static void store_s16( struct lc3_decoder *decoder, int16_t *pcm, int pitch) { enum lc3_dt dt = decoder->dt; - enum lc3_srate sr = decoder->sr; + enum lc3_srate sr = decoder->sr_pcm; float *xs = decoder->xs; int ns = LC3_NS(dt, sr); @@ -391,8 +399,9 @@ static void synthesize(struct lc3_decoder *decoder, { enum lc3_dt dt = decoder->dt; enum lc3_srate sr = decoder->sr; - int ns = LC3_NS(dt, sr); - int nh = LC3_NH(sr); + enum lc3_srate sr_pcm = decoder->sr_pcm; + int ns = LC3_NS(dt, sr_pcm); + int nh = LC3_NH(sr_pcm); float *xf = decoder->xs; float *xg = decoder->xg; @@ -408,15 +417,15 @@ static void synthesize(struct lc3_decoder *decoder, lc3_sns_synthesize(dt, sr, &side->sns, xf, xg); - lc3_mdct_inverse(dt, sr, xg, xd, xs); + lc3_mdct_inverse(dt, sr_pcm, sr, xg, xd, xs); } else { lc3_plc_synthesize(dt, sr, &decoder->plc, xg, xf); - lc3_mdct_inverse(dt, sr, xf, xd, xs); + lc3_mdct_inverse(dt, sr_pcm, sr, xf, xd, xs); } - lc3_ltpf_synthesize(dt, sr, nbytes, &decoder->ltpf, + lc3_ltpf_synthesize(dt, sr_pcm, nbytes, &decoder->ltpf, side && side->pitch_present ? &side->ltpf : NULL, xs); memmove(xs - nh, xs - nh+ns, nh * sizeof(*xs)); @@ -438,21 +447,27 @@ unsigned lc3_decoder_size(int dt_us, int sr_hz) /** * Setup decoder */ -struct lc3_decoder *lc3_setup_decoder(int dt_us, int sr_hz, void *mem) +struct lc3_decoder *lc3_setup_decoder( + int dt_us, int sr_hz, int sr_pcm_hz, void *mem) { + if (sr_pcm_hz <= 0) + sr_pcm_hz = sr_hz; + enum lc3_dt dt = resolve_dt(dt_us); enum lc3_srate sr = resolve_sr(sr_hz); + enum lc3_srate sr_pcm = resolve_sr(sr_pcm_hz); - if (dt >= LC3_NUM_DT || sr >= LC3_NUM_SRATE || !mem) + if (dt >= LC3_NUM_DT || sr_pcm >= LC3_NUM_SRATE || sr > sr_pcm || !mem) return NULL; struct lc3_decoder *decoder = mem; - int nh = LC3_NH(sr); - int ns = LC3_NS(dt, sr); - int nd = LC3_ND(dt, sr); + int nh = LC3_NH(sr_pcm); + int ns = LC3_NS(dt, sr_pcm); + int nd = LC3_ND(dt, sr_pcm); *decoder = (struct lc3_decoder){ .dt = dt, .sr = sr, + .sr_pcm = sr_pcm, .xs = decoder->s + nh, .xd = decoder->s + nh+ns, .xg = decoder->s + nh+ns+nd, @@ -461,7 +476,7 @@ struct lc3_decoder *lc3_setup_decoder(int dt_us, int sr_hz, void *mem) lc3_plc_reset(&decoder->plc); memset(decoder->s, 0, - LC3_DECODER_BUFFER_COUNT(dt_us, sr_hz) * sizeof(float)); + LC3_DECODER_BUFFER_COUNT(dt_us, sr_pcm_hz) * sizeof(float)); return decoder; } @@ -472,8 +487,6 @@ struct lc3_decoder *lc3_setup_decoder(int dt_us, int sr_hz, void *mem) int lc3_decode(struct lc3_decoder *decoder, const void *in, int nbytes, int16_t *pcm, int pitch) { - struct side_data side; - /* --- Check parameters --- */ if (!decoder) @@ -485,6 +498,8 @@ int lc3_decode(struct lc3_decoder *decoder, /* --- Processing --- */ + struct side_data side; + int ret = !in || (decode(decoder, in, nbytes, &side) < 0); synthesize(decoder, ret ? NULL : &side, nbytes); diff --git a/system/embdrv/lc3/src/mdct.c b/system/embdrv/lc3/src/mdct.c index 8e95284f81..c02904a1be 100644 --- a/system/embdrv/lc3/src/mdct.c +++ b/system/embdrv/lc3/src/mdct.c @@ -464,9 +464,10 @@ static void imdct_window(enum lc3_dt dt, enum lc3_srate sr, * Forward MDCT transformation */ void lc3_mdct_forward(enum lc3_dt dt, enum lc3_srate sr, - const float *x, float *y) + enum lc3_srate sr_dst, const float *x, float *y) { const struct lc3_mdct_rot_def *rot = lc3_mdct_rot[dt][sr]; + int nf = LC3_NS(dt, sr_dst); int ns = LC3_NS(dt, sr); union { float *f; struct lc3_complex *z; } u = { .f = y }; @@ -476,16 +477,17 @@ void lc3_mdct_forward(enum lc3_dt dt, enum lc3_srate sr, mdct_pre_fft(rot, u.f, u.z); u.z = fft(false, u.z, ns/2, u.z, z); - mdct_post_fft(rot, u.z, y, sqrtf(2.f / ns)); + mdct_post_fft(rot, u.z, y, sqrtf( (2.f*nf) / (ns*ns) )); } /** * Inverse MDCT transformation */ void lc3_mdct_inverse(enum lc3_dt dt, enum lc3_srate sr, - const float *x, float *d, float *y) + enum lc3_srate sr_src, const float *x, float *d, float *y) { const struct lc3_mdct_rot_def *rot = lc3_mdct_rot[dt][sr]; + int nf = LC3_NS(dt, sr_src); int ns = LC3_NS(dt, sr); struct lc3_complex buffer[ns/2]; @@ -494,7 +496,7 @@ void lc3_mdct_inverse(enum lc3_dt dt, enum lc3_srate sr, imdct_pre_fft(rot, x, z); z = fft(true, z, ns/2, z, u.z); - imdct_post_fft(rot, z, u.f, sqrtf(2.f / ns)); + imdct_post_fft(rot, z, u.f, sqrtf(2.f / nf)); imdct_window(dt, sr, u.f, d, y); } diff --git a/system/embdrv/lc3/src/mdct.h b/system/embdrv/lc3/src/mdct.h index c2c3bdcb85..27e48f40e3 100644 --- a/system/embdrv/lc3/src/mdct.h +++ b/system/embdrv/lc3/src/mdct.h @@ -32,6 +32,7 @@ /** * Forward MDCT transformation * dt, sr Duration and samplerate (size of the transform) + * sr_dst Samplerate destination, scale transforam accordingly * x [-nd..-1] Previous, [0..ns-1] Current samples * y Output `ns` frequency coefficients * @@ -40,18 +41,19 @@ * nd: `ns` * 5/ 8 for 10ms frame duration */ void lc3_mdct_forward(enum lc3_dt dt, enum lc3_srate sr, - const float *x, float *y); + enum lc3_srate sr_dst, const float *x, float *y); /** * Inverse MDCT transformation * dt, sr Duration and samplerate (size of the transform) + * sr_src Samplerate source, scale transforam accordingly * x, d Frequency coefficients and delayed buffer * y, d Output `ns` samples and `nd` delayed ones * * `x` and `y` can be the same buffer */ void lc3_mdct_inverse(enum lc3_dt dt, enum lc3_srate sr, - const float *x, float *d, float *y); + enum lc3_srate sr_src, const float *x, float *d, float *y); #endif /* __LC3_MDCT_H */ diff --git a/system/embdrv/lc3/src/tns.c b/system/embdrv/lc3/src/tns.c index 0ddd72caa4..8545d78380 100644 --- a/system/embdrv/lc3/src/tns.c +++ b/system/embdrv/lc3/src/tns.c @@ -448,7 +448,7 @@ void lc3_tns_get_data(lc3_bits_t *bits, lc3_tns_order_models + data->lpc_weighting); for (int i = 0; i < data->rc_order[f]; i++) - data->rc[f][i] = lc3_get_symbol(bits, + data->rc[f][i] = (int)lc3_get_symbol(bits, lc3_tns_coeffs_models + i) - 8; } } diff --git a/system/embdrv/lc3_dec/Android.bp b/system/embdrv/lc3_dec/Android.bp deleted file mode 100644 index 36c4099518..0000000000 --- a/system/embdrv/lc3_dec/Android.bp +++ /dev/null @@ -1,69 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "system_bt_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["system_bt_license"], -} - -cc_library_static { - name: "liblc3codec", - host_supported: true, - apex_available: [ - - "//apex_available:platform", - "com.android.bluetooth" - ], - defaults: ["fluoride_defaults"], - srcs: [ - "Common/*.cpp", - "Common/fft/*.c", - "Common/Tables/*.cpp", - "Decoder/*.cpp", - "TestSupport/DatapointsAndroid.cpp", - ], - cflags: [ - "-Werror", - "-Wmissing-braces", - "-Wno-unused-parameter", - "-Wno-#warnings", - "-Wuninitialized", - "-Wno-self-assign", - "-Wno-implicit-fallthrough", - ], - target: { - android: { - sanitize: { - misc_undefined:[ - "unsigned-integer-overflow", - "signed-integer-overflow", - "bounds", - ], - cfi: true, - }, - }, - }, - shared_libs: [ - "liblog", - ], - export_include_dirs: [ - "Api", - "Common", - "Common/fft", - "Common/Tables", - "TestSupport", - ], -} - -cc_fuzz { - name: "liblc3codec_decoder_fuzzer", - - srcs: [ - "fuzzer/liblc3codec_decoder_fuzzer.cpp", - ], - - static_libs: [ - "liblc3codec", - ], -}
\ No newline at end of file diff --git a/system/embdrv/lc3_dec/Api/Lc3Config.hpp b/system/embdrv/lc3_dec/Api/Lc3Config.hpp deleted file mode 100644 index 94469050f8..0000000000 --- a/system/embdrv/lc3_dec/Api/Lc3Config.hpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Lc3Config.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef __LC3_CONFIG_HPP_ -#define __LC3_CONFIG_HPP_ - -#include <cstdint> - -/* - * The LC3 encoder and decoder have a common set of essential session - * configuration parameters - see LC3 specification Sections 2.2 "Encoder - * interfaces" and Section 2.4 "Decoder interfaces" (dr09r07). The set of common - * session configuration parameters is represented by an instance of class - * Lc3Config. - * - * Lc3Config is designed such that all parameters need to be - * providing when constructing an instance. Afterwards, success of creation, - * the actual parameter values, and derived parameter values are provided - * by corresponding const getter methods or public const fields. - * - * When parameters need to be changes, a new instance of Lc3Config has to be - * created. - * - * Instances of Lc3Config are provided to instances of Lc3Encoder and Lc3Decoder - * when constructing them. - * - * The main purpose of Lc3Config is to verify and handle common LC3 session - * configuration parameters in a consistent way. - * - */ -class Lc3Config { - public: - /* - * Enumeration of supported frame durations N_ms = 7.5ms and N_ms = 10ms. - * - * Note: although the LC3 specification describes frame duration N_ms as - * a parameter with floating point values 7.5 and 10.0, we decided - * to make this parameter a discrete enumeration of supported - * frame durations. There are too many codec parts that need - * specifically listed constants dependent on the configured - * frame duration, so that it never will be possible to chose from a - * larger set of floating point values for N_ms. - * Making the data type of N_ms an enumeration supports - * straight forwards verification that meaningful parameters are given. - */ - enum class FrameDuration { d10ms, d7p5ms }; - - // configuration error (see "getErrorStatus") - static const uint8_t ERROR_FREE = 0x00; - static const uint8_t INVALID_SAMPLING_RATE = 0x01; - static const uint8_t INVALID_FRAME_DURATION = 0x02; - static const uint8_t INVALID_NUMBER_OF_CHANNELS = 0x04; - - /* - * Constructor of an instance of Lc3Config - * Parameters: - * (see also see LC3 specification Sections 2.2 "Encoder interfaces" - * and Section 2.4 "Decoder interfaces" (dr09r07) ) - * - * Fs_ : Sampling frequency in Hz -> defines public constant Fs - * Supported values are - * 8000 Hz - * 16000 Hz - * 24000 Hz - * 32000 Hz - * 44100 Hz - * 48000 Hz - * - * N_ms_ : Frame duration given by value from enumeration FrameDuration (see - * above) - * -> defines public constant N_ms - * Supported values see enumeration FrameDuration. - * - * Nc_ : Number of channels -> defines public constant Nc - * Supported values are Nc > 0 and Nc < 256 such that device - * resources are not exhausted. Notes: - * - Exhausting device resources can mean that there is not enough - * memory to instantiate the corresponding number of encoders and/or decoders, - * but also that computing the encoders and/or decoders in real-time is not - * possible. - * - The parameter N_c_max described in the LC3 specifciation is - * not given here, since there is too little knowledge on the target devices - * where this code may be used. - * - */ - Lc3Config(uint16_t Fs_, FrameDuration N_ms_, uint8_t Nc_); - - // no default constructor supported - Lc3Config() = delete; - - // Destructor - virtual ~Lc3Config(); - - /* - * Getter "isValid" provides a convenience function that returns true when an - * instance of Lc3Config could be created without error. - */ - bool isValid() const; - - /* - * Getter "getErrorStatus" provides details on the success of instantiating - * Lc3Config. The possible return values are listed as constants in this class - * (see configuration error constants above) - */ - uint8_t getErrorStatus() const; - - /* - * Getter "getByteCountFromBitrate" provides the number of bytes available in - * one encoded frame of one channel (see "nbytes" as described in - * Section 3.2.5 "Bit budget and bitrate" (dr09r07) ) - * - * The number of bytes "nbytes" to use for encoding a single channel is a - * required external input to each single channel LC3 encoder. The same number - * of bytes (now to be used for decoding) is also a required external input to - * each single channel LC3 decoder. The corresponding number of bits available - * in one frame is thus "nbits 8*nbytes". The codec works on a byte boundary, - * i.e. the variable "nbytes" shall be an integer number. A certain "bitrate" - * can be converted to a number of bytes "nbytes" where the number of bytes is - * rounded towards the nearest lower integer. - * - * The algorithm is verified from the bitrate corresponding to - * nbytes = 20 up to the bitrate corresponding to - * nbytes = 400 per channel for all sampling rates. - * The LC3 specification does not specify or recommend what bitrate to use for - * encoding a frame of audio samples. This is specified by the profiles making - * use of the LC3. - */ - uint16_t getByteCountFromBitrate( - uint32_t bitrate) const; // meant for a single channel - - /* - * Getter "getBitrateFromByteCount" provides the bitrate of the codec in bits - * per second of one channel (see Section 3.2.5 "Bit budget and bitrate" - * (dr1.0r03) ) - * - * This is a convenience utility and not directly used by the LC3 - * implementation. - * - * The bitrate of the codec in bits per second is - * "bitrate = ceil(nbits / frame_duration) = ceil(nbits*Fs/NF) = - * ceil(8*nbytes*Fs/NF)". - * - * The LC3 specification does not specify or recommend what bitrate to use for - * encoding a frame of audio samples. This is specified by the profiles making - * use of the LC3. - */ - uint32_t getBitrateFromByteCount(uint16_t nbytes) const; - - /* - * Getter "getFscal" provides a utility used within the LC3 implementation - * for easier parameter mapping when Fs == 44100 - * (see Section 3.2.2 "Sampling rates" (dr1.0r03) ) - */ - double getFscal() const; - - /* - * Getter "getNmsValue" provides a utility used within the LC3 implementation - * that converts FrameDuration N_ms enumeration values to duration values in - * milliseconds. - */ - double getNmsValue() const; - - private: - // internal utilities used for verifying the given input parameters and - // computing derived parameters - uint8_t getFs_ind(uint16_t Fs); - uint16_t getNF(uint16_t Fs, FrameDuration N_ms); - uint16_t getNE(uint16_t NF, FrameDuration N_ms); - - // errors status set during construction and returned by getErrorStatus() - uint8_t errorStatus; - - public: - // configuration details -> see also Section 3.1.2 "Mathematical symbols" - // (dr09r07) - const uint16_t Fs; // Sampling rate (in Hz) - const uint8_t Fs_ind; // Sampling rate index (see also Section 3.2.2 - // "Sampling rates" (dr09r07) - const FrameDuration N_ms; // Frame duration -> see Lc3Config constructor - // documentation Note: that the actual frame - // duration is longer by a factor of 480/441 - // if the sampling rate is 44100 Hz - const uint16_t NF; // Number of samples processed in one frame of one channel - // (also known as frame size) - const uint16_t - NE; // Number of encoded spectral lines (per frame and channel) - const uint16_t Z; // Number of leading zeros in MDCT window - const uint8_t Nc; // Number of channels - const uint8_t N_b; // Number of bands -}; - -#endif // __LC3_CONFIG_HPP_ diff --git a/system/embdrv/lc3_dec/Api/Lc3Decoder.hpp b/system/embdrv/lc3_dec/Api/Lc3Decoder.hpp deleted file mode 100644 index aec64fe933..0000000000 --- a/system/embdrv/lc3_dec/Api/Lc3Decoder.hpp +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Lc3Decoder.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef API_LC3DECODER_HPP_ -#define API_LC3DECODER_HPP_ - -#include <cstdint> -#include <vector> - -#include "Lc3Config.hpp" - -/* - * Forward declaration of the "internal" class DecoderTop, so - * that the private vector of single channel decoders can be declared in - * Lc3Decoder. - */ -namespace Lc3Dec { -class DecoderTop; -} - -/* - * The LC3 decoder interface is specified in - * LC3 specification Sections 2.4 "Decoder interfaces" (dr09r07). - * - * Lc3Decoder is designed such that all specified features are provided. - * - * In contrast to the Lc3Encoder, even 24bit and 32bit decoded audio - * data can be provided - however in one fix byte arrangement which will - * not meet all meaningful options. Providing 24bit and 32bit decoded audio - * data makes the API more complex but does not increase the needed - * resources when basic 16bit/sample audio data is desired only. - * - * Instantiating Lc3Decoder implies providing a Lc3Config instance. A copy of - * this instance is available as public const member so that all essential - * session parameters can be obtained throughout the lifetime of the Lc3Decoder - * instance. - * - * There is no possibility of changing Lc3Config within Lc3Decoder. When session - * parameters have to be changed, the calling application has to create a new - * instance of Lc3Decoder. - * - * Lc3 supports operation with variable encoded bitrate. It is possible to - * change the bitrate from frame to frame, where for preciseness the parameter - * is not given as bitrate directly but in terms of the byte_count per frame. - * This parameter has to be in the range of 20 to 400 (see LC3 specification - * Section 3.2.5 "Bit budget and bitrate"). LC3 specification Sections 2.4 - * "Decoder interfaces" specifies "byte_count_max" of the decoder to allow - * pre-allocation of resources. This parameter is provided here for completeness - * and used for verifying the byte_count value of individual frames only. The - * needed memory has to be provided by the calling application anyway, so that - * it is up to the application whether a pre-allocation of memory is useful. - * - */ - -class Lc3Decoder { - public: - /* - * Convenience constructor of Lc3Decoder with two simple parameter only. - * Note that this constructor instantiated Lc3Config implicitly with - * Lc3Decoder(Lc3Config(Fs,frameDuration, 1)) that means that this - * constructor provides processing of one channel (mono) and 16bit/sample - * PCM output only. - * - * Parameters: - * Fs : Sampling frequency in Hz -> see Lc3Config.hpp for supported values - * - * frameDuration : frame duration of 10ms (default) or 7.5ms - * -> see Lc3Config.hpp for more details - */ - Lc3Decoder(uint16_t Fs, Lc3Config::FrameDuration frameDuration = - Lc3Config::FrameDuration::d10ms); - - /* - * General constructor of Lc3Decoder. - * - * Parameters: - * lc3Config_ : instance of Lc3Config. See documentation of Lc3Config for - * more details. Note: providing an invalid instance of Lc3Config will result - * in skipping any processing later. - * The provided instance of Lc3Config will be copied to the - * public field "lc3Config" (see below). - * - * bits_per_audio_sample_dec_ : Bits per audio sample for the output PCM - * signal. See LC3 specification Section 2.4 "Decoder interfaces" and - * Section 3.2.3 "Bits per sample" for the general LC3 requirement to support - * 16, 24 and 32 bit. Note: This parameter may differ from the encoder input - * PCM setting "bits_per_audio_sample_enc". - * - * byte_count_max_dec_ : Maximum allowed payload byte_count for a single - * channel. When using and allowing external rate control, the maximum byte - * count for the session may be used to configure the - * session buffers without a need to dynamically reallocate memory during the - * session. - * - * datapoints : pointer to an instance of a class allowing to collect internal - * data. Note: this feature is used and prepared for testing of the codec - * implementation only. See general "Readme.txt" - */ - Lc3Decoder(Lc3Config lc3Config_, uint8_t bits_per_audio_sample_dec_ = 16, - uint16_t byte_count_max_dec_ = 400, void* datapoints = nullptr); - - // no default constructor supported - Lc3Decoder() = delete; - - // Destructor - virtual ~Lc3Decoder(); - - /* - * Configuration provided during instantiation accessible as public const - * fields. Note: Lc3Config provides a getter to check whether the - * configuration is valid. - */ - const Lc3Config lc3Config; - const uint8_t bits_per_audio_sample_dec; - const uint16_t byte_count_max_dec; - - // encoding error (see return values of "run" methods) - static const uint8_t ERROR_FREE = 0x00; - static const uint8_t INVALID_CONFIGURATION = 0x01; - static const uint8_t INVALID_BYTE_COUNT = 0x02; - static const uint8_t INVALID_X_OUT_SIZE = 0x03; - static const uint8_t INVALID_BITS_PER_AUDIO_SAMPLE = 0x04; - static const uint8_t DECODER_ALLOCATION_ERROR = 0x05; - - /* - * Decoding one 16 bit/sample output frame for one channel - * - * Note that this methods returns the error INVALID_BITS_PER_AUDIO_SAMPLE - * when the session has been configured for any bits_per_audio_sample_dec - * != 16. - * - * Further, note that this method can be used for multi-channel configurations - * as well, particularly when the provided multi-channel "run" (see below) is - * not supporting the kind of byte stream concatenation existing in the - * calling application. - * - * Parameters: - * bytes : pointer to byte array holding the input LC3 encoded byte stream - * of the given channel. - * The size of this memory is given by the byte_count parameter. - * - * byte_count : number of encoded bytes; byte count to be used for decoding - * the received frame payload. - * Supported values are 20 bytes to byte_count_max_dec bytes. - * - * BFI : Bad Frame Indication flags - * "0" signifies that no bit errors where detected in given "bytes" - * "1" signifies a corrupt payload packet was detected in given - * "bytes" - * - * x_out : pointer to output PCM data (16 bit/sample), where the memory - * has to be provided by the calling application. - * - * x_out_size : number of 16 bit values supported by x_out - * Note: this parameter has been introduced for clarity and - * verification purpose only. The method will return - * the error INVALID_X_OUT_SIZE when x_out_size != - * lc3Config.NF. - * - * BEC_detect : flag indication bit errors detected during decoding of input - * bytes Note: a basic packet loss concealment (PLC) will be applied when - * BEC_detect!=0, so that the returned audio data stays - * somewhat acceptable. - * - * channelNr : index of channel to be processed (default=0), where channelNr - * < lc3Config.Nc - * - * - * Return value: error code as listed above. - */ - uint8_t run(const uint8_t* bytes, uint16_t byte_count, uint8_t BFI, - int16_t* x_out, uint16_t x_out_size, uint8_t& BEC_detect, - uint8_t channelNr = 0); - - /* - * Decoding one 16, 24, or 32 bit/sample output frame for one channel - * - * Note that every output PCM sample will need one 32 bit memory place in the - * output stream independently from the configured bits_per_audio_sample_dec. - * - * Further, note that this method can be used for multi-channel configurations - * as well, particularly when the provided multi-channel "run" (see below) is - * not supporting the kind of byte stream concatenation existing in the - * calling application. - * - * Parameters: - * bytes : pointer to byte array holding the input LC3 encoded byte stream - * of the given channel. - * The size of this memory is given by the byte_count parameter. - * - * byte_count : number of encoded bytes; byte count to be used for decoding - * the received frame payload. - * Supported values are 20 bytes to byte_count_max_dec bytes. - * - * BFI : Bad Frame Indication flags - * "0" signifies that no bit errors where detected in given "bytes" - * "1" signifies a corrupt payload packet was detected in given - * "bytes" - * - * x_out : pointer to output PCM data (memory 32 bit/sample, precision 16 - * bit/sample, 24 bit/sample or 32 bit/sample), where the memory has to be - * provided by the calling application. - * - * x_out_size : number of 32 bit values supported by x_out - * Note: this parameter has been introduced for clarity and - * verification purpose only. The method will return - * the error INVALID_X_OUT_SIZE when x_out_size != - * lc3Config.NF. - * - * BEC_detect : flag indication bit errors detected during decoding of input - * bytes Note: a basic packet loss concealment (PLC) will be applied when - * BEC_detect!=0, so that the returned audio data stays - * somewhat acceptable. - * - * channelNr : index of channel to be processed (default=0), where channelNr - * < lc3Config.Nc - * - * - * Return value: error code as listed above. - */ - uint8_t run(const uint8_t* bytes, uint16_t byte_count, uint8_t BFI, - int32_t* x_out, uint16_t x_out_size, uint8_t& BEC_detect, - uint8_t channelNr = 0); - - /* - * Decoding one 16 bit/sample output frame for multiple channels. - * - * Note that this methods returns the error INVALID_BITS_PER_AUDIO_SAMPLE - * when the session has been configured for any bits_per_audio_sample_dec - * != 16. - * - * Parameters: - * bytes : pointer to byte array holding the input LC3 encoded byte stream - * of all given channels. - * The size of this memory is given by the sum of all - * byte_count_per_channel values (see parameter byte_count_per_channel). Note - * that the encoded values of all channels are expected to be concatenated - * without any stuffing bytes of meta data in between. - * - * byte_count_per_channel : number of encoded bytes; byte count to be used - * for decoding the received frame payload per channel. Thus, - * byte_count_per_channel is an array of byte_count values with length - * lc3Conig.Nc Supported values are 20 bytes to byte_count_max_dec bytes per - * channel. - * - * BFI_per_channel : lc3Conig.Nc length array of Bad Frame Indication flags - * "0" signifies that no bit errors where detected in - * given "bytes" "1" signifies a corrupt payload packet was detected in given - * "bytes" - * - * x_out : pointer to output 16 bit/sample PCM data, where the memory - * has to be provided by the calling application. - * - * x_out_size : number of 16 bit values supported by x_out - * Note: this parameter has been introduced for clarity and - * verification purpose only. The method will return - * the error INVALID_X_OUT_SIZE when x_out_size != - * lc3Config.NF * lc3Conig.Nc. - * - * BEC_detect_per_channel : lc3Conig.Nc length array of flags indicating bit - * errors detected during decoding of input bytes of a certain channel. Note: - * a basic packet loss concealment (PLC) will be applied when BEC_detect!=0, - * so that the returned audio data stays somewhat acceptable. - * - * - * Return value: error code via "or" concatenation of the error codes of - * processing the individual channels. Note: this "or" concatenation make - * specific error diagnosis impossible. Thus only checking != ERROR_FREE is - * meaningful. When more specific information is needed, the single channel - * call (see above) need to be called. - */ - uint8_t run(const uint8_t* bytes, const uint16_t* byte_count_per_channel, - const uint8_t* BFI_per_channel, int16_t* x_out, - uint32_t x_out_size, uint8_t* BEC_detect_per_channel); - - /* - * Decoding one 16, 24, or 32 bit/sample output frame for multiple channels - * - * Note that every output PCM sample will need one 32 bit memory place in the - * output stream independently from the configured bits_per_audio_sample_dec. - * - * Parameters: - * bytes : pointer to byte array holding the input LC3 encoded byte stream - * of all given channels. - * The size of this memory is given by the sum of all - * byte_count_per_channel values (see parameter byte_count_per_channel). Note - * that the encoded values of all channels are expected to be concatenated - * without any stuffing bytes of meta data in between. - * - * byte_count_per_channel : number of encoded bytes; byte count to be used - * for decoding the received frame payload per channel. Thus, - * byte_count_per_channel is an array of byte_count values with length - * lc3Conig.Nc Supported values are 20 bytes to byte_count_max_dec bytes per - * channel. - * - * BFI_per_channel : lc3Conig.Nc length array of Bad Frame Indication flags - * "0" signifies that no bit errors where detected in - * given "bytes" "1" signifies a corrupt payload packet was detected in given - * "bytes" - * - * x_out : pointer to output 16, 24, or 32 bit/sample PCM data, where the - * memory has to be provided by the calling application. - * - * x_out_size : number of 32 bit values supported by x_out - * Note: this parameter has been introduced for clarity and - * verification purpose only. The method will return - * the error INVALID_X_OUT_SIZE when x_out_size != - * lc3Config.NF * lc3Conig.Nc. - * - * BEC_detect_per_channel : lc3Conig.Nc length array of flags indicating bit - * errors detected during decoding of input bytes of a certain channel. Note: - * a basic packet loss concealment (PLC) will be applied when BEC_detect!=0, - * so that the returned audio data stays somewhat acceptable. - * - * - * Return value: error code via "or" concatenation of the error codes of - * processing the individual channels. Note: this "or" concatenation make - * specific error diagnosis impossible. Thus only checking != ERROR_FREE is - * meaningful. When more specific information is needed, the single channel - * call (see above) need to be called. - */ - uint8_t run(const uint8_t* bytes, const uint16_t* byte_count_per_channel, - const uint8_t* BFI_per_channel, int32_t* x_out, - uint32_t x_out_size, uint8_t* BEC_detect_per_channel); - - private: - std::vector<Lc3Dec::DecoderTop*> decoderList; -}; - -#endif /* API_LC3DECODER_HPP_ */ diff --git a/system/embdrv/lc3_dec/Common/DctIV.cpp b/system/embdrv/lc3_dec/Common/DctIV.cpp deleted file mode 100644 index 798322e57f..0000000000 --- a/system/embdrv/lc3_dec/Common/DctIV.cpp +++ /dev/null @@ -1,299 +0,0 @@ -/* - * DctIV.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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 "DctIV.hpp" - -#include <cmath> - -/* - * Notes on the choice of the applied FFT library: - * - Different fast transform implementations for the DCT-IV can be selected - * via USE_FFTW USE_FFTW_FOR_FFT // assume NF being 4 times an integer - * USE_KISSFFT // assume NF being 4 times an integer - * where only one of them is meaningful to be defined - * - * - Defining none of the fast transforms will lead to a direct implementation - * which is good for testing but usually to slow for practial applications - * - * - USE_FFTW: The free "fftw" library should be fastest, but may be more - * complicated to be build for embedded target devices. It provides dedicated - * optimization for the DCT-IV and thus is preferred from a technical - * perspective. In terms of licences "fftw" is free in the sense of GPL, which - * is not liked in some products. There might be the option to ask the authors - * for other licences (which they propose). Nevertheless, the "license" issue - * has driven us to not bundle "fftw" directly with the LC3 implementation, - * although the API for using it is provided and tested. - * - * - USE_FFTW_FOR_FFT: this is a not fully optimized alternative approach using - * the complex fft provided by "fftw" instead of the dedicated optimized DCT-IV - * implementation. This option is mainly provided to demonstrate the transition - * from USE_FFTW to USE_KISSFFT - * - * - USE_KISSFFT: the free "kissfft" library is sligthly slower than "fftw", - * but gives a majority of the possible performance gain over a "stupid" direct - * DCT-IV implementation. "kissfft" does not provide a dedicated optimization - * for DCT-IV so that some additional code for implementing a DCT-IV by a - * complex fft has to be added. This also implies additional memory needed. The - * big advantage of the "kissfft" is that it is less restrictive in terms of its - * license. Further, the template based C++ implementation reduces its impact on - * the build system to a minimum (we just need to include the right header - * without needing to compile and link a separate file). - * - * - USE_KISSFFT is defined below to be the default choice. The other - * alternatives may be selecting by providing its define via the compiler switch - * -D<define> - * - * - The impact of the defines is restricted to this *.cpp file for clarity - * reasons. Ok, to make this work, we needed a few "ugly" pointer casts, but we - * really wanted to make sure, that no other code or build impact is generated - * by the options in this file. - */ -#define USE_OWN_FFT - -#if defined USE_FFTW || defined USE_FFTW_FOR_FFT -#include <fftw3.h> - -#elif defined USE_KISSFFT -#include "kissfft.hh" - -class KissfftConfig { - public: - KissfftConfig(uint16_t N) : inbuf(nullptr), outbuf(nullptr), fft(nullptr) { - inbuf = new std::complex<double>[N]; - outbuf = new std::complex<double>[N]; - twiddle = new std::complex<double>[N]; - fft = new kissfft<double>(N, false); - - const double pi = std::acos(-1); - for (uint16_t n = 0; n < N; n++) { - twiddle[n] = - std::complex<double>(std::cos(-pi * (8 * n + 1) / (8.0 * N * 2)), - std::sin(-pi * (8 * n + 1) / (8.0 * N * 2))); - } - } - - ~KissfftConfig() { - if (nullptr != fft) { - delete fft; - } - if (nullptr != inbuf) { - delete[] inbuf; - } - if (nullptr != outbuf) { - delete[] outbuf; - } - if (nullptr != twiddle) { - delete[] twiddle; - } - } - - void transform() { - if (nullptr != fft) { - fft->transform(inbuf, outbuf); - } - } - - std::complex<double>* inbuf; - std::complex<double>* outbuf; - std::complex<double>* twiddle; - kissfft<double>* fft; -}; - -#elif defined USE_OWN_FFT -#include <complex> - -#include "fft.h" -#endif - -DctIVDbl::DctIVDbl(uint16_t NF_) - : NF(NF_), in(nullptr), out(nullptr), dctIVconfig(nullptr) { - in = new double[NF]; - out = new double[NF]; - -#if defined USE_FFTW - dctIVconfig = fftw_plan_r2r_1d(NF, in, out, FFTW_REDFT11, FFTW_ESTIMATE); - -#elif defined USE_FFTW_FOR_FFT - dctIVconfig = fftw_plan_dft_1d(NF / 2, reinterpret_cast<fftw_complex*>(in), - reinterpret_cast<fftw_complex*>(out), - FFTW_FORWARD, FFTW_ESTIMATE); - -#elif defined USE_KISSFFT - dctIVconfig = new KissfftConfig(NF / 2); - -#elif defined USE_OWN_FFT - - int N = NF / 2; - std::complex<double>* twiddle = new std::complex<double>[N]; - dctIVconfig = twiddle; - const double pi = std::acos(-1); - for (uint16_t n = 0; n < N; n++) { - twiddle[n] = - std::complex<double>(std::cos(-pi * (8 * n + 1) / (8.0 * N * 2)), - std::sin(-pi * (8 * n + 1) / (8.0 * N * 2))); - } - -#endif - - for (uint16_t n = 0; n < NF; n++) { - in[n] = 0; - out[n] = 0; - } -} - -DctIVDbl::~DctIVDbl() { -#if defined USE_FFTW || defined USE_FFTW_FOR_FFT - if (nullptr != dctIVconfig) { - fftw_destroy_plan(reinterpret_cast<fftw_plan>(dctIVconfig)); - } - -#elif defined USE_KISSFFT - if (nullptr != dctIVconfig) { - KissfftConfig* kissfftConfig = - reinterpret_cast<KissfftConfig*>(dctIVconfig); - delete kissfftConfig; - } - -#elif defined USE_OWN_FFT - std::complex<double>* twiddle = (std::complex<double>*)dctIVconfig; - delete[] twiddle; - -#endif - if (nullptr != in) { - delete[] in; - } - if (nullptr != out) { - delete[] out; - } -} - -void DctIVDirectDbl(uint16_t N, const double* const tw, double* const X) { - const double pi = std::acos(-1); - for (uint16_t k = 0; k < N; k++) { - X[k] = 0; - for (uint16_t n = 0; n < N; n++) { - X[k] += tw[n] * std::cos(pi / N * (n + 0.5) * (k + 0.5)); - } - X[k] *= 2; - } -} - -void DctIVDbl::run() { -#ifdef USE_FFTW - fftw_execute(reinterpret_cast<fftw_plan>(dctIVconfig)); - -#elif defined USE_FFTW_FOR_FFT - const double pi = std::acos(-1); - // assume NF being 4 times an integer - for (uint16_t n = 1; n < NF / 2; n += 2) { - double buffer; - buffer = in[n]; - in[n] = in[NF - n]; - in[NF - n] = buffer; - } - for (uint16_t n = 0; n < NF; n += 2) { - double real = in[n + 0]; - double imag = in[n + 1]; - in[n + 0] = real * std::cos(-pi * (4 * n + 1) / (8.0 * NF)) - - imag * std::sin(-pi * (4 * n + 1) / (8.0 * NF)); - in[n + 1] = real * std::sin(-pi * (4 * n + 1) / (8.0 * NF)) + - imag * std::cos(-pi * (4 * n + 1) / (8.0 * NF)); - } - - fftw_execute(reinterpret_cast<fftw_plan>(dctIVconfig)); - - for (uint16_t n = 0; n < NF; n += 2) { - double real = out[n + 0]; - double imag = out[n + 1]; - out[n + 0] = 2 * (real * std::cos(-pi * (4 * n + 1) / (8.0 * NF)) - - imag * std::sin(-pi * (4 * n + 1) / (8.0 * NF))); - out[n + 1] = 2 * (real * std::sin(-pi * (4 * n + 1) / (8.0 * NF)) + - imag * std::cos(-pi * (4 * n + 1) / (8.0 * NF))); - } - for (uint16_t n = 1; n < NF / 2; n += 2) { - double buffer; - buffer = out[n]; - out[n] = -out[NF - n]; - out[NF - n] = -buffer; - } - -#elif defined USE_KISSFFT - // assume NF being 4 times an integer - KissfftConfig* kissfftConfig = reinterpret_cast<KissfftConfig*>(dctIVconfig); - for (uint16_t n = 0; n < NF / 2; n++) { - kissfftConfig->inbuf[n] = - kissfftConfig->twiddle[n] * - std::complex<double>(in[2 * n], in[NF - 2 * n - 1]); - } - - kissfftConfig->transform(); - - for (uint16_t n = 0; n < NF / 2; n++) { - std::complex<double> complexOut = - kissfftConfig->twiddle[n] * kissfftConfig->outbuf[n]; - out[2 * n] = complexOut.real() * 2; - out[NF - 2 * n - 1] = -complexOut.imag() * 2; - } - -#elif defined USE_OWN_FFT - - fft_complex inbuf[NF / 2]; - fft_complex outbuf[NF / 2]; - - // assume NF being 4 times an integer - for (uint16_t n = 1; n < NF / 2; n += 2) { - double buffer; - buffer = in[n]; - in[n] = in[NF - n]; - in[NF - n] = buffer; - } - - std::complex<double>* twiddle = (std::complex<double>*)dctIVconfig; - for (uint16_t n = 0; n < NF / 2; n++) { - double real = in[2 * n + 0]; - double imag = in[2 * n + 1]; - in[2 * n + 0] = real * twiddle[n].real() - imag * twiddle[n].imag(); - in[2 * n + 1] = real * twiddle[n].imag() + imag * twiddle[n].real(); - } - - for (uint16_t n = 0; n < NF / 2; n++) { - inbuf[n].re = in[2 * n]; - inbuf[n].im = in[2 * n + 1]; - } - - fft_complex* actal_output = fft(false, inbuf, NF / 2, inbuf, outbuf); - - for (uint16_t n = 0; n < NF / 2; n++) { - double real = actal_output[n].re; - double imag = actal_output[n].im; - out[2 * n + 0] = 2 * (real * twiddle[n].real() - imag * twiddle[n].imag()); - out[2 * n + 1] = 2 * (real * twiddle[n].imag() + imag * twiddle[n].real()); - } - - for (uint16_t n = 1; n < NF / 2; n += 2) { - double buffer; - buffer = out[n]; - out[n] = -out[NF - n]; - out[NF - n] = -buffer; - } - -#else - DctIVDirectDbl(NF, in, out); -#endif -} diff --git a/system/embdrv/lc3_dec/Common/DctIV.hpp b/system/embdrv/lc3_dec/Common/DctIV.hpp deleted file mode 100644 index 1e40d23f9d..0000000000 --- a/system/embdrv/lc3_dec/Common/DctIV.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * DctIV.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef DCT_IV_H_ -#define DCT_IV_H_ - -#include <cstdint> - -class DctIVDbl { - public: - DctIVDbl(uint16_t NF_); - virtual ~DctIVDbl(); - - void run(); - - const uint16_t NF; - double* in; - double* out; - void* dctIVconfig; -}; - -#endif // DCT_IV_H_ diff --git a/system/embdrv/lc3_dec/Common/Lc3Config.cpp b/system/embdrv/lc3_dec/Common/Lc3Config.cpp deleted file mode 100644 index 1d58b04f8e..0000000000 --- a/system/embdrv/lc3_dec/Common/Lc3Config.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Lc3Config.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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 "Lc3Config.hpp" - -#include <cmath> - -Lc3Config::Lc3Config(uint16_t Fs_, FrameDuration N_ms_, uint8_t Nc_) - : errorStatus(ERROR_FREE), - Fs(Fs_), - Fs_ind(getFs_ind(Fs)), - N_ms(N_ms_), - NF(getNF(Fs, N_ms_)), - NE(getNE(NF, N_ms_)), - Z((N_ms == FrameDuration::d10ms) ? 3 * NF / 8 : 7 * NF / 30), - Nc(Nc_), - N_b(((N_ms == Lc3Config::FrameDuration::d7p5ms) && (Fs == 8000)) ? 60 - : 64) { - if (0 == Nc) // we do not restrict the maximum yet (naturally limited to 255 - // because of the chosen datatype) - { - errorStatus |= INVALID_NUMBER_OF_CHANNELS; - } -} - -Lc3Config::~Lc3Config() {} - -bool Lc3Config::isValid() const { return ERROR_FREE == errorStatus; } - -uint8_t Lc3Config::getErrorStatus() const { return errorStatus; } - -uint8_t Lc3Config::getFs_ind(uint16_t Fs) { - uint8_t fs_ind = 0; - switch (Fs) { - case 8000: - fs_ind = 0; - break; - case 16000: - fs_ind = 1; - break; - case 24000: - fs_ind = 2; - break; - case 32000: - fs_ind = 3; - break; - case 44100:; - case 48000: - fs_ind = 4; - break; - default: - errorStatus |= INVALID_SAMPLING_RATE; - } - return fs_ind; -} - -uint16_t Lc3Config::getNF(uint16_t Fs, FrameDuration N_ms) { - uint16_t NF = 80; - if (FrameDuration::d10ms == N_ms) { - switch (Fs) { - case 8000: - NF = 80; - break; - case 16000: - NF = 160; - break; - case 24000: - NF = 240; - break; - case 32000: - NF = 320; - break; - case 44100:; - case 48000: - NF = 480; - break; - default: - errorStatus |= INVALID_SAMPLING_RATE; - } - } else if (FrameDuration::d7p5ms == N_ms) { - switch (Fs) { - case 8000: - NF = 60; - break; - case 16000: - NF = 120; - break; - case 24000: - NF = 180; - break; - case 32000: - NF = 240; - break; - case 44100:; - case 48000: - NF = 360; - break; - default: - errorStatus |= INVALID_SAMPLING_RATE; - } - } else { - // We never should reach this line unless - // strange things happen. However, we want - // to be on the safe side and thus handle - // this case explicitly. - errorStatus |= INVALID_FRAME_DURATION; - } - return NF; -} - -uint16_t Lc3Config::getNE(uint16_t NF, FrameDuration N_ms) { - // 3.3.4.3 Time-Frequency Transformation (d09r04_*implementorComments*) - if (FrameDuration::d10ms == N_ms) { - return (480 == NF) ? 400 : NF; - } else { - return (360 == NF) ? 300 : NF; - } -} - -uint16_t Lc3Config::getByteCountFromBitrate(uint32_t bitrate) const { - // Section 3.2.5 Bit budget and bitrate (LC3_Specification_d09r06) - double f_scal = getFscal(); - double N_ms_value = getNmsValue(); - return floor((bitrate * N_ms_value * f_scal) / 8000.0); -} - -uint32_t Lc3Config::getBitrateFromByteCount(uint16_t nbytes) const { - // Section 3.2.5 Bit budget and bitrate (LC3_Specification_d1.0r03) - // Notes: - // - this implementation includes Errata 15051 - // - this utility function is not used within the LC3 code so far, but - // provided here for completeness - double f_scal = getFscal(); - double N_ms_value = getNmsValue(); - return ceil((8000.0 * nbytes) / (N_ms_value * f_scal)); -} - -double Lc3Config::getFscal() const { - // Section 3.2.2 Sampling rates (LC3_Specification_d1.0r03) - return (44100 == Fs) ? 48000.0 / 44100.0 : 1.0; -} - -double Lc3Config::getNmsValue() const { - return (FrameDuration::d10ms == N_ms) ? 10.0 : 7.5; -} diff --git a/system/embdrv/lc3_dec/Common/Tables/BandIndexTables.cpp b/system/embdrv/lc3_dec/Common/Tables/BandIndexTables.cpp deleted file mode 100644 index 26bc3ba513..0000000000 --- a/system/embdrv/lc3_dec/Common/Tables/BandIndexTables.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * BandIndexTables.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -// LC3 Specification d09r01.pdf -// Section 5.7.1 Band Tables Index I_fs -#include "BandIndexTables.hpp" - -// LC3 Specification d09r01.pdf; Page 86 of 177 -// LC3 Specification Section 3.7.2 (d09r04_*implementorComments*) -// Page 115 of 256 -// Band tables index I_fs for 10 ms frame duration -int I_8000[65] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 53, - 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 80}; -int I_16000[65] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 30, 32, 34, 36, - 38, 40, 42, 44, 46, 48, 50, 52, 55, 58, 61, - 64, 67, 70, 73, 76, 80, 84, 88, 92, 96, 101, - 106, 111, 116, 121, 127, 133, 139, 146, 153, 160}; -int I_24000[65] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, - 43, 46, 49, 52, 55, 58, 61, 64, 68, 72, 76, - 80, 85, 90, 95, 100, 106, 112, 118, 125, 132, 139, - 147, 155, 164, 173, 183, 193, 204, 215, 227, 240}; -int I_32000[65] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, - 24, 26, 28, 30, 32, 34, 36, 38, 41, 44, 47, - 50, 53, 56, 60, 64, 68, 72, 76, 81, 86, 91, - 97, 103, 109, 116, 123, 131, 139, 148, 157, 166, 176, - 187, 199, 211, 224, 238, 252, 268, 284, 302, 320}; -int I_48000[65] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24, - 26, 28, 30, 32, 34, 36, 39, 42, 45, 48, 51, - 55, 59, 63, 67, 71, 76, 81, 86, 92, 98, 105, - 112, 119, 127, 135, 144, 154, 164, 175, 186, 198, 211, - 225, 240, 256, 273, 291, 310, 330, 352, 375, 400}; - -// LC3 Specification Section 3.7.2 (d09r04_*implementorComments*) -// Page 115/116 of 256 -// Band tables index I_fs for 7.5 ms frame duration -int I_8000_7p5ms[61] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60}; -int I_16000_7p5ms[65] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 65, 68, - 71, 74, 77, 80, 83, 86, 90, 94, 98, 102, 106, 110, 115, 120}; -int I_24000_7p5ms[65] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 29, 31, 33, 35, 37, - 39, 41, 43, 45, 47, 49, 52, 55, 58, 61, 64, - 67, 70, 74, 78, 82, 86, 90, 95, 100, 105, 110, - 115, 121, 127, 134, 141, 148, 155, 163, 171, 180}; -int I_32000_7p5ms[65] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 26, 28, 30, 32, 34, 36, 38, 40, - 42, 45, 48, 51, 54, 57, 60, 63, 67, 71, 75, - 79, 84, 89, 94, 99, 105, 111, 117, 124, 131, 138, - 146, 154, 163, 172, 182, 192, 203, 215, 227, 240}; -int I_48000_7p5ms[65] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 43, - 46, 49, 52, 55, 59, 63, 67, 71, 75, 80, 85, - 90, 96, 102, 108, 115, 122, 129, 137, 146, 155, 165, - 175, 186, 197, 209, 222, 236, 251, 266, 283, 300}; diff --git a/system/embdrv/lc3_dec/Common/Tables/BandIndexTables.hpp b/system/embdrv/lc3_dec/Common/Tables/BandIndexTables.hpp deleted file mode 100644 index dfe7734d58..0000000000 --- a/system/embdrv/lc3_dec/Common/Tables/BandIndexTables.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * BandIndexTables.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef BAND_INDEX_TABLES_H_ -#define BAND_INDEX_TABLES_H_ - -// LC3 Specification d09r01.pdf -// Section 5.7.1 Band Tables Index I_fs - -// LC3 Specification d09r04_*implementorComments* -// Section 3.7.1 Band tables index I_fs for 10 ms frame duration - -extern int I_8000[65]; -extern int I_16000[65]; -extern int I_24000[65]; -extern int I_32000[65]; -extern int I_48000[65]; - -// LC3 Specification d09r04_*implementorComments* -// Section 3.7.2 Band tables index I_fs for 7.5 ms frame duration - -extern int I_8000_7p5ms[61]; -extern int I_16000_7p5ms[65]; -extern int I_24000_7p5ms[65]; -extern int I_32000_7p5ms[65]; -extern int I_48000_7p5ms[65]; - -#endif // BAND_INDEX_TABLES_H_ diff --git a/system/embdrv/lc3_dec/Common/Tables/LongTermPostfilterCoefficients.cpp b/system/embdrv/lc3_dec/Common/Tables/LongTermPostfilterCoefficients.cpp deleted file mode 100644 index 340ae20022..0000000000 --- a/system/embdrv/lc3_dec/Common/Tables/LongTermPostfilterCoefficients.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/* - * LongTermPostfilterCoefficients.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -// LC3 Specification d09r01.pdf -// Section 5.7.5 Long Term Postfiltering -#include "LongTermPostfilterCoefficients.hpp" - -// LC3 Specification d09r01.pdf; Page 110 of 177 -double tab_resamp_filter[239] = { - -2.043055832879108e-05, -4.463458936757081e-05, -7.163663994481459e-05, - -1.001011132655914e-04, -1.283728480660395e-04, -1.545438297704662e-04, - -1.765445671257668e-04, -1.922569599584802e-04, -1.996438192500382e-04, - -1.968886856400547e-04, -1.825383318834690e-04, -1.556394266046803e-04, - -1.158603651792638e-04, -6.358930335348977e-05, +2.810064795067786e-19, - +7.292180213001337e-05, +1.523970757644272e-04, +2.349207769898906e-04, - +3.163786496265269e-04, +3.922117380894736e-04, +4.576238491064392e-04, - +5.078242936704864e-04, +5.382955231045915e-04, +5.450729176175875e-04, - +5.250221548270982e-04, +4.760984242947349e-04, +3.975713799264791e-04, - +2.902002172907180e-04, +1.563446669975615e-04, -5.818801416923580e-19, - -1.732527127898052e-04, -3.563859653300760e-04, -5.411552308801147e-04, - -7.184140229675020e-04, -8.785052315963854e-04, -1.011714513697282e-03, - -1.108767055632304e-03, -1.161345220483996e-03, -1.162601694464620e-03, - -1.107640974148221e-03, -9.939415631563015e-04, -8.216921898513225e-04, - // LC3 Specification d09r01.pdf; Page 111 of 177 - -5.940177657925908e-04, -3.170746535382728e-04, +9.746950818779534e-19, - +3.452937604228947e-04, +7.044808705458705e-04, +1.061334465662964e-03, - +1.398374734488549e-03, +1.697630799350524e-03, +1.941486748731660e-03, - +2.113575906669355e-03, +2.199682452179964e-03, +2.188606246517629e-03, - +2.072945458973295e-03, +1.849752491313908e-03, +1.521021876908738e-03, - +1.093974255016849e-03, +5.811080624426164e-04, -1.422482656398999e-18, - -6.271537303228204e-04, -1.274251404913447e-03, -1.912238389850182e-03, - -2.510269249380764e-03, -3.037038298629825e-03, -3.462226871101535e-03, - -3.758006719596473e-03, -3.900532466948409e-03, -3.871352309895838e-03, - -3.658665583679722e-03, -3.258358512646846e-03, -2.674755551508349e-03, - -1.921033054368456e-03, -1.019254326838640e-03, +1.869623690895593e-18, - +1.098415446732263e-03, +2.231131973532823e-03, +3.348309272768835e-03, - +4.397022774386510e-03, +5.323426722644900e-03, +6.075105310368700e-03, - +6.603520247552113e-03, +6.866453987193027e-03, +6.830342695906946e-03, - +6.472392343549424e-03, +5.782375213956374e-03, +4.764012726389739e-03, - +3.435863514113467e-03, +1.831652835406657e-03, -2.251898372838663e-18, - -1.996476188279370e-03, -4.082668858919100e-03, -6.173080374929424e-03, - -8.174448945974208e-03, -9.988823864332691e-03, -1.151698705819990e-02, - -1.266210056063963e-02, -1.333344579518481e-02, -1.345011199343934e-02, - -1.294448809639154e-02, -1.176541543002924e-02, -9.880867320401294e-03, - -7.280036402392082e-03, -3.974730209151807e-03, +2.509617777250391e-18, - +4.586044219717467e-03, +9.703248998383679e-03, +1.525124770818010e-02, - +2.111205854013017e-02, +2.715337236094137e-02, +3.323242450843114e-02, - +3.920032029020130e-02, +4.490666443426786e-02, +5.020433088017846e-02, - +5.495420172681558e-02, +5.902970324375908e-02, +6.232097270672976e-02, - +6.473850225260731e-02, +6.621612450840858e-02, +6.671322871619612e-02, - +6.621612450840858e-02, +6.473850225260731e-02, +6.232097270672976e-02, - +5.902970324375908e-02, +5.495420172681558e-02, +5.020433088017846e-02, - +4.490666443426786e-02, +3.920032029020130e-02, +3.323242450843114e-02, - +2.715337236094137e-02, +2.111205854013017e-02, +1.525124770818010e-02, - +9.703248998383679e-03, +4.586044219717467e-03, +2.509617777250391e-18, - -3.974730209151807e-03, -7.280036402392082e-03, -9.880867320401294e-03, - -1.176541543002924e-02, -1.294448809639154e-02, -1.345011199343934e-02, - -1.333344579518481e-02, -1.266210056063963e-02, -1.151698705819990e-02, - -9.988823864332691e-03, -8.174448945974208e-03, -6.173080374929424e-03, - -4.082668858919100e-03, -1.996476188279370e-03, -2.251898372838663e-18, - +1.831652835406657e-03, +3.435863514113467e-03, +4.764012726389739e-03, - +5.782375213956374e-03, +6.472392343549424e-03, +6.830342695906946e-03, - +6.866453987193027e-03, +6.603520247552113e-03, +6.075105310368700e-03, - +5.323426722644900e-03, +4.397022774386510e-03, +3.348309272768835e-03, - +2.231131973532823e-03, +1.098415446732263e-03, +1.869623690895593e-18, - -1.019254326838640e-03, -1.921033054368456e-03, -2.674755551508349e-03, - -3.258358512646846e-03, -3.658665583679722e-03, -3.871352309895838e-03, - -3.900532466948409e-03, -3.758006719596473e-03, -3.462226871101535e-03, - -3.037038298629825e-03, -2.510269249380764e-03, -1.912238389850182e-03, - -1.274251404913447e-03, -6.271537303228204e-04, -1.422482656398999e-18, - +5.811080624426164e-04, +1.093974255016849e-03, +1.521021876908738e-03, - +1.849752491313908e-03, +2.072945458973295e-03, +2.188606246517629e-03, - +2.199682452179964e-03, +2.113575906669355e-03, +1.941486748731660e-03, - +1.697630799350524e-03, +1.398374734488549e-03, +1.061334465662964e-03, - +7.044808705458705e-04, +3.452937604228947e-04, +9.746950818779534e-19, - -3.170746535382728e-04, -5.940177657925908e-04, -8.216921898513225e-04, - -9.939415631563015e-04, -1.107640974148221e-03, -1.162601694464620e-03, - -1.161345220483996e-03, -1.108767055632304e-03, -1.011714513697282e-03, - -8.785052315963854e-04, -7.184140229675020e-04, -5.411552308801147e-04, - -3.563859653300760e-04, -1.732527127898052e-04, -5.818801416923580e-19, - // LC3 Specification d09r01.pdf; Page 112 of 177 - +1.563446669975615e-04, +2.902002172907180e-04, +3.975713799264791e-04, - +4.760984242947349e-04, +5.250221548270982e-04, +5.450729176175875e-04, - +5.382955231045915e-04, +5.078242936704864e-04, +4.576238491064392e-04, - +3.922117380894736e-04, +3.163786496265269e-04, +2.349207769898906e-04, - +1.523970757644272e-04, +7.292180213001337e-05, +2.810064795067786e-19, - -6.358930335348977e-05, -1.158603651792638e-04, -1.556394266046803e-04, - -1.825383318834690e-04, -1.968886856400547e-04, -1.996438192500382e-04, - -1.922569599584802e-04, -1.765445671257668e-04, -1.545438297704662e-04, - -1.283728480660395e-04, -1.001011132655914e-04, -7.163663994481459e-05, - -4.463458936757081e-05, -2.043055832879108e-05}; -double tab_ltpf_interp_R[31] = { - -2.874561161519444e-03, -3.001251025861499e-03, +2.745471654059321e-03, - +1.535727698935322e-02, +2.868234046665657e-02, +2.950385026557377e-02, - +4.598334491135473e-03, -4.729632459043440e-02, -1.058359163062837e-01, - -1.303050213607112e-01, -7.544046357555201e-02, +8.357885725250529e-02, - +3.301825710764459e-01, +6.032970076366158e-01, +8.174886856243178e-01, - +8.986382851273982e-01, +8.174886856243178e-01, +6.032970076366158e-01, - +3.301825710764459e-01, +8.357885725250529e-02, -7.544046357555201e-02, - -1.303050213607112e-01, -1.058359163062837e-01, -4.729632459043440e-02, - +4.598334491135473e-03, +2.950385026557377e-02, +2.868234046665657e-02, - +1.535727698935322e-02, +2.745471654059321e-03, -3.001251025861499e-03, - -2.874561161519444e-03}; -double tab_ltpf_interp_x12k8[15] = { - +6.698858366939680e-03, +3.967114782344967e-02, +1.069991860896389e-01, - +2.098804630681809e-01, +3.356906254147840e-01, +4.592209296082350e-01, - +5.500750019177116e-01, +5.835275754221211e-01, +5.500750019177116e-01, - +4.592209296082350e-01, +3.356906254147840e-01, +2.098804630681809e-01, - +1.069991860896389e-01, +3.967114782344967e-02, +6.698858366939680e-03}; -double tab_ltpf_num_8000[4][3] = { - {6.023618207009578e-01, 4.197609261363617e-01, -1.883424527883687e-02}, - {5.994768582584314e-01, 4.197609261363620e-01, -1.594928283631041e-02}, - {5.967764663733787e-01, 4.197609261363617e-01, -1.324889095125780e-02}, - {5.942410120098895e-01, 4.197609261363618e-01, -1.071343658776831e-02}}; -double tab_ltpf_num_16000[4][3] = { - {6.023618207009578e-01, 4.197609261363617e-01, -1.883424527883687e-02}, - {5.994768582584314e-01, 4.197609261363620e-01, -1.594928283631041e-02}, - {5.967764663733787e-01, 4.197609261363617e-01, -1.324889095125780e-02}, - {5.942410120098895e-01, 4.197609261363618e-01, -1.071343658776831e-02}}; -double tab_ltpf_num_24000[4][5] = { - {3.989695588963494e-01, 5.142508607708275e-01, 1.004382966157454e-01, - -1.278893956818042e-02, -1.572280075461383e-03}, - {3.948634911286333e-01, 5.123819208048688e-01, 1.043194926386267e-01, - -1.091999960222166e-02, -1.347408330627317e-03}, - {3.909844475885914e-01, 5.106053522688359e-01, 1.079832524685944e-01, - -9.143431066188848e-03, -1.132124620551895e-03}, - {3.873093888199928e-01, 5.089122083363975e-01, 1.114517380217371e-01, - -7.450287133750717e-03, -9.255514050963111e-04}}; -double tab_ltpf_num_32000[4][7] = { - // LC3 Specification d09r01.pdf; Page 113 of 177 - {2.982379446702096e-01, 4.652809203721290e-01, 2.105997428614279e-01, - 3.766780380806063e-02, -1.015696155796564e-02, -2.535880996101096e-03, - -3.182946168719958e-04}, - {2.943834154510240e-01, 4.619294002718798e-01, 2.129465770091844e-01, - 4.066175002688857e-02, -8.693272297010050e-03, -2.178307114679820e-03, - -2.742888063983188e-04}, - {2.907439213122688e-01, 4.587461910960279e-01, 2.151456974108970e-01, - 4.350104772529774e-02, -7.295495347716925e-03, -1.834395637237086e-03, - -2.316920186482416e-04}, - {2.872975852589158e-01, 4.557148886861379e-01, 2.172126950911401e-01, - 4.620088878229615e-02, -5.957463802125952e-03, -1.502934284345198e-03, - -1.903851911308866e-04}}; -double tab_ltpf_num_48000[4][11] = { - {1.981363739883217e-01, 3.524494903964904e-01, 2.513695269649414e-01, - 1.424146237314458e-01, 5.704731023952599e-02, 9.293366241586384e-03, - -7.226025368953745e-03, -3.172679890356356e-03, -1.121835963567014e-03, - -2.902957238400140e-04, -4.270815593769240e-05}, - {1.950709426598375e-01, 3.484660408341632e-01, 2.509988459466574e-01, - 1.441167412482088e-01, 5.928947317677285e-02, 1.108923827452231e-02, - -6.192908108653504e-03, -2.726705509251737e-03, -9.667125826217151e-04, - -2.508100923165204e-04, -3.699938766131869e-05}, - {1.921810055196015e-01, 3.446945561091513e-01, 2.506220094626024e-01, - 1.457102447664837e-01, 6.141132133664525e-02, 1.279941396562798e-02, - -5.203721087886321e-03, -2.297324511109085e-03, -8.165608133217555e-04, - -2.123855748277408e-04, -3.141271330981649e-05}, - {1.894485314175868e-01, 3.411139251108252e-01, 2.502406876894361e-01, - 1.472065631098081e-01, 6.342477229539051e-02, 1.443203434150312e-02, - -4.254449144657098e-03, -1.883081472613493e-03, -6.709619060722140e-04, - -1.749363341966872e-04, -2.593864735284285e-05}}; -double tab_ltpf_den_8000[4][5] = { - {0.000000000000000e+00, 2.098804630681809e-01, 5.835275754221211e-01, - 2.098804630681809e-01, 0.000000000000000e+00}, - {0.000000000000000e+00, 1.069991860896389e-01, 5.500750019177116e-01, - 3.356906254147840e-01, 6.698858366939680e-03}, - {0.000000000000000e+00, 3.967114782344967e-02, 4.592209296082350e-01, - 4.592209296082350e-01, 3.967114782344967e-02}, - {0.000000000000000e+00, 6.698858366939680e-03, 3.356906254147840e-01, - 5.500750019177116e-01, 1.069991860896389e-01}}; -double tab_ltpf_den_16000[4][5] = { - {0.000000000000000e+00, 2.098804630681809e-01, 5.835275754221211e-01, - 2.098804630681809e-01, 0.000000000000000e+00}, - {0.000000000000000e+00, 1.069991860896389e-01, 5.500750019177116e-01, - 3.356906254147840e-01, 6.698858366939680e-03}, - {0.000000000000000e+00, 3.967114782344967e-02, 4.592209296082350e-01, - 4.592209296082350e-01, 3.967114782344967e-02}, - {0.000000000000000e+00, 6.698858366939680e-03, 3.356906254147840e-01, - 5.500750019177116e-01, 1.069991860896389e-01}}; -double tab_ltpf_den_24000[4][7] = { - {0.000000000000000e+00, 6.322231627323796e-02, 2.507309606013235e-01, - 3.713909428901578e-01, 2.507309606013235e-01, 6.322231627323796e-02, - 0.000000000000000e+00}, - // LC3 Specification d09r01.pdf; Page 114 of 177 - {0.000000000000000e+00, 3.459272174099855e-02, 1.986515602645028e-01, - 3.626411726581452e-01, 2.986750548992179e-01, 1.013092873505928e-01, - 4.263543712369752e-03}, - {0.000000000000000e+00, 1.535746784963907e-02, 1.474344878058222e-01, - 3.374259553990717e-01, 3.374259553990717e-01, 1.474344878058222e-01, - 1.535746784963907e-02}, - {0.000000000000000e+00, 4.263543712369752e-03, 1.013092873505928e-01, - 2.986750548992179e-01, 3.626411726581452e-01, 1.986515602645028e-01, - 3.459272174099855e-02}}; -double tab_ltpf_den_32000[4][9] = { - {0.000000000000000e+00, 2.900401878228730e-02, 1.129857420560927e-01, - 2.212024028097570e-01, 2.723909472446145e-01, 2.212024028097570e-01, - 1.129857420560927e-01, 2.900401878228730e-02, 0.000000000000000e+00}, - {0.000000000000000e+00, 1.703153418385261e-02, 8.722503785537784e-02, - 1.961407762232199e-01, 2.689237982237257e-01, 2.424999102756389e-01, - 1.405773364650031e-01, 4.474877169485788e-02, 3.127030243100724e-03}, - {0.000000000000000e+00, 8.563673748488349e-03, 6.426222944493845e-02, - 1.687676705918012e-01, 2.587445937795505e-01, 2.587445937795505e-01, - 1.687676705918012e-01, 6.426222944493845e-02, 8.563673748488349e-03}, - {0.000000000000000e+00, 3.127030243100724e-03, 4.474877169485788e-02, - 1.405773364650031e-01, 2.424999102756389e-01, 2.689237982237257e-01, - 1.961407762232199e-01, 8.722503785537784e-02, 1.703153418385261e-02}}; -double tab_ltpf_den_48000[4][13] = { - {0.000000000000000e+00, 1.082359386659387e-02, 3.608969221303979e-02, - 7.676401468099964e-02, 1.241530577501703e-01, 1.627596438300696e-01, - 1.776771417779109e-01, 1.627596438300696e-01, 1.241530577501703e-01, - 7.676401468099964e-02, 3.608969221303979e-02, 1.082359386659387e-02, - 0.000000000000000e+00}, - {0.000000000000000e+00, 7.041404930459358e-03, 2.819702319820420e-02, - 6.547044935127551e-02, 1.124647986743299e-01, 1.548418956489015e-01, - 1.767122381341857e-01, 1.691507213057663e-01, 1.352901577989766e-01, - 8.851425011427483e-02, 4.499353848562444e-02, 1.557613714732002e-02, - 2.039721956502016e-03}, - {0.000000000000000e+00, 4.146998467444788e-03, 2.135757310741917e-02, - 5.482735584552816e-02, 1.004971444643720e-01, 1.456060342830002e-01, - 1.738439838565869e-01, 1.738439838565869e-01, 1.456060342830002e-01, - 1.004971444643720e-01, 5.482735584552816e-02, 2.135757310741917e-02, - 4.146998467444788e-03}, - {0.000000000000000e+00, 2.039721956502016e-03, 1.557613714732002e-02, - 4.499353848562444e-02, 8.851425011427483e-02, 1.352901577989766e-01, - 1.691507213057663e-01, 1.767122381341857e-01, 1.548418956489015e-01, - 1.124647986743299e-01, 6.547044935127551e-02, 2.819702319820420e-02, - 7.041404930459358e-03}}; diff --git a/system/embdrv/lc3_dec/Common/Tables/LongTermPostfilterCoefficients.hpp b/system/embdrv/lc3_dec/Common/Tables/LongTermPostfilterCoefficients.hpp deleted file mode 100644 index 5ab9775599..0000000000 --- a/system/embdrv/lc3_dec/Common/Tables/LongTermPostfilterCoefficients.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * LongTermPostfilterCoefficients.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -// LC3 Specification d09r01.pdf -// Section 5.7.5 Long Term Postfiltering - -#ifndef LONG_TERM_POSTFILTER_COEFFICIENTS_H_ -#define LONG_TERM_POSTFILTER_COEFFICIENTS_H_ - -extern double tab_resamp_filter[239]; -extern double tab_ltpf_interp_R[31]; -extern double tab_ltpf_interp_x12k8[15]; -extern double tab_ltpf_num_8000[4][3]; -extern double tab_ltpf_num_16000[4][3]; -extern double tab_ltpf_num_24000[4][5]; -extern double tab_ltpf_num_32000[4][7]; -extern double tab_ltpf_num_48000[4][11]; -extern double tab_ltpf_den_8000[4][5]; -extern double tab_ltpf_den_16000[4][5]; -extern double tab_ltpf_den_24000[4][7]; -extern double tab_ltpf_den_32000[4][9]; -extern double tab_ltpf_den_48000[4][13]; - -#endif // LONG_TERM_POSTFILTER_COEFFICIENTS_H_ diff --git a/system/embdrv/lc3_dec/Common/Tables/MdctWindows.cpp b/system/embdrv/lc3_dec/Common/Tables/MdctWindows.cpp deleted file mode 100644 index 595d5738b5..0000000000 --- a/system/embdrv/lc3_dec/Common/Tables/MdctWindows.cpp +++ /dev/null @@ -1,1573 +0,0 @@ -/* - * MdctWindows.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -// LC3 Specification d09r01.pdf -// Section 5.7.2 -#include "MdctWindows.hpp" - -// LC3 Specification d09r01.pdf; Page 86 of 177 - -// LC3 Specification d09r04_*implementorComments* -// Section 3.7.3 Low delay MDCT windows -// Section 3.7.3.1 10 ms Frame Duration - -// Section 5.7.2.1 w80 (d09r01.pdf) -double w_N80[160] = { - -7.078546706512391e-04, -2.098197727900724e-03, -4.525198076002370e-03, - -8.233976327300612e-03, -1.337713096257934e-02, -1.999721557401502e-02, - -2.800909464274782e-02, -3.721502082245055e-02, -4.731768261606175e-02, - -5.794654834034055e-02, -6.867606753531441e-02, -7.904647440788692e-02, - -8.859705468085925e-02, -9.688303623049199e-02, -1.034961241263523e-01, - -1.080766457616878e-01, -1.103242262600913e-01, -1.099809851424550e-01, - -1.068172142230882e-01, -1.006190418791648e-01, -9.116452506492527e-02, - -7.820617483254730e-02, -6.146688124166948e-02, -4.063362855701623e-02, - -1.536329520788766e-02, +1.470155068746303e-02, +4.989736509080558e-02, - +9.050369257152079e-02, +1.366911019414417e-01, +1.884686389218322e-01, - +2.456456803467095e-01, +3.077789078889820e-01, +3.741642373060188e-01, - +4.438114799213576e-01, +5.154735456539700e-01, +5.876661722564289e-01, - +6.587619767809000e-01, +7.270576699841359e-01, +7.908752989295335e-01, - +8.486643364959733e-01, +8.991320235484349e-01, +9.413348145272842e-01, - +9.747634827941575e-01, +9.994114730415857e-01, +1.015760373791603e+00, - +1.024736164069697e+00, +1.027634294456205e+00, +1.025991493983836e+00, - +1.021427210603284e+00, +1.015439859549357e+00, +1.009366925499550e+00, - +1.003508162416449e+00, +9.988898206257559e-01, +9.953133902427869e-01, - +9.925943919208190e-01, +9.905771957917731e-01, +9.891371616557014e-01, - +9.881790747212391e-01, +9.876249269174586e-01, +9.874056275509585e-01, - // LC3 Specification d09r01.pdf; Page 87 of 177 - +9.874524849192456e-01, +9.876951134084213e-01, +9.880640617030884e-01, - +9.884926873551375e-01, +9.889230031022089e-01, +9.893074965384659e-01, - +9.896146331889107e-01, +9.898319269347060e-01, +9.899693102025342e-01, - +9.900603352632121e-01, +9.901575015155720e-01, +9.903255289051605e-01, - +9.906303787150326e-01, +9.911298894709990e-01, +9.918665491182922e-01, - +9.928619727154252e-01, +9.941156069136238e-01, +9.956033775539884e-01, - +9.972793109558521e-01, +9.990784840729244e-01, +1.000922365901945e+00, - +1.002728111386909e+00, +1.004416038098237e+00, +1.005919224127911e+00, - +1.007189345025525e+00, +1.008200146369426e+00, +1.008949493525753e+00, - +1.009458241425143e+00, +1.009768980817384e+00, +1.009940336228694e+00, - +1.010039453539107e+00, +1.010132323996401e+00, +1.010272524848519e+00, - +1.010494354532353e+00, +1.010808068774316e+00, +1.011201071127927e+00, - +1.011641272406023e+00, +1.012080125934687e+00, +1.012458183122033e+00, - +1.012706955800289e+00, +1.012755013843985e+00, +1.012530134411619e+00, - +1.011962331100864e+00, +1.010982135506986e+00, +1.009512438049510e+00, - +1.007460860286395e+00, +1.004708677491086e+00, +1.001111413242302e+00, - +9.965041017623596e-01, +9.907199995730845e-01, +9.823765865983288e-01, - +9.708821747608998e-01, +9.546732976073705e-01, +9.321553861564006e-01, - +9.018003682081348e-01, +8.623984077953557e-01, +8.132817365236141e-01, - +7.544551974836834e-01, +6.866580716267418e-01, +6.113488038789190e-01, - +5.306181649316597e-01, +4.471309850999502e-01, +3.639114681156236e-01, - +2.841647033392408e-01, +2.110209448747969e-01, +1.472287968327703e-01, - +9.482665349502291e-02, +5.482436608328477e-02, +2.701461405056264e-02, - +9.996743588367519e-03, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00}; - -// Section 5.7.2.2 w160 (d09r01.pdf) -double w_N160[320] = { - -4.619898752628163e-04, -9.747166718929050e-04, -1.664473096973725e-03, - -2.597106916737789e-03, -3.806285163352241e-03, -5.324608721716763e-03, - -7.175885277771099e-03, -9.382480860899108e-03, -1.195270300743193e-02, - -1.489528159506296e-02, -1.820666399965468e-02, -2.187570925786862e-02, - -2.588471937157619e-02, -3.020862738245264e-02, -3.481597793538342e-02, - -3.967067992672979e-02, -4.472698045914417e-02, -4.994225863256500e-02, - -5.526334794593565e-02, -6.063717235243996e-02, -6.600961519440657e-02, - -7.131966266443390e-02, -7.651178225890490e-02, -8.152964005319532e-02, - -8.631137544905677e-02, -9.080411291245728e-02, -9.495377758870335e-02, - -9.870736514214426e-02, -1.020202684361974e-01, -1.048438825017798e-01, - -1.071382314127799e-01, -1.088690135027248e-01, -1.099969655786929e-01, - -1.104898474883336e-01, -1.103225838568563e-01, -1.094621746650760e-01, - -1.078834293141886e-01, -1.055612509762041e-01, -1.024650162703341e-01, - -9.857014566194629e-02, -9.384684920715425e-02, -8.826309993000785e-02, - -8.178792716809512e-02, -7.438785600211463e-02, -6.602189797715241e-02, - -5.665655641133161e-02, -4.624456893420224e-02, -3.474585776145929e-02, - -2.211581608120528e-02, -8.310425696208936e-03, +6.717697635290676e-03, - // LC3 Specification d09r01.pdf; Page 88 of 177 - +2.300642061077823e-02, +4.060106462625085e-02, +5.953239090915557e-02, - +7.983354189816511e-02, +1.015233140203748e-01, +1.246171387327525e-01, - +1.491152519299797e-01, +1.750067399059861e-01, +2.022699854906251e-01, - +2.308655379767671e-01, +2.607365124918583e-01, +2.918144694729168e-01, - +3.240095704645023e-01, +3.572175180786021e-01, +3.913146885756875e-01, - +4.261571642320424e-01, +4.615925445090212e-01, +4.974471592901086e-01, - +5.335326819631583e-01, +5.696546730080154e-01, +6.056083823929643e-01, - +6.411830842823245e-01, +6.761653499550255e-01, +7.103400549562944e-01, - +7.434943718765665e-01, +7.754281892901473e-01, +8.059437233154637e-01, - +8.348589373399948e-01, +8.620108336276733e-01, +8.872599706865123e-01, - +9.104863121445679e-01, +9.315962496426278e-01, +9.505220861927248e-01, - +9.672366712325431e-01, +9.817397501303696e-01, +9.940557180662704e-01, - +1.004247514102417e+00, +1.012407428282884e+00, +1.018650990561848e+00, - +1.023118841384460e+00, +1.025972450969440e+00, +1.027397523939210e+00, - +1.027585830688143e+00, +1.026738673647482e+00, +1.025061777648234e+00, - +1.022756514615106e+00, +1.020009139549275e+00, +1.016996499560845e+00, - +1.013915946100629e+00, +1.011044869639164e+00, +1.007773858455400e+00, - +1.004848753962734e+00, +1.002245009135684e+00, +9.999393169239009e-01, - +9.979055415627330e-01, +9.961203379971326e-01, +9.945597525471822e-01, - +9.932031606606762e-01, +9.920297273323891e-01, +9.910230654424902e-01, - +9.901668953434221e-01, +9.894488374513719e-01, +9.888556356037892e-01, - +9.883778520531268e-01, +9.880051626345804e-01, +9.877295459610343e-01, - +9.875412739766566e-01, +9.874329809802893e-01, +9.873949921033299e-01, - +9.874197049003676e-01, +9.874973205882319e-01, +9.876201238703241e-01, - +9.877781920433015e-01, +9.879637979933339e-01, +9.881678007807095e-01, - +9.883835200189653e-01, +9.886022219397892e-01, +9.888182771263505e-01, - +9.890247977602895e-01, +9.892178658748239e-01, +9.893923680007577e-01, - +9.895463342815009e-01, +9.896772011542693e-01, +9.897859195209235e-01, - +9.898725363809847e-01, +9.899410789223559e-01, +9.899945557067980e-01, - +9.900394023736973e-01, +9.900814722948890e-01, +9.901293790312005e-01, - +9.901902265696609e-01, +9.902734448815004e-01, +9.903862280081246e-01, - +9.905379830873822e-01, +9.907348826312993e-01, +9.909842592301273e-01, - +9.912905118607647e-01, +9.916586940166509e-01, +9.920906151219310e-01, - +9.925887208794144e-01, +9.931516528513824e-01, +9.937790866568735e-01, - +9.944668184371617e-01, +9.952116634297566e-01, +9.960068616185641e-01, - +9.968461329825753e-01, +9.977203369515556e-01, +9.986213520769593e-01, - +9.995382582242990e-01, +1.000461955079660e+00, +1.001380551217109e+00, - +1.002284871786226e+00, +1.003163845364970e+00, +1.004009147462043e+00, - +1.004811375053364e+00, +1.005563968008037e+00, +1.006259855360867e+00, - +1.006895570408563e+00, +1.007466616298057e+00, +1.007972441990187e+00, - +1.008411468616852e+00, +1.008786009787269e+00, +1.009097763850333e+00, - +1.009351762546296e+00, +1.009552401900961e+00, +1.009707093778162e+00, - +1.009822090220407e+00, +1.009906958448099e+00, +1.009969021400474e+00, - +1.010017890428877e+00, +1.010060809299530e+00, +1.010106564965965e+00, - +1.010161131093372e+00, +1.010231078494249e+00, +1.010319484524512e+00, - +1.010430470494512e+00, +1.010564099281000e+00, +1.010721360243234e+00, - +1.010899655674578e+00, +1.011096993993037e+00, +1.011308167670753e+00, - +1.011529185153809e+00, +1.011753008569803e+00, +1.011973876511603e+00, - +1.012182837094955e+00, +1.012373028737774e+00, +1.012535058602453e+00, - +1.012660975529858e+00, +1.012740575296603e+00, +1.012765922449960e+00, - +1.012726958954961e+00, +1.012615904116265e+00, +1.012422888521601e+00, - +1.012140460211194e+00, +1.011758810583150e+00, +1.011269960947744e+00, - +1.010663676735228e+00, +1.009930754807923e+00, +1.009058249873833e+00, - +1.008034308295421e+00, +1.006843352506855e+00, +1.005470005637052e+00, - +1.003894772403371e+00, +1.002098854400575e+00, +1.000060686758758e+00, - +9.977600196406868e-01, +9.951746430061121e-01, +9.922861082472264e-01, - // LC3 Specification d09r01.pdf; Page 89 of 177 - +9.890757868707590e-01, +9.847362453480265e-01, +9.798613526271561e-01, - +9.741378617337759e-01, +9.673331975559332e-01, +9.592539757044516e-01, - +9.496984081652284e-01, +9.384634163826711e-01, +9.253567968750328e-01, - +9.101986790930605e-01, +8.928338316495705e-01, +8.731437835983047e-01, - +8.510420440685049e-01, +8.264839911291133e-01, +7.994681492797084e-01, - +7.700431275216928e-01, +7.383028603058783e-01, +7.043814340356083e-01, - +6.684616478236647e-01, +6.307755329382612e-01, +5.915799587176216e-01, - +5.511703155400274e-01, +5.098915423728179e-01, +4.681017110047964e-01, - +4.261772971493010e-01, +3.845172335531009e-01, +3.435228672445613e-01, - +3.036004651973099e-01, +2.651434678028531e-01, +2.285283969438072e-01, - +1.941021906320984e-01, +1.621735416384830e-01, +1.330015240938615e-01, - +1.067840430193724e-01, +8.365057236623041e-02, +6.365188111381356e-02, - +4.676538412257621e-02, +3.288072750732215e-02, +2.183057564646270e-02, - +1.336381425803019e-02, +6.758124889697787e-03, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00}; - -// Section 5.7.2.3 w240 (d09r01.pdf) -double w_N240[480] = { - -3.613496418928369e-04, -7.078546706512391e-04, -1.074443637110903e-03, - -1.533478537964509e-03, -2.098197727900724e-03, -2.778420871815740e-03, - -3.584129920673041e-03, -4.525198076002370e-03, -5.609327243712055e-03, - -6.843234536105624e-03, -8.233976327300612e-03, -9.785314755557023e-03, - -1.149880303071551e-02, -1.337713096257934e-02, -1.542181679511618e-02, - -1.762979910961727e-02, -1.999721557401502e-02, -2.252080561390149e-02, - -2.519406300389030e-02, -2.800909464274782e-02, -3.095765092956728e-02, - -3.402996266948349e-02, -3.721502082245055e-02, -4.050053247568393e-02, - -4.387219218706189e-02, -4.731768261606175e-02, -5.082325342672667e-02, - -5.437166635159518e-02, -5.794654834034055e-02, -6.153426201732499e-02, - -6.511708163113709e-02, -6.867606753531441e-02, -7.219447805250771e-02, - -7.565695975592170e-02, -7.904647440788692e-02, -8.234442557322251e-02, - -8.553324579905185e-02, -8.859705468085925e-02, -9.152091100798199e-02, - -9.428847446755965e-02, -9.688303623049198e-02, -9.929123258537813e-02, - -1.015008467688577e-01, -1.034961241263523e-01, -1.052637003544443e-01, - -1.067939984687745e-01, -1.080766457616878e-01, -1.090997300590506e-01, - // LC3 Specification d09r01.pdf; Page 90 of 177 - -1.098524491515805e-01, -1.103242262600913e-01, -1.105084619148789e-01, - -1.103977408741932e-01, -1.099809851424550e-01, -1.092492774392824e-01, - -1.081974227416502e-01, -1.068172142230882e-01, -1.050995803285455e-01, - -1.030360111111103e-01, -1.006190418791648e-01, -9.784120023411771e-02, - -9.469304216883027e-02, -9.116452506492527e-02, -8.724644532866996e-02, - -8.293043914044632e-02, -7.820617483254730e-02, -7.306142427456862e-02, - -6.748468182105991e-02, -6.146688124166948e-02, -5.499497258200362e-02, - -4.805444424454820e-02, -4.063362855701623e-02, -3.272045590229335e-02, - -2.430122582451853e-02, -1.536329520788766e-02, -5.891434269890659e-03, - +4.126595858583295e-03, +1.470155068746303e-02, +2.584738191459814e-02, - +3.757652772246801e-02, +4.989736509080558e-02, +6.282034030592902e-02, - +7.635397728566121e-02, +9.050369257152079e-02, +1.052747118478660e-01, - +1.206703467513333e-01, +1.366911019414417e-01, +1.533343890681390e-01, - +1.705954709184399e-01, +1.884686389218322e-01, +2.069449962574092e-01, - +2.260093000067393e-01, +2.456456803467095e-01, +2.658346019332584e-01, - +2.865543814049772e-01, +3.077789078889820e-01, +3.294769437072290e-01, - +3.516171481750350e-01, +3.741642373060188e-01, +3.970739591211551e-01, - +4.203043046885219e-01, +4.438114799213576e-01, +4.675442291623012e-01, - +4.914498631045615e-01, +5.154735456539700e-01, +5.395557644293222e-01, - +5.636399817032525e-01, +5.876661722564289e-01, +6.115695310143157e-01, - +6.352890592874099e-01, +6.587619767809000e-01, +6.819230974423550e-01, - +7.047092819314779e-01, +7.270576699841359e-01, +7.489068963384272e-01, - +7.701990187606995e-01, +7.908752989295335e-01, +8.108788692151807e-01, - +8.301579139160681e-01, +8.486643364959733e-01, +8.663548164329093e-01, - +8.831896853053627e-01, +8.991320235484349e-01, +9.141540563656075e-01, - +9.282282546151819e-01, +9.413348145272842e-01, +9.534619388400459e-01, - +9.646048250501910e-01, +9.747634827941575e-01, +9.839435385219192e-01, - +9.921529097154242e-01, +9.994114730415857e-01, +1.005746084650236e+00, - +1.011183971347815e+00, +1.015760373791603e+00, +1.019515072412387e+00, - +1.022490937034641e+00, +1.024736164069697e+00, +1.026304095700693e+00, - +1.027250978292214e+00, +1.027634294456205e+00, +1.027511063644843e+00, - +1.026942795115598e+00, +1.025991493983836e+00, +1.024716149969084e+00, - +1.023175976163407e+00, +1.021427210603284e+00, +1.019521566634239e+00, - +1.017510118327508e+00, +1.015439859549357e+00, +1.013460916839174e+00, - +1.011654901040475e+00, +1.009366925499550e+00, +1.007263182132894e+00, - +1.005313192386866e+00, +1.003508162416449e+00, +1.001840787319378e+00, - +1.000303927234380e+00, +9.988898206257559e-01, +9.975915283480670e-01, - +9.964015284765968e-01, +9.953133902427869e-01, +9.943201078053212e-01, - +9.934158959186011e-01, +9.925943919208190e-01, +9.918510277326026e-01, - +9.911797988363887e-01, +9.905771957917731e-01, +9.900381047643838e-01, - +9.895594394179152e-01, +9.891371616557014e-01, +9.887684373604154e-01, - +9.884497924570929e-01, +9.881790747212391e-01, +9.879528358230726e-01, - +9.877691368590689e-01, +9.876249269174586e-01, +9.875179947346887e-01, - +9.874458127312921e-01, +9.874056275509585e-01, +9.873951115886979e-01, - +9.874115368168944e-01, +9.874524849192456e-01, +9.875149888347144e-01, - +9.875968894760857e-01, +9.876951134084213e-01, +9.878075819424549e-01, - +9.879311998177238e-01, +9.880640617030884e-01, +9.882032571565917e-01, - +9.883471084085503e-01, +9.884926873551375e-01, +9.886386592120545e-01, - +9.887825578295630e-01, +9.889230031022089e-01, +9.890581715933395e-01, - +9.891867674284610e-01, +9.893074965384659e-01, +9.894196399062921e-01, - +9.895220757174378e-01, +9.896146331889107e-01, +9.896970346678272e-01, - +9.897692596535289e-01, +9.898319269347060e-01, +9.898852572653667e-01, - +9.899307640365727e-01, +9.899693102025343e-01, +9.900025692522435e-01, - +9.900321562263099e-01, +9.900603352632121e-01, +9.900889812894406e-01, - +9.901206586012907e-01, +9.901575015155720e-01, +9.902023946214220e-01, - +9.902575406142213e-01, +9.903255289051605e-01, +9.904087914462694e-01, - // LC3 Specification d09r01.pdf; Page 91 of 177 - +9.905096491583045e-01, +9.906303787150326e-01, +9.907727108894024e-01, - +9.909387444078919e-01, +9.911298894709990e-01, +9.913476318763218e-01, - +9.915928560402563e-01, +9.918665491182922e-01, +9.921691315380984e-01, - +9.925010851461232e-01, +9.928619727154252e-01, +9.932519181564613e-01, - +9.936700207375173e-01, +9.941156069136238e-01, +9.945873147903244e-01, - +9.950837402063278e-01, +9.956033775539884e-01, +9.961439922621166e-01, - +9.967034533921340e-01, +9.972793109558521e-01, +9.978690858367024e-01, - +9.984697087896268e-01, +9.990784840729244e-01, +9.996919011206490e-01, - +1.000308193833526e+00, +1.000922365901945e+00, +1.001532636590676e+00, - +1.002135464655177e+00, +1.002728111386909e+00, +1.003307449770187e+00, - +1.003870934089686e+00, +1.004416038098237e+00, +1.004940548815171e+00, - +1.005442141810160e+00, +1.005919224127911e+00, +1.006370303149314e+00, - +1.006793927824538e+00, +1.007189345025525e+00, +1.007555573455895e+00, - +1.007892674961336e+00, +1.008200146369426e+00, +1.008478423284851e+00, - +1.008727884997619e+00, +1.008949493525753e+00, +1.009144112734761e+00, - +1.009313224929575e+00, +1.009458241425143e+00, +1.009581280555682e+00, - +1.009684090687164e+00, +1.009768980817384e+00, +1.009838308708799e+00, - +1.009894548257807e+00, +1.009940336228694e+00, +1.009977916643680e+00, - +1.010010230290263e+00, +1.010039453539107e+00, +1.010068202038694e+00, - +1.010098388689342e+00, +1.010132323996401e+00, +1.010171656775640e+00, - +1.010218096148412e+00, +1.010272524848519e+00, +1.010336490294771e+00, - +1.010410221483215e+00, +1.010494354532353e+00, +1.010588873699422e+00, - +1.010693501186928e+00, +1.010808068774316e+00, +1.010931436739342e+00, - +1.011062876503041e+00, +1.011201071127927e+00, +1.011344700694417e+00, - +1.011491904228184e+00, +1.011641272406023e+00, +1.011790282474963e+00, - +1.011937567254485e+00, +1.012080125934687e+00, +1.012216235487353e+00, - +1.012342907951334e+00, +1.012458183122033e+00, +1.012558879696851e+00, - +1.012642857380847e+00, +1.012706955800289e+00, +1.012748952907404e+00, - +1.012765799894453e+00, +1.012755013843985e+00, +1.012713798678211e+00, - +1.012639775003457e+00, +1.012530134411619e+00, +1.012382309473470e+00, - +1.012194068117524e+00, +1.011962331100864e+00, +1.011685173724601e+00, - +1.011359143572147e+00, +1.010982135506986e+00, +1.010550715971368e+00, - +1.010062133151922e+00, +1.009512438049510e+00, +1.008898689394160e+00, - +1.008215923600973e+00, +1.007460860286395e+00, +1.006627741823389e+00, - +1.005712337656749e+00, +1.004708677491086e+00, +1.003611467285588e+00, - +1.002414286392268e+00, +1.001111413242302e+00, +9.996961651093181e-01, - +9.981625949525345e-01, +9.965041017623596e-01, +9.947148884277037e-01, - +9.927891912841345e-01, +9.907199995730845e-01, +9.884793707533194e-01, - +9.855347660016696e-01, +9.823765865983286e-01, +9.789747333404933e-01, - +9.751623811486372e-01, +9.708821747608998e-01, +9.660805524695870e-01, - +9.606976399184645e-01, +9.546732976073706e-01, +9.479479345282376e-01, - +9.404609052933396e-01, +9.321553861564006e-01, +9.229775478442888e-01, - +9.128745354570823e-01, +9.018003682081348e-01, +8.897163275605041e-01, - +8.765908974996186e-01, +8.623984077953557e-01, +8.471200801854385e-01, - +8.307479727020245e-01, +8.132817365236141e-01, +7.947291447585267e-01, - +7.751108841891807e-01, +7.544551974836834e-01, +7.327963552921717e-01, - +7.101790843209148e-01, +6.866580716267418e-01, +6.622962432368731e-01, - +6.371684119604742e-01, +6.113488038789190e-01, +5.849206604934815e-01, - +5.579747428663487e-01, +5.306181649316717e-01, +5.029523957059122e-01, - +4.750868825511614e-01, +4.471309850999535e-01, +4.192049917945288e-01, - +3.914252910998820e-01, +3.639114681156252e-01, +3.367837772954476e-01, - +3.101627843160973e-01, +2.841647033392418e-01, +2.589033711808454e-01, - +2.344880603710975e-01, +2.110209448747974e-01, +1.885997642296488e-01, - +1.673100807904834e-01, +1.472287968327706e-01, +1.284223074167396e-01, - +1.109422548710344e-01, +9.482665349502306e-02, +8.009914366829558e-02, - +6.676765847398403e-02, +5.482436608328485e-02, +4.424588851571281e-02, - // LC3 Specification d09r01.pdf; Page 92 of 177 - +3.499361000717621e-02, +2.701461405056267e-02, +2.024370180670145e-02, - +1.460796755137538e-02, +9.996743588367531e-03, +5.305235098871444e-03, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00}; - -// Section 5.7.2.4 w320 (d09r01.pdf) -double w_N320[640] = { - -3.021153494057143e-04, -5.867737487939294e-04, -8.366504004139796e-04, - -1.126635355725494e-03, -1.470492941694331e-03, -1.873473391018495e-03, - -2.339292362082021e-03, -2.872008069419264e-03, -3.476256385086407e-03, - -4.155963816705528e-03, -4.914563787665504e-03, -5.755172503953251e-03, - -6.680623380533122e-03, -7.693816924650567e-03, -8.796760749750191e-03, - -9.990503073705982e-03, -1.127574117138621e-02, -1.265334152129685e-02, - -1.412438986522702e-02, -1.568889620430290e-02, -1.734512089366117e-02, - -1.909097368362797e-02, -2.092546711168754e-02, -2.284684792818856e-02, - -2.485207716234951e-02, -2.693746704328349e-02, -2.909952486193999e-02, - -3.133504629493832e-02, -3.363960728361352e-02, -3.600820974457969e-02, - -3.843601741746971e-02, -4.091746034850161e-02, -4.344654894948344e-02, - -4.601786724624048e-02, -4.862598509282497e-02, -5.126474204655663e-02, - -5.392644753556616e-02, -5.660384311081047e-02, -5.929116747072080e-02, - -6.198268202511926e-02, -6.467025548071184e-02, -6.734542216184526e-02, - -7.000099017198280e-02, -7.263057011354321e-02, -7.522784961377151e-02, - -7.778525942347714e-02, -8.029480247839878e-02, -8.274924535373614e-02, - -8.514125464087215e-02, -8.746379123238275e-02, -8.971069341834263e-02, - -9.187564084638347e-02, -9.395176975347193e-02, -9.593137735886889e-02, - -9.780843257659243e-02, -9.957851303827886e-02, -1.012361165314596e-01, - // LC3 Specification d09r01.pdf; Page 93 of 177 - -1.027741036495644e-01, -1.041861222641119e-01, -1.054680247057000e-01, - -1.066160875985523e-01, -1.076255384835563e-01, -1.084912299471198e-01, - -1.092087422379003e-01, -1.097736146613313e-01, -1.101808861640070e-01, - -1.104271876052675e-01, -1.105108362290460e-01, -1.104281465492726e-01, - -1.101739218186236e-01, -1.097437360338336e-01, -1.091353125572511e-01, - -1.083467335729228e-01, -1.073739938306107e-01, -1.062130155324388e-01, - -1.048606145834788e-01, -1.033132401525343e-01, -1.015673163469357e-01, - -9.962005506126154e-02, -9.746803229469267e-02, -9.510723623306666e-02, - -9.253303383231506e-02, -8.974125216128212e-02, -8.672877689119252e-02, - -8.349213839083708e-02, -8.002639902061687e-02, -7.632679536516856e-02, - -7.238806162166744e-02, -6.820576796149519e-02, -6.377611429172260e-02, - -5.909386001558149e-02, -5.415316322402774e-02, -4.894812724598650e-02, - -4.347347112195197e-02, -3.772461300253332e-02, -3.169587609244436e-02, - -2.538179830690266e-02, -1.877689096555516e-02, -1.187461378850388e-02, - -4.669099247423082e-03, +2.844096748870385e-03, +1.066976124794342e-02, - +1.881355950582949e-02, +2.728156010437695e-02, +3.607810469851272e-02, - +4.520702759803914e-02, +5.467238802204326e-02, +6.447866054615346e-02, - +7.462862199422061e-02, +8.512490568723846e-02, +9.596983987496970e-02, - +1.071650779014335e-01, +1.187115850305241e-01, +1.306101067250375e-01, - +1.428596447589721e-01, +1.554584725339102e-01, +1.684041609371527e-01, - +1.816947894623263e-01, +1.953273880886783e-01, +2.092963206850239e-01, - +2.235945635254679e-01, +2.382160219461597e-01, +2.531529721334063e-01, - +2.683961570569586e-01, +2.839361392493072e-01, +2.997624255177811e-01, - +3.158619077906196e-01, +3.322210551086769e-01, +3.488264676990591e-01, - +3.656640377499646e-01, +3.827152968157059e-01, +3.999611859760947e-01, - +4.173843265025887e-01, +4.349669624916473e-01, +4.526876397402144e-01, - +4.705242008503956e-01, +4.884539254831315e-01, +5.064545550235134e-01, - +5.245006748662190e-01, +5.425674372882107e-01, +5.606312044701524e-01, - +5.786672646386708e-01, +5.966477035050948e-01, +6.145458904162185e-01, - +6.323361944662236e-01, +6.499926319211774e-01, +6.674874032292857e-01, - +6.847932667399612e-01, +7.018835463513400e-01, +7.187322544823347e-01, - +7.353128213893310e-01, +7.516001985652684e-01, +7.675699252273948e-01, - +7.831974571624924e-01, +7.984583859818390e-01, +8.133295347030278e-01, - +8.277892271515950e-01, +8.418178561101360e-01, +8.553961300139363e-01, - +8.685068980898102e-01, +8.811334436653052e-01, +8.932596784799233e-01, - +9.048748835980528e-01, +9.159657608120536e-01, +9.265215299450000e-01, - +9.365339988633418e-01, +9.459977028429117e-01, +9.549088408436811e-01, - +9.632658122557368e-01, +9.710688896122810e-01, +9.783204156360773e-01, - +9.850226760127131e-01, +9.911792082081333e-01, +9.967989944502682e-01, - +1.001894024615659e+00, +1.006474342231823e+00, +1.010552057109195e+00, - +1.014142538208007e+00, +1.017262593268930e+00, +1.019928842669923e+00, - +1.022159867011177e+00, +1.023976320927187e+00, +1.025400734608122e+00, - +1.026455340400072e+00, +1.027164510654160e+00, +1.027552729180790e+00, - +1.027644462380432e+00, +1.027463246660797e+00, +1.027035903410657e+00, - +1.026389068000259e+00, +1.025548201799728e+00, +1.024537134749709e+00, - +1.023380803775376e+00, +1.022103695693341e+00, +1.020728359657958e+00, - +1.019275334687329e+00, +1.017765178792830e+00, +1.016217355867531e+00, - +1.014665311686846e+00, +1.013249071090664e+00, +1.011948006992127e+00, - +1.010189090179223e+00, +1.008557961167850e+00, +1.007011287608451e+00, - +1.005548764575910e+00, +1.004168417268956e+00, +1.002867268893035e+00, - +1.001641769115897e+00, +1.000489068954641e+00, +9.994060799749374e-01, - +9.983898865406841e-01, +9.974370849972721e-01, +9.965444836911705e-01, - +9.957098545943852e-01, +9.949302413030897e-01, +9.942024045863540e-01, - +9.935241604969254e-01, +9.928930430130044e-01, +9.923068103443909e-01, - +9.917633778190438e-01, +9.912597642374404e-01, +9.907954498484041e-01, - +9.903677893656558e-01, +9.899751611066148e-01, +9.896160337369861e-01, - // LC3 Specification d09r01.pdf; Page 94 of 177 - +9.892890160408989e-01, +9.889928511129679e-01, +9.887260333430423e-01, - +9.884868721088945e-01, +9.882751039537586e-01, +9.880892168751595e-01, - +9.879277114724612e-01, +9.877898261218510e-01, +9.876743442038471e-01, - +9.875807496078497e-01, +9.875072021876561e-01, +9.874529447589979e-01, - +9.874169741527905e-01, +9.873984685207834e-01, +9.873958301311858e-01, - +9.874080027710336e-01, +9.874343401290739e-01, +9.874736235387018e-01, - +9.875243137719285e-01, +9.875856201221135e-01, +9.876563785063032e-01, - +9.877358921155149e-01, +9.878225576787804e-01, +9.879150968481590e-01, - +9.880132731565830e-01, +9.881156946084619e-01, +9.882211314188272e-01, - +9.883289032519310e-01, +9.884378310018685e-01, +9.885476787868710e-01, - +9.886568414746639e-01, +9.887645868459630e-01, +9.888708540445242e-01, - +9.889744320992592e-01, +9.890747269455915e-01, +9.891710038703801e-01, - +9.892631024032380e-01, +9.893507219573624e-01, +9.894330645494204e-01, - +9.895096919388534e-01, +9.895810813422480e-01, +9.896467469067676e-01, - +9.897067365020641e-01, +9.897606930400666e-01, +9.898094478563998e-01, - +9.898530133261707e-01, +9.898914705684924e-01, +9.899254194103574e-01, - +9.899554202030650e-01, +9.899824494486951e-01, +9.900065116928948e-01, - +9.900284805353695e-01, +9.900497484789281e-01, +9.900709561632662e-01, - +9.900928358611601e-01, +9.901163920607219e-01, +9.901427479709606e-01, - +9.901734275350572e-01, +9.902087332329851e-01, +9.902498637985275e-01, - +9.902983686695558e-01, +9.903548501470234e-01, +9.904205084933333e-01, - +9.904959297726740e-01, +9.905825150202904e-01, +9.906812569810133e-01, - +9.907922087340426e-01, +9.909165464981378e-01, +9.910550740962871e-01, - +9.912084614290896e-01, +9.913768610980639e-01, +9.915605826937839e-01, - +9.917604214872976e-01, +9.919767175562684e-01, +9.922091101818779e-01, - +9.924579135466506e-01, +9.927231225056266e-01, +9.930049538427406e-01, - +9.933027281437943e-01, +9.936161084869942e-01, +9.939453714404443e-01, - +9.942895145656371e-01, +9.946481676207727e-01, +9.950203031067961e-01, - +9.954058173659507e-01, +9.958038713694317e-01, +9.962130271017117e-01, - +9.966324689957675e-01, +9.970615306490058e-01, +9.974990583293081e-01, - +9.979437430375855e-01, +9.983940572002874e-01, +9.988493116887893e-01, - +9.993083430214909e-01, +9.997689221333534e-01, +1.000231131275969e+00, - +1.000692135698996e+00, +1.001152013920163e+00, +1.001608526000461e+00, - +1.002060493867275e+00, +1.002507212061815e+00, +1.002947129400411e+00, - +1.003378909587027e+00, +1.003801368578070e+00, +1.004213810320699e+00, - +1.004615386562846e+00, +1.005004618375781e+00, +1.005380628601598e+00, - +1.005743282364652e+00, +1.006091510392348e+00, +1.006424907424988e+00, - +1.006742427727669e+00, +1.007044321511378e+00, +1.007330218597112e+00, - +1.007599401798709e+00, +1.007852064386603e+00, +1.008088176165563e+00, - +1.008308033204578e+00, +1.008511247273756e+00, +1.008698144207627e+00, - +1.008869515256392e+00, +1.009025659761512e+00, +1.009166718967367e+00, - +1.009293362609020e+00, +1.009406398832440e+00, +1.009507017171120e+00, - +1.009595264293017e+00, +1.009672145744679e+00, +1.009739084785160e+00, - +1.009796675060142e+00, +1.009846137382005e+00, +1.009888083631667e+00, - +1.009924092276850e+00, +1.009955384765721e+00, +1.009982268770147e+00, - +1.010006298177305e+00, +1.010028618428735e+00, +1.010050254076988e+00, - +1.010071952131355e+00, +1.010094366238073e+00, +1.010118917317053e+00, - +1.010146497096682e+00, +1.010177110711677e+00, +1.010211755260102e+00, - +1.010251003469427e+00, +1.010295468653759e+00, +1.010345234996637e+00, - +1.010400316698172e+00, +1.010461564316351e+00, +1.010528615445659e+00, - +1.010601521285347e+00, +1.010679788081867e+00, +1.010763905869062e+00, - +1.010853429760676e+00, +1.010947547074519e+00, +1.011045953108263e+00, - +1.011148486293359e+00, +1.011254397791134e+00, +1.011363082075863e+00, - +1.011473302008831e+00, +1.011584996312149e+00, +1.011697416504599e+00, - +1.011808919793469e+00, +1.011919264025716e+00, +1.012027240794153e+00, - +1.012132151631041e+00, +1.012232734564333e+00, +1.012327560477901e+00, - // LC3 Specification d09r01.pdf; Page 95 of 177 - +1.012416383754384e+00, +1.012497890726292e+00, +1.012570434021054e+00, - +1.012633295255708e+00, +1.012685277016726e+00, +1.012725564992284e+00, - +1.012752577651415e+00, +1.012765062889864e+00, +1.012762356719162e+00, - +1.012743376077777e+00, +1.012706484200181e+00, +1.012650842226435e+00, - +1.012575427778520e+00, +1.012479473490919e+00, +1.012361105121003e+00, - +1.012219809594718e+00, +1.012054359992419e+00, +1.011864000215460e+00, - +1.011647223869087e+00, +1.011402518267713e+00, +1.011129654652857e+00, - +1.010826951260377e+00, +1.010492924436361e+00, +1.010126353960416e+00, - +1.009725892479312e+00, +1.009290060983833e+00, +1.008817301052548e+00, - +1.008305027555130e+00, +1.007752833675443e+00, +1.007157827358150e+00, - +1.006518049344503e+00, +1.005831403532018e+00, +1.005095592119373e+00, - +1.004308630055050e+00, +1.003467498305776e+00, +1.002569500413888e+00, - +1.001612710105563e+00, +1.000594272975683e+00, +9.995111701168786e-01, - +9.983609218719522e-01, +9.971409288327860e-01, +9.958488863050556e-01, - +9.944818543153893e-01, +9.930375282832211e-01, +9.915146560759479e-01, - +9.899136802423638e-01, +9.881930623810997e-01, +9.859422591203311e-01, - +9.835667898378924e-01, +9.811423034808365e-01, +9.785214441250228e-01, - +9.756636036109838e-01, +9.725453442532574e-01, +9.691456634185092e-01, - +9.654406178310209e-01, +9.614043615076308e-01, +9.570113065179300e-01, - +9.522367669696690e-01, +9.470548839544214e-01, +9.414403740008491e-01, - +9.353691612846549e-01, +9.288190093977164e-01, +9.217662887169115e-01, - +9.141896283466009e-01, +9.060694681113471e-01, +8.973891675497357e-01, - +8.881332000806269e-01, +8.782893885841422e-01, +8.678469565343039e-01, - +8.567970644671067e-01, +8.451334654019180e-01, +8.328542805780399e-01, - +8.199594783897041e-01, +8.064511006873497e-01, +7.923346478686025e-01, - +7.776204488292163e-01, +7.623206183595970e-01, +7.464486491227057e-01, - +7.300205729992958e-01, +7.130567383226717e-01, +6.955805444755916e-01, - +6.776173229836567e-01, +6.591955305148172e-01, +6.403486426892321e-01, - +6.211072197441818e-01, +6.015049275244730e-01, +5.815787608870452e-01, - +5.613674511156324e-01, +5.409188627354076e-01, +5.202736834971303e-01, - +4.994780733459294e-01, +4.785774177949064e-01, +4.576172599874928e-01, - +4.366490208265804e-01, +4.157221460415995e-01, +3.948856590950757e-01, - +3.741903189229770e-01, +3.536868899553974e-01, +3.334260017756462e-01, - +3.134586473252229e-01, +2.938337904395871e-01, +2.745992637590817e-01, - +2.558030636168172e-01, +2.374902188466697e-01, +2.197036032185785e-01, - +2.024855415115456e-01, +1.858749915117319e-01, +1.699067802117410e-01, - +1.546132267478873e-01, +1.400238206749695e-01, +1.261637395672913e-01, - +1.130534434072719e-01, +1.007084973747940e-01, +8.914024389873081e-02, - +7.835612100141792e-02, +6.835821233920988e-02, +5.914211536028976e-02, - +5.069893012340832e-02, +4.301717763585550e-02, +3.608020726673359e-02, - +2.986316337017630e-02, +2.433722657129812e-02, +1.947675241971700e-02, - +1.525710171255895e-02, +1.163787492636240e-02, +8.433087782643718e-03, - +4.449668997344735e-03, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - // LC3 Specification d09r01.pdf; Page 96 of 177 - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00}; - -// Section 5.7.2.5 w480 (d09r01.pdf) -double w_N480[960] = { - -2.353032150516754e-04, -4.619898752628163e-04, -6.262931535610879e-04, - -7.929180432976445e-04, -9.747166718929050e-04, -1.180256894474562e-03, - -1.409209039594871e-03, -1.664473096973725e-03, -1.946591608170231e-03, - -2.257081732588478e-03, -2.597106916737789e-03, -2.967607624839524e-03, - -3.370454877988472e-03, -3.806285163352241e-03, -4.276873767639064e-03, - -4.782469904501813e-03, -5.324608721716763e-03, -5.903403814095400e-03, - -6.520419726599805e-03, -7.175885277771099e-03, -7.871422820642307e-03, - -8.606586039759667e-03, -9.382480860899108e-03, -1.019827182163307e-02, - -1.105520547739066e-02, -1.195270300743193e-02, -1.289205910303846e-02, - -1.387263484323160e-02, -1.489528159506296e-02, -1.595856621933800e-02, - -1.706288556735433e-02, -1.820666399965468e-02, -1.939065975232718e-02, - -2.061355417582714e-02, -2.187570925786862e-02, -2.317526315266411e-02, - -2.451227449041489e-02, -2.588471937157619e-02, -2.729263737090799e-02, - -2.873390902713615e-02, -3.020862738245264e-02, -3.171440372994384e-02, - -3.325098858986303e-02, -3.481597793538342e-02, -3.640892406933019e-02, - -3.802742318209150e-02, -3.967067992672979e-02, -4.133575417353826e-02, - -4.302203371734278e-02, -4.472698045914417e-02, -4.645022292934329e-02, - -4.818891490266687e-02, -4.994225863256500e-02, -5.170690802826666e-02, - -5.348162036097223e-02, -5.526334794593565e-02, -5.705123152423822e-02, - -5.884271749745559e-02, -6.063717235243996e-02, -6.243104027829089e-02, - -6.422303545004304e-02, -6.600961519440657e-02, -6.778962269634495e-02, - -6.955996868581379e-02, -7.131966266443390e-02, -7.306581273272733e-02, - -7.479758913001458e-02, -7.651178225890490e-02, -7.820711420768856e-02, - -7.988010693411644e-02, -8.152964005319532e-02, -8.315237353264004e-02, - // LC3 Specification d09r01.pdf; Page 97 of 177 - -8.474728946770714e-02, -8.631137544905677e-02, -8.784374452959058e-02, - -8.934164364321417e-02, -9.080411291245728e-02, -9.222795761428432e-02, - -9.361232867223340e-02, -9.495377758870335e-02, -9.625155313139856e-02, - -9.750284620437569e-02, -9.870736514214426e-02, -9.986271288271026e-02, - -1.009680221406219e-01, -1.020202684361974e-01, -1.030183804850491e-01, - -1.039596356759290e-01, -1.048438825017798e-01, -1.056686838192766e-01, - -1.064342821660323e-01, -1.071382314127799e-01, -1.077799961121537e-01, - -1.083570625865931e-01, -1.088690135027248e-01, -1.093135588677235e-01, - -1.096903559498340e-01, -1.099969655786929e-01, -1.102332261219973e-01, - -1.103972812085189e-01, -1.104898474883336e-01, -1.105086416532167e-01, - -1.104537426996073e-01, -1.103225838568563e-01, -1.101145827722143e-01, - -1.098276928170364e-01, -1.094621746650760e-01, -1.090163960055733e-01, - -1.084908852561722e-01, -1.078834293141886e-01, -1.071937180231978e-01, - -1.064196358069465e-01, -1.055612509762041e-01, -1.046162812518618e-01, - -1.035849043557610e-01, -1.024650162703341e-01, -1.012568997532046e-01, - -9.995864571932928e-02, -9.857014566194627e-02, -9.708911135857967e-02, - -9.551545820689084e-02, -9.384684920715425e-02, -9.208300062891550e-02, - -9.022171021406450e-02, -8.826309993000785e-02, -8.620493821803937e-02, - -8.404742152815330e-02, -8.178792716809512e-02, -7.942625026703617e-02, - -7.695980775819990e-02, -7.438785600211463e-02, -7.170797002873608e-02, - -6.891994783815969e-02, -6.602189797715241e-02, -6.301349420724424e-02, - -5.989191912667712e-02, -5.665655641133161e-02, -5.330406164482222e-02, - -4.983427241976235e-02, -4.624456893420224e-02, -4.253455686336916e-02, - -3.870195772538443e-02, -3.474585776145929e-02, -3.066341518682682e-02, - -2.645425077642105e-02, -2.211581608120528e-02, -1.764740541599136e-02, - -1.304581363895818e-02, -8.310425696208936e-03, -3.438268661133170e-03, - +1.570315476576933e-03, +6.717697635290676e-03, +1.200477020244778e-02, - +1.743398319747869e-02, +2.300642061077823e-02, +2.872481423270595e-02, - +3.458896350634671e-02, +4.060106462625085e-02, +4.676102915752826e-02, - +5.307133911821893e-02, +5.953239090915557e-02, +6.614647812869151e-02, - +7.291293184312803e-02, +7.983354189816511e-02, +8.690807412770696e-02, - +9.413813765275064e-02, +1.015233140203748e-01, +1.090651518336202e-01, - +1.167626546016197e-01, +1.246171387327525e-01, +1.326272948938113e-01, - +1.407938190608664e-01, +1.491152519299797e-01, +1.575921408388593e-01, - +1.662224799248571e-01, +1.750067399059861e-01, +1.839431938620024e-01, - +1.930318183054904e-01, +2.022699854906251e-01, +2.116567430906184e-01, - +2.211888523410642e-01, +2.308655379767671e-01, +2.406837992341654e-01, - +2.506420640291662e-01, +2.607365124918583e-01, +2.709659073501196e-01, - +2.813259021832532e-01, +2.918144694729168e-01, +3.024270279840051e-01, - +3.131603499997996e-01, +3.240095704645023e-01, +3.349719592361666e-01, - +3.460422935204829e-01, +3.572175180786021e-01, +3.684915649120530e-01, - +3.798595119591716e-01, +3.913146885756875e-01, +4.028532873867052e-01, - +4.144688328137527e-01, +4.261571642320424e-01, +4.379113897565727e-01, - +4.497256320417501e-01, +4.615925445090212e-01, +4.735067030065239e-01, - +4.854600184866710e-01, +4.974471592901086e-01, +5.094597228333853e-01, - +5.214909841729947e-01, +5.335326819631583e-01, +5.455789811615239e-01, - +5.576217157959890e-01, +5.696546730080154e-01, +5.816685576268035e-01, - +5.936560624526468e-01, +6.056083823929643e-01, +6.175192060085208e-01, - +6.293796611336280e-01, +6.411830842823245e-01, +6.529203544876097e-01, - +6.645840786371451e-01, +6.761653499550255e-01, +6.876573952173626e-01, - +6.990511539119996e-01, +7.103400549562944e-01, +7.215149331458728e-01, - +7.325691772738999e-01, +7.434943718765665e-01, +7.542846327442048e-01, - +7.649313654540612e-01, +7.754281892901473e-01, +7.857670170752049e-01, - +7.959414651061612e-01, +8.059437233154637e-01, +8.157687070715176e-01, - +8.254086223972127e-01, +8.348589373399948e-01, +8.441125827416620e-01, - +8.531651194538425e-01, +8.620108336276733e-01, +8.706456337542150e-01, - // LC3 Specification d09r01.pdf; Page 98 of 177 - +8.790631561061171e-01, +8.872599706865123e-01, +8.952313288619367e-01, - +9.029751680353524e-01, +9.104863121445679e-01, +9.177625550620636e-01, - +9.247997426966093e-01, +9.315962496426278e-01, +9.381494858921667e-01, - +9.444588390359354e-01, +9.505220861927248e-01, +9.563402921286364e-01, - +9.619114522936701e-01, +9.672366712325431e-01, +9.723156637834687e-01, - +9.771501187120180e-01, +9.817397501303696e-01, +9.860865871353246e-01, - +9.901906380163595e-01, +9.940557180662704e-01, +9.976842395284637e-01, - +1.001080961257010e+00, +1.004247514102417e+00, +1.007188578458507e+00, - +1.009906654565108e+00, +1.012407428282884e+00, +1.014694702432600e+00, - +1.016774659209400e+00, +1.018650990561848e+00, +1.020330464463111e+00, - +1.021817328911793e+00, +1.023118841384460e+00, +1.024240262467000e+00, - +1.025189721888128e+00, +1.025972450969440e+00, +1.026596938589443e+00, - +1.027069179375841e+00, +1.027397523939210e+00, +1.027587902203109e+00, - +1.027648951922701e+00, +1.027585830688143e+00, +1.027408519661012e+00, - +1.027122986826984e+00, +1.026738673647482e+00, +1.026261663878092e+00, - +1.025701002415063e+00, +1.025061777648234e+00, +1.024353980976701e+00, - +1.023582385618774e+00, +1.022756514615106e+00, +1.021880604350422e+00, - +1.020963871317665e+00, +1.020009139549275e+00, +1.019027285501251e+00, - +1.018019442784231e+00, +1.016996499560845e+00, +1.015957433206324e+00, - +1.014923441259795e+00, +1.013915946100629e+00, +1.013047565149327e+00, - +1.012216130365610e+00, +1.011044869639164e+00, +1.009914592130044e+00, - +1.008824888092573e+00, +1.007773858455400e+00, +1.006761700412993e+00, - +1.005786648810854e+00, +1.004848753962734e+00, +1.003946083413733e+00, - +1.003078846506546e+00, +1.002245009135684e+00, +1.001444733905817e+00, - +1.000676188436651e+00, +9.999393169239009e-01, +9.992320848298057e-01, - +9.985548127155425e-01, +9.979055415627330e-01, +9.972842679758880e-01, - +9.966890948441745e-01, +9.961203379971326e-01, +9.955761256313581e-01, - +9.950565724564597e-01, +9.945597525471822e-01, +9.940860378486615e-01, - +9.936337788972491e-01, +9.932031606606759e-01, +9.927921871265732e-01, - +9.924015177880798e-01, +9.920297273323891e-01, +9.916767775088281e-01, - +9.913408767719142e-01, +9.910230654424902e-01, +9.907216425865902e-01, - +9.904366799536263e-01, +9.901668953434221e-01, +9.899131011580791e-01, - +9.896735637374597e-01, +9.894488374513719e-01, +9.892374835404283e-01, - +9.890401927796704e-01, +9.888556356037892e-01, +9.886843467692753e-01, - +9.885247606051014e-01, +9.883778520531268e-01, +9.882423270582524e-01, - +9.881185638915363e-01, +9.880051626345804e-01, +9.879032023766432e-01, - +9.878111744348976e-01, +9.877295459610343e-01, +9.876571983429736e-01, - +9.875949843246187e-01, +9.875412739766566e-01, +9.874969061399389e-01, - +9.874606249127551e-01, +9.874329809802893e-01, +9.874126414437681e-01, - +9.874004750404033e-01, +9.873949921033299e-01, +9.873969162747074e-01, - +9.874049060317581e-01, +9.874197049003676e-01, +9.874399717110517e-01, - +9.874663281231737e-01, +9.874973205882319e-01, +9.875338926695315e-01, - +9.875746535410983e-01, +9.876201238703241e-01, +9.876689801932402e-01, - +9.877221556193183e-01, +9.877781920433015e-01, +9.878376489591358e-01, - +9.878991990245439e-01, +9.879637979933339e-01, +9.880300303653743e-01, - +9.880984675859855e-01, +9.881678007807095e-01, +9.882390300097154e-01, - +9.883107693992456e-01, +9.883835200189653e-01, +9.884560159878955e-01, - +9.885294200392185e-01, +9.886022219397892e-01, +9.886749404176028e-01, - +9.887466261142505e-01, +9.888182771263505e-01, +9.888882480852147e-01, - +9.889574384705896e-01, +9.890247977602895e-01, +9.890911247701029e-01, - +9.891551701556196e-01, +9.892178658748239e-01, +9.892779555818088e-01, - +9.893365186903538e-01, +9.893923680007577e-01, +9.894462830852175e-01, - +9.894972124952000e-01, +9.895463342815009e-01, +9.895923617530382e-01, - +9.896362652966239e-01, +9.896772011542693e-01, +9.897162195263046e-01, - +9.897520286480039e-01, +9.897859195209235e-01, +9.898170267411330e-01, - +9.898462068764986e-01, +9.898725363809847e-01, +9.898975138787787e-01, - // LC3 Specification d09r01.pdf; Page 99 of 177 - +9.899200050208486e-01, +9.899410789223559e-01, +9.899600605054418e-01, - +9.899782261038060e-01, +9.899945557067980e-01, +9.900103500807507e-01, - +9.900248320990181e-01, +9.900394023736973e-01, +9.900532105829365e-01, - +9.900674746047259e-01, +9.900814722948890e-01, +9.900966926051257e-01, - +9.901122448734595e-01, +9.901293790312005e-01, +9.901474648912307e-01, - +9.901680598867444e-01, +9.901902265696609e-01, +9.902151896501201e-01, - +9.902424418296485e-01, +9.902734448815004e-01, +9.903071270768942e-01, - +9.903448913950654e-01, +9.903862280081246e-01, +9.904324484666853e-01, - +9.904825650601110e-01, +9.905379830873822e-01, +9.905980602136440e-01, - +9.906640366554630e-01, +9.907348826312993e-01, +9.908120376822228e-01, - +9.908947858311721e-01, +9.909842592301273e-01, +9.910795247770178e-01, - +9.911819240108124e-01, +9.912905118607647e-01, +9.914064705361564e-01, - +9.915288011543961e-01, +9.916586940166509e-01, +9.917952720685562e-01, - +9.919396217291009e-01, +9.920906151219310e-01, +9.922495028313456e-01, - +9.924152398352751e-01, +9.925887208794144e-01, +9.927688708468421e-01, - +9.929569112537944e-01, +9.931516528513824e-01, +9.933539244159140e-01, - +9.935626893131695e-01, +9.937790866568735e-01, +9.940016434044485e-01, - +9.942312024833810e-01, +9.944668184371617e-01, +9.947093441694513e-01, - +9.949572854565533e-01, +9.952116634297566e-01, +9.954712635321227e-01, - +9.957367951478069e-01, +9.960068616185641e-01, +9.962823025614079e-01, - +9.965617986382630e-01, +9.968461329825753e-01, +9.971338271912752e-01, - +9.974256691222113e-01, +9.977203369515556e-01, +9.980185087055744e-01, - +9.983185871761977e-01, +9.986213520769593e-01, +9.989255426466267e-01, - +9.992317314100975e-01, +9.995382582242990e-01, +9.998461160718275e-01, - +1.000153907612080e+00, +1.000461955079660e+00, +1.000768859280338e+00, - +1.001075613053728e+00, +1.001380551217109e+00, +1.001684244734497e+00, - +1.001985425397567e+00, +1.002284871786226e+00, +1.002580975161843e+00, - +1.002874411368430e+00, +1.003163845364970e+00, +1.003450063374329e+00, - +1.003731570287893e+00, +1.004009147462043e+00, +1.004281457582935e+00, - +1.004549339226336e+00, +1.004811375053364e+00, +1.005068272394360e+00, - +1.005318795748286e+00, +1.005563968008037e+00, +1.005802269635282e+00, - +1.006034554002353e+00, +1.006259855360867e+00, +1.006479018139540e+00, - +1.006690541428116e+00, +1.006895570408563e+00, +1.007093045696527e+00, - +1.007283799246233e+00, +1.007466616298057e+00, +1.007642728426847e+00, - +1.007811036585595e+00, +1.007972441990187e+00, +1.008125875904472e+00, - +1.008272602383284e+00, +1.008411468616852e+00, +1.008543573152632e+00, - +1.008668018334797e+00, +1.008786009787269e+00, +1.008896526233555e+00, - +1.009000766336071e+00, +1.009097763850333e+00, +1.009188880897370e+00, - +1.009273163797313e+00, +1.009351762546296e+00, +1.009423944949143e+00, - +1.009491175244507e+00, +1.009552401900961e+00, +1.009608886895764e+00, - +1.009659973830751e+00, +1.009707093778162e+00, +1.009749238562067e+00, - +1.009787744284661e+00, +1.009822090220407e+00, +1.009853706282597e+00, - +1.009881498943010e+00, +1.009906958448099e+00, +1.009929567021562e+00, - +1.009950573483366e+00, +1.009969021400474e+00, +1.009986499185054e+00, - +1.010002363879044e+00, +1.010017890428877e+00, +1.010032170180360e+00, - +1.010046722045583e+00, +1.010060809299530e+00, +1.010075674445289e+00, - +1.010090449982098e+00, +1.010106564965965e+00, +1.010123226584120e+00, - +1.010141762173145e+00, +1.010161131093372e+00, +1.010182635897876e+00, - +1.010205587931660e+00, +1.010231078494249e+00, +1.010257950227988e+00, - +1.010287732968580e+00, +1.010319484524512e+00, +1.010354079663767e+00, - +1.010390635488037e+00, +1.010430470494512e+00, +1.010472266495074e+00, - +1.010517096381509e+00, +1.010564099281000e+00, +1.010614266894512e+00, - +1.010666285876455e+00, +1.010721360243234e+00, +1.010778416755264e+00, - +1.010838252644461e+00, +1.010899655674578e+00, +1.010963729626641e+00, - +1.011029191301694e+00, +1.011096993993037e+00, +1.011165861239173e+00, - +1.011236610341260e+00, +1.011308167670753e+00, +1.011381453638912e+00, - // LC3 Specification d09r01.pdf; Page 100 of 177 - +1.011454785713102e+00, +1.011529185153809e+00, +1.011603680910505e+00, - +1.011678803938046e+00, +1.011753008569803e+00, +1.011827484797985e+00, - +1.011900936547881e+00, +1.011973876511603e+00, +1.012044885003304e+00, - +1.012114985644919e+00, +1.012182837094955e+00, +1.012249023976742e+00, - +1.012312095063070e+00, +1.012373028737774e+00, +1.012430463679316e+00, - +1.012484972246822e+00, +1.012535058602453e+00, +1.012581678169188e+00, - +1.012623472898504e+00, +1.012660975529858e+00, +1.012692758750213e+00, - +1.012719789201144e+00, +1.012740575296603e+00, +1.012755753887085e+00, - +1.012763948841204e+00, +1.012765922449960e+00, +1.012760298661069e+00, - +1.012747819936584e+00, +1.012726958954961e+00, +1.012698607692183e+00, - +1.012661400539405e+00, +1.012615904116265e+00, +1.012560833005713e+00, - +1.012497050269805e+00, +1.012422888521601e+00, +1.012339226241367e+00, - +1.012244921966297e+00, +1.012140460211194e+00, +1.012024302085441e+00, - +1.011897560567707e+00, +1.011758810583150e+00, +1.011608449127642e+00, - +1.011445162723270e+00, +1.011269960947744e+00, +1.011081255645969e+00, - +1.010879608424312e+00, +1.010663676735228e+00, +1.010434184200640e+00, - +1.010189681124657e+00, +1.009930754807923e+00, +1.009655660215271e+00, - +1.009365251564694e+00, +1.009058249873833e+00, +1.008734758578989e+00, - +1.008393079963091e+00, +1.008034308295421e+00, +1.007656661215973e+00, - +1.007260142622887e+00, +1.006843352506855e+00, +1.006407009542103e+00, - +1.005949145170711e+00, +1.005470005637052e+00, +1.004967986424467e+00, - +1.004443531995945e+00, +1.003894772403371e+00, +1.003321903663793e+00, - +1.002723127308148e+00, +1.002098854400575e+00, +1.001447278873483e+00, - +1.000768505317086e+00, +1.000060686758758e+00, +9.993242684851855e-01, - +9.985573503390627e-01, +9.977600196406868e-01, +9.969306036935497e-01, - +9.960694269553644e-01, +9.951746430061121e-01, +9.942466438407230e-01, - +9.932837131068657e-01, +9.922861082472264e-01, +9.912523092989319e-01, - +9.901827419790691e-01, +9.890757868707590e-01, +9.879313024174022e-01, - +9.863553220272523e-01, +9.847362453480265e-01, +9.831750948772566e-01, - +9.815583336011345e-01, +9.798613526271561e-01, +9.780617486993630e-01, - +9.761574317374303e-01, +9.741378617337759e-01, +9.719990112065752e-01, - +9.697327413658168e-01, +9.673331975559332e-01, +9.647915124057732e-01, - +9.621011497566145e-01, +9.592539757044516e-01, +9.562427177295731e-01, - +9.530600909726344e-01, +9.496984081652284e-01, +9.461498120176854e-01, - +9.424071613625743e-01, +9.384634163826711e-01, +9.343112966094085e-01, - +9.299449872197452e-01, +9.253567968750328e-01, +9.205404627076625e-01, - +9.154896280575360e-01, +9.101986790930605e-01, +9.046620597741508e-01, - +8.988755194372424e-01, +8.928338316495705e-01, +8.865337190368053e-01, - +8.799712722567934e-01, +8.731437835983047e-01, +8.660476534563131e-01, - +8.586812520174252e-01, +8.510420440685049e-01, +8.431297226886574e-01, - +8.349435141989714e-01, +8.264839911291133e-01, +8.177505366573690e-01, - +8.087449817124315e-01, +7.994681492797084e-01, +7.899235162194718e-01, - +7.801137731566502e-01, +7.700431275216928e-01, +7.597145736971065e-01, - +7.491330971820804e-01, +7.383028603058783e-01, +7.272298755824693e-01, - +7.159201919962611e-01, +7.043814340356083e-01, +6.926196927377140e-01, - +6.806438831866077e-01, +6.684616478236647e-01, +6.560830137986515e-01, - +6.435179268559957e-01, +6.307755329382612e-01, +6.178641647786525e-01, - +6.047954625702541e-01, +5.915799587176216e-01, +5.782289366005894e-01, - +5.647535885752191e-01, +5.511703155400274e-01, +5.374905090437071e-01, - +5.237263500445715e-01, +5.098915423728255e-01, +4.960008074926423e-01, - +4.820662943337458e-01, +4.681017110048007e-01, +4.541216995958746e-01, - +4.401421815729068e-01, +4.261772971493010e-01, +4.122417888542512e-01, - +3.983499612526493e-01, +3.845172335531009e-01, +3.707583717376236e-01, - +3.570886786795506e-01, +3.435228672445627e-01, +3.300763764703638e-01, - +3.167640325043893e-01, +3.036004651973109e-01, +2.905996158436682e-01, - +2.777758503744847e-01, +2.651434678028531e-01, +2.527161881181577e-01, - // LC3 Specification d09r01.pdf; Page 101 of 177 - +2.405069849650012e-01, +2.285283969438072e-01, +2.167933432162879e-01, - +2.053139897833021e-01, +1.941021906320988e-01, +1.831680872008943e-01, - +1.725221947208913e-01, +1.621735416384834e-01, +1.521320683467849e-01, - +1.424052801149985e-01, +1.330015240938615e-01, +1.239260664828526e-01, - +1.151858295527293e-01, +1.067840430193724e-01, +9.872637505002878e-02, - +9.101379000888035e-02, +8.365057236623055e-02, +7.663508305536153e-02, - +6.997033405748826e-02, +6.365188111381365e-02, +5.768176015814392e-02, - +5.205244216987966e-02, +4.676538412257621e-02, +4.180950541438362e-02, - +3.718640251368464e-02, +3.288072750732215e-02, +2.889548499582958e-02, - +2.520980565928884e-02, +2.183057564646272e-02, +1.872896194002638e-02, - +1.592127815153420e-02, +1.336381425803020e-02, +1.108558877807282e-02, - +8.943474189364638e-03, +6.758124889697787e-03, +3.504438130619497e-03, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - // LC3 Specification d09r01.pdf; Page 102 of 177 - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00, - +0.000000000000000e+00, +0.000000000000000e+00, +0.000000000000000e+00}; - -// LC3 Specification d09r04_*implementorComments* -// Section 3.7.3 Low delay MDCT windows -// Section 3.7.3.2 7.5 ms Frame Duration - -// Section 3.7.3.2.1 w_7.5_60 (d09r04_*implementorComments*) -double w_N60_7p5ms[120] = { - 2.950608593187313e-03, 7.175411316438510e-03, 1.376953735371754e-02, - 2.309535564877266e-02, 3.540362298325999e-02, 5.082893035710152e-02, - 6.946962925951473e-02, 9.138842778133426e-02, 1.166045748296231e-01, - 1.450735459839195e-01, 1.767111740534608e-01, 2.113429529554800e-01, - 2.487686144599148e-01, 2.887011017469859e-01, 3.308238711499938e-01, - 3.748145444067251e-01, 4.203080130472308e-01, 4.669049179648736e-01, - 5.141853413578332e-01, 5.617100406669413e-01, 6.090263461524341e-01, - 6.556710162134097e-01, 7.012183842298189e-01, 7.452406787622362e-01, - 7.873692060484326e-01, 8.272238334368036e-01, 8.645136750188277e-01, - 8.989774146126214e-01, 9.304075179845523e-01, 9.585999373974852e-01, - 9.834477193784226e-01, 1.004882833289021e+00, 1.022853807278541e+00, - 1.037404947967044e+00, 1.048597914202596e+00, 1.056561843427440e+00, - 1.061493706243562e+00, 1.063625783716980e+00, 1.063259727973876e+00, - 1.060745048351166e+00, 1.056435897894500e+00, 1.050695001011264e+00, - 1.043924345068839e+00, 1.036477246028582e+00, 1.028728673666003e+00, - 1.021064859918030e+00, 1.014006582262175e+00, 1.007274550102931e+00, - 1.001722497437142e+00, 9.973095916665831e-01, 9.939851582601669e-01, - 9.916833348089591e-01, 9.903253250249126e-01, 9.898226125376152e-01, - 9.900747339893667e-01, 9.909753143689592e-01, 9.924128512256524e-01, - 9.942731493578623e-01, 9.964391574315900e-01, 9.987916157534086e-01, - 1.001209846205687e+00, 1.003573567479612e+00, 1.005759836364722e+00, - 1.007645153692818e+00, 1.009106872290545e+00, 1.010024764464639e+00, - 1.010282031682720e+00, 1.009769188700535e+00, 1.008386412173240e+00, - 1.006051238984656e+00, 1.002697666156926e+00, 9.982804644584213e-01, - 9.927779867939798e-01, 9.861868921689572e-01, 9.776341643922554e-01, - 9.674472695701162e-01, 9.551297254161167e-01, 9.403898774115922e-01, - 9.229592799642977e-01, 9.026073499372684e-01, 8.792026885629480e-01, - 8.526417497265664e-01, 8.228812716163106e-01, 7.899717151715774e-01, - 7.540303276706357e-01, 7.152557417328465e-01, 6.739369112409073e-01, - 6.304147162292445e-01, 5.850788579084674e-01, 5.383985182966198e-01, - 4.908337531732809e-01, 4.428858232573716e-01, 3.950910240537553e-01, - 3.480043431985102e-01, 3.021967102409465e-01, 2.582274305805284e-01, - 2.166414164389013e-01, 1.779221215201146e-01, 1.424805471287674e-01, - 1.106521943353717e-01, 8.269959669528287e-02, 5.883345162013132e-02, - 3.920308484545646e-02, 2.386291074479415e-02, 1.269762234246248e-02, - 5.356653610215987e-03, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00}; - -// Section 3.7.3.2.2 w_7.5_120 (d09r04_*implementorComments*) -double w_N120_7p5ms[240] = { - 2.208248743046650e-03, 3.810144195090351e-03, 5.915524734289813e-03, - 8.583614568030036e-03, 1.187597226083452e-02, 1.583353014097089e-02, - 2.049186515516006e-02, 2.588835928921542e-02, 3.204158944817544e-02, - 3.896167212395468e-02, 4.667421691393490e-02, 5.518493372761350e-02, - 6.450383844383757e-02, 7.464110714806732e-02, 8.560001618878993e-02, - 9.738467025048170e-02, 1.099936025389733e-01, 1.234192774722812e-01, - 1.376554565476283e-01, 1.526904374639564e-01, 1.685133626404965e-01, - 1.850931046131430e-01, 2.024104194879864e-01, 2.204503651331880e-01, - 2.391679406203077e-01, 2.585261682883327e-01, 2.784985387736362e-01, - 2.990384315995911e-01, 3.201048623655521e-01, 3.416586222430363e-01, - 3.636600340252121e-01, 3.860626951895035e-01, 4.088152724594432e-01, - 4.318710458458660e-01, 4.551769877048139e-01, 4.786765926352632e-01, - 5.023248131381035e-01, 5.260609162248473e-01, 5.498312828850233e-01, - 5.735768827770059e-01, 5.972413384410342e-01, 6.207702424193973e-01, - 6.440996624336124e-01, 6.671763816763950e-01, 6.899588537658654e-01, - 7.123799800931302e-01, 7.343963718694788e-01, 7.559666880505324e-01, - 7.770369811015168e-01, 7.975581136897942e-01, 8.174908555311138e-01, - 8.367969496408532e-01, 8.554473095679163e-01, 8.734007983991156e-01, - 8.906357189698083e-01, 9.071287701238782e-01, 9.228487835702877e-01, - 9.377633225341820e-01, 9.518602062527468e-01, 9.651306001536289e-01, - 9.775565405467248e-01, 9.891262086779957e-01, 9.998469191683163e-01, - 1.009700729703874e+00, 1.018682286908352e+00, 1.026814550859190e+00, - 1.034089812751720e+00, 1.040511956629397e+00, 1.046108368522362e+00, - 1.050885649534276e+00, 1.054862887578656e+00, 1.058072205849552e+00, - 1.060534138670111e+00, 1.062276617517642e+00, 1.063338150260194e+00, - 1.063755566766962e+00, 1.063566320618061e+00, 1.062821557530121e+00, - 1.061559958917576e+00, 1.059817091581481e+00, 1.057658760384513e+00, - 1.055120057365395e+00, 1.052239850719546e+00, 1.049087785713381e+00, - 1.045698595146235e+00, 1.042108306824389e+00, 1.038380985588667e+00, - 1.034552762539362e+00, 1.030671997181282e+00, 1.026791666942681e+00, - 1.022955584022344e+00, 1.019207332137853e+00, 1.015872887197225e+00, - 1.012210174593533e+00, 1.008845591036958e+00, 1.005778512486221e+00, - 1.003002618498964e+00, 1.000514601809148e+00, 9.983092287560527e-01, - 9.963786013745719e-01, 9.947181322797367e-01, 9.933162157118496e-01, - 9.921669569649387e-01, 9.912586027088507e-01, 9.905811038723256e-01, - 9.901231181863754e-01, 9.898737119947000e-01, 9.898187066647253e-01, - 9.899468001787191e-01, 9.902431753677082e-01, 9.906955635514434e-01, - 9.912885401035934e-01, 9.920094690635668e-01, 9.928426927501408e-01, - 9.937750666306635e-01, 9.947903979828719e-01, 9.958755336221258e-01, - 9.970143670156726e-01, 9.981928706842119e-01, 9.993945064762333e-01, - 1.000605860368296e+00, 1.001810400944408e+00, 1.002994573682287e+00, - 1.004141548053574e+00, 1.005236884099094e+00, 1.006263925890636e+00, - 1.007208903587772e+00, 1.008054893814649e+00, 1.008788016348394e+00, - 1.009391822060050e+00, 1.009852958217732e+00, 1.010155293011166e+00, - 1.010286018304889e+00, 1.010229878703309e+00, 1.009975407736885e+00, - 1.009508455280294e+00, 1.008818483155921e+00, 1.007894884001199e+00, - 1.006728757854175e+00, 1.005309913983530e+00, 1.003634560818982e+00, - 1.001693634792953e+00, 9.994856628696702e-01, 9.970063702291652e-01, - 9.942546868773952e-01, 9.912319673936767e-01, 9.879371153343368e-01, - 9.843751246861034e-01, 9.798909633127684e-01, 9.752698788428587e-01, - 9.701804980040253e-01, 9.645800268203278e-01, 9.584255335155275e-01, - 9.516840138455831e-01, 9.443202322315050e-01, 9.362906241698766e-01, - 9.275805069442316e-01, 9.181534137230351e-01, 9.079765240138057e-01, - 8.970500584793123e-01, 8.853513603848177e-01, 8.728579265043998e-01, - 8.595798186504622e-01, 8.455026150386550e-01, 8.306199433014801e-01, - 8.149466481575340e-01, 7.984893775294407e-01, 7.812624496601451e-01, - 7.632917692550881e-01, 7.445908434203883e-01, 7.251992870809165e-01, - 7.051536683608545e-01, 6.844905446038185e-01, 6.632452099313783e-01, - 6.414771616618185e-01, 6.192353336355413e-01, 5.965591325427860e-01, - 5.735199893648143e-01, 5.501738510234542e-01, 5.265685382300127e-01, - 5.027811586638018e-01, 4.788608890561979e-01, 4.548778943490807e-01, - 4.308981228989757e-01, 4.069939642056274e-01, 3.832340305827807e-01, - 3.596800983344559e-01, 3.364081000913040e-01, 3.134964181526467e-01, - 2.910105654938709e-01, 2.690195851087463e-01, 2.475843475618672e-01, - 2.267884333851992e-01, 2.066777706538489e-01, 1.873103432384193e-01, - 1.687396441250691e-01, 1.510123820588979e-01, 1.341718422797088e-01, - 1.182546623256353e-01, 1.032907339774596e-01, 8.931173602725516e-02, - 7.634297866041775e-02, 6.440772914585903e-02, 5.352437147393933e-02, - 4.370844528199230e-02, 3.496670991534089e-02, 2.729846292648297e-02, - 2.068958080348781e-02, 1.511251252352759e-02, 1.052287538118900e-02, - 6.855473143120779e-03, 4.023511190940974e-03, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00}; - -// Section 3.7.3.2.3 w_7.5_180 (d09r04_*implementorComments*) -double w_N180_7p5ms[360] = { - 1.970849076512990e-03, 2.950608593187313e-03, 4.124477213467950e-03, - 5.526886639437362e-03, 7.175411316438510e-03, 9.087577304291669e-03, - 1.128191051703656e-02, 1.376953735371754e-02, 1.656002661605294e-02, - 1.966508945492317e-02, 2.309535564877266e-02, 2.686128938982976e-02, - 3.096325597431720e-02, 3.540362298325999e-02, 4.019156101100901e-02, - 4.533314033337320e-02, 5.082893035710152e-02, 5.668154478534839e-02, - 6.289353044640154e-02, 6.946962925951473e-02, 7.641063136809326e-02, - 8.371600156519982e-02, 9.138842778133426e-02, 9.942940076792395e-02, - 1.078347249723074e-01, 1.166045748296231e-01, 1.257365027864348e-01, - 1.352268113395951e-01, 1.450735459839195e-01, 1.552738186648721e-01, - 1.658221942341435e-01, 1.767111740534608e-01, 1.879287758848813e-01, - 1.994731798188807e-01, 2.113429529554800e-01, 2.235245540318082e-01, - 2.360030996517997e-01, 2.487686144599148e-01, 2.618138107489893e-01, - 2.751291608544314e-01, 2.887011017469859e-01, 3.025140336309949e-01, - 3.165588052366450e-01, 3.308238711499938e-01, 3.452955666730954e-01, - 3.599639915662127e-01, 3.748145444067251e-01, 3.898318165532388e-01, - 4.050010096015846e-01, 4.203080130472308e-01, 4.357395152859960e-01, - 4.512778173547499e-01, 4.669049179648736e-01, 4.826090405673480e-01, - 4.983754662664123e-01, 5.141853413578332e-01, 5.300214783136831e-01, - 5.458693517886994e-01, 5.617100406669413e-01, 5.775281514417204e-01, - 5.933046964262578e-01, 6.090263461524341e-01, 6.246741889386914e-01, - 6.402275547146322e-01, 6.556710162134097e-01, 6.709959346439072e-01, - 6.861845587972498e-01, 7.012183842298189e-01, 7.160784485622184e-01, - 7.307560841550591e-01, 7.452406787622362e-01, 7.595151215738793e-01, - 7.735619554086122e-01, 7.873692060484326e-01, 8.009231377307978e-01, - 8.142113863131932e-01, 8.272238334368036e-01, 8.399523741938065e-01, - 8.523861023610134e-01, 8.645136750188277e-01, 8.763240788355384e-01, - 8.878142883924764e-01, 8.989774146126214e-01, 9.098033189281092e-01, - 9.202843119253094e-01, 9.304075179845523e-01, 9.401696522166354e-01, - 9.495677949302647e-01, 9.585999373974852e-01, 9.672602600117832e-01, - 9.755451659417252e-01, 9.834477193784226e-01, 9.909719572606611e-01, - 9.981192686440387e-01, 1.004882833289021e+00, 1.011257731140136e+00, - 1.017244362189382e+00, 1.022853807278541e+00, 1.028087338709125e+00, - 1.032937063258800e+00, 1.037404947967044e+00, 1.041501641198980e+00, - 1.045232355730946e+00, 1.048597914202596e+00, 1.051603395002874e+00, - 1.054255050268478e+00, 1.056561843427440e+00, 1.058534002822506e+00, - 1.060174135407872e+00, 1.061493706243562e+00, 1.062499430330238e+00, - 1.063205771472337e+00, 1.063625783716980e+00, 1.063764865344437e+00, - 1.063637778334477e+00, 1.063259727973876e+00, 1.062646953245063e+00, - 1.061804962699513e+00, 1.060745048351166e+00, 1.059484915739590e+00, - 1.058045332777575e+00, 1.056435897894500e+00, 1.054662178717384e+00, - 1.052740474459255e+00, 1.050695001011264e+00, 1.048538935354313e+00, - 1.046278982648917e+00, 1.043924345068839e+00, 1.041495397384132e+00, - 1.039010026880522e+00, 1.036477246028582e+00, 1.033907928361672e+00, - 1.031319893754215e+00, 1.028728673666003e+00, 1.026148319362665e+00, - 1.023589880840269e+00, 1.021064859918030e+00, 1.018562619376553e+00, - 1.016557703375972e+00, 1.014006582262175e+00, 1.011629525863078e+00, - 1.009385901800645e+00, 1.007274550102931e+00, 1.005296164582239e+00, - 1.003445259887302e+00, 1.001722497437142e+00, 1.000127924463537e+00, - 9.986575334669062e-01, 9.973095916665831e-01, 9.960835710929218e-01, - 9.949765689814285e-01, 9.939851582601669e-01, 9.931075300522219e-01, - 9.923413052310536e-01, 9.916833348089591e-01, 9.911300696314259e-01, - 9.906783251641723e-01, 9.903253250249126e-01, 9.900675621816006e-01, - 9.899012818722897e-01, 9.898226125376152e-01, 9.898278454016073e-01, - 9.899132411259368e-01, 9.900747339893667e-01, 9.903082558387314e-01, - 9.906098517881138e-01, 9.909753143689592e-01, 9.914003304461825e-01, - 9.918809661701072e-01, 9.924128512256524e-01, 9.929917790758115e-01, - 9.936133813858116e-01, 9.942731493578623e-01, 9.949669577858075e-01, - 9.956903701113655e-01, 9.964391574315900e-01, 9.972085721948355e-01, - 9.979942749676792e-01, 9.987916157534086e-01, 9.995960619759856e-01, - 1.000404101255877e+00, 1.001209846205687e+00, 1.002009756050340e+00, - 1.002799241686241e+00, 1.003573567479612e+00, 1.004328283187225e+00, - 1.005058501867633e+00, 1.005759836364722e+00, 1.006427669689071e+00, - 1.007057682723931e+00, 1.007645153692818e+00, 1.008185492117307e+00, - 1.008674265369618e+00, 1.009106872290545e+00, 1.009479158919060e+00, - 1.009786593319936e+00, 1.010024764464639e+00, 1.010189538289831e+00, - 1.010276690684798e+00, 1.010282031682720e+00, 1.010201742651156e+00, - 1.010032080837507e+00, 1.009769188700535e+00, 1.009409386073207e+00, - 1.008949310126241e+00, 1.008386412173240e+00, 1.007717803066923e+00, - 1.006940305796912e+00, 1.006051238984656e+00, 1.005048793283357e+00, - 1.003931827630468e+00, 1.002697666156926e+00, 1.001344271172154e+00, - 9.998720918990379e-01, 9.982804644584213e-01, 9.965665691741982e-01, - 9.947317370056415e-01, 9.927779867939798e-01, 9.907013741881066e-01, - 9.885041652445283e-01, 9.861868921689572e-01, 9.837119886839835e-01, - 9.805846431095010e-01, 9.776341643922554e-01, 9.744550331507363e-01, - 9.710629155613092e-01, 9.674472695701162e-01, 9.635939262874074e-01, - 9.594913983473223e-01, 9.551297254161167e-01, 9.505013259120755e-01, - 9.455928103144016e-01, 9.403898774115922e-01, 9.348867604141315e-01, - 9.290805587106350e-01, 9.229592799642976e-01, 9.165095791928667e-01, - 9.097244560733702e-01, 9.026073499372684e-01, 8.951550837577193e-01, - 8.873561542082500e-01, 8.792026885629480e-01, 8.706996978416294e-01, - 8.618474244579353e-01, 8.526417497265664e-01, 8.430778332415034e-01, - 8.331549046805315e-01, 8.228812716163106e-01, 8.122575969197091e-01, - 8.012854392434710e-01, 7.899717151715774e-01, 7.783181771724644e-01, - 7.663377104116385e-01, 7.540303276706357e-01, 7.414079909457567e-01, - 7.284775008035390e-01, 7.152557417328465e-01, 7.017517394571592e-01, - 6.879756318118113e-01, 6.739369112409073e-01, 6.596525732013095e-01, - 6.451394890668392e-01, 6.304147162292445e-01, 6.154836219271654e-01, - 6.003658519413984e-01, 5.850788579084674e-01, 5.696495364564049e-01, - 5.540848098312343e-01, 5.383985182966198e-01, 5.226147377537511e-01, - 5.067568049662954e-01, 4.908337531732726e-01, 4.748660326525270e-01, - 4.588765658108130e-01, 4.428858232573716e-01, 4.269065392300330e-01, - 4.109709733914872e-01, 3.950910240537540e-01, 3.792913270170828e-01, - 3.635874169858631e-01, 3.480043431985094e-01, 3.325632006175457e-01, - 3.172874848823412e-01, 3.021967102409465e-01, 2.873094025754711e-01, - 2.726439916003860e-01, 2.582274305805277e-01, 2.440728561740129e-01, - 2.302089773823469e-01, 2.166414164389010e-01, 2.033984806897052e-01, - 1.904861615463941e-01, 1.779221215201146e-01, 1.657266744835887e-01, - 1.539063966799855e-01, 1.424805471287671e-01, 1.314539801011583e-01, - 1.208417782380949e-01, 1.106521943353716e-01, 1.008917341936222e-01, - 9.157188508647542e-02, 8.269959669528287e-02, 7.428155288862677e-02, - 6.632423815331720e-02, 5.883345162013123e-02, 5.181406762377953e-02, - 4.526983455651076e-02, 3.920308484545643e-02, 3.361441594214110e-02, - 2.850233081562859e-02, 2.386291074479415e-02, 1.968942265531783e-02, - 1.597205270240860e-02, 1.269762234246247e-02, 9.849377394464552e-03, - 7.407244632998355e-03, 5.356653610215985e-03, 3.832265518746914e-03, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00}; - -// Section 3.7.3.2.4 w_7.5_240 (d09r04_*implementorComments*) -double w_N240_7p5ms[480] = { - 1.848330370601890e-03, 2.564818394430541e-03, 3.367621175255762e-03, - 4.287366172947020e-03, 5.338301429131479e-03, 6.526792229804446e-03, - 7.861125872744963e-03, 9.346281793294168e-03, 1.099168677073023e-02, - 1.280111724327587e-02, 1.478059105262588e-02, 1.693070430750747e-02, - 1.925923070409017e-02, 2.176969372101092e-02, 2.446859826144651e-02, - 2.735565427385896e-02, 3.043192302576378e-02, 3.369804639006632e-02, - 3.715835772551574e-02, 4.081481795207546e-02, 4.467080684234739e-02, - 4.872629952625619e-02, 5.298206325441551e-02, 5.743824696664848e-02, - 6.209685798752235e-02, 6.696097666085293e-02, 7.202983636789818e-02, - 7.730391464771366e-02, 8.278255740953620e-02, 8.846821015931731e-02, - 9.436075664518449e-02, 1.004602720036002e-01, 1.067638237504515e-01, - 1.132736794406103e-01, 1.199864202730101e-01, 1.269035206805856e-01, - 1.340208531277774e-01, 1.413395568701277e-01, 1.488572112889720e-01, - 1.565736853381255e-01, 1.644846220563571e-01, 1.725890765381433e-01, - 1.808790898204713e-01, 1.893543196006846e-01, 1.980122435284018e-01, - 2.068541409946420e-01, 2.158753187570538e-01, 2.250686723708130e-01, - 2.344274072499690e-01, 2.439483137105153e-01, 2.536279928378056e-01, - 2.634640609879333e-01, 2.734504944781370e-01, 2.835821889865098e-01, - 2.938534694786572e-01, 3.042573734615632e-01, 3.147909140113310e-01, - 3.254491234269504e-01, 3.362274096618026e-01, 3.471187602907065e-01, - 3.581201769604495e-01, 3.692246633783371e-01, 3.804277928712796e-01, - 3.917200227416179e-01, 4.030970221548365e-01, 4.145519552168687e-01, - 4.260817186124239e-01, 4.376763184816823e-01, 4.493301956572350e-01, - 4.610348550393067e-01, 4.727860432828289e-01, 4.845767771787368e-01, - 4.964017067665196e-01, 5.082524575564947e-01, 5.201220784839651e-01, - 5.320020770005417e-01, 5.438880897441558e-01, 5.557716011811357e-01, - 5.676457387746829e-01, 5.795027863150121e-01, 5.913350345927856e-01, - 6.031383674734400e-01, 6.149041716859808e-01, 6.266239411056014e-01, - 6.382888344252021e-01, 6.498933747767719e-01, 6.614323601501731e-01, - 6.729025139063478e-01, 6.842937498334491e-01, 6.956004595358826e-01, - 7.068117836489756e-01, 7.179234245192330e-01, 7.289313857272890e-01, - 7.398327727973596e-01, 7.506189823719328e-01, 7.612840534177552e-01, - 7.718189187016244e-01, 7.822209919639922e-01, 7.924813304551203e-01, - 8.025994477230463e-01, 8.125652295019083e-01, 8.223771289200885e-01, - 8.320305183749199e-01, 8.415232076745133e-01, 8.508483129483138e-01, - 8.600024117819522e-01, 8.689798808251054e-01, 8.777783467294870e-01, - 8.863959039558345e-01, 8.948294207910807e-01, 9.030776256602892e-01, - 9.111326521556180e-01, 9.189935853649371e-01, 9.266529369336567e-01, - 9.341114204165168e-01, 9.413643442928993e-01, 9.484129673709889e-01, - 9.552556295973936e-01, 9.618920131378678e-01, 9.683163629086772e-01, - 9.745301563621191e-01, 9.805283381417256e-01, 9.863139277672938e-01, - 9.918860486198928e-01, 9.972463447664014e-01, 1.002391896644578e+00, - 1.007319464375827e+00, 1.012027073435850e+00, 1.016516541512393e+00, - 1.020794302688699e+00, 1.024860815794490e+00, 1.028714705809749e+00, - 1.032351702719174e+00, 1.035773750472822e+00, 1.038984315074006e+00, - 1.041987855398911e+00, 1.044785643573356e+00, 1.047378184121997e+00, - 1.049767431495211e+00, 1.051954045543143e+00, 1.053942898562160e+00, - 1.055734631473796e+00, 1.057341767323983e+00, 1.058757264938716e+00, - 1.059986744473714e+00, 1.061036716870687e+00, 1.061906510844496e+00, - 1.062603694906377e+00, 1.063132893292572e+00, 1.063502373941053e+00, - 1.063709808061891e+00, 1.063763223461893e+00, 1.063667646046172e+00, - 1.063430118187021e+00, 1.063056564385666e+00, 1.062554210368898e+00, - 1.061922346664364e+00, 1.061167017783231e+00, 1.060294689234573e+00, - 1.059314689493745e+00, 1.058234647303768e+00, 1.057058907527535e+00, - 1.055789482473656e+00, 1.054429786866560e+00, 1.052987925902714e+00, - 1.051475051645344e+00, 1.049899300533228e+00, 1.048262129495776e+00, - 1.046566906015578e+00, 1.044816992642391e+00, 1.043021249196200e+00, - 1.041187680907488e+00, 1.039323391025476e+00, 1.037431684165083e+00, - 1.035517573311265e+00, 1.033585105989712e+00, 1.031643708543028e+00, - 1.029699545977279e+00, 1.027759438517856e+00, 1.025827187037112e+00, - 1.023907910886626e+00, 1.022008050685529e+00, 1.020139101207016e+00, - 1.018263100813380e+00, 1.016879010849981e+00, 1.014921948187593e+00, - 1.013096623369458e+00, 1.011342052440818e+00, 1.009659122960534e+00, - 1.008050363886717e+00, 1.006517540250988e+00, 1.005057992517306e+00, - 1.003669560904293e+00, 1.002353273092562e+00, 1.001109808447114e+00, - 9.999375230640204e-01, 9.988345237783536e-01, 9.978006059268592e-01, - 9.968357558473706e-01, 9.959388811568640e-01, 9.951084589555501e-01, - 9.943434110903315e-01, 9.936429211981983e-01, 9.930058324270904e-01, - 9.924309837770386e-01, 9.919174926403282e-01, 9.914638980147298e-01, - 9.910682139572967e-01, 9.907292184488009e-01, 9.904462245644213e-01, - 9.902178185518503e-01, 9.900419630667118e-01, 9.899170852600004e-01, - 9.898419746989491e-01, 9.898150482937847e-01, 9.898343291371600e-01, - 9.898982107247224e-01, 9.900054030605746e-01, 9.901541892638673e-01, - 9.903424269195302e-01, 9.905684589910844e-01, 9.908309527413479e-01, - 9.911280379271901e-01, 9.914575656842904e-01, 9.918178809274675e-01, - 9.922075589719793e-01, 9.926247572992801e-01, 9.930673584123647e-01, - 9.935333982795475e-01, 9.940214100660039e-01, 9.945296851337717e-01, - 9.950559636181178e-01, 9.955983505434736e-01, 9.961555801042186e-01, - 9.967256267769223e-01, 9.973060922083319e-01, 9.978952138542876e-01, - 9.984914406319209e-01, 9.990928899877792e-01, 9.996970625756828e-01, - 1.000303029223210e+00, 1.000907933607887e+00, 1.001510838557739e+00, - 1.002109225614564e+00, 1.002701184533730e+00, 1.003285129964668e+00, - 1.003859256498246e+00, 1.004421109631332e+00, 1.004968601327613e+00, - 1.005500403806944e+00, 1.006014548452834e+00, 1.006508690831783e+00, - 1.006981038626341e+00, 1.007430041056790e+00, 1.007853640055005e+00, - 1.008249618432853e+00, 1.008616036239346e+00, 1.008951378362138e+00, - 1.009253896674588e+00, 1.009521341935844e+00, 1.009751751331617e+00, - 1.009943714668776e+00, 1.010095497366507e+00, 1.010204876790192e+00, - 1.010270073045154e+00, 1.010289752336835e+00, 1.010262269696272e+00, - 1.010185615431975e+00, 1.010058196828792e+00, 1.009878817836722e+00, - 1.009645930489341e+00, 1.009357533197330e+00, 1.009012281815637e+00, - 1.008609594360786e+00, 1.008148366592626e+00, 1.007626743165711e+00, - 1.007043430506158e+00, 1.006397749801444e+00, 1.005688767931258e+00, - 1.004915585834316e+00, 1.004077678781271e+00, 1.003174288376062e+00, - 1.002204242070086e+00, 1.001166836141424e+00, 1.000062480839591e+00, - 9.988914218622672e-01, 9.976522518001048e-01, 9.963438555404762e-01, - 9.949674620221296e-01, 9.935246630184282e-01, 9.920139269077016e-01, - 9.904332831340030e-01, 9.887851470099116e-01, 9.870726808604894e-01, - 9.852974426119764e-01, 9.834011611313795e-01, 9.809494177655508e-01, - 9.787827290446353e-01, 9.764682383490441e-01, 9.740428502007106e-01, - 9.714988482797869e-01, 9.688299679017578e-01, 9.660309739278938e-01, - 9.630951038651144e-01, 9.600181976898812e-01, 9.567957384046786e-01, - 9.534262666962353e-01, 9.499034823039632e-01, 9.462221151684139e-01, - 9.423758195026390e-01, 9.383617015143452e-01, 9.341777978631194e-01, - 9.298231239088762e-01, 9.252923195046721e-01, 9.205801200661107e-01, - 9.156797929682001e-01, 9.105906042938267e-01, 9.053150301587091e-01, - 8.998527561071954e-01, 8.941994971184931e-01, 8.883501524279332e-01, - 8.823016313374981e-01, 8.760548741525249e-01, 8.696123849407055e-01, - 8.629727993296973e-01, 8.561351975749198e-01, 8.490981786073120e-01, - 8.418570243421116e-01, 8.344140550191105e-01, 8.267746168752393e-01, - 8.189392440268611e-01, 8.109048914872936e-01, 8.026753184506191e-01, - 7.942537505258295e-01, 7.856416615920516e-01, 7.768386086617421e-01, - 7.678531932560713e-01, 7.586851806705738e-01, 7.493306577133620e-01, - 7.398091711550503e-01, 7.301099443577747e-01, 7.202477806201014e-01, - 7.102241609901638e-01, 7.000443258461506e-01, 6.897118895404929e-01, - 6.792311541046628e-01, 6.686081789247391e-01, 6.578509967842496e-01, - 6.469657182336516e-01, 6.359596166227444e-01, 6.248403358991607e-01, - 6.136035026791002e-01, 6.022650906421884e-01, 5.908290833732823e-01, - 5.793094079430561e-01, 5.677111240020907e-01, 5.560374156751429e-01, - 5.442936643492620e-01, 5.324897680536480e-01, 5.206360841136255e-01, - 5.087432727680400e-01, 4.968111660413653e-01, 4.848498807089364e-01, - 4.728681073650310e-01, 4.608759183794885e-01, 4.488810806327018e-01, - 4.368910387727512e-01, 4.249120223507826e-01, 4.129606031641687e-01, - 4.010358962877044e-01, 3.891578667449375e-01, 3.773221988116735e-01, - 3.655437668630012e-01, 3.538323564250667e-01, 3.421961154339837e-01, - 3.306448201086834e-01, 3.191875589898712e-01, 3.078333093391901e-01, - 2.965881816516454e-01, 2.854637165360221e-01, 2.744624088577634e-01, - 2.636095844768899e-01, 2.528831011433226e-01, 2.423234889711821e-01, - 2.319257462841697e-01, 2.216908373695833e-01, 2.116380576950307e-01, - 2.017669202945304e-01, 1.920822358183417e-01, 1.825891600132626e-01, - 1.733059967407588e-01, 1.642292000450303e-01, 1.553626542479246e-01, - 1.467170785977411e-01, 1.382993914151456e-01, 1.301050780767305e-01, - 1.221453099291547e-01, 1.144234581921691e-01, 1.069410759923033e-01, - 9.970258934460623e-02, 9.271242833748693e-02, 8.597374270620267e-02, - 7.948933111952143e-02, 7.326165794605345e-02, 6.729341023108891e-02, - 6.158740810076327e-02, 5.614580025932222e-02, 5.097007470356519e-02, - 4.606170471457775e-02, 4.142201169265410e-02, 3.705141887506228e-02, - 3.294946662279392e-02, 2.911533269413120e-02, 2.554764013238235e-02, - 2.224377112828603e-02, 1.920006589797908e-02, 1.641222045266977e-02, - 1.387476111201306e-02, 1.158063529909875e-02, 9.522136642215920e-03, - 7.691373795814687e-03, 6.072078331193099e-03, 4.625812168742676e-03, - 3.606851641625968e-03, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00}; - -// Section 3.7.3.2.5 w_7.5_360 (d09r04_*implementorComments*) -double w_N360_7p5ms[720] = { - 1.721526681611966e-03, 2.208248743046650e-03, 2.689017522595345e-03, - 3.226133417706577e-03, 3.810144195090351e-03, 4.453719317184182e-03, - 5.153692399681317e-03, 5.915524734289813e-03, 6.738691584410875e-03, - 7.628618406907552e-03, 8.583614568030036e-03, 9.609384374613759e-03, - 1.070607532160120e-02, 1.187597226083452e-02, 1.311901297315944e-02, - 1.443901078588673e-02, 1.583353014097089e-02, 1.730630810758647e-02, - 1.885847112173313e-02, 2.049186515516006e-02, 2.220614764140174e-02, - 2.400571662419946e-02, 2.588835928921542e-02, 2.785523259150068e-02, - 2.990591454016386e-02, 3.204158944817544e-02, 3.426100132985917e-02, - 3.656809727321165e-02, 3.896167212395468e-02, 4.144358235567028e-02, - 4.401407955156517e-02, 4.667421691393490e-02, 4.942146249896087e-02, - 5.225884889914327e-02, 5.518493372761350e-02, 5.820051428449914e-02, - 6.130598448769178e-02, 6.450383844383757e-02, 6.779139227807153e-02, - 7.117078328947134e-02, 7.464110714806732e-02, 7.820280530933912e-02, - 8.185495207937329e-02, 8.560001618878993e-02, 8.943576174662307e-02, - 9.336425891679158e-02, 9.738467025048170e-02, 1.014967178422148e-01, - 1.056987601379146e-01, 1.099936025389733e-01, 1.143782870006880e-01, - 1.188535076446910e-01, 1.234192774722812e-01, 1.280759966861818e-01, - 1.328205805921621e-01, 1.376554565476283e-01, 1.425786478649834e-01, - 1.475905216894996e-01, 1.526904374639564e-01, 1.578788527293271e-01, - 1.631525285166384e-01, 1.685133626404965e-01, 1.739579689655531e-01, - 1.794847365410843e-01, 1.850931046131430e-01, 1.907848350801405e-01, - 1.965564972779563e-01, 2.024104194879864e-01, 2.083454334275949e-01, - 2.143598248322309e-01, 2.204503651331880e-01, 2.266172963796335e-01, - 2.328562792793315e-01, 2.391679406203077e-01, 2.455506417347264e-01, - 2.520039508016560e-01, 2.585261682883327e-01, 2.651184076263592e-01, - 2.717759113203786e-01, 2.784985387736362e-01, 2.852846062288917e-01, - 2.921324591263930e-01, 2.990384315995911e-01, 3.060042559686472e-01, - 3.130265290443111e-01, 3.201048623655521e-01, 3.272373243719107e-01, - 3.344232095441687e-01, 3.416586222430363e-01, 3.489449761645191e-01, - 3.562792519116003e-01, 3.636600340252121e-01, 3.710851463600319e-01, - 3.785543267164805e-01, 3.860626951895035e-01, 3.936105536140438e-01, - 4.011952247532815e-01, 4.088152724594432e-01, 4.164684603494585e-01, - 4.241554113955093e-01, 4.318710458458660e-01, 4.396147439144481e-01, - 4.473840194903529e-01, 4.551769877048139e-01, 4.629901375019677e-01, - 4.708246187885389e-01, 4.786765926352632e-01, 4.865454331135768e-01, - 4.944287144003222e-01, 5.023248131381035e-01, 5.102294714645887e-01, - 5.181429265558146e-01, 5.260609162248473e-01, 5.339828176544869e-01, - 5.419068167854945e-01, 5.498312828850233e-01, 5.577512337479950e-01, - 5.656676362338563e-01, 5.735768827770059e-01, 5.814766655477682e-01, - 5.893646610908023e-01, 5.972413384410342e-01, 6.051020131945327e-01, - 6.129461702965266e-01, 6.207702424193973e-01, 6.285720938000074e-01, - 6.363485261821292e-01, 6.440996624336124e-01, 6.518209733012164e-01, - 6.595138217057872e-01, 6.671763816763950e-01, 6.748067951703918e-01, - 6.824007108459023e-01, 6.899588537658654e-01, 6.974757223488888e-01, - 7.049501447553026e-01, 7.123799800931302e-01, 7.197654340542331e-01, - 7.271038329243241e-01, 7.343963718694788e-01, 7.416385606661200e-01, - 7.488296394277816e-01, 7.559666880505324e-01, 7.630492594418218e-01, - 7.700722734566787e-01, 7.770369811015168e-01, 7.839411079555614e-01, - 7.907812565704104e-01, 7.975581136897942e-01, 8.042713809653173e-01, - 8.109149005929875e-01, 8.174908555311138e-01, 8.239970937711972e-01, - 8.304327850184938e-01, 8.367969496408532e-01, 8.430892979726279e-01, - 8.493058471422328e-01, 8.554473095679163e-01, 8.615110365133289e-01, - 8.674962806836773e-01, 8.734007983991156e-01, 8.792275183442975e-01, - 8.849724383046952e-01, 8.906357189698083e-01, 8.962171727097513e-01, - 9.017164138681113e-01, 9.071287701238782e-01, 9.124565781610174e-01, - 9.176972608396821e-01, 9.228487835702877e-01, 9.279099172570797e-01, - 9.328825964768623e-01, 9.377633225341820e-01, 9.425533559491475e-01, - 9.472524281763984e-01, 9.518602062527468e-01, 9.563760599307146e-01, - 9.608006016536426e-01, 9.651306001536289e-01, 9.693666888567923e-01, - 9.735088121912839e-01, 9.775565405467248e-01, 9.815072260762016e-01, - 9.853645802900605e-01, 9.891262086779957e-01, 9.927942006806012e-01, - 9.963675450849775e-01, 9.998469191683163e-01, 1.003228124845146e+00, - 1.006513411821911e+00, 1.009700729703874e+00, 1.012790289606342e+00, - 1.015782934360887e+00, 1.018682286908352e+00, 1.021486570410198e+00, - 1.024197718428813e+00, 1.026814550859190e+00, 1.029335981099974e+00, - 1.031760429936344e+00, 1.034089812751720e+00, 1.036323258515780e+00, - 1.038463607653629e+00, 1.040511956629397e+00, 1.042468314695544e+00, - 1.044333310154580e+00, 1.046108368522362e+00, 1.047790183156567e+00, - 1.049383335559126e+00, 1.050885649534276e+00, 1.052299234616223e+00, - 1.053625218490635e+00, 1.054862887578656e+00, 1.056015206502275e+00, - 1.057087459299065e+00, 1.058072205849552e+00, 1.058975241719203e+00, - 1.059794467230661e+00, 1.060534138670111e+00, 1.061194118632638e+00, - 1.061773655564821e+00, 1.062276617517642e+00, 1.062703237255151e+00, - 1.063055685508735e+00, 1.063338150260194e+00, 1.063547997184066e+00, - 1.063686067900426e+00, 1.063755566766962e+00, 1.063757434953141e+00, - 1.063693583520601e+00, 1.063566320618061e+00, 1.063377073891492e+00, - 1.063127819699189e+00, 1.062821557530121e+00, 1.062457815392427e+00, - 1.062036342819983e+00, 1.061559958917576e+00, 1.061029510184661e+00, - 1.060447965083549e+00, 1.059817091581481e+00, 1.059141628118411e+00, - 1.058421358875364e+00, 1.057658760384513e+00, 1.056853774077034e+00, - 1.056007614360998e+00, 1.055120057365395e+00, 1.054195045438248e+00, - 1.053233455551333e+00, 1.052239850719546e+00, 1.051216675517538e+00, - 1.050166369287038e+00, 1.049087785713381e+00, 1.047983664181190e+00, - 1.046853337647985e+00, 1.045698595146235e+00, 1.044520564730305e+00, - 1.043323481681635e+00, 1.042108306824389e+00, 1.040879073476582e+00, - 1.039636032987793e+00, 1.038380985588667e+00, 1.037114029603682e+00, - 1.035838134533162e+00, 1.034552762539362e+00, 1.033262000621490e+00, - 1.031967497567261e+00, 1.030671997181282e+00, 1.029375639312502e+00, - 1.028082437365047e+00, 1.026791666942681e+00, 1.025506352493464e+00, - 1.024226550306258e+00, 1.022955584022344e+00, 1.021692989563247e+00, - 1.020444748460154e+00, 1.019207332137853e+00, 1.017999919156420e+00, - 1.017160217193961e+00, 1.015872887197225e+00, 1.014617829299498e+00, - 1.013397380801344e+00, 1.012210174593533e+00, 1.011056516187721e+00, - 1.009934436494794e+00, 1.008845591036958e+00, 1.007789557609578e+00, - 1.006767901472734e+00, 1.005778512486221e+00, 1.004821733696763e+00, - 1.003895920161236e+00, 1.003002618498964e+00, 1.002140907258662e+00, - 1.001312127031557e+00, 1.000514601809148e+00, 9.997489875663875e-01, - 9.990134860651736e-01, 9.983092287560527e-01, 9.976349335738018e-01, - 9.969918851181095e-01, 9.963786013745719e-01, 9.957959823242557e-01, - 9.952422174315529e-01, 9.947181322797367e-01, 9.942221216035205e-01, - 9.937553132700969e-01, 9.933162157118496e-01, 9.929058092648040e-01, - 9.925224215680564e-01, 9.921669569649387e-01, 9.918377038474807e-01, - 9.915355084098528e-01, 9.912586027088507e-01, 9.910078784250421e-01, - 9.907817226664765e-01, 9.905811038723256e-01, 9.904043360106435e-01, - 9.902522665150607e-01, 9.901231181863754e-01, 9.900177259420802e-01, - 9.899343252516752e-01, 9.898737119947000e-01, 9.898341100636087e-01, - 9.898163585163330e-01, 9.898187066647253e-01, 9.898419976335596e-01, - 9.898844376083749e-01, 9.899468001787191e-01, 9.900272871794666e-01, - 9.901266804330273e-01, 9.902431753677082e-01, 9.903775935673591e-01, - 9.905281337320039e-01, 9.906955635514434e-01, 9.908780432538649e-01, - 9.910763016962206e-01, 9.912885401035934e-01, 9.915156019790364e-01, - 9.917556658638569e-01, 9.920094690635668e-01, 9.922751554325331e-01, - 9.925534864640656e-01, 9.928426927501408e-01, 9.931435333387140e-01, - 9.934540796611835e-01, 9.937750666306635e-01, 9.941046890713076e-01, - 9.944437415635388e-01, 9.947903979828719e-01, 9.951453611435701e-01, - 9.955067995758305e-01, 9.958755336221258e-01, 9.962496814968456e-01, - 9.966299185765186e-01, 9.970143670156726e-01, 9.974037994063020e-01, - 9.977964044701016e-01, 9.981928706842119e-01, 9.985912855613679e-01, - 9.989924362978263e-01, 9.993945064762333e-01, 9.997982470741876e-01, - 1.000201793638269e+00, 1.000605860368296e+00, 1.001008579910682e+00, - 1.001410701714506e+00, 1.001810400944408e+00, 1.002208462087081e+00, - 1.002602958395831e+00, 1.002994573682287e+00, 1.003381477277237e+00, - 1.003764436338408e+00, 1.004141548053574e+00, 1.004513480396200e+00, - 1.004878321344784e+00, 1.005236884099094e+00, 1.005587302935534e+00, - 1.005930271724399e+00, 1.006263925890636e+00, 1.006589051746658e+00, - 1.006903802351948e+00, 1.007208903587772e+00, 1.007502380110983e+00, - 1.007784982346051e+00, 1.008054893814649e+00, 1.008312868199207e+00, - 1.008556999006399e+00, 1.008788016348394e+00, 1.009004047709048e+00, - 1.009205932867561e+00, 1.009391822060050e+00, 1.009562440424896e+00, - 1.009715896739930e+00, 1.009852958217732e+00, 1.009971774079105e+00, - 1.010073169648632e+00, 1.010155293011166e+00, 1.010218932642345e+00, - 1.010262246288524e+00, 1.010286018304889e+00, 1.010288415013601e+00, - 1.010270296641665e+00, 1.010229878703309e+00, 1.010168022758243e+00, - 1.010082924574326e+00, 1.009975407736885e+00, 1.009843687123529e+00, - 1.009688632854747e+00, 1.009508455280294e+00, 1.009304044596942e+00, - 1.009073713509976e+00, 1.008818483155921e+00, 1.008536750845889e+00, - 1.008229467503460e+00, 1.007894884001199e+00, 1.007533913863759e+00, - 1.007144877861525e+00, 1.006728757854175e+00, 1.006283927891016e+00, - 1.005811456284196e+00, 1.005309913983530e+00, 1.004780527277797e+00, - 1.004221766054862e+00, 1.003634560818982e+00, 1.003017190938855e+00, - 1.002370673225852e+00, 1.001693634792953e+00, 1.000987488105603e+00, - 1.000251075456674e+00, 9.994856628696702e-01, 9.986895923896904e-01, - 9.978636664333774e-01, 9.970063702291652e-01, 9.961191991291183e-01, - 9.952014038559622e-01, 9.942546868773952e-01, 9.932775951012806e-01, - 9.922706506028359e-01, 9.912319673936767e-01, 9.901632857185525e-01, - 9.890643935223216e-01, 9.879371153343368e-01, 9.867797361083076e-01, - 9.855927730842358e-01, 9.843751246861034e-01, 9.831292878900623e-01, - 9.813484629113276e-01, 9.798909633127684e-01, 9.784004589849064e-01, - 9.768604354115724e-01, 9.752698788428587e-01, 9.736273532416118e-01, - 9.719313409832228e-01, 9.701804980040253e-01, 9.683726519652567e-01, - 9.665069522597068e-01, 9.645800268203277e-01, 9.625923175883123e-01, - 9.605409863432730e-01, 9.584255335155275e-01, 9.562443932750193e-01, - 9.539984159028931e-01, 9.516840138455831e-01, 9.493011853637791e-01, - 9.468468843298323e-01, 9.443202322315050e-01, 9.417184043233268e-01, - 9.390425796467096e-01, 9.362906241698766e-01, 9.334640497363101e-01, - 9.305608538768808e-01, 9.275805069442316e-01, 9.245195917195164e-01, - 9.213784714413848e-01, 9.181534137230349e-01, 9.148446956130220e-01, - 9.114516516017124e-01, 9.079765240138057e-01, 9.044175450831859e-01, - 9.007763077278617e-01, 8.970500584793123e-01, 8.932383978549314e-01, - 8.893386805647778e-01, 8.853513603848177e-01, 8.812740229566767e-01, - 8.771096379139661e-01, 8.728579265043998e-01, 8.685195050926551e-01, - 8.640927964490425e-01, 8.595798186504622e-01, 8.549760065595760e-01, - 8.502852201263446e-01, 8.455026150386550e-01, 8.406304703204051e-01, - 8.356679254927833e-01, 8.306199433014801e-01, 8.254820069905587e-01, - 8.202589087059164e-01, 8.149466481575340e-01, 8.095466959213909e-01, - 8.040599778581757e-01, 7.984893775294406e-01, 7.928314173180783e-01, - 7.870906681120101e-01, 7.812624496601451e-01, 7.753539468965313e-01, - 7.693636129738075e-01, 7.632917692550881e-01, 7.571390164385375e-01, - 7.509017111797436e-01, 7.445908434203883e-01, 7.382051359832217e-01, - 7.317380750199757e-01, 7.251992870809165e-01, 7.185882252895927e-01, - 7.119056866892599e-01, 7.051536683608545e-01, 6.983326341551366e-01, - 6.914441012238667e-01, 6.844905446038185e-01, 6.774701192768717e-01, - 6.703883753752553e-01, 6.632452099313783e-01, 6.560457800753937e-01, - 6.487886269109083e-01, 6.414771616618185e-01, 6.341143226974428e-01, - 6.267020002885999e-01, 6.192353336355413e-01, 6.117205957668128e-01, - 6.041616120083719e-01, 5.965591325427860e-01, 5.889144007425270e-01, - 5.812347834141942e-01, 5.735199893648143e-01, 5.657706158383411e-01, - 5.579880671567978e-01, 5.501738510234542e-01, 5.423301939386325e-01, - 5.344607980557825e-01, 5.265685382300127e-01, 5.186563241060174e-01, - 5.107288126105302e-01, 5.027811586638018e-01, 4.948194909906872e-01, - 4.868451392486417e-01, 4.788608890561871e-01, 4.708699282370115e-01, - 4.628751440565413e-01, 4.548778943490807e-01, 4.468825120278060e-01, - 4.388893249911809e-01, 4.308981228989757e-01, 4.229183223777856e-01, - 4.149508779761170e-01, 4.069939642056243e-01, 3.990526483957498e-01, - 3.911346135115557e-01, 3.832340305827807e-01, 3.753546526584436e-01, - 3.675020596488621e-01, 3.596800983344559e-01, 3.518873119772211e-01, - 3.441301658282572e-01, 3.364081000913025e-01, 3.287289661673846e-01, - 3.210905051632958e-01, 3.134964181526467e-01, 3.059515649397201e-01, - 2.984543187240678e-01, 2.910105654938703e-01, 2.836211093775042e-01, - 2.762854150573731e-01, 2.690195851087454e-01, 2.618124452057962e-01, - 2.546592323719683e-01, 2.475843475618672e-01, 2.405786941912602e-01, - 2.336470086662776e-01, 2.267884333851989e-01, 2.200019917678347e-01, - 2.133013251703927e-01, 2.066777706538484e-01, 2.001404091043453e-01, - 1.936836302775967e-01, 1.873103432384193e-01, 1.810273838836248e-01, - 1.748394760623094e-01, 1.687396441250690e-01, 1.627372734819174e-01, - 1.568252770506826e-01, 1.510123820588976e-01, 1.452982295367473e-01, - 1.396874693829809e-01, 1.341718422797088e-01, 1.287625441360194e-01, - 1.234555620731477e-01, 1.182546623256352e-01, 1.131596767663045e-01, - 1.081714392735899e-01, 1.032907339774594e-01, 9.852029779063426e-02, - 9.386000226048140e-02, 8.931173602725516e-02, 8.487521028829931e-02, - 8.055237373221881e-02, 7.634297866041770e-02, 7.224892456088809e-02, - 6.826991195487858e-02, 6.440772914585895e-02, 6.066200028414472e-02, - 5.703437111472432e-02, 5.352437147393933e-02, 5.013346896851077e-02, - 4.686107896077298e-02, 4.370844528199226e-02, 4.067483652594974e-02, - 3.776122690656316e-02, 3.496670991534084e-02, 3.229192748331241e-02, - 2.973576687031024e-02, 2.729846292648297e-02, 2.497871856111264e-02, - 2.277625418320712e-02, 2.068958080348780e-02, 1.871781693470649e-02, - 1.685934175287805e-02, 1.511251252352758e-02, 1.347570944951177e-02, - 1.194627091218482e-02, 1.052287538118900e-02, 9.201309412840026e-03, - 7.981243163732707e-03, 6.855473143120775e-03, 5.826573343851640e-03, - 4.878385254226555e-03, 4.023511190940970e-03, 3.154186627586960e-03, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00, - 0.000000000000000e+00, 0.000000000000000e+00, 0.000000000000000e+00}; diff --git a/system/embdrv/lc3_dec/Common/Tables/MdctWindows.hpp b/system/embdrv/lc3_dec/Common/Tables/MdctWindows.hpp deleted file mode 100644 index 8b6bcc6a5b..0000000000 --- a/system/embdrv/lc3_dec/Common/Tables/MdctWindows.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * MdctWindows.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef MDCT_WINDOWS_H_ -#define MDCT_WINDOWS_H_ - -// LC3 Specification d09r01.pdf -// Section 5.7.2 - -// LC3 Specification d09r04_*implementorComments* -// Section 3.7.3 Low delay MDCT windows -// Section 3.7.3.1 10 ms Frame Duration - -extern double w_N80[160]; -extern double w_N160[320]; -extern double w_N240[480]; -extern double w_N320[640]; -extern double w_N480[960]; - -// Section 3.7.3.2 7.5 ms Frame Duration - -extern double w_N60_7p5ms[120]; -extern double w_N120_7p5ms[240]; -extern double w_N180_7p5ms[360]; -extern double w_N240_7p5ms[480]; -extern double w_N360_7p5ms[720]; - -#endif // MDCT_WINDOWS_H_ diff --git a/system/embdrv/lc3_dec/Common/Tables/SnsQuantizationTables.cpp b/system/embdrv/lc3_dec/Common/Tables/SnsQuantizationTables.cpp deleted file mode 100644 index 55b3462cda..0000000000 --- a/system/embdrv/lc3_dec/Common/Tables/SnsQuantizationTables.cpp +++ /dev/null @@ -1,363 +0,0 @@ -/* - * SnsQuantizationTables.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -// LC3 Specification d09r01.pdf -// Section 5.7.3 SNS Quantization - -// LC3 Specification d09r04_*implementorComments* -// Section 3.7.4 SNS Quantization - -#include "SnsQuantizationTables.hpp" - -// LC3 Specification d09r01.pdf; Page 102 of 177 -double LFCB[32][8] = { - {+2.262833655926780e+00, +8.133112690613385e-01, -5.301934948714359e-01, - -1.356648359034418e+00, -1.599521765631959e+00, -1.440987684300950e+00, - -1.143816483058210e+00, -7.552037679090641e-01}, // 0 - {+2.945164791913764e+00, +2.411433179566788e+00, +9.604551064007274e-01, - -4.432264880769172e-01, -1.229136124255896e+00, -1.555900391181699e+00, - -1.496886559523759e+00, -1.116899865014692e+00}, // 1 - {-2.186107070099790e+00, -1.971521356752276e+00, -1.787186196810059e+00, - -1.918658956855768e+00, -1.793991218365963e+00, -1.357384042572884e+00, - -7.054442793538694e-01, -4.781729447777114e-02}, // 2 - {+6.936882365289195e-01, +9.556098571582197e-01, +5.752307870387333e-01, - -1.146034194628886e-01, -6.460506374360290e-01, -9.523513704496247e-01, - -1.074052472261504e+00, -7.580877070949045e-01}, // 3 - {-1.297521323152956e+00, -7.403690571778526e-01, -3.453724836421064e-01, - -3.132856962479401e-01, -4.029772428244766e-01, -3.720208534652272e-01, - -7.834141773237381e-02, +9.704413039922949e-02}, // 4 - {+9.146520378306716e-01, +1.742930434352573e+00, +1.909066268599861e+00, - +1.544084838426651e+00, +1.093449607614550e+00, +6.474795495182776e-01, - +3.617907524496421e-02, -2.970928071788889e-01}, // 5 - {-2.514288125789621e+00, -2.891752713843728e+00, -2.004506667594338e+00, - -7.509122739031269e-01, +4.412021049046914e-01, +1.201909876010087e+00, - +1.327428572572904e+00, +1.220490811409839e+00}, // 6 - {-9.221884048123851e-01, +6.324951414405520e-01, +1.087364312546411e+00, - +6.086286245358197e-01, +1.311745675473482e-01, -2.961491577437521e-01, - -2.070135165256287e-01, +1.349249166420795e-01}, // 7 - {+7.903222883692664e-01, +6.284012618761988e-01, +3.931179235404499e-01, - +4.800077108669007e-01, +4.478151380501427e-01, +2.097342145522343e-01, - +6.566919964280205e-03, -8.612423420618573e-02}, // 8 - // LC3 Specification d09r01.pdf; Page 103 of 177 - {+1.447755801787238e+00, +2.723999516749523e+00, +2.310832687375278e+00, - +9.350512695665294e-01, -2.747439113836877e-01, -9.020776968286019e-01, - -9.406815119454044e-01, -6.336970389743102e-01}, // 9 - {+7.933545264174744e-01, +1.439311855234535e-02, -5.678348447296789e-01, - -6.547604679167449e-01, -4.794589984757430e-01, -1.738946619028885e-01, - +6.801627055154381e-02, +2.951259483697938e-01}, // 10 - {+2.724253473850336e+00, +2.959475724048243e+00, +1.849535592684608e+00, - +5.632849223223643e-01, +1.399170881250724e-01, +3.596410933662221e-01, - +6.894613547745887e-01, +6.397901768331046e-01}, // 11 - {-5.308301983754000e-01, -2.126906828121638e-01, +5.766136283770966e-03, - +4.248714843837454e-01, +4.731289521586675e-01, +8.588941993212806e-01, - +1.191111608544352e+00, +9.961896696383581e-01}, // 12 - {+1.687284108450062e+00, +2.436145092376558e+00, +2.330194290782250e+00, - +1.779837778350905e+00, +1.444112953900818e+00, +1.519951770097301e+00, - +1.471993937504249e+00, +9.776824738917613e-01}, // 13 - {-2.951832728018580e+00, -1.593934967733454e+00, -1.099187728780224e-01, - +3.886090729192574e-01, +5.129326495175837e-01, +6.281125970634966e-01, - +8.226217964306339e-01, +8.758914246550805e-01}, // 14 - {+1.018783427856281e-01, +5.898573242289165e-01, +6.190476467934656e-01, - +1.267313138517963e+00, +2.419610477698038e+00, +2.251742525721865e+00, - +5.265370309912005e-01, -3.965915132279989e-01}, // 15 - {+2.682545754984259e+00, +1.327380108994199e+00, +1.301852738040482e-01, - -3.385330885113471e-01, -3.682192358996665e-01, -1.916899467159607e-01, - -1.547823771539079e-01, -2.342071777743923e-01}, // 16 - {+4.826979236804030e+00, +3.119478044924880e+00, +1.395136713851784e+00, - +2.502953159187215e-01, -3.936138393797931e-01, -6.434581730547007e-01, - -6.425707368569433e-01, -7.231932234440720e-01}, // 17 - {+8.784199364703349e-02, -5.695868402385010e-01, -1.145060156688110e+00, - -1.669684881725975e+00, -1.845344176036817e+00, -1.564680273288019e+00, - -1.117467590764198e+00, -5.339816633667862e-01}, // 18 - {+1.391023082043259e+00, +1.981464791994655e+00, +1.112657963887701e+00, - -2.201075094207434e-01, -7.749656115523655e-01, -5.940638741491173e-01, - +1.369376806289231e-01, +8.182428912643381e-01}, // 19 - {+3.845858938891820e-01, -1.605887855365100e-01, -5.393668095577095e-01, - -5.293090787898571e-01, +1.904335474379324e-01, +2.560629181065215e+00, - +2.818963982452484e+00, +6.566708756961611e-01}, // 20 - {+1.932273994417191e+00, +3.010301804120569e+00, +3.065438938262036e+00, - +2.501101608700079e+00, +1.930895929789344e+00, +5.721538109618367e-01, - -8.117417940810907e-01, -1.176418108619025e+00}, // 21 - {+1.750804628998837e-01, -7.505228322489846e-01, -1.039438933422309e+00, - -1.135775089376484e+00, -1.041979038374938e+00, -1.520600989933816e-02, - +2.070483917167066e+00, +3.429489180816891e+00}, // 22 - // LC3 Specification d09r01.pdf; Page 104 of 177 - {-1.188170202505555e+00, +3.667928736626364e-01, +1.309578304090959e+00, - +1.683306872804914e+00, +1.251009242251268e+00, +9.423757516286146e-01, - +8.262504833741330e-01, +4.399527411209563e-01}, // 23 - {+2.533222033270612e+00, +2.112746426959081e+00, +1.262884115020644e+00, - +7.615135124304274e-01, +5.221179379761699e-01, +1.186800697571213e-01, - -4.523468275073703e-01, -7.003524261611032e-01}, // 24 - {+3.998898374856063e+00, +4.079017514519560e+00, +2.822856611024964e+00, - +1.726072128495800e+00, +6.471443773486192e-01, -3.311485212172380e-01, - -8.840425708487493e-01, -1.126973406454781e+00}, // 25 - {+5.079025931863813e-01, +1.588384497895265e+00, +1.728990238692094e+00, - +1.006922302417256e+00, +3.771212318163816e-01, +4.763707668994976e-01, - +1.087547403721699e+00, +1.087562660992209e+00}, // 26 - {+3.168568251075689e+00, +3.258534581594065e+00, +2.422305913285988e+00, - +1.794460776432612e+00, +1.521779106530886e+00, +1.171967065376021e+00, - +4.893945969806952e-01, -6.227957157187685e-02}, // 27 - {+1.894147667317636e+00, +1.251086946092320e+00, +5.904512107206275e-01, - +6.083585832937136e-01, +8.781710100110816e-01, +1.119125109509496e+00, - +1.018576615503421e+00, +6.204538910117241e-01}, // 28 - {+9.488806045171881e-01, +2.132394392499823e+00, +2.723453503442780e+00, - +2.769860768665877e+00, +2.542869732549456e+00, +2.020462638250194e+00, - +8.300458594009102e-01, -2.755691738882634e-02}, // 29 - {-1.880267570456275e+00, -1.264310727587049e+00, +3.114249769686986e-01, - +1.836702103064300e+00, +2.256341918398738e+00, +2.048189984634735e+00, - +2.195268374585677e+00, +2.026596138366193e+00}, // 30 - {+2.463757462771289e-01, +9.556217733930993e-01, +1.520467767417663e+00, - +1.976474004194571e+00, +1.940438671774617e+00, +2.233758472826862e+00, - +1.988359777584072e+00, +1.272326725547010e+00}}; // 31 -double HFCB[32][8] = { - {+2.320284191244650e-01, -1.008902706044547e+00, -2.142235027894714e+00, - -2.375338135706641e+00, -2.230419330496551e+00, -2.175958812236960e+00, - -2.290659135409999e+00, -2.532863979798455e+00}, // 0 - {-1.295039366736175e+00, -1.799299653843385e+00, -1.887031475315188e+00, - -1.809916596873323e+00, -1.763400384792061e+00, -1.834184284679500e+00, - -1.804809806874051e+00, -1.736795453174010e+00}, // 1 - {+1.392857160458027e-01, -2.581851261717519e-01, -6.508045726701103e-01, - -1.068157317819692e+00, -1.619287415243023e+00, -2.187625664417564e+00, - -2.637575869390537e+00, -2.978977495750963e+00}, // 2 - {-3.165131021857248e-01, -4.777476572098050e-01, -5.511620758797545e-01, - -4.847882833811970e-01, -2.383883944558142e-01, -1.430245072855038e-01, - +6.831866736490735e-02, +8.830617172880660e-02}, // 3 - {+8.795184052264962e-01, +2.983400960071886e-01, -9.153863964057101e-01, - // LC3 Specification d09r01.pdf; Page 105 of 177 - -2.206459747397620e+00, -2.741421809599509e+00, -2.861390742768913e+00, - -2.888415971052714e+00, -2.951826082625207e+00}, // 4 - {-2.967019224553751e-01, -9.750049191745525e-01, -1.358575002469926e+00, - -9.837211058374442e-01, -6.529569391008090e-01, -9.899869929218105e-01, - -1.614672245988999e+00, -2.407123023851163e+00}, // 5 - {+3.409811004696971e-01, +2.688997889460545e-01, +5.633356848280326e-02, - +4.991140468266853e-02, -9.541307274143691e-02, -7.601661460838854e-01, - -2.327581201770068e+00, -3.771554853856562e+00}, // 6 - {-1.412297590775968e+00, -1.485221193498518e+00, -1.186035798347001e+00, - -6.250016344413516e-01, +1.539024974683036e-01, +5.763864978107553e-01, - +7.950926037988714e-01, +5.965646321449126e-01}, // 7 - {-2.288395118273794e-01, -3.337190697846616e-01, -8.093213593246560e-01, - -1.635878769237973e+00, -1.884863973309819e+00, -1.644966913163562e+00, - -1.405157780466116e+00, -1.466664713261457e+00}, // 8 - {-1.071486285444486e+00, -1.417670154562606e+00, -1.548917622654407e+00, - -1.452960624755303e+00, -1.031829700622701e+00, -6.906426402725842e-01, - -4.288438045321706e-01, -4.949602154088736e-01}, // 9 - {-5.909885111880511e-01, -7.117377585376282e-02, +3.457195229473127e-01, - +3.005494609962507e-01, -1.118652182958568e+00, -2.440891511480490e+00, - -2.228547324507349e+00, -1.895092282108533e+00}, // 10 - {-8.484340988361639e-01, -5.832268107088888e-01, +9.004236881428734e-02, - +8.450250075568864e-01, +1.065723845017161e+00, +7.375829993777555e-01, - +2.565904524599121e-01, -4.919633597623784e-01}, // 11 - {+1.140691455623824e+00, +9.640168923982929e-01, +3.814612059847975e-01, - -4.828493406089983e-01, -1.816327212605887e+00, -2.802795127285548e+00, - -3.233857248338638e+00, -3.459087144914729e+00}, // 12 - {-3.762832379674643e-01, +4.256754620961052e-02, +5.165476965923055e-01, - +2.517168818646298e-01, -2.161799675243032e-01, -5.340740911245042e-01, - -6.407860962621957e-01, -8.697450323741350e-01}, // 13 - {+6.650041205984020e-01, +1.097907646907945e+00, +1.383426671120792e+00, - +1.343273586282854e+00, +8.229788368559223e-01, +2.158767985156789e-01, - -4.049257530802925e-01, -1.070256058705229e+00}, // 14 - {-8.262659539826793e-01, -6.711812327666034e-01, -2.284955927794715e-01, - +5.189808525519373e-01, +1.367218963402784e+00, +2.180230382530922e+00, - +2.535960927501071e+00, +2.201210988600361e+00}, // 15 - {+1.410083268321729e+00, +7.544419078354684e-01, -1.305505849586310e+00, - -1.871337113509707e+00, -1.240086851563054e+00, -1.267129248662737e+00, - -2.036708130039070e+00, -2.896851622423807e+00}, // 16 - {+3.613868175743476e-01, -2.199917054278258e-02, -5.793688336338242e-01, - -8.794279609410701e-01, -8.506850234081188e-01, -7.793970501558157e-01, - -7.321829272918255e-01, -8.883485148212548e-01}, // 17 - {+4.374692393303287e-01, +3.054404196059607e-01, -7.387865664783739e-03, - // LC3 Specification d09r01.pdf; Page 106 of 177 - -4.956498547102520e-01, -8.066512711183929e-01, -1.224318919844005e+00, - -1.701577700431810e+00, -2.244919137556108e+00}, // 18 - {+6.481003189965029e-01, +6.822991336406795e-01, +2.532474643329756e-01, - +7.358421437884688e-02, +3.142167093890103e-01, +2.347298809236790e-01, - +1.446001344798368e-01, -6.821201788801744e-02}, // 19 - {+1.119198330913041e+00, +1.234655325360046e+00, +5.891702380853181e-01, - -1.371924596531664e+00, -2.370957072415767e+00, -2.007797826823599e+00, - -1.666885402243946e+00, -1.926318462584058e+00}, // 20 - {+1.418474970871759e-01, -1.106600706331509e-01, -2.828245925436287e-01, - -6.598134746141936e-03, +2.859292796272158e-01, +4.604455299529710e-02, - -6.025964155778858e-01, -2.265687286325748e+00}, // 21 - {+5.040469553902519e-01, +8.269821629590972e-01, +1.119812362918282e+00, - +1.179140443327336e+00, +1.079874291972597e+00, +6.975362390675000e-01, - -9.125488173710808e-01, -3.576847470627726e+00}, // 22 - {-5.010760504793567e-01, -3.256780060814170e-01, +2.807981949470768e-02, - +2.620545547631326e-01, +3.605908060857668e-01, +6.356237220536995e-01, - +9.590124671781544e-01, +1.307451566886533e+00}, // 23 - {+3.749709827096420e+00, +1.523426118470452e+00, -4.577156618978547e-01, - -7.987110082431923e-01, -3.868193293091003e-01, -3.759010622312032e-01, - -6.578368999305377e-01, -1.281639642436027e+00}, // 24 - {-1.152589909805491e+00, -1.108008859062412e+00, -5.626151165124718e-01, - -2.205621237656746e-01, -3.498428803366437e-01, -7.534327702504950e-01, - -9.885965933963837e-01, -1.287904717914711e+00}, // 25 - {+1.028272464221398e+00, +1.097705193898282e+00, +7.686455457647760e-01, - +2.060819777407656e-01, -3.428057350919982e-01, -7.549394046253397e-01, - -1.041961776319998e+00, -1.503356529555287e+00}, // 26 - {+1.288319717078174e-01, +6.894393952648783e-01, +1.123469050095749e+00, - +1.309345231065936e+00, +1.355119647139345e+00, +1.423113814707990e+00, - +1.157064491909045e+00, +4.063194375168383e-01}, // 27 - {+1.340330303347565e+00, +1.389968250677893e+00, +1.044679217088833e+00, - +6.358227462443666e-01, -2.747337555184823e-01, -1.549233724306950e+00, - -2.442397102780069e+00, -3.024576069445502e+00}, // 28 - {+2.138431054193125e+00, +4.247112673031041e+00, +2.897341098304393e+00, - +9.327306580268148e-01, -2.928222497298096e-01, -8.104042968531823e-01, - -7.888680987564828e-01, -9.353531487613377e-01}, // 29 - {+5.648304873553961e-01, +1.591849779587432e+00, +2.397716990151462e+00, - +3.036973436007040e+00, +2.664243503371508e+00, +1.393044850326060e+00, - +4.038340235957454e-01, -6.562709713281135e-01}, // 30 - {-4.224605475860865e-01, +3.261496250498011e-01, +1.391713133422612e+00, - +2.231466146364735e+00, +2.611794421696881e+00, +2.665403401965702e+00, - +2.401035541057067e+00, +1.759203796708810e+00} // 31 -}; -// LC3 Specification d09r01.pdf; Page 107 of 177 -double sns_vq_reg_adj_gains[2] = {8915.0 / 4096.0, 12054.0 / 4096.0}; -double sns_vq_reg_lf_adj_gains[4] = {6245.0 / 4096.0, 15043.0 / 4096.0, - 17861.0 / 4096.0, 21014.0 / 4096.0}; -double sns_vq_near_adj_gains[4] = {7099.0 / 4096.0, 9132.0 / 4096.0, - 11253.0 / 4096.0, 14808.0 / 4096.0}; -double sns_vq_far_adj_gains[8] = { - 4336.0 / 4096.0, 5067.0 / 4096.0, 5895.0 / 4096.0, 8149.0 / 4096.0, - 10235.0 / 4096.0, 12825.0 / 4096.0, 16868.0 / 4096.0, 19882.0 / 4096.0}; -int sns_gainMSBbits[4] = {1, 1, 2, 2}; -int sns_gainLSBbits[4] = {0, 1, 0, 1}; -unsigned int MPVQ_offsets[16][1 + 10] = { - /* k=0, k=1, k=2,... , k=10 */ - {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* n=0*/ - {0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19}, /* n=1*/ - {0, 1, 5, 13, 25, 41, 61, 85, 113, 145, 181}, - {0, 1, 7, 25, 63, 129, 231, 377, 575, 833, 1159}, - {0, 1, 9, 41, 129, 321, 681, 1289, 2241, 3649, 5641}, - {0, 1, 11, 61, 231, 681, 1683, 3653, 7183, 13073, 22363}, - {0, 1, 13, 85, 377, 1289, 3653, 8989, 19825, 40081, 75517}, - {0, 1, 15, 113, 575, 2241, 7183, 19825, 48639, 108545, 224143}, - {0, 1, 17, 145, 833, 3649, 13073, 40081, 108545, 265729, 598417}, - {0, 1, 19, 181, 1159, 5641, 22363, 75517, 224143, 598417, 1462563}, - {0, 1, 21, 221, 1561, 8361, 36365, 134245, 433905, 1256465, 3317445}, - {0, 1, 23, 265, 2047, 11969, 56695, 227305, 795455, 2485825, 7059735}, - {0, 1, 25, 313, 2625, 16641, 85305, 369305, 1392065, 4673345, 14218905}, - {0, 1, 27, 365, 3303, 22569, 124515, 579125, 2340495, 8405905, 27298155}, - {0, 1, 29, 421, 4089, 29961, 177045, 880685, 3800305, 14546705, - 50250765}, /* n=14*/ - {0, 1, 31, 481, 4991, 39041, 246047, 1303777, 5984767, 24331777, - 89129247}, /* n=15*/ -}; -double D[16][16] = { - /* D consists of the base vectors of the DCT (orthogonalized DCT-II)*/ - /* (the DCT base vector are stored in column-wise in this table)*/ - /* first row results in the first coeff in fwd synthesis (dec+(enc))*/ - /* first column results in the first coeff in the analysis(encoder) */ - {+2.500000000000000e-01, +3.518509343815957e-01, +3.467599613305369e-01, - +3.383295002935882e-01, +3.266407412190941e-01, +3.118062532466678e-01, - +2.939689006048397e-01, +2.733004667504394e-01, +2.500000000000001e-01, - +2.242918965856591e-01, +1.964237395967756e-01, +1.666639146194367e-01, - +1.352990250365493e-01, +1.026311318805893e-01, +6.897484482073578e-02, - +3.465429229977293e-02}, // 0 Note: needed a ',' as correction compared to - // d09r01 (already fixed in d09r02_F2F) - {+2.500000000000000e-01, +3.383295002935882e-01, +2.939689006048397e-01, - +2.242918965856591e-01, +1.352990250365493e-01, +3.465429229977286e-02, - -6.897484482073579e-02, -1.666639146194366e-01, -2.500000000000001e-01, - -3.118062532466678e-01, -3.467599613305369e-01, -3.518509343815956e-01, - -3.266407412190941e-01, -2.733004667504394e-01, -1.964237395967756e-01, - -1.026311318805893e-01}, // 1 - // LC3 Specification d09r01.pdf; Page 108 of 177 - {+2.500000000000000e-01, +3.118062532466678e-01, +1.964237395967756e-01, - +3.465429229977286e-02, -1.352990250365493e-01, -2.733004667504394e-01, - -3.467599613305369e-01, -3.383295002935882e-01, -2.500000000000001e-01, - -1.026311318805894e-01, +6.897484482073574e-02, +2.242918965856590e-01, - +3.266407412190941e-01, +3.518509343815957e-01, +2.939689006048397e-01, - +1.666639146194367e-01}, // 2 - {+2.500000000000000e-01, +2.733004667504394e-01, +6.897484482073575e-02, - -1.666639146194366e-01, -3.266407412190941e-01, -3.383295002935882e-01, - -1.964237395967755e-01, +3.465429229977288e-02, +2.500000000000001e-01, - +3.518509343815957e-01, +2.939689006048397e-01, +1.026311318805893e-01, - -1.352990250365493e-01, -3.118062532466679e-01, -3.467599613305369e-01, - -2.242918965856590e-01}, // 3 - {+2.500000000000000e-01, +2.242918965856591e-01, -6.897484482073575e-02, - -3.118062532466678e-01, -3.266407412190941e-01, -1.026311318805894e-01, - +1.964237395967755e-01, +3.518509343815957e-01, +2.500000000000001e-01, - -3.465429229977282e-02, -2.939689006048397e-01, -3.383295002935882e-01, - -1.352990250365493e-01, +1.666639146194367e-01, +3.467599613305369e-01, - +2.733004667504394e-01}, // 4 - {+2.500000000000000e-01, +1.666639146194366e-01, -1.964237395967756e-01, - -3.518509343815956e-01, -1.352990250365493e-01, +2.242918965856591e-01, - +3.467599613305369e-01, +1.026311318805894e-01, -2.500000000000001e-01, - -3.383295002935882e-01, -6.897484482073574e-02, +2.733004667504394e-01, - +3.266407412190941e-01, +3.465429229977289e-02, -2.939689006048397e-01, - -3.118062532466677e-01}, // 5 - {+2.500000000000000e-01, +1.026311318805894e-01, -2.939689006048397e-01, - -2.733004667504393e-01, +1.352990250365493e-01, +3.518509343815957e-01, - +6.897484482073579e-02, -3.118062532466678e-01, -2.500000000000001e-01, - +1.666639146194366e-01, +3.467599613305369e-01, +3.465429229977293e-02, - -3.266407412190941e-01, -2.242918965856591e-01, +1.964237395967756e-01, - +3.383295002935882e-01}, // 6 - {+2.500000000000000e-01, +3.465429229977287e-02, -3.467599613305369e-01, - -1.026311318805893e-01, +3.266407412190941e-01, +1.666639146194366e-01, - -2.939689006048397e-01, -2.242918965856591e-01, +2.500000000000001e-01, - +2.733004667504393e-01, -1.964237395967756e-01, -3.118062532466678e-01, - +1.352990250365493e-01, +3.383295002935882e-01, -6.897484482073578e-02, - -3.518509343815956e-01}, // 7 - {+2.500000000000000e-01, -3.465429229977287e-02, -3.467599613305369e-01, - +1.026311318805893e-01, +3.266407412190941e-01, -1.666639146194366e-01, - -2.939689006048397e-01, +2.242918965856591e-01, +2.500000000000001e-01, - -2.733004667504393e-01, -1.964237395967756e-01, +3.118062532466678e-01, - +1.352990250365493e-01, -3.383295002935882e-01, -6.897484482073578e-02, - +3.518509343815956e-01}, // 8 - {+2.500000000000000e-01, -1.026311318805894e-01, -2.939689006048397e-01, - +2.733004667504393e-01, +1.352990250365493e-01, -3.518509343815957e-01, - +6.897484482073579e-02, +3.118062532466678e-01, -2.500000000000001e-01, - -1.666639146194366e-01, +3.467599613305369e-01, -3.465429229977293e-02, - -3.266407412190941e-01, +2.242918965856591e-01, +1.964237395967756e-01, - -3.383295002935882e-01}, // 9 - // LC3 Specification d09r01.pdf; Page 109 of 177 - {+2.500000000000000e-01, -1.666639146194366e-01, -1.964237395967756e-01, - +3.518509343815956e-01, -1.352990250365493e-01, -2.242918965856591e-01, - +3.467599613305369e-01, -1.026311318805894e-01, -2.500000000000001e-01, - +3.383295002935882e-01, -6.897484482073574e-02, -2.733004667504394e-01, - +3.266407412190941e-01, -3.465429229977289e-02, -2.939689006048397e-01, - +3.118062532466677e-01}, // 10 - {+2.500000000000000e-01, -2.242918965856591e-01, -6.897484482073575e-02, - +3.118062532466678e-01, -3.266407412190941e-01, +1.026311318805894e-01, - +1.964237395967755e-01, -3.518509343815957e-01, +2.500000000000001e-01, - +3.465429229977282e-02, -2.939689006048397e-01, +3.383295002935882e-01, - -1.352990250365493e-01, -1.666639146194367e-01, +3.467599613305369e-01, - -2.733004667504394e-01}, // 11 - {+2.500000000000000e-01, -2.733004667504394e-01, +6.897484482073575e-02, - +1.666639146194366e-01, -3.266407412190941e-01, +3.383295002935882e-01, - -1.964237395967755e-01, -3.465429229977288e-02, +2.500000000000001e-01, - -3.518509343815957e-01, +2.939689006048397e-01, -1.026311318805893e-01, - -1.352990250365493e-01, +3.118062532466679e-01, -3.467599613305369e-01, - +2.242918965856590e-01}, // 12 - {+2.500000000000000e-01, -3.118062532466678e-01, +1.964237395967756e-01, - -3.465429229977286e-02, -1.352990250365493e-01, +2.733004667504394e-01, - -3.467599613305369e-01, +3.383295002935882e-01, -2.500000000000001e-01, - +1.026311318805894e-01, +6.897484482073574e-02, -2.242918965856590e-01, - +3.266407412190941e-01, -3.518509343815957e-01, +2.939689006048397e-01, - -1.666639146194367e-01}, // 13 - {+2.500000000000000e-01, -3.383295002935882e-01, +2.939689006048397e-01, - -2.242918965856591e-01, +1.352990250365493e-01, -3.465429229977286e-02, - -6.897484482073579e-02, +1.666639146194366e-01, -2.500000000000001e-01, - +3.118062532466678e-01, -3.467599613305369e-01, +3.518509343815956e-01, - -3.266407412190941e-01, +2.733004667504394e-01, -1.964237395967756e-01, - +1.026311318805893e-01}, // 14 - {+2.500000000000000e-01, -3.518509343815957e-01, +3.467599613305369e-01, - -3.383295002935882e-01, +3.266407412190941e-01, -3.118062532466678e-01, - +2.939689006048397e-01, -2.733004667504394e-01, +2.500000000000001e-01, - -2.242918965856591e-01, +1.964237395967756e-01, -1.666639146194367e-01, - +1.352990250365493e-01, -1.026311318805893e-01, +6.897484482073578e-02, - -3.465429229977293e-02}}; // 15 diff --git a/system/embdrv/lc3_dec/Common/Tables/SnsQuantizationTables.hpp b/system/embdrv/lc3_dec/Common/Tables/SnsQuantizationTables.hpp deleted file mode 100644 index 2d447398ca..0000000000 --- a/system/embdrv/lc3_dec/Common/Tables/SnsQuantizationTables.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SnsQuantizationTables.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef SNS_QUANTIZATION_TABLES_H_ -#define SNS_QUANTIZATION_TABLES_H_ - -// LC3 Specification d09r01.pdf -// Section 5.7.3 SNS Quantization - -// LC3 Specification d09r04_*implementorComments* -// Section 3.7.4 SNS Quantization - -extern double LFCB[32][8]; -extern double HFCB[32][8]; -extern double sns_vq_reg_adj_gains[2]; -extern double sns_vq_reg_lf_adj_gains[4]; -extern double sns_vq_near_adj_gains[4]; -extern double sns_vq_far_adj_gains[8]; -extern int sns_gainMSBbits[4]; -extern int sns_gainLSBbits[4]; -extern unsigned int MPVQ_offsets[16][1 + 10]; -extern double D[16][16]; - -#endif // SNS_QUANTIZATION_TABLES_H_ diff --git a/system/embdrv/lc3_dec/Common/Tables/SpectralDataTables.cpp b/system/embdrv/lc3_dec/Common/Tables/SpectralDataTables.cpp deleted file mode 100644 index 2ed6b15257..0000000000 --- a/system/embdrv/lc3_dec/Common/Tables/SpectralDataTables.cpp +++ /dev/null @@ -1,706 +0,0 @@ -/* - * SpectralDataTables.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -// LC3 Specification d09r01.pdf -// Section 5.7.6 Spectral data -#include "SpectralDataTables.hpp" - -// LC3 Specification d09r01.pdf; Page 114 of 177 -unsigned char ac_spec_lookup[4096] = { - 0x01, 0x27, 0x07, 0x19, 0x16, 0x16, 0x1C, 0x16, 0x16, 0x16, 0x16, 0x1C, - 0x1C, 0x1C, 0x22, 0x1F, 0x1F, 0x28, 0x2B, 0x2E, 0x31, 0x34, 0x0E, 0x11, - 0x24, 0x24, 0x24, 0x26, 0x00, 0x39, 0x26, 0x16, 0x00, 0x08, 0x09, 0x0B, - 0x2F, 0x0E, 0x0E, 0x11, - // LC3 Specification d09r01.pdf; Page 115 of 177 - 0x24, 0x24, 0x24, 0x26, 0x3B, 0x3B, 0x26, 0x16, 0x16, 0x1A, 0x2E, 0x1D, - 0x1E, 0x20, 0x21, 0x23, 0x24, 0x24, 0x24, 0x26, 0x00, 0x3B, 0x17, 0x16, - 0x2E, 0x2E, 0x2D, 0x2F, 0x30, 0x32, 0x32, 0x12, 0x36, 0x36, 0x36, 0x26, - 0x3B, 0x3B, 0x3B, 0x16, 0x00, 0x3E, 0x3F, 0x03, 0x21, 0x02, 0x02, 0x3D, - 0x14, 0x14, 0x14, 0x15, 0x3B, 0x3B, 0x27, 0x1C, 0x1C, 0x3F, 0x3F, 0x03, - 0x21, 0x02, 0x02, 0x3D, 0x26, 0x26, 0x26, 0x15, 0x3B, 0x3B, 0x27, 0x1C, - 0x1C, 0x06, 0x06, 0x06, 0x02, 0x12, 0x3D, 0x14, 0x15, 0x15, 0x15, 0x3B, - 0x27, 0x27, 0x07, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x33, 0x33, 0x33, - 0x35, 0x36, 0x14, 0x26, 0x26, 0x39, 0x27, 0x27, 0x27, 0x07, 0x18, 0x22, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x38, 0x26, 0x39, - 0x39, 0x3B, 0x07, 0x07, 0x07, 0x2A, 0x2A, 0x22, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x05, 0x04, 0x04, 0x05, 0x15, 0x15, 0x3B, 0x07, 0x07, 0x07, 0x07, - 0x19, 0x19, 0x19, 0x22, 0x04, 0x04, 0x04, 0x04, 0x05, 0x17, 0x17, 0x27, - 0x07, 0x07, 0x07, 0x2A, 0x19, 0x19, 0x16, 0x1F, 0x1F, 0x27, 0x27, 0x27, - 0x27, 0x07, 0x07, 0x2A, 0x00, 0x19, 0x16, 0x16, 0x16, 0x1C, 0x22, 0x1F, - 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, - 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x28, 0x08, 0x09, 0x31, 0x31, 0x34, - 0x11, 0x11, 0x11, 0x04, 0x00, 0x14, 0x11, 0x3C, 0x28, 0x28, 0x08, 0x2B, - 0x1B, 0x31, 0x31, 0x0E, 0x11, 0x11, 0x11, 0x24, 0x2A, 0x2A, 0x11, 0x39, - 0x39, 0x28, 0x08, 0x1A, 0x1B, 0x31, 0x0C, 0x0E, 0x11, 0x11, 0x11, 0x24, - 0x00, 0x26, 0x24, 0x01, 0x08, 0x08, 0x2B, 0x09, 0x0B, 0x31, 0x0C, 0x0E, - 0x0E, 0x21, 0x32, 0x32, 0x32, 0x3D, 0x24, 0x27, 0x08, 0x08, 0x2B, 0x2E, - 0x31, 0x34, 0x1E, 0x0E, 0x0E, 0x21, 0x32, 0x32, 0x32, 0x32, 0x12, 0x19, - 0x08, 0x08, 0x2B, 0x2E, 0x31, 0x34, 0x1E, 0x0E, 0x0E, 0x12, 0x05, 0x05, - 0x05, 0x3D, 0x12, 0x17, 0x2B, 0x2B, 0x2B, 0x09, 0x31, 0x34, 0x03, 0x0E, - 0x0E, 0x32, 0x32, 0x32, 0x32, 0x3D, 0x11, 0x18, 0x2B, 0x2B, 0x2B, 0x2B, - 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, - 0x2B, 0x2B, 0x2B, 0x09, 0x0B, 0x34, 0x34, 0x0E, 0x0E, 0x11, 0x3D, 0x3D, - 0x3D, 0x36, 0x11, 0x27, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, - 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2C, 0x1B, - 0x1D, 0x34, 0x30, 0x34, 0x34, 0x11, 0x11, 0x11, 0x11, 0x02, 0x11, 0x07, - 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, - 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x09, 0x1B, 0x1B, 0x0C, 0x34, 0x0E, - 0x0E, 0x3A, 0x29, 0x29, 0x29, 0x06, 0x11, 0x25, 0x09, 0x09, 0x09, 0x1B, - 0x0B, 0x31, 0x0C, 0x34, - // LC3 Specification d09r01.pdf; Page 116 of 177 - 0x0E, 0x0E, 0x0E, 0x32, 0x00, 0x35, 0x11, 0x1C, 0x34, 0x34, 0x31, 0x34, - 0x0C, 0x34, 0x1E, 0x0E, 0x0E, 0x11, 0x02, 0x02, 0x02, 0x26, 0x26, 0x22, - 0x1F, 0x22, 0x22, 0x1F, 0x1F, 0x1F, 0x1F, 0x13, 0x13, 0x13, 0x13, 0x13, - 0x13, 0x13, 0x1F, 0x13, 0x2C, 0x2C, 0x3E, 0x1E, 0x20, 0x3A, 0x23, 0x24, - 0x24, 0x26, 0x00, 0x3B, 0x07, 0x07, 0x27, 0x22, 0x22, 0x2D, 0x2F, 0x30, - 0x21, 0x23, 0x23, 0x24, 0x26, 0x26, 0x26, 0x3B, 0x07, 0x07, 0x27, 0x22, - 0x22, 0x3E, 0x1E, 0x0F, 0x32, 0x35, 0x35, 0x36, 0x15, 0x15, 0x15, 0x3B, - 0x07, 0x07, 0x07, 0x22, 0x1E, 0x1E, 0x30, 0x21, 0x3A, 0x12, 0x12, 0x38, - 0x17, 0x17, 0x17, 0x3B, 0x07, 0x07, 0x18, 0x22, 0x22, 0x06, 0x06, 0x3A, - 0x35, 0x36, 0x36, 0x15, 0x3B, 0x3B, 0x3B, 0x27, 0x07, 0x07, 0x2A, 0x22, - 0x06, 0x06, 0x21, 0x3A, 0x35, 0x36, 0x3D, 0x15, 0x3B, 0x3B, 0x3B, 0x27, - 0x07, 0x07, 0x2A, 0x22, 0x22, 0x33, 0x33, 0x35, 0x36, 0x38, 0x38, 0x39, - 0x27, 0x27, 0x27, 0x07, 0x2A, 0x2A, 0x19, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x04, 0x04, 0x04, 0x05, 0x17, 0x17, 0x27, 0x07, 0x07, 0x07, 0x2A, - 0x19, 0x19, 0x16, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x05, 0x05, 0x05, - 0x05, 0x39, 0x39, 0x27, 0x18, 0x18, 0x18, 0x2A, 0x16, 0x16, 0x1C, 0x1F, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x29, 0x29, 0x29, 0x29, 0x27, 0x27, 0x07, - 0x2A, 0x2A, 0x2A, 0x19, 0x1C, 0x1C, 0x1C, 0x1F, 0x1F, 0x29, 0x29, 0x29, - 0x29, 0x27, 0x27, 0x18, 0x19, 0x19, 0x19, 0x16, 0x1C, 0x1C, 0x22, 0x1F, - 0x1F, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x1C, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x1F, 0x13, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x0B, - 0x2F, 0x20, 0x32, 0x12, 0x12, 0x14, 0x15, 0x15, 0x15, 0x27, 0x3B, 0x22, - 0x1A, 0x1A, 0x1B, 0x1D, 0x1E, 0x21, 0x32, 0x12, 0x12, 0x14, 0x39, 0x39, - 0x39, 0x3B, 0x3B, 0x22, 0x1B, 0x1B, 0x0B, 0x0C, 0x30, 0x32, 0x3A, 0x3D, - 0x3D, 0x38, 0x39, 0x39, 0x39, 0x3B, 0x27, 0x22, 0x2D, 0x2D, 0x0C, 0x1E, - 0x20, 0x02, 0x02, 0x3D, 0x26, 0x26, 0x26, 0x39, 0x00, 0x3B, 0x27, 0x22, - 0x3F, 0x3F, 0x03, 0x20, 0x3A, 0x12, 0x12, 0x14, 0x15, 0x15, 0x15, 0x3B, - 0x27, 0x27, 0x07, 0x1F, 0x1F, 0x03, 0x03, 0x21, 0x3A, 0x12, 0x12, 0x14, - 0x15, 0x15, 0x15, 0x3B, 0x07, 0x07, 0x07, 0x1F, 0x06, 0x06, 0x33, 0x33, - 0x35, 0x36, 0x36, 0x26, 0x39, 0x39, 0x39, 0x27, 0x07, 0x07, 0x2A, 0x1F, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x33, 0x35, 0x35, 0x36, 0x38, 0x38, 0x39, - 0x3B, 0x3B, 0x3B, 0x07, 0x18, 0x18, 0x19, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x1F, 0x1F, - // LC3 Specification d09r01.pdf; Page 117 of 177 - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x04, 0x04, 0x04, - 0x36, 0x15, 0x15, 0x39, 0x27, 0x27, 0x27, 0x07, 0x2A, 0x2A, 0x16, 0x1F, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x05, 0x05, 0x05, 0x05, 0x17, 0x17, 0x3B, - 0x07, 0x07, 0x07, 0x2A, 0x16, 0x16, 0x1C, 0x1F, 0x1F, 0x04, 0x04, 0x04, - 0x05, 0x17, 0x17, 0x27, 0x18, 0x18, 0x18, 0x19, 0x1C, 0x1C, 0x22, 0x1F, - 0x1F, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x1C, 0x22, 0x22, 0x22, 0x1F, - 0x1F, 0x1F, 0x1F, 0x13, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x10, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0D, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x3C, - 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, - 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, - 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, - 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, - 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, - 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, - 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, - 0x0D, 0x0D, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, - 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0D, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - // LC3 Specification d09r01.pdf; Page 118 of 177 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x00, 0x0D, 0x3C, - 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, - 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x25, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x10, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x10, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x3C, 0x3C, 0x10, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x10, 0x3C, 0x3C, 0x3C, 0x3C, - 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x25, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - // LC3 Specification d09r01.pdf; Page 119 of 177 - 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x3C, 0x3C, 0x3C, 0x10, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x25, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - // LC3 Specification d09r01.pdf; Page 120 of 177 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0D, 0x0D, 0x0D, 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x0D, 0x0D, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, - 0x00, 0x00, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x0D, 0x0D, 0x0D, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, - 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, - 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - // LC3 Specification d09r01.pdf; Page 121 of 177 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x3C, 0x3C, 0x3C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0D, 0x0D, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x3C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x3C, - 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - // LC3 Specification d09r01.pdf; Page 122 of 177 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0D, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - // LC3 Specification d09r01.pdf; Page 123 of 177 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - // LC3 Specification d09r01.pdf; Page 124 of 177 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -short ac_spec_cumfreq[64][17] = { - {0, 1, 2, 177, 225, 226, 227, 336, 372, 543, 652, 699, 719, 768, 804, 824, - 834}, - {0, 18, 44, 61, 71, 98, 135, 159, 175, 197, 229, 251, 265, 282, 308, 328, - 341}, - {0, 71, 163, 212, 237, 318, 420, 481, 514, 556, 613, 652, 675, 697, 727, - 749, 764}, - {0, 160, 290, 336, 354, 475, 598, 653, 677, 722, 777, 808, 823, 842, 866, - 881, 890}, - {0, 71, 144, 177, 195, 266, 342, 385, 411, 445, 489, 519, 539, 559, 586, - 607, 622}, - {0, 48, 108, 140, 159, 217, 285, 327, 354, 385, 427, 457, 478, 497, 524, - 545, 561}, - {0, 138, 247, 290, 308, 419, 531, 584, 609, 655, 710, 742, 759, 780, 807, - 825, 836}, - {0, 16, 40, 62, 79, 103, 139, 170, 195, 215, 245, 270, 290, 305, 327, 346, - 362}, - {0, 579, 729, 741, 743, 897, 970, 980, 982, 996, 1007, 1010, 1011, 1014, - 1017, 1018, 1019}, - {0, 398, 582, 607, 612, 788, 902, 925, 931, 956, 979, 987, 990, 996, 1002, - 1005, 1007}, - {0, 13, 34, 52, 63, 83, 112, 134, 149, 163, 183, 199, 211, 221, 235, 247, - 257}, - {0, 281, 464, 501, 510, 681, 820, 857, 867, 902, 938, 953, 959, 968, 978, - 984, 987}, - {0, 198, 362, 408, 421, 575, 722, 773, 789, 832, 881, 905, 915, 928, 944, - 954, 959}, - {0, 1, 2, 95, 139, 140, 141, 213, 251, 337, 407, 450, 475, 515, 551, 576, - 592}, - {0, 133, 274, 338, 366, 483, 605, 664, 691, 730, 778, 807, 822, 837, 857, - 870, 878}, - {0, 128, 253, 302, 320, 443, 577, 636, 659, 708, 767, 799, 814, 833, 857, - 872, 881}, - {0, 1, 2, 25, 42, 43, 44, 67, 85, 105, 126, 144, 159, 174, 191, 205, 217}, - {0, 70, 166, 229, 267, 356, 468, 533, 569, 606, 653, 685, 705, 722, 745, - 762, 774}, - {0, 55, 130, 175, 200, 268, 358, 416, 449, 488, 542, 581, 606, 628, 659, - 683, 699}, - {0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}, - {0, 34, 85, 123, 147, 196, 265, 317, 352, 386, 433, 470, 497, 518, 549, 574, - 593}, - {0, 30, 73, 105, 127, 170, 229, 274, 305, 335, 377, 411, 436, 455, 483, 506, - 524}, - {0, 9, 24, 38, 51, 65, 87, 108, 126, 139, 159, 177, 193, 204, 221, 236, - 250}, - {0, 30, 74, 105, 125, 166, 224, 266, 294, 322, 361, 391, 413, 431, 457, 478, - 494}, - {0, 15, 38, 58, 73, 95, 128, 156, 178, 196, 222, 245, 263, 276, 296, 314, - 329}, - // LC3 Specification d09r01.pdf; Page 125 of 177 - {0, 11, 28, 44, 57, 74, 100, 123, 142, 157, 179, 199, 216, 228, 246, 262, - 276}, - {0, 448, 619, 639, 643, 821, 926, 944, 948, 971, 991, 998, 1000, 1005, 1010, - 1012, 1013}, - {0, 332, 520, 549, 555, 741, 874, 903, 910, 940, 970, 981, 985, 991, 998, - 1002, 1004}, - {0, 8, 21, 34, 45, 58, 78, 96, 112, 124, 141, 157, 170, 180, 194, 207, 219}, - {0, 239, 415, 457, 468, 631, 776, 820, 833, 872, 914, 933, 940, 951, 964, - 971, 975}, - {0, 165, 310, 359, 375, 513, 652, 707, 727, 774, 828, 856, 868, 884, 904, - 916, 923}, - {0, 3, 8, 13, 18, 23, 30, 37, 44, 48, 55, 62, 68, 72, 78, 84, 90}, - {0, 115, 237, 289, 311, 422, 547, 608, 635, 680, 737, 771, 788, 807, 832, - 849, 859}, - {0, 107, 221, 272, 293, 399, 521, 582, 610, 656, 714, 749, 767, 787, 813, - 831, 842}, - {0, 6, 16, 26, 35, 45, 60, 75, 89, 98, 112, 125, 137, 145, 157, 168, 178}, - {0, 72, 160, 210, 236, 320, 422, 482, 514, 555, 608, 644, 665, 685, 712, - 732, 745}, - {0, 45, 108, 153, 183, 244, 327, 385, 421, 455, 502, 536, 559, 578, 605, - 626, 641}, - {0, 1, 2, 9, 16, 17, 18, 26, 34, 40, 48, 55, 62, 68, 75, 82, 88}, - {0, 29, 73, 108, 132, 174, 236, 284, 318, 348, 391, 426, 452, 471, 500, 524, - 543}, - {0, 20, 51, 76, 93, 123, 166, 200, 225, 247, 279, 305, 326, 342, 365, 385, - 401}, - {0, 742, 845, 850, 851, 959, 997, 1001, 1002, 1009, 1014, 1016, 1017, 1019, - 1020, 1021, 1022}, - {0, 42, 94, 121, 137, 186, 244, 280, 303, 330, 366, 392, 410, 427, 451, 470, - 484}, - {0, 13, 33, 51, 66, 85, 114, 140, 161, 178, 203, 225, 243, 256, 275, 292, - 307}, - {0, 501, 670, 689, 693, 848, 936, 952, 956, 975, 991, 997, 999, 1004, 1008, - 1010, 1011}, - {0, 445, 581, 603, 609, 767, 865, 888, 895, 926, 954, 964, 968, 977, 986, - 991, 993}, - {0, 285, 442, 479, 489, 650, 779, 818, 830, 870, 912, 930, 937, 949, 963, - 971, 975}, - {0, 349, 528, 561, 569, 731, 852, 883, 892, 923, 953, 965, 970, 978, 987, - 992, 994}, - {0, 199, 355, 402, 417, 563, 700, 750, 767, 811, 860, 884, 894, 909, 926, - 936, 942}, - {0, 141, 275, 325, 343, 471, 606, 664, 686, 734, 791, 822, 836, 854, 877, - 891, 899}, - {0, 243, 437, 493, 510, 649, 775, 820, 836, 869, 905, 923, 931, 941, 953, - 960, 964}, - {0, 91, 197, 248, 271, 370, 487, 550, 580, 625, 684, 721, 741, 761, 788, - 807, 819}, - {0, 107, 201, 242, 262, 354, 451, 503, 531, 573, 626, 660, 680, 701, 730, - 751, 765}, - {0, 168, 339, 407, 432, 553, 676, 731, 755, 789, 830, 854, 866, 879, 895, - 906, 912}, - // LC3 Specification d09r01.pdf; Page 126 of 177 - {0, 67, 147, 191, 214, 290, 384, 441, 472, 513, 567, 604, 627, 648, 678, - 700, 715}, - {0, 46, 109, 148, 171, 229, 307, 359, 391, 427, 476, 513, 537, 558, 588, - 612, 629}, - {0, 848, 918, 920, 921, 996, 1012, 1013, 1014, 1016, 1017, 1018, 1019, 1020, - 1021, 1022, 1023}, - {0, 36, 88, 123, 145, 193, 260, 308, 340, 372, 417, 452, 476, 496, 525, 548, - 565}, - {0, 24, 61, 90, 110, 145, 196, 237, 266, 292, 330, 361, 385, 403, 430, 453, - 471}, - {0, 85, 182, 230, 253, 344, 454, 515, 545, 590, 648, 685, 706, 727, 756, - 776, 789}, - {0, 22, 55, 82, 102, 135, 183, 222, 252, 278, 315, 345, 368, 385, 410, 431, - 448}, - {0, 1, 2, 56, 89, 90, 91, 140, 172, 221, 268, 303, 328, 358, 388, 412, 430}, - {0, 45, 109, 152, 177, 239, 320, 376, 411, 448, 499, 537, 563, 585, 616, - 640, 658}, - {0, 247, 395, 433, 445, 599, 729, 771, 785, 829, 875, 896, 905, 920, 937, - 946, 951}, - {0, 231, 367, 408, 423, 557, 676, 723, 742, 786, 835, 860, 872, 889, 909, - 921, 928}}; -short ac_spec_freq[64][17] = { - {1, 1, 175, 48, 1, 1, 109, 36, 171, 109, 47, 20, 49, 36, 20, 10, 190}, - {18, 26, 17, 10, 27, 37, 24, 16, 22, 32, 22, 14, 17, 26, 20, 13, 683}, - {71, 92, 49, 25, 81, 102, 61, 33, 42, 57, 39, 23, 22, 30, 22, 15, 260}, - {160, 130, 46, 18, 121, 123, 55, 24, 45, 55, 31, 15, 19, 24, 15, 9, 134}, - {71, 73, 33, 18, 71, 76, 43, 26, 34, 44, 30, 20, 20, 27, 21, 15, 402}, - {48, 60, 32, 19, 58, 68, 42, 27, 31, 42, 30, 21, 19, 27, 21, 16, 463}, - {138, 109, 43, 18, 111, 112, 53, 25, 46, 55, 32, 17, 21, 27, 18, 11, 188}, - {16, 24, 22, 17, 24, 36, 31, 25, 20, 30, 25, 20, 15, 22, 19, 16, 662}, - {579, 150, 12, 2, 154, 73, 10, 2, 14, 11, 3, 1, 3, 3, 1, 1, 5}, - {398, 184, 25, 5, 176, 114, 23, 6, 25, 23, 8, 3, 6, 6, 3, 2, 17}, - {13, 21, 18, 11, 20, 29, 22, 15, 14, 20, 16, 12, 10, 14, 12, 10, 767}, - {281, 183, 37, 9, 171, 139, 37, 10, 35, 36, 15, 6, 9, 10, 6, 3, 37}, - {198, 164, 46, 13, 154, 147, 51, 16, 43, 49, 24, 10, 13, 16, 10, 5, 65}, - {1, 1, 93, 44, 1, 1, 72, 38, 86, 70, 43, 25, 40, 36, 25, 16, 432}, - {133, 141, 64, 28, 117, 122, 59, 27, 39, 48, 29, 15, 15, 20, 13, 8, 146}, - // LC3 Specification d09r01.pdf; Page 127 of 177 - {128, 125, 49, 18, 123, 134, 59, 23, 49, 59, 32, 15, 19, 24, 15, 9, 143}, - {1, 1, 23, 17, 1, 1, 23, 18, 20, 21, 18, 15, 15, 17, 14, 12, 807}, - {70, 96, 63, 38, 89, 112, 65, 36, 37, 47, 32, 20, 17, 23, 17, 12, 250}, - {55, 75, 45, 25, 68, 90, 58, 33, 39, 54, 39, 25, 22, 31, 24, 16, 325}, - {1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 993}, - {34, 51, 38, 24, 49, 69, 52, 35, 34, 47, 37, 27, 21, 31, 25, 19, 431}, - {30, 43, 32, 22, 43, 59, 45, 31, 30, 42, 34, 25, 19, 28, 23, 18, 500}, - {9, 15, 14, 13, 14, 22, 21, 18, 13, 20, 18, 16, 11, 17, 15, 14, 774}, - {30, 44, 31, 20, 41, 58, 42, 28, 28, 39, 30, 22, 18, 26, 21, 16, 530}, - {15, 23, 20, 15, 22, 33, 28, 22, 18, 26, 23, 18, 13, 20, 18, 15, 695}, - {11, 17, 16, 13, 17, 26, 23, 19, 15, 22, 20, 17, 12, 18, 16, 14, 748}, - {448, 171, 20, 4, 178, 105, 18, 4, 23, 20, 7, 2, 5, 5, 2, 1, 11}, - {332, 188, 29, 6, 186, 133, 29, 7, 30, 30, 11, 4, 6, 7, 4, 2, 20}, - {8, 13, 13, 11, 13, 20, 18, 16, 12, 17, 16, 13, 10, 14, 13, 12, 805}, - {239, 176, 42, 11, 163, 145, 44, 13, 39, 42, 19, 7, 11, 13, 7, 4, 49}, - {165, 145, 49, 16, 138, 139, 55, 20, 47, 54, 28, 12, 16, 20, 12, 7, 101}, - {3, 5, 5, 5, 5, 7, 7, 7, 4, 7, 7, 6, 4, 6, 6, 6, 934}, - {115, 122, 52, 22, 111, 125, 61, 27, 45, 57, 34, 17, 19, 25, 17, 10, 165}, - {107, 114, 51, 21, 106, 122, 61, 28, 46, 58, 35, 18, 20, 26, 18, 11, 182}, - {6, 10, 10, 9, 10, 15, 15, 14, 9, 14, 13, 12, 8, 12, 11, 10, 846}, - {72, 88, 50, 26, 84, 102, 60, 32, 41, 53, 36, 21, 20, 27, 20, 13, 279}, - {45, 63, 45, 30, 61, 83, 58, 36, 34, 47, 34, 23, 19, 27, 21, 15, 383}, - {1, 1, 7, 7, 1, 1, 8, 8, 6, 8, 7, 7, 6, 7, 7, 6, 936}, - {29, 44, 35, 24, 42, 62, 48, 34, 30, 43, 35, 26, 19, 29, 24, 19, 481}, - {20, 31, 25, 17, 30, 43, 34, 25, 22, 32, 26, 21, 16, 23, 20, 16, 623}, - {742, 103, 5, 1, 108, 38, 4, 1, 7, 5, 2, 1, 2, 1, 1, 1, 2}, - {42, 52, 27, 16, 49, 58, 36, 23, 27, 36, 26, 18, 17, 24, 19, 14, 540}, - {13, 20, 18, 15, 19, 29, 26, 21, 17, 25, 22, 18, 13, 19, 17, 15, 717}, - // LC3 Specification d09r01.pdf; Page 128 of 177 - {501, 169, 19, 4, 155, 88, 16, 4, 19, 16, 6, 2, 5, 4, 2, 1, 13}, - {445, 136, 22, 6, 158, 98, 23, 7, 31, 28, 10, 4, 9, 9, 5, 2, 31}, - {285, 157, 37, 10, 161, 129, 39, 12, 40, 42, 18, 7, 12, 14, 8, 4, 49}, - {349, 179, 33, 8, 162, 121, 31, 9, 31, 30, 12, 5, 8, 9, 5, 2, 30}, - {199, 156, 47, 15, 146, 137, 50, 17, 44, 49, 24, 10, 15, 17, 10, 6, 82}, - {141, 134, 50, 18, 128, 135, 58, 22, 48, 57, 31, 14, 18, 23, 14, 8, 125}, - {243, 194, 56, 17, 139, 126, 45, 16, 33, 36, 18, 8, 10, 12, 7, 4, 60}, - {91, 106, 51, 23, 99, 117, 63, 30, 45, 59, 37, 20, 20, 27, 19, 12, 205}, - {107, 94, 41, 20, 92, 97, 52, 28, 42, 53, 34, 20, 21, 29, 21, 14, 259}, - {168, 171, 68, 25, 121, 123, 55, 24, 34, 41, 24, 12, 13, 16, 11, 6, 112}, - {67, 80, 44, 23, 76, 94, 57, 31, 41, 54, 37, 23, 21, 30, 22, 15, 309}, - {46, 63, 39, 23, 58, 78, 52, 32, 36, 49, 37, 24, 21, 30, 24, 17, 395}, - {848, 70, 2, 1, 75, 16, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1}, - {36, 52, 35, 22, 48, 67, 48, 32, 32, 45, 35, 24, 20, 29, 23, 17, 459}, - {24, 37, 29, 20, 35, 51, 41, 29, 26, 38, 31, 24, 18, 27, 23, 18, 553}, - {85, 97, 48, 23, 91, 110, 61, 30, 45, 58, 37, 21, 21, 29, 20, 13, 235}, - {22, 33, 27, 20, 33, 48, 39, 30, 26, 37, 30, 23, 17, 25, 21, 17, 576}, - {1, 1, 54, 33, 1, 1, 49, 32, 49, 47, 35, 25, 30, 30, 24, 18, 594}, - {45, 64, 43, 25, 62, 81, 56, 35, 37, 51, 38, 26, 22, 31, 24, 18, 366}, - {247, 148, 38, 12, 154, 130, 42, 14, 44, 46, 21, 9, 15, 17, 9, 5, 73}, - {231, 136, 41, 15, 134, 119, 47, 19, 44, 49, 25, 12, 17, 20, 12, 7, 96}}; -short ac_spec_bits[64][17] = { - {20480, 20480, 5220, 9042, 20480, 20480, 6619, 9892, 5289, 6619, 9105, - 11629, 8982, 9892, 11629, 13677, 4977}, - {11940, 10854, 12109, 13677, 10742, 9812, 11090, 12288, 11348, 10240, 11348, - 12683, 12109, 10854, 11629, 12902, 1197}, - {7886, 7120, 8982, 10970, 7496, 6815, 8334, 10150, 9437, 8535, 9656, 11216, - 11348, 10431, 11348, 12479, 4051}, - {5485, 6099, 9168, 11940, 6311, 6262, 8640, 11090, 9233, 8640, 10334, 12479, - 11781, 11090, 12479, 13988, 6009}, - {7886, 7804, 10150, 11940, 7886, 7685, 9368, 10854, 10061, 9300, 10431, - 11629, 11629, 10742, 11485, 12479, 2763}, - // LC3 Specification d09r01.pdf; Page 129 of 177 - {9042, 8383, 10240, 11781, 8483, 8013, 9437, 10742, 10334, 9437, 10431, - 11485, 11781, 10742, 11485, 12288, 2346}, - {5922, 6619, 9368, 11940, 6566, 6539, 8750, 10970, 9168, 8640, 10240, 12109, - 11485, 10742, 11940, 13396, 5009}, - {12288, 11090, 11348, 12109, 11090, 9892, 10334, 10970, 11629, 10431, 10970, - 11629, 12479, 11348, 11781, 12288, 1289}, - {1685, 5676, 13138, 18432, 5598, 7804, 13677, 18432, 12683, 13396, 17234, - 20480, 17234, 17234, 20480, 20480, 15725}, - {2793, 5072, 10970, 15725, 5204, 6487, 11216, 15186, 10970, 11216, 14336, - 17234, 15186, 15186, 17234, 18432, 12109}, - {12902, 11485, 11940, 13396, 11629, 10531, 11348, 12479, 12683, 11629, - 12288, 13138, 13677, 12683, 13138, 13677, 854}, - {3821, 5088, 9812, 13988, 5289, 5901, 9812, 13677, 9976, 9892, 12479, 15186, - 13988, 13677, 15186, 17234, 9812}, - {4856, 5412, 9168, 12902, 5598, 5736, 8863, 12288, 9368, 8982, 11090, 13677, - 12902, 12288, 13677, 15725, 8147}, - {20480, 20480, 7088, 9300, 20480, 20480, 7844, 9733, 7320, 7928, 9368, - 10970, 9581, 9892, 10970, 12288, 2550}, - {6031, 5859, 8192, 10635, 6410, 6286, 8433, 10742, 9656, 9042, 10531, 12479, - 12479, 11629, 12902, 14336, 5756}, - {6144, 6215, 8982, 11940, 6262, 6009, 8433, 11216, 8982, 8433, 10240, 12479, - 11781, 11090, 12479, 13988, 5817}, - {20480, 20480, 11216, 12109, 20480, 20480, 11216, 11940, 11629, 11485, - 11940, 12479, 12479, 12109, 12683, 13138, 704}, - {7928, 6994, 8239, 9733, 7218, 6539, 8147, 9892, 9812, 9105, 10240, 11629, - 12109, 11216, 12109, 13138, 4167}, - {8640, 7724, 9233, 10970, 8013, 7185, 8483, 10150, 9656, 8694, 9656, 10970, - 11348, 10334, 11090, 12288, 3391}, - {20480, 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, - 18432, 18432, 18432, 18432, 18432, 18432, 91}, - {10061, 8863, 9733, 11090, 8982, 7970, 8806, 9976, 10061, 9105, 9812, 10742, - 11485, 10334, 10970, 11781, 2557}, - {10431, 9368, 10240, 11348, 9368, 8433, 9233, 10334, 10431, 9437, 10061, - 10970, 11781, 10635, 11216, 11940, 2119}, - {13988, 12479, 12683, 12902, 12683, 11348, 11485, 11940, 12902, 11629, - 11940, 12288, 13396, 12109, 12479, 12683, 828}, - {10431, 9300, 10334, 11629, 9508, 8483, 9437, 10635, 10635, 9656, 10431, - 11348, 11940, 10854, 11485, 12288, 1946}, - {12479, 11216, 11629, 12479, 11348, 10150, 10635, 11348, 11940, 10854, - 11216, 11940, 12902, 11629, 11940, 12479, 1146}, - {13396, 12109, 12288, 12902, 12109, 10854, 11216, 11781, 12479, 11348, - 11629, 12109, 13138, 11940, 12288, 12683, 928}, - {2443, 5289, 11629, 16384, 5170, 6730, 11940, 16384, 11216, 11629, 14731, - 18432, 15725, 15725, 18432, 20480, 13396}, - {3328, 5009, 10531, 15186, 5040, 6031, 10531, 14731, 10431, 10431, 13396, - 16384, 15186, 14731, 16384, 18432, 11629}, - {14336, 12902, 12902, 13396, 12902, 11629, 11940, 12288, 13138, 12109, - 12288, 12902, 13677, 12683, 12902, 13138, 711}, - // LC3 Specification d09r01.pdf; Page 130 of 177 - {4300, 5204, 9437, 13396, 5430, 5776, 9300, 12902, 9656, 9437, 11781, 14731, - 13396, 12902, 14731, 16384, 8982}, - {5394, 5776, 8982, 12288, 5922, 5901, 8640, 11629, 9105, 8694, 10635, 13138, - 12288, 11629, 13138, 14731, 6844}, - {17234, 15725, 15725, 15725, 15725, 14731, 14731, 14731, 16384, 14731, - 14731, 15186, 16384, 15186, 15186, 15186, 272}, - {6461, 6286, 8806, 11348, 6566, 6215, 8334, 10742, 9233, 8535, 10061, 12109, - 11781, 10970, 12109, 13677, 5394}, - {6674, 6487, 8863, 11485, 6702, 6286, 8334, 10635, 9168, 8483, 9976, 11940, - 11629, 10854, 11940, 13396, 5105}, - {15186, 13677, 13677, 13988, 13677, 12479, 12479, 12683, 13988, 12683, - 12902, 13138, 14336, 13138, 13396, 13677, 565}, - {7844, 7252, 8922, 10854, 7389, 6815, 8383, 10240, 9508, 8750, 9892, 11485, - 11629, 10742, 11629, 12902, 3842}, - {9233, 8239, 9233, 10431, 8334, 7424, 8483, 9892, 10061, 9105, 10061, 11216, - 11781, 10742, 11485, 12479, 2906}, - {20480, 20480, 14731, 14731, 20480, 20480, 14336, 14336, 15186, 14336, - 14731, 14731, 15186, 14731, 14731, 15186, 266}, - {10531, 9300, 9976, 11090, 9437, 8286, 9042, 10061, 10431, 9368, 9976, - 10854, 11781, 10531, 11090, 11781, 2233}, - {11629, 10334, 10970, 12109, 10431, 9368, 10061, 10970, 11348, 10240, 10854, - 11485, 12288, 11216, 11629, 12288, 1469}, - {952, 6787, 15725, 20480, 6646, 9733, 16384, 20480, 14731, 15725, 18432, - 20480, 18432, 20480, 20480, 20480, 18432}, - {9437, 8806, 10742, 12288, 8982, 8483, 9892, 11216, 10742, 9892, 10854, - 11940, 12109, 11090, 11781, 12683, 1891}, - {12902, 11629, 11940, 12479, 11781, 10531, 10854, 11485, 12109, 10970, - 11348, 11940, 12902, 11781, 12109, 12479, 1054}, - {2113, 5323, 11781, 16384, 5579, 7252, 12288, 16384, 11781, 12288, 15186, - 18432, 15725, 16384, 18432, 20480, 12902}, - {2463, 5965, 11348, 15186, 5522, 6934, 11216, 14731, 10334, 10635, 13677, - 16384, 13988, 13988, 15725, 18432, 10334}, - {3779, 5541, 9812, 13677, 5467, 6122, 9656, 13138, 9581, 9437, 11940, 14731, - 13138, 12683, 14336, 16384, 8982}, - {3181, 5154, 10150, 14336, 5448, 6311, 10334, 13988, 10334, 10431, 13138, - 15725, 14336, 13988, 15725, 18432, 10431}, - {4841, 5560, 9105, 12479, 5756, 5944, 8922, 12109, 9300, 8982, 11090, 13677, - 12479, 12109, 13677, 15186, 7460}, - {5859, 6009, 8922, 11940, 6144, 5987, 8483, 11348, 9042, 8535, 10334, 12683, - 11940, 11216, 12683, 14336, 6215}, - {4250, 4916, 8587, 12109, 5901, 6191, 9233, 12288, 10150, 9892, 11940, - 14336, 13677, 13138, 14731, 16384, 8383}, - {7153, 6702, 8863, 11216, 6904, 6410, 8239, 10431, 9233, 8433, 9812, 11629, - 11629, 10742, 11781, 13138, 4753}, - {6674, 7057, 9508, 11629, 7120, 6964, 8806, 10635, 9437, 8750, 10061, 11629, - 11485, 10531, 11485, 12683, 4062}, - {5341, 5289, 8013, 10970, 6311, 6262, 8640, 11090, 10061, 9508, 11090, - 13138, 12902, 12288, 13396, 15186, 6539}, - {8057, 7533, 9300, 11216, 7685, 7057, 8535, 10334, 9508, 8694, 9812, 11216, - 11485, 10431, 11348, 12479, 3541}, - {9168, 8239, 9656, 11216, 8483, 7608, 8806, 10240, 9892, 8982, 9812, 11090, - 11485, 10431, 11090, 12109, 2815}, - // LC3 Specification d09r01.pdf; Page 131 of 177 - {558, 7928, 18432, 20480, 7724, 12288, 20480, 20480, 18432, 20480, 20480, - 20480, 20480, 20480, 20480, 20480, 20480}, - {9892, 8806, 9976, 11348, 9042, 8057, 9042, 10240, 10240, 9233, 9976, 11090, - 11629, 10531, 11216, 12109, 2371}, - {11090, 9812, 10531, 11629, 9976, 8863, 9508, 10531, 10854, 9733, 10334, - 11090, 11940, 10742, 11216, 11940, 1821}, - {7354, 6964, 9042, 11216, 7153, 6592, 8334, 10431, 9233, 8483, 9812, 11485, - 11485, 10531, 11629, 12902, 4349}, - {11348, 10150, 10742, 11629, 10150, 9042, 9656, 10431, 10854, 9812, 10431, - 11216, 12109, 10970, 11485, 12109, 1700}, - {20480, 20480, 8694, 10150, 20480, 20480, 8982, 10240, 8982, 9105, 9976, - 10970, 10431, 10431, 11090, 11940, 1610}, - {9233, 8192, 9368, 10970, 8286, 7496, 8587, 9976, 9812, 8863, 9733, 10854, - 11348, 10334, 11090, 11940, 3040}, - {4202, 5716, 9733, 13138, 5598, 6099, 9437, 12683, 9300, 9168, 11485, 13988, - 12479, 12109, 13988, 15725, 7804}, - {4400, 5965, 9508, 12479, 6009, 6360, 9105, 11781, 9300, 8982, 10970, 13138, - 12109, 11629, 13138, 14731, 6994}}; diff --git a/system/embdrv/lc3_dec/Common/Tables/SpectralDataTables.hpp b/system/embdrv/lc3_dec/Common/Tables/SpectralDataTables.hpp deleted file mode 100644 index 6c031b6383..0000000000 --- a/system/embdrv/lc3_dec/Common/Tables/SpectralDataTables.hpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SpectralDataTables.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -// LC3 Specification d09r01.pdf -// Section 5.7.6 Spectral data - -#ifndef SPECTRAL_DATA_TABLES_H_ -#define SPECTRAL_DATA_TABLES_H_ - -extern unsigned char ac_spec_lookup[4096]; -extern short ac_spec_cumfreq[64][17]; -extern short ac_spec_freq[64][17]; -extern short ac_spec_bits[64][17]; - -#endif // SPECTRAL_DATA_TABLES_H_ diff --git a/system/embdrv/lc3_dec/Common/Tables/TemporalNoiseShapingTables.cpp b/system/embdrv/lc3_dec/Common/Tables/TemporalNoiseShapingTables.cpp deleted file mode 100644 index 4660663788..0000000000 --- a/system/embdrv/lc3_dec/Common/Tables/TemporalNoiseShapingTables.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * TemporalNoiseShapingTables.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -// LC3 Specification d09r01.pdf -// Section 5.7.4 Temporal Noise Shaping -#include "TemporalNoiseShapingTables.hpp" - -// LC3 Specification d09r01.pdf; Page 109 of 177 -short ac_tns_order_bits[2][8] = { - {17234, 13988, 11216, 8694, 6566, 4977, 3961, 3040}, - {12683, 9437, 6874, 5541, 5121, 5170, 5359, 5056}}; -short ac_tns_order_freq[2][8] = {{3, 9, 23, 54, 111, 190, 268, 366}, - {14, 42, 100, 157, 181, 178, 167, 185}}; -short ac_tns_order_cumfreq[2][8] = {{0, 3, 12, 35, 89, 200, 390, 658}, - {0, 14, 56, 156, 313, 494, 672, 839}}; -// LC3 Specification d09r01.pdf; Page 110 of 177 -short ac_tns_coef_bits[8][17] = { - {20480, 15725, 12479, 10334, 8694, 7320, 6964, 6335, 5504, 5637, 6566, 6758, - 8433, 11348, 15186, 20480, 20480}, - {20480, 20480, 20480, 20480, 12902, 9368, 7057, 5901, 5254, 5485, 5598, - 6076, 7608, 10742, 15186, 20480, 20480}, - {20480, 20480, 20480, 20480, 13988, 9368, 6702, 4841, 4585, 4682, 5859, - 7764, 12109, 20480, 20480, 20480, 20480}, - {20480, 20480, 20480, 20480, 18432, 13396, 8982, 4767, 3779, 3658, 6335, - 9656, 13988, 20480, 20480, 20480, 20480}, - {20480, 20480, 20480, 20480, 20480, 14731, 9437, 4275, 3249, 3493, 8483, - 13988, 17234, 20480, 20480, 20480, 20480}, - {20480, 20480, 20480, 20480, 20480, 20480, 12902, 4753, 3040, 2953, 9105, - 15725, 20480, 20480, 20480, 20480, 20480}, - {20480, 20480, 20480, 20480, 20480, 20480, 12902, 3821, 3346, 3000, 12109, - 20480, 20480, 20480, 20480, 20480, 20480}, - {20480, 20480, 20480, 20480, 20480, 20480, 15725, 3658, 20480, 1201, 10854, - 18432, 20480, 20480, 20480, 20480, 20480}}; -short ac_tns_coef_freq[8][17] = { - {1, 5, 15, 31, 54, 86, 97, 120, 159, 152, 111, 104, 59, 22, 6, 1, 1}, - {1, 1, 1, 1, 13, 43, 94, 139, 173, 160, 154, 131, 78, 27, 6, 1, 1}, - {1, 1, 1, 1, 9, 43, 106, 199, 217, 210, 141, 74, 17, 1, 1, 1, 1}, - {1, 1, 1, 1, 2, 11, 49, 204, 285, 297, 120, 39, 9, 1, 1, 1, 1}, - {1, 1, 1, 1, 1, 7, 42, 241, 341, 314, 58, 9, 3, 1, 1, 1, 1}, - {1, 1, 1, 1, 1, 1, 13, 205, 366, 377, 47, 5, 1, 1, 1, 1, 1}, - {1, 1, 1, 1, 1, 1, 13, 281, 330, 371, 17, 1, 1, 1, 1, 1, 1}, - {1, 1, 1, 1, 1, 1, 5, 297, 1, 682, 26, 2, 1, 1, 1, 1, 1}}; -short ac_tns_coef_cumfreq[8][17] = {{0, 1, 6, 21, 52, 106, 192, 289, 409, 568, - 720, 831, 935, 994, 1016, 1022, 1023}, - {0, 1, 2, 3, 4, 17, 60, 154, 293, 466, 626, - 780, 911, 989, 1016, 1022, 1023}, - {0, 1, 2, 3, 4, 13, 56, 162, 361, 578, 788, - 929, 1003, 1020, 1021, 1022, 1023}, - {0, 1, 2, 3, 4, 6, 17, 66, 270, 555, 852, - 972, 1011, 1020, 1021, 1022, 1023}, - {0, 1, 2, 3, 4, 5, 12, 54, 295, 636, 950, - 1008, 1017, 1020, 1021, 1022, 1023}, - {0, 1, 2, 3, 4, 5, 6, 19, 224, 590, 967, - 1014, 1019, 1020, 1021, 1022, 1023}, - {0, 1, 2, 3, 4, 5, 6, 19, 300, 630, 1001, - 1018, 1019, 1020, 1021, 1022, 1023}, - {0, 1, 2, 3, 4, 5, 6, 11, 308, 309, 991, - 1017, 1019, 1020, 1021, 1022, 1023}}; diff --git a/system/embdrv/lc3_dec/Common/Tables/TemporalNoiseShapingTables.hpp b/system/embdrv/lc3_dec/Common/Tables/TemporalNoiseShapingTables.hpp deleted file mode 100644 index ca298b6320..0000000000 --- a/system/embdrv/lc3_dec/Common/Tables/TemporalNoiseShapingTables.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * TemporalNoiseShapingTables.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -// LC3 Specification d09r01.pdf -// Section 5.7.4 Temporal Noise Shaping - -#ifndef TEMPORAL_NOISE_SHAPING_TABLES_H_ -#define TEMPORAL_NOISE_SHAPING_TABLES_H_ - -// LC3 Specification d09r01.pdf; Page 109 of 177 -extern short ac_tns_order_bits[2][8]; -extern short ac_tns_order_freq[2][8]; -extern short ac_tns_order_cumfreq[2][8]; - -extern short ac_tns_coef_bits[8][17]; -extern short ac_tns_coef_freq[8][17]; -extern short ac_tns_coef_cumfreq[8][17]; - -#endif // TEMPORAL_NOISE_SHAPING_TABLES_H_ diff --git a/system/embdrv/lc3_dec/Common/fft/fft.c b/system/embdrv/lc3_dec/Common/fft/fft.c deleted file mode 100644 index d684302938..0000000000 --- a/system/embdrv/lc3_dec/Common/fft/fft.c +++ /dev/null @@ -1,677 +0,0 @@ -/****************************************************************************** - * - * Copyright 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - -#include "fft.h" - -/* ---------------------------------------------------------------------------- - * FFT processing - * -------------------------------------------------------------------------- */ - -/** - * Tables - * - * T_N[0..N-1] = - * { cos(-2Pi i/N) + j sin(-2Pi i/N), - * cos(-2Pi 2i/N) + j sin(-2Pi 2i/N) } , N=15, 45, 90 - * - * T_N[0..N/2-1] = - * cos(-2Pi i/N) + j sin(-2Pi i/N) , N=10, 20, ... - */ - -struct fft_bf2_twiddles { - int n2; - const struct fft_complex* t; -}; -struct fft_bf3_twiddles { - int n3; - const struct fft_complex (*t)[2]; -}; - -static const struct fft_bf2_twiddles twiddles_10 = { - .n2 = 10 / 2, - .t = (const struct fft_complex[]){ - {1.0000000e+00, -0.0000000e+00}, - {8.0901699e-01, -5.8778525e-01}, - {3.0901699e-01, -9.5105652e-01}, - {-3.0901699e-01, -9.5105652e-01}, - {-8.0901699e-01, -5.8778525e-01}, - }}; - -static const struct fft_bf2_twiddles twiddles_20 = { - .n2 = 20 / 2, - .t = (const struct fft_complex[]){ - {1.0000000e+00, -0.0000000e+00}, - {9.5105652e-01, -3.0901699e-01}, - {8.0901699e-01, -5.8778525e-01}, - {5.8778525e-01, -8.0901699e-01}, - {3.0901699e-01, -9.5105652e-01}, - {6.1232340e-17, -1.0000000e+00}, - {-3.0901699e-01, -9.5105652e-01}, - {-5.8778525e-01, -8.0901699e-01}, - {-8.0901699e-01, -5.8778525e-01}, - {-9.5105652e-01, -3.0901699e-01}, - }}; - -static const struct fft_bf2_twiddles twiddles_30 = { - .n2 = 30 / 2, - .t = (const struct fft_complex[]){ - {1.0000000e+00, -0.0000000e+00}, - {9.7814760e-01, -2.0791169e-01}, - {9.1354546e-01, -4.0673664e-01}, - {8.0901699e-01, -5.8778525e-01}, - {6.6913061e-01, -7.4314483e-01}, - {5.0000000e-01, -8.6602540e-01}, - {3.0901699e-01, -9.5105652e-01}, - {1.0452846e-01, -9.9452190e-01}, - {-1.0452846e-01, -9.9452190e-01}, - {-3.0901699e-01, -9.5105652e-01}, - {-5.0000000e-01, -8.6602540e-01}, - {-6.6913061e-01, -7.4314483e-01}, - {-8.0901699e-01, -5.8778525e-01}, - {-9.1354546e-01, -4.0673664e-01}, - {-9.7814760e-01, -2.0791169e-01}, - }}; - -static const struct fft_bf2_twiddles twiddles_40 = { - .n2 = 40 / 2, - .t = (const struct fft_complex[]){ - {1.0000000e+00, -0.0000000e+00}, {9.8768834e-01, -1.5643447e-01}, - {9.5105652e-01, -3.0901699e-01}, {8.9100652e-01, -4.5399050e-01}, - {8.0901699e-01, -5.8778525e-01}, {7.0710678e-01, -7.0710678e-01}, - {5.8778525e-01, -8.0901699e-01}, {4.5399050e-01, -8.9100652e-01}, - {3.0901699e-01, -9.5105652e-01}, {1.5643447e-01, -9.8768834e-01}, - {6.1232340e-17, -1.0000000e+00}, {-1.5643447e-01, -9.8768834e-01}, - {-3.0901699e-01, -9.5105652e-01}, {-4.5399050e-01, -8.9100652e-01}, - {-5.8778525e-01, -8.0901699e-01}, {-7.0710678e-01, -7.0710678e-01}, - {-8.0901699e-01, -5.8778525e-01}, {-8.9100652e-01, -4.5399050e-01}, - {-9.5105652e-01, -3.0901699e-01}, {-9.8768834e-01, -1.5643447e-01}, - }}; - -static const struct fft_bf2_twiddles twiddles_60 = { - .n2 = 60 / 2, - .t = (const struct fft_complex[]){ - {1.0000000e+00, -0.0000000e+00}, {9.9452190e-01, -1.0452846e-01}, - {9.7814760e-01, -2.0791169e-01}, {9.5105652e-01, -3.0901699e-01}, - {9.1354546e-01, -4.0673664e-01}, {8.6602540e-01, -5.0000000e-01}, - {8.0901699e-01, -5.8778525e-01}, {7.4314483e-01, -6.6913061e-01}, - {6.6913061e-01, -7.4314483e-01}, {5.8778525e-01, -8.0901699e-01}, - {5.0000000e-01, -8.6602540e-01}, {4.0673664e-01, -9.1354546e-01}, - {3.0901699e-01, -9.5105652e-01}, {2.0791169e-01, -9.7814760e-01}, - {1.0452846e-01, -9.9452190e-01}, {2.8327694e-16, -1.0000000e+00}, - {-1.0452846e-01, -9.9452190e-01}, {-2.0791169e-01, -9.7814760e-01}, - {-3.0901699e-01, -9.5105652e-01}, {-4.0673664e-01, -9.1354546e-01}, - {-5.0000000e-01, -8.6602540e-01}, {-5.8778525e-01, -8.0901699e-01}, - {-6.6913061e-01, -7.4314483e-01}, {-7.4314483e-01, -6.6913061e-01}, - {-8.0901699e-01, -5.8778525e-01}, {-8.6602540e-01, -5.0000000e-01}, - {-9.1354546e-01, -4.0673664e-01}, {-9.5105652e-01, -3.0901699e-01}, - {-9.7814760e-01, -2.0791169e-01}, {-9.9452190e-01, -1.0452846e-01}, - }}; - -static const struct fft_bf2_twiddles twiddles_80 = { - .n2 = 80 / 2, - .t = (const struct fft_complex[]){ - {1.0000000e+00, -0.0000000e+00}, {9.9691733e-01, -7.8459096e-02}, - {9.8768834e-01, -1.5643447e-01}, {9.7236992e-01, -2.3344536e-01}, - {9.5105652e-01, -3.0901699e-01}, {9.2387953e-01, -3.8268343e-01}, - {8.9100652e-01, -4.5399050e-01}, {8.5264016e-01, -5.2249856e-01}, - {8.0901699e-01, -5.8778525e-01}, {7.6040597e-01, -6.4944805e-01}, - {7.0710678e-01, -7.0710678e-01}, {6.4944805e-01, -7.6040597e-01}, - {5.8778525e-01, -8.0901699e-01}, {5.2249856e-01, -8.5264016e-01}, - {4.5399050e-01, -8.9100652e-01}, {3.8268343e-01, -9.2387953e-01}, - {3.0901699e-01, -9.5105652e-01}, {2.3344536e-01, -9.7236992e-01}, - {1.5643447e-01, -9.8768834e-01}, {7.8459096e-02, -9.9691733e-01}, - {6.1232340e-17, -1.0000000e+00}, {-7.8459096e-02, -9.9691733e-01}, - {-1.5643447e-01, -9.8768834e-01}, {-2.3344536e-01, -9.7236992e-01}, - {-3.0901699e-01, -9.5105652e-01}, {-3.8268343e-01, -9.2387953e-01}, - {-4.5399050e-01, -8.9100652e-01}, {-5.2249856e-01, -8.5264016e-01}, - {-5.8778525e-01, -8.0901699e-01}, {-6.4944805e-01, -7.6040597e-01}, - {-7.0710678e-01, -7.0710678e-01}, {-7.6040597e-01, -6.4944805e-01}, - {-8.0901699e-01, -5.8778525e-01}, {-8.5264016e-01, -5.2249856e-01}, - {-8.9100652e-01, -4.5399050e-01}, {-9.2387953e-01, -3.8268343e-01}, - {-9.5105652e-01, -3.0901699e-01}, {-9.7236992e-01, -2.3344536e-01}, - {-9.8768834e-01, -1.5643447e-01}, {-9.9691733e-01, -7.8459096e-02}, - }}; - -static const struct fft_bf2_twiddles twiddles_90 = { - .n2 = 90 / 2, - .t = (const struct fft_complex[]){ - {1.0000000e+00, -0.0000000e+00}, {9.9756405e-01, -6.9756474e-02}, - {9.9026807e-01, -1.3917310e-01}, {9.7814760e-01, -2.0791169e-01}, - {9.6126170e-01, -2.7563736e-01}, {9.3969262e-01, -3.4202014e-01}, - {9.1354546e-01, -4.0673664e-01}, {8.8294759e-01, -4.6947156e-01}, - {8.4804810e-01, -5.2991926e-01}, {8.0901699e-01, -5.8778525e-01}, - {7.6604444e-01, -6.4278761e-01}, {7.1933980e-01, -6.9465837e-01}, - {6.6913061e-01, -7.4314483e-01}, {6.1566148e-01, -7.8801075e-01}, - {5.5919290e-01, -8.2903757e-01}, {5.0000000e-01, -8.6602540e-01}, - {4.3837115e-01, -8.9879405e-01}, {3.7460659e-01, -9.2718385e-01}, - {3.0901699e-01, -9.5105652e-01}, {2.4192190e-01, -9.7029573e-01}, - {1.7364818e-01, -9.8480775e-01}, {1.0452846e-01, -9.9452190e-01}, - {3.4899497e-02, -9.9939083e-01}, {-3.4899497e-02, -9.9939083e-01}, - {-1.0452846e-01, -9.9452190e-01}, {-1.7364818e-01, -9.8480775e-01}, - {-2.4192190e-01, -9.7029573e-01}, {-3.0901699e-01, -9.5105652e-01}, - {-3.7460659e-01, -9.2718385e-01}, {-4.3837115e-01, -8.9879405e-01}, - {-5.0000000e-01, -8.6602540e-01}, {-5.5919290e-01, -8.2903757e-01}, - {-6.1566148e-01, -7.8801075e-01}, {-6.6913061e-01, -7.4314483e-01}, - {-7.1933980e-01, -6.9465837e-01}, {-7.6604444e-01, -6.4278761e-01}, - {-8.0901699e-01, -5.8778525e-01}, {-8.4804810e-01, -5.2991926e-01}, - {-8.8294759e-01, -4.6947156e-01}, {-9.1354546e-01, -4.0673664e-01}, - {-9.3969262e-01, -3.4202014e-01}, {-9.6126170e-01, -2.7563736e-01}, - {-9.7814760e-01, -2.0791169e-01}, {-9.9026807e-01, -1.3917310e-01}, - {-9.9756405e-01, -6.9756474e-02}, - }}; - -static const struct fft_bf2_twiddles twiddles_120 = { - .n2 = 120 / 2, - .t = (const struct fft_complex[]){ - {1.0000000e+00, -0.0000000e+00}, {9.9862953e-01, -5.2335956e-02}, - {9.9452190e-01, -1.0452846e-01}, {9.8768834e-01, -1.5643447e-01}, - {9.7814760e-01, -2.0791169e-01}, {9.6592583e-01, -2.5881905e-01}, - {9.5105652e-01, -3.0901699e-01}, {9.3358043e-01, -3.5836795e-01}, - {9.1354546e-01, -4.0673664e-01}, {8.9100652e-01, -4.5399050e-01}, - {8.6602540e-01, -5.0000000e-01}, {8.3867057e-01, -5.4463904e-01}, - {8.0901699e-01, -5.8778525e-01}, {7.7714596e-01, -6.2932039e-01}, - {7.4314483e-01, -6.6913061e-01}, {7.0710678e-01, -7.0710678e-01}, - {6.6913061e-01, -7.4314483e-01}, {6.2932039e-01, -7.7714596e-01}, - {5.8778525e-01, -8.0901699e-01}, {5.4463904e-01, -8.3867057e-01}, - {5.0000000e-01, -8.6602540e-01}, {4.5399050e-01, -8.9100652e-01}, - {4.0673664e-01, -9.1354546e-01}, {3.5836795e-01, -9.3358043e-01}, - {3.0901699e-01, -9.5105652e-01}, {2.5881905e-01, -9.6592583e-01}, - {2.0791169e-01, -9.7814760e-01}, {1.5643447e-01, -9.8768834e-01}, - {1.0452846e-01, -9.9452190e-01}, {5.2335956e-02, -9.9862953e-01}, - {2.8327694e-16, -1.0000000e+00}, {-5.2335956e-02, -9.9862953e-01}, - {-1.0452846e-01, -9.9452190e-01}, {-1.5643447e-01, -9.8768834e-01}, - {-2.0791169e-01, -9.7814760e-01}, {-2.5881905e-01, -9.6592583e-01}, - {-3.0901699e-01, -9.5105652e-01}, {-3.5836795e-01, -9.3358043e-01}, - {-4.0673664e-01, -9.1354546e-01}, {-4.5399050e-01, -8.9100652e-01}, - {-5.0000000e-01, -8.6602540e-01}, {-5.4463904e-01, -8.3867057e-01}, - {-5.8778525e-01, -8.0901699e-01}, {-6.2932039e-01, -7.7714596e-01}, - {-6.6913061e-01, -7.4314483e-01}, {-7.0710678e-01, -7.0710678e-01}, - {-7.4314483e-01, -6.6913061e-01}, {-7.7714596e-01, -6.2932039e-01}, - {-8.0901699e-01, -5.8778525e-01}, {-8.3867057e-01, -5.4463904e-01}, - {-8.6602540e-01, -5.0000000e-01}, {-8.9100652e-01, -4.5399050e-01}, - {-9.1354546e-01, -4.0673664e-01}, {-9.3358043e-01, -3.5836795e-01}, - {-9.5105652e-01, -3.0901699e-01}, {-9.6592583e-01, -2.5881905e-01}, - {-9.7814760e-01, -2.0791169e-01}, {-9.8768834e-01, -1.5643447e-01}, - {-9.9452190e-01, -1.0452846e-01}, {-9.9862953e-01, -5.2335956e-02}, - }}; - -static const struct fft_bf2_twiddles twiddles_160 = { - .n2 = 160 / 2, - .t = (const struct fft_complex[]){ - {1.0000000e+00, -0.0000000e+00}, {9.9922904e-01, -3.9259816e-02}, - {9.9691733e-01, -7.8459096e-02}, {9.9306846e-01, -1.1753740e-01}, - {9.8768834e-01, -1.5643447e-01}, {9.8078528e-01, -1.9509032e-01}, - {9.7236992e-01, -2.3344536e-01}, {9.6245524e-01, -2.7144045e-01}, - {9.5105652e-01, -3.0901699e-01}, {9.3819134e-01, -3.4611706e-01}, - {9.2387953e-01, -3.8268343e-01}, {9.0814317e-01, -4.1865974e-01}, - {8.9100652e-01, -4.5399050e-01}, {8.7249601e-01, -4.8862124e-01}, - {8.5264016e-01, -5.2249856e-01}, {8.3146961e-01, -5.5557023e-01}, - {8.0901699e-01, -5.8778525e-01}, {7.8531693e-01, -6.1909395e-01}, - {7.6040597e-01, -6.4944805e-01}, {7.3432251e-01, -6.7880075e-01}, - {7.0710678e-01, -7.0710678e-01}, {6.7880075e-01, -7.3432251e-01}, - {6.4944805e-01, -7.6040597e-01}, {6.1909395e-01, -7.8531693e-01}, - {5.8778525e-01, -8.0901699e-01}, {5.5557023e-01, -8.3146961e-01}, - {5.2249856e-01, -8.5264016e-01}, {4.8862124e-01, -8.7249601e-01}, - {4.5399050e-01, -8.9100652e-01}, {4.1865974e-01, -9.0814317e-01}, - {3.8268343e-01, -9.2387953e-01}, {3.4611706e-01, -9.3819134e-01}, - {3.0901699e-01, -9.5105652e-01}, {2.7144045e-01, -9.6245524e-01}, - {2.3344536e-01, -9.7236992e-01}, {1.9509032e-01, -9.8078528e-01}, - {1.5643447e-01, -9.8768834e-01}, {1.1753740e-01, -9.9306846e-01}, - {7.8459096e-02, -9.9691733e-01}, {3.9259816e-02, -9.9922904e-01}, - {6.1232340e-17, -1.0000000e+00}, {-3.9259816e-02, -9.9922904e-01}, - {-7.8459096e-02, -9.9691733e-01}, {-1.1753740e-01, -9.9306846e-01}, - {-1.5643447e-01, -9.8768834e-01}, {-1.9509032e-01, -9.8078528e-01}, - {-2.3344536e-01, -9.7236992e-01}, {-2.7144045e-01, -9.6245524e-01}, - {-3.0901699e-01, -9.5105652e-01}, {-3.4611706e-01, -9.3819134e-01}, - {-3.8268343e-01, -9.2387953e-01}, {-4.1865974e-01, -9.0814317e-01}, - {-4.5399050e-01, -8.9100652e-01}, {-4.8862124e-01, -8.7249601e-01}, - {-5.2249856e-01, -8.5264016e-01}, {-5.5557023e-01, -8.3146961e-01}, - {-5.8778525e-01, -8.0901699e-01}, {-6.1909395e-01, -7.8531693e-01}, - {-6.4944805e-01, -7.6040597e-01}, {-6.7880075e-01, -7.3432251e-01}, - {-7.0710678e-01, -7.0710678e-01}, {-7.3432251e-01, -6.7880075e-01}, - {-7.6040597e-01, -6.4944805e-01}, {-7.8531693e-01, -6.1909395e-01}, - {-8.0901699e-01, -5.8778525e-01}, {-8.3146961e-01, -5.5557023e-01}, - {-8.5264016e-01, -5.2249856e-01}, {-8.7249601e-01, -4.8862124e-01}, - {-8.9100652e-01, -4.5399050e-01}, {-9.0814317e-01, -4.1865974e-01}, - {-9.2387953e-01, -3.8268343e-01}, {-9.3819134e-01, -3.4611706e-01}, - {-9.5105652e-01, -3.0901699e-01}, {-9.6245524e-01, -2.7144045e-01}, - {-9.7236992e-01, -2.3344536e-01}, {-9.8078528e-01, -1.9509032e-01}, - {-9.8768834e-01, -1.5643447e-01}, {-9.9306846e-01, -1.1753740e-01}, - {-9.9691733e-01, -7.8459096e-02}, {-9.9922904e-01, -3.9259816e-02}, - }}; - -static const struct fft_bf2_twiddles twiddles_180 = { - .n2 = 180 / 2, - .t = (const struct fft_complex[]){ - {1.0000000e+00, -0.0000000e+00}, {9.9939083e-01, -3.4899497e-02}, - {9.9756405e-01, -6.9756474e-02}, {9.9452190e-01, -1.0452846e-01}, - {9.9026807e-01, -1.3917310e-01}, {9.8480775e-01, -1.7364818e-01}, - {9.7814760e-01, -2.0791169e-01}, {9.7029573e-01, -2.4192190e-01}, - {9.6126170e-01, -2.7563736e-01}, {9.5105652e-01, -3.0901699e-01}, - {9.3969262e-01, -3.4202014e-01}, {9.2718385e-01, -3.7460659e-01}, - {9.1354546e-01, -4.0673664e-01}, {8.9879405e-01, -4.3837115e-01}, - {8.8294759e-01, -4.6947156e-01}, {8.6602540e-01, -5.0000000e-01}, - {8.4804810e-01, -5.2991926e-01}, {8.2903757e-01, -5.5919290e-01}, - {8.0901699e-01, -5.8778525e-01}, {7.8801075e-01, -6.1566148e-01}, - {7.6604444e-01, -6.4278761e-01}, {7.4314483e-01, -6.6913061e-01}, - {7.1933980e-01, -6.9465837e-01}, {6.9465837e-01, -7.1933980e-01}, - {6.6913061e-01, -7.4314483e-01}, {6.4278761e-01, -7.6604444e-01}, - {6.1566148e-01, -7.8801075e-01}, {5.8778525e-01, -8.0901699e-01}, - {5.5919290e-01, -8.2903757e-01}, {5.2991926e-01, -8.4804810e-01}, - {5.0000000e-01, -8.6602540e-01}, {4.6947156e-01, -8.8294759e-01}, - {4.3837115e-01, -8.9879405e-01}, {4.0673664e-01, -9.1354546e-01}, - {3.7460659e-01, -9.2718385e-01}, {3.4202014e-01, -9.3969262e-01}, - {3.0901699e-01, -9.5105652e-01}, {2.7563736e-01, -9.6126170e-01}, - {2.4192190e-01, -9.7029573e-01}, {2.0791169e-01, -9.7814760e-01}, - {1.7364818e-01, -9.8480775e-01}, {1.3917310e-01, -9.9026807e-01}, - {1.0452846e-01, -9.9452190e-01}, {6.9756474e-02, -9.9756405e-01}, - {3.4899497e-02, -9.9939083e-01}, {6.1232340e-17, -1.0000000e+00}, - {-3.4899497e-02, -9.9939083e-01}, {-6.9756474e-02, -9.9756405e-01}, - {-1.0452846e-01, -9.9452190e-01}, {-1.3917310e-01, -9.9026807e-01}, - {-1.7364818e-01, -9.8480775e-01}, {-2.0791169e-01, -9.7814760e-01}, - {-2.4192190e-01, -9.7029573e-01}, {-2.7563736e-01, -9.6126170e-01}, - {-3.0901699e-01, -9.5105652e-01}, {-3.4202014e-01, -9.3969262e-01}, - {-3.7460659e-01, -9.2718385e-01}, {-4.0673664e-01, -9.1354546e-01}, - {-4.3837115e-01, -8.9879405e-01}, {-4.6947156e-01, -8.8294759e-01}, - {-5.0000000e-01, -8.6602540e-01}, {-5.2991926e-01, -8.4804810e-01}, - {-5.5919290e-01, -8.2903757e-01}, {-5.8778525e-01, -8.0901699e-01}, - {-6.1566148e-01, -7.8801075e-01}, {-6.4278761e-01, -7.6604444e-01}, - {-6.6913061e-01, -7.4314483e-01}, {-6.9465837e-01, -7.1933980e-01}, - {-7.1933980e-01, -6.9465837e-01}, {-7.4314483e-01, -6.6913061e-01}, - {-7.6604444e-01, -6.4278761e-01}, {-7.8801075e-01, -6.1566148e-01}, - {-8.0901699e-01, -5.8778525e-01}, {-8.2903757e-01, -5.5919290e-01}, - {-8.4804810e-01, -5.2991926e-01}, {-8.6602540e-01, -5.0000000e-01}, - {-8.8294759e-01, -4.6947156e-01}, {-8.9879405e-01, -4.3837115e-01}, - {-9.1354546e-01, -4.0673664e-01}, {-9.2718385e-01, -3.7460659e-01}, - {-9.3969262e-01, -3.4202014e-01}, {-9.5105652e-01, -3.0901699e-01}, - {-9.6126170e-01, -2.7563736e-01}, {-9.7029573e-01, -2.4192190e-01}, - {-9.7814760e-01, -2.0791169e-01}, {-9.8480775e-01, -1.7364818e-01}, - {-9.9026807e-01, -1.3917310e-01}, {-9.9452190e-01, -1.0452846e-01}, - {-9.9756405e-01, -6.9756474e-02}, {-9.9939083e-01, -3.4899497e-02}, - }}; - -static const struct fft_bf2_twiddles twiddles_240 = { - .n2 = 240 / 2, - .t = (const struct fft_complex[]){ - {1.0000000e+00, -0.0000000e+00}, {9.9965732e-01, -2.6176948e-02}, - {9.9862953e-01, -5.2335956e-02}, {9.9691733e-01, -7.8459096e-02}, - {9.9452190e-01, -1.0452846e-01}, {9.9144486e-01, -1.3052619e-01}, - {9.8768834e-01, -1.5643447e-01}, {9.8325491e-01, -1.8223553e-01}, - {9.7814760e-01, -2.0791169e-01}, {9.7236992e-01, -2.3344536e-01}, - {9.6592583e-01, -2.5881905e-01}, {9.5881973e-01, -2.8401534e-01}, - {9.5105652e-01, -3.0901699e-01}, {9.4264149e-01, -3.3380686e-01}, - {9.3358043e-01, -3.5836795e-01}, {9.2387953e-01, -3.8268343e-01}, - {9.1354546e-01, -4.0673664e-01}, {9.0258528e-01, -4.3051110e-01}, - {8.9100652e-01, -4.5399050e-01}, {8.7881711e-01, -4.7715876e-01}, - {8.6602540e-01, -5.0000000e-01}, {8.5264016e-01, -5.2249856e-01}, - {8.3867057e-01, -5.4463904e-01}, {8.2412619e-01, -5.6640624e-01}, - {8.0901699e-01, -5.8778525e-01}, {7.9335334e-01, -6.0876143e-01}, - {7.7714596e-01, -6.2932039e-01}, {7.6040597e-01, -6.4944805e-01}, - {7.4314483e-01, -6.6913061e-01}, {7.2537437e-01, -6.8835458e-01}, - {7.0710678e-01, -7.0710678e-01}, {6.8835458e-01, -7.2537437e-01}, - {6.6913061e-01, -7.4314483e-01}, {6.4944805e-01, -7.6040597e-01}, - {6.2932039e-01, -7.7714596e-01}, {6.0876143e-01, -7.9335334e-01}, - {5.8778525e-01, -8.0901699e-01}, {5.6640624e-01, -8.2412619e-01}, - {5.4463904e-01, -8.3867057e-01}, {5.2249856e-01, -8.5264016e-01}, - {5.0000000e-01, -8.6602540e-01}, {4.7715876e-01, -8.7881711e-01}, - {4.5399050e-01, -8.9100652e-01}, {4.3051110e-01, -9.0258528e-01}, - {4.0673664e-01, -9.1354546e-01}, {3.8268343e-01, -9.2387953e-01}, - {3.5836795e-01, -9.3358043e-01}, {3.3380686e-01, -9.4264149e-01}, - {3.0901699e-01, -9.5105652e-01}, {2.8401534e-01, -9.5881973e-01}, - {2.5881905e-01, -9.6592583e-01}, {2.3344536e-01, -9.7236992e-01}, - {2.0791169e-01, -9.7814760e-01}, {1.8223553e-01, -9.8325491e-01}, - {1.5643447e-01, -9.8768834e-01}, {1.3052619e-01, -9.9144486e-01}, - {1.0452846e-01, -9.9452190e-01}, {7.8459096e-02, -9.9691733e-01}, - {5.2335956e-02, -9.9862953e-01}, {2.6176948e-02, -9.9965732e-01}, - {2.8327694e-16, -1.0000000e+00}, {-2.6176948e-02, -9.9965732e-01}, - {-5.2335956e-02, -9.9862953e-01}, {-7.8459096e-02, -9.9691733e-01}, - {-1.0452846e-01, -9.9452190e-01}, {-1.3052619e-01, -9.9144486e-01}, - {-1.5643447e-01, -9.8768834e-01}, {-1.8223553e-01, -9.8325491e-01}, - {-2.0791169e-01, -9.7814760e-01}, {-2.3344536e-01, -9.7236992e-01}, - {-2.5881905e-01, -9.6592583e-01}, {-2.8401534e-01, -9.5881973e-01}, - {-3.0901699e-01, -9.5105652e-01}, {-3.3380686e-01, -9.4264149e-01}, - {-3.5836795e-01, -9.3358043e-01}, {-3.8268343e-01, -9.2387953e-01}, - {-4.0673664e-01, -9.1354546e-01}, {-4.3051110e-01, -9.0258528e-01}, - {-4.5399050e-01, -8.9100652e-01}, {-4.7715876e-01, -8.7881711e-01}, - {-5.0000000e-01, -8.6602540e-01}, {-5.2249856e-01, -8.5264016e-01}, - {-5.4463904e-01, -8.3867057e-01}, {-5.6640624e-01, -8.2412619e-01}, - {-5.8778525e-01, -8.0901699e-01}, {-6.0876143e-01, -7.9335334e-01}, - {-6.2932039e-01, -7.7714596e-01}, {-6.4944805e-01, -7.6040597e-01}, - {-6.6913061e-01, -7.4314483e-01}, {-6.8835458e-01, -7.2537437e-01}, - {-7.0710678e-01, -7.0710678e-01}, {-7.2537437e-01, -6.8835458e-01}, - {-7.4314483e-01, -6.6913061e-01}, {-7.6040597e-01, -6.4944805e-01}, - {-7.7714596e-01, -6.2932039e-01}, {-7.9335334e-01, -6.0876143e-01}, - {-8.0901699e-01, -5.8778525e-01}, {-8.2412619e-01, -5.6640624e-01}, - {-8.3867057e-01, -5.4463904e-01}, {-8.5264016e-01, -5.2249856e-01}, - {-8.6602540e-01, -5.0000000e-01}, {-8.7881711e-01, -4.7715876e-01}, - {-8.9100652e-01, -4.5399050e-01}, {-9.0258528e-01, -4.3051110e-01}, - {-9.1354546e-01, -4.0673664e-01}, {-9.2387953e-01, -3.8268343e-01}, - {-9.3358043e-01, -3.5836795e-01}, {-9.4264149e-01, -3.3380686e-01}, - {-9.5105652e-01, -3.0901699e-01}, {-9.5881973e-01, -2.8401534e-01}, - {-9.6592583e-01, -2.5881905e-01}, {-9.7236992e-01, -2.3344536e-01}, - {-9.7814760e-01, -2.0791169e-01}, {-9.8325491e-01, -1.8223553e-01}, - {-9.8768834e-01, -1.5643447e-01}, {-9.9144486e-01, -1.3052619e-01}, - {-9.9452190e-01, -1.0452846e-01}, {-9.9691733e-01, -7.8459096e-02}, - {-9.9862953e-01, -5.2335956e-02}, {-9.9965732e-01, -2.6176948e-02}, - }}; - -static const struct fft_bf3_twiddles twiddles_15 = { - .n3 = 15 / 3, - .t = (const struct fft_complex[][2]){ - {{1.0000000e+0, -0.0000000e+0}, {1.0000000e+0, -0.0000000e+0}}, - {{9.1354546e-1, -4.0673664e-1}, {6.6913061e-1, -7.4314483e-1}}, - {{6.6913061e-1, -7.4314483e-1}, {-1.0452846e-1, -9.9452190e-1}}, - {{3.0901699e-1, -9.5105652e-1}, {-8.0901699e-1, -5.8778525e-1}}, - {{-1.0452846e-1, -9.9452190e-1}, {-9.7814760e-1, 2.0791169e-1}}, - {{-5.0000000e-1, -8.6602540e-1}, {-5.0000000e-1, 8.6602540e-1}}, - {{-8.0901699e-1, -5.8778525e-1}, {3.0901699e-1, 9.5105652e-1}}, - {{-9.7814760e-1, -2.0791169e-1}, {9.1354546e-1, 4.0673664e-1}}, - {{-9.7814760e-1, 2.0791169e-1}, {9.1354546e-1, -4.0673664e-1}}, - {{-8.0901699e-1, 5.8778525e-1}, {3.0901699e-1, -9.5105652e-1}}, - {{-5.0000000e-1, 8.6602540e-1}, {-5.0000000e-1, -8.6602540e-1}}, - {{-1.0452846e-1, 9.9452190e-1}, {-9.7814760e-1, -2.0791169e-1}}, - {{3.0901699e-1, 9.5105652e-1}, {-8.0901699e-1, 5.8778525e-1}}, - {{6.6913061e-1, 7.4314483e-1}, {-1.0452846e-1, 9.9452190e-1}}, - {{9.1354546e-1, 4.0673664e-1}, {6.6913061e-1, 7.4314483e-1}}, - }}; - -static const struct fft_bf3_twiddles twiddles_45 = { - .n3 = 45 / 3, - .t = (const struct fft_complex[][2]){ - {{1.0000000e+0, -0.0000000e+0}, {1.0000000e+0, -0.0000000e+0}}, - {{9.9026807e-1, -1.3917310e-1}, {9.6126170e-1, -2.7563736e-1}}, - {{9.6126170e-1, -2.7563736e-1}, {8.4804810e-1, -5.2991926e-1}}, - {{9.1354546e-1, -4.0673664e-1}, {6.6913061e-1, -7.4314483e-1}}, - {{8.4804810e-1, -5.2991926e-1}, {4.3837115e-1, -8.9879405e-1}}, - {{7.6604444e-1, -6.4278761e-1}, {1.7364818e-1, -9.8480775e-1}}, - {{6.6913061e-1, -7.4314483e-1}, {-1.0452846e-1, -9.9452190e-1}}, - {{5.5919290e-1, -8.2903757e-1}, {-3.7460659e-1, -9.2718385e-1}}, - {{4.3837115e-1, -8.9879405e-1}, {-6.1566148e-1, -7.8801075e-1}}, - {{3.0901699e-1, -9.5105652e-1}, {-8.0901699e-1, -5.8778525e-1}}, - {{1.7364818e-1, -9.8480775e-1}, {-9.3969262e-1, -3.4202014e-1}}, - {{3.4899497e-2, -9.9939083e-1}, {-9.9756405e-1, -6.9756474e-2}}, - {{-1.0452846e-1, -9.9452190e-1}, {-9.7814760e-1, 2.0791169e-1}}, - {{-2.4192190e-1, -9.7029573e-1}, {-8.8294759e-1, 4.6947156e-1}}, - {{-3.7460659e-1, -9.2718385e-1}, {-7.1933980e-1, 6.9465837e-1}}, - {{-5.0000000e-1, -8.6602540e-1}, {-5.0000000e-1, 8.6602540e-1}}, - {{-6.1566148e-1, -7.8801075e-1}, {-2.4192190e-1, 9.7029573e-1}}, - {{-7.1933980e-1, -6.9465837e-1}, {3.4899497e-2, 9.9939083e-1}}, - {{-8.0901699e-1, -5.8778525e-1}, {3.0901699e-1, 9.5105652e-1}}, - {{-8.8294759e-1, -4.6947156e-1}, {5.5919290e-1, 8.2903757e-1}}, - {{-9.3969262e-1, -3.4202014e-1}, {7.6604444e-1, 6.4278761e-1}}, - {{-9.7814760e-1, -2.0791169e-1}, {9.1354546e-1, 4.0673664e-1}}, - {{-9.9756405e-1, -6.9756474e-2}, {9.9026807e-1, 1.3917310e-1}}, - {{-9.9756405e-1, 6.9756474e-2}, {9.9026807e-1, -1.3917310e-1}}, - {{-9.7814760e-1, 2.0791169e-1}, {9.1354546e-1, -4.0673664e-1}}, - {{-9.3969262e-1, 3.4202014e-1}, {7.6604444e-1, -6.4278761e-1}}, - {{-8.8294759e-1, 4.6947156e-1}, {5.5919290e-1, -8.2903757e-1}}, - {{-8.0901699e-1, 5.8778525e-1}, {3.0901699e-1, -9.5105652e-1}}, - {{-7.1933980e-1, 6.9465837e-1}, {3.4899497e-2, -9.9939083e-1}}, - {{-6.1566148e-1, 7.8801075e-1}, {-2.4192190e-1, -9.7029573e-1}}, - {{-5.0000000e-1, 8.6602540e-1}, {-5.0000000e-1, -8.6602540e-1}}, - {{-3.7460659e-1, 9.2718385e-1}, {-7.1933980e-1, -6.9465837e-1}}, - {{-2.4192190e-1, 9.7029573e-1}, {-8.8294759e-1, -4.6947156e-1}}, - {{-1.0452846e-1, 9.9452190e-1}, {-9.7814760e-1, -2.0791169e-1}}, - {{3.4899497e-2, 9.9939083e-1}, {-9.9756405e-1, 6.9756474e-2}}, - {{1.7364818e-1, 9.8480775e-1}, {-9.3969262e-1, 3.4202014e-1}}, - {{3.0901699e-1, 9.5105652e-1}, {-8.0901699e-1, 5.8778525e-1}}, - {{4.3837115e-1, 8.9879405e-1}, {-6.1566148e-1, 7.8801075e-1}}, - {{5.5919290e-1, 8.2903757e-1}, {-3.7460659e-1, 9.2718385e-1}}, - {{6.6913061e-1, 7.4314483e-1}, {-1.0452846e-1, 9.9452190e-1}}, - {{7.6604444e-1, 6.4278761e-1}, {1.7364818e-1, 9.8480775e-1}}, - {{8.4804810e-1, 5.2991926e-1}, {4.3837115e-1, 8.9879405e-1}}, - {{9.1354546e-1, 4.0673664e-1}, {6.6913061e-1, 7.4314483e-1}}, - {{9.6126170e-1, 2.7563736e-1}, {8.4804810e-1, 5.2991926e-1}}, - {{9.9026807e-1, 1.3917310e-1}, {9.6126170e-1, 2.7563736e-1}}, - }}; - -/** - * FFT 5 Points template - * s Sign -1: Forward 1: Inverse - * x, y Input and output coefficients, of size 5xn - * n Number of interleaved transform to perform - */ -static inline void xfft_5(const float s, const struct fft_complex* x, - struct fft_complex* y, int n) { - static const float cos1 = 0.3090169944; /* cos(-2Pi 1/5) */ - static const float cos2 = -0.8090169944; /* cos(-2Pi 2/5) */ - - static const float sin1 = -0.9510565163; /* sin(-2Pi 1/5) */ - static const float sin2 = -0.5877852523; /* sin(-2Pi 2/5) */ - - for (int i = 0; i < n; i++, x++, y += 5) { - struct fft_complex s14 = {x[1 * n].re + x[4 * n].re, - x[1 * n].im + x[4 * n].im}; - struct fft_complex d14 = {x[1 * n].re - x[4 * n].re, - x[1 * n].im - x[4 * n].im}; - - struct fft_complex s23 = {x[2 * n].re + x[3 * n].re, - x[2 * n].im + x[3 * n].im}; - struct fft_complex d23 = {x[2 * n].re - x[3 * n].re, - x[2 * n].im - x[3 * n].im}; - - y[0].re = x[0].re + s14.re + s23.re; - y[0].im = x[0].im + s14.im + s23.im; - - y[1].re = x[0].re + s14.re * cos1 + s * d14.im * sin1 + s23.re * cos2 + - s * d23.im * sin2; - - y[1].im = x[0].im + s14.im * cos1 - s * d14.re * sin1 + s23.im * cos2 - - s * d23.re * sin2; - - y[2].re = x[0].re + s14.re * cos2 + s * d14.im * sin2 + s23.re * cos1 - - s * d23.im * sin1; - - y[2].im = x[0].im + s14.im * cos2 - s * d14.re * sin2 + s23.im * cos1 + - s * d23.re * sin1; - - y[3].re = x[0].re + s14.re * cos2 - s * d14.im * sin2 + s23.re * cos1 + - s * d23.im * sin1; - - y[3].im = x[0].im + s14.im * cos2 + s * d14.re * sin2 + s23.im * cos1 - - s * d23.re * sin1; - - y[4].re = x[0].re + s14.re * cos1 - s * d14.im * sin1 + s23.re * cos2 - - s * d23.im * sin2; - - y[4].im = x[0].im + s14.im * cos1 + s * d14.re * sin1 + s23.im * cos2 + - s * d23.re * sin2; - } -} - -/** - * FFT Butterfly 3 Points template - * s Sign -1: Forward 1: Inverse - * x, y Input and output coefficients - * twiddles Twiddles factors, determine size of transform - * n Number of interleaved transforms - */ -static inline void xfft_bf3(const float s, - const struct fft_bf3_twiddles* twiddles, - const struct fft_complex* x, struct fft_complex* y, - int n) { - int n3 = twiddles->n3; - const struct fft_complex(*w0)[2] = twiddles->t; - const struct fft_complex(*w1)[2] = w0 + n3, (*w2)[2] = w1 + n3; - - const struct fft_complex *x0 = x, *x1 = x0 + n * n3, *x2 = x1 + n * n3; - struct fft_complex *y0 = y, *y1 = y0 + n3, *y2 = y1 + n3; - - for (int i = 0; i < n; i++, y0 += 3 * n3, y1 += 3 * n3, y2 += 3 * n3) { - for (int j = 0; j < n3; j++, x0++, x1++, x2++) { - y0[j].re = x0->re + x1->re * w0[j][0].re + s * x1->im * w0[j][0].im + - x2->re * w0[j][1].re + s * x2->im * w0[j][1].im; - - y0[j].im = x0->im + x1->im * w0[j][0].re - s * x1->re * w0[j][0].im + - x2->im * w0[j][1].re - s * x2->re * w0[j][1].im; - - y1[j].re = x0->re + x1->re * w1[j][0].re + s * x1->im * w1[j][0].im + - x2->re * w1[j][1].re + s * x2->im * w1[j][1].im; - - y1[j].im = x0->im + x1->im * w1[j][0].re - s * x1->re * w1[j][0].im + - x2->im * w1[j][1].re - s * x2->re * w1[j][1].im; - - y2[j].re = x0->re + x1->re * w2[j][0].re + s * x1->im * w2[j][0].im + - x2->re * w2[j][1].re + s * x2->im * w2[j][1].im; - - y2[j].im = x0->im + x1->im * w2[j][0].re - s * x1->re * w2[j][0].im + - x2->im * w2[j][1].re - s * x2->re * w2[j][1].im; - } - } -} - -/** - * FFT Butterfly 2 Points template - * s Sign -1: Forward 1: Inverse - * twiddles Twiddles factors, determine size of transform - * x, y Input and output coefficients - * n Number of interleaved transforms - */ -static inline void xfft_bf2(const float s, - const struct fft_bf2_twiddles* twiddles, - const struct fft_complex* x, struct fft_complex* y, - int n) { - int n2 = twiddles->n2; - const struct fft_complex* w = twiddles->t; - - const struct fft_complex *x0 = x, *x1 = x0 + n * n2; - struct fft_complex *y0 = y, *y1 = y0 + n2; - - for (int i = 0; i < n; i++, y0 += 2 * n2, y1 += 2 * n2) { - for (int j = 0; j < n2; j++, x0++, x1++) { - y0[j].re = x0->re + x1->re * w[j].re + s * x1->im * w[j].im; - y0[j].im = x0->im + x1->im * w[j].re - s * x1->re * w[j].im; - - y1[j].re = x0->re - x1->re * w[j].re - s * x1->im * w[j].im; - y1[j].im = x0->im - x1->im * w[j].re + s * x1->re * w[j].im; - } - } -} - -/** - * Forward FFT 5 Points - * x, y Input and output coefficients, of size 5xn - * n Number of interleaved transform to perform - */ -static void ffft_5(const struct fft_complex* x, struct fft_complex* y, int n) { - xfft_5(-1, x, y, n); -} - -/** - * Inverse FFT 5 Points - * x, y Input and output coefficients, of size 5xn - * n Number of interleaved transform to perform - */ -static void ifft_5(const struct fft_complex* x, struct fft_complex* y, int n) { - xfft_5(1, x, y, n); -} - -/** - * Forward FFT Butterfly 3 Points - * twiddles Twiddles factors, determine size of transform - * x, y Input and output coefficients - * n Number of interleaved transforms - */ -static void ffft_bf3(const struct fft_bf3_twiddles* twiddles, - const struct fft_complex* x, struct fft_complex* y, - int n) { - xfft_bf3(-1, twiddles, x, y, n); -} - -/** - * Inverse FFT Butterfly 3 Points - * twiddles Twiddles factors, determine size of transform - * x, y Input and output coefficients - * n Number of interleaved transforms - */ -static void ifft_bf3(const struct fft_bf3_twiddles* twiddles, - const struct fft_complex* x, struct fft_complex* y, - int n) { - xfft_bf3(1, twiddles, x, y, n); -} - -/** - * Forward FFT Butterfly 2 Points - * twiddles Twiddles factors, determine size of transform - * x, y Input and output coefficients - * n Number of interleaved transforms - */ -static void ffft_bf2(const struct fft_bf2_twiddles* twiddles, - const struct fft_complex* x, struct fft_complex* y, - int n) { - xfft_bf2(-1, twiddles, x, y, n); -} - -/** - * InverseIFFT Butterfly 2 Points - * twiddles Twiddles factors, determine size of transform - * x, y Input and output coefficients - * n Number of interleaved transforms - */ -static void ifft_bf2(const struct fft_bf2_twiddles* twiddles, - const struct fft_complex* x, struct fft_complex* y, - int n) { - xfft_bf2(1, twiddles, x, y, n); -} - -/** - * Perform FFT - * inverse True on inverse transform else forward - * x, y0, y1 Input, and 2 scratch buffers of size `n` - * n Number of points 30, 40, 60, 80, 90, 120, 160, 180, 240 - * return The buffer `y0` or `y1` that hold the result - * - * Input `x` can be the same as the `y0` second scratch buffer - */ -struct fft_complex* fft(bool inverse, const struct fft_complex* x, int n, - struct fft_complex* y0, struct fft_complex* y1) { - static const struct fft_bf3_twiddles* twiddles_bf3[] = {&twiddles_15, - &twiddles_45}; - - static const struct fft_bf2_twiddles* twiddles_bf2[][3] = { - {&twiddles_10, &twiddles_30, &twiddles_90}, - {&twiddles_20, &twiddles_60, &twiddles_180}, - {&twiddles_40, &twiddles_120}, - {&twiddles_80, &twiddles_240}, - {&twiddles_160}}; - - struct fft_complex* y[2] = {y1, y0}; - int i2, i3, is = 0; - - /* The number of points `n` can be decomposed as : - * - * n = 5^1 * 3^n3 * 2^n2 - * - * for n = 40, 80, 160 n3 = 0, n2 = [3..5] - * n = 30, 60, 120, 240 n3 = 1, n2 = [1..4] - * n = 90, 180 n3 = 2, n2 = [1..2] - * - * Note that the expression `n & (n-1) == 0` is equivalent - * to the check that `n` is a power of 2. */ - - (inverse ? ifft_5 : ffft_5)(x, y[is], n /= 5); - - for (i3 = 0; n & (n - 1); i3++, is ^= 1) - (inverse ? ifft_bf3 : ffft_bf3)(twiddles_bf3[i3], y[is], y[is ^ 1], n /= 3); - - for (i2 = 0; n > 1; i2++, is ^= 1) - (inverse ? ifft_bf2 : ffft_bf2)(twiddles_bf2[i2][i3], y[is], y[is ^ 1], - n >>= 1); - - return y[is]; -} diff --git a/system/embdrv/lc3_dec/Common/fft/fft.h b/system/embdrv/lc3_dec/Common/fft/fft.h deleted file mode 100644 index efc5e11ac9..0000000000 --- a/system/embdrv/lc3_dec/Common/fft/fft.h +++ /dev/null @@ -1,52 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 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. - * - ******************************************************************************/ - -#ifndef __LC3_OWN_FFT_H -#define __LC3_OWN_FFT_H - -#include <stdbool.h> - -/** - * Complex floating point number - */ - -struct fft_complex { - float re, im; -}; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Perform FFT - * inverse True on inverse transform else forward - * x, y0, y1 Input, and 2 scratch buffers of size `n` - * n Number of points 30, 40, 60, 80, 90, 120, 160, 180, 240 - * return The buffer `y0` or `y1` that hold the result - * - * Input `x` can be the same as the `y0` second scratch buffer - */ -struct fft_complex* fft(bool inverse, const struct fft_complex* x, int n, - struct fft_complex* y0, struct fft_complex* y1); - -#ifdef __cplusplus -} -#endif - -#endif /* __LC3_OWN_FFT_H */
\ No newline at end of file diff --git a/system/embdrv/lc3_dec/Decoder/ArithmeticDec.cpp b/system/embdrv/lc3_dec/Decoder/ArithmeticDec.cpp deleted file mode 100644 index d8ea214899..0000000000 --- a/system/embdrv/lc3_dec/Decoder/ArithmeticDec.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* - * ArithmeticDec.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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 "ArithmeticDec.hpp" - -#include <algorithm> // std::min -#include <cmath> -#include <cstring> - -#include "BitReader.hpp" -#include "SpectralDataTables.hpp" -#include "TemporalNoiseShapingTables.hpp" - -namespace Lc3Dec { - -ArithmeticDec::ArithmeticDec(uint16_t NF_, uint16_t NE_, uint16_t rateFlag_, - uint8_t tns_lpc_weighting_) - : NF(NF_), - NE(NE_), - rateFlag(rateFlag_), - tns_lpc_weighting(tns_lpc_weighting_), - X_hat_q_ari(nullptr), - save_lev(nullptr), - nf_seed(0), - nbits_residual(0) { - X_hat_q_ari = new int16_t[NE]; - save_lev = new uint8_t[NE]; -} - -ArithmeticDec::~ArithmeticDec() { - delete[] X_hat_q_ari; - delete[] save_lev; -} - -void ac_dec_init(const uint8_t bytes[], uint16_t* bp, struct ac_dec_state* st) { - st->low = 0; - st->range = 0x00ffffff; - for (uint8_t i = 0; i < 3; i++) { - st->low <<= 8; - st->low += bytes[(*bp)++]; - } -} - -uint8_t ac_decode(const uint8_t bytes[], uint16_t* bp, struct ac_dec_state* st, - int16_t cum_freq[], int16_t sym_freq[], uint8_t numsym, - uint8_t& BEC_detect) { - uint32_t tmp = st->range >> 10; - if (st->low >= (tmp << 10)) { - BEC_detect = 1; - return 0; - } - uint8_t val = numsym - 1; - while (st->low < tmp * cum_freq[val]) { - val--; - } - st->low -= tmp * cum_freq[val]; - st->range = tmp * sym_freq[val]; - while (st->range < 0x10000) { - st->low <<= 8; - st->low &= 0x00ffffff; - st->low += bytes[(*bp)++]; - st->range <<= 8; - } - return val; -} - -double ArithmeticDec::rc_q(uint8_t k, uint8_t f) { - // with Δ =π/17 - const double pi = std::acos(-1); - double quantizer_stepsize = pi / 17.0; - return sin(quantizer_stepsize * (rc_i[k + 8 * f] - 8)); -} - -void ArithmeticDec::run(const uint8_t* bytes, uint16_t& bp, uint16_t& bp_side, - uint8_t& mask_side, int16_t& num_tns_filters, - int16_t rc_order[], const uint8_t& lsbMode, - const int16_t& lastnz, uint16_t nbits, - uint8_t& BEC_detect) { - int16_t c = 0; - - // make local copy of rc_order (is this really what we want) - rc_order_ari[0] = rc_order[0]; - rc_order_ari[1] = rc_order[1]; - - /* Arithmetic Decoder Initialization */ - ac_dec_init(bytes, &bp, &st); - - /* TNS data */ - // Note: some initialization code like that below can be found in d09r02, - // but there has been none in d09r01. However, the complete - // initialization has been added here, in order to get a proper match to - // the reference output data - for (uint8_t f = 0; f < 2; f++) { - for (uint8_t k = 0; k < 8; k++) { - rc_i[k + 8 * f] = 8; - } - } - for (uint8_t f = 0; f < num_tns_filters; f++) { - // if (𝑟𝑐𝑜𝑟𝑑𝑒𝑟(𝑓) > 0) - if (rc_order[f] > 0) { - //𝑟𝑐𝑜𝑟𝑑𝑒𝑟(𝑓) = ac_decode(bytes, &bp, &st, - rc_order_ari[f] = - ac_decode(bytes, &bp, &st, ac_tns_order_cumfreq[tns_lpc_weighting], - ac_tns_order_freq[tns_lpc_weighting], 8, BEC_detect); - if (BEC_detect) { - // early exit to avoid unpredictable side-effects - return; - } - - rc_order_ari[f] = rc_order_ari[f] + 1; - // specification (d09r02_F2F) proposes initialization - // of rc_i at this place; here implemented above in order - // to be performed independet from num_tns_filters - for (uint8_t k = 0; k < rc_order_ari[f]; k++) { - //𝑟𝑐𝑖(𝑘,𝑓) = ac_decode(bytes, &bp, &st, ac_tns_coef_cumfreq[k], - // rc_i[k][f] = ac_decode(bytes, &bp, &st, ac_tns_coef_cumfreq[k], - rc_i[k + 8 * f] = ac_decode(bytes, &bp, &st, ac_tns_coef_cumfreq[k], - ac_tns_coef_freq[k], 17, BEC_detect); - if (BEC_detect) { - // early exit to avoid unpredictable side-effects - return; - } - } - } - } - - /* Spectral data */ - for (uint16_t k = 0; k < lastnz; k += 2) { - uint16_t t = c + rateFlag; - // if (k > 𝑁𝐸/2) - if (k > NE / 2) { - t += 256; - } - //𝑋𝑞̂[k] = 𝑋𝑞̂[k+1] = 0; - X_hat_q_ari[k] = X_hat_q_ari[k + 1] = 0; - uint8_t lev; - uint8_t sym; - for (lev = 0; lev < 14; lev++) { - uint8_t pki = - ac_spec_lookup[t + std::min(lev, static_cast<uint8_t>(3U)) * 1024]; - sym = ac_decode(bytes, &bp, &st, ac_spec_cumfreq[pki], ac_spec_freq[pki], - 17, BEC_detect); - if (BEC_detect) { - // early exit to avoid unpredictable side-effects - return; - } - if (sym < 16) { - break; - } - if (lsbMode == 0 || lev > 0) { - uint8_t bit = read_bit(bytes, &bp_side, &mask_side); - //𝑋𝑞̂[k] += bit << lev; - X_hat_q_ari[k] += bit << lev; - bit = read_bit(bytes, &bp_side, &mask_side); - //𝑋𝑞̂[k+1] += bit << lev; - X_hat_q_ari[k + 1] += bit << lev; - } - } - if (lev == 14) { - BEC_detect = 1; - return; - } - if (lsbMode == 1) { - save_lev[k] = lev; - } - uint8_t a = sym & 0x3; - uint8_t b = sym >> 2; - //𝑋𝑞̂[k] += a << lev; - //𝑋𝑞̂[k+1] += b << lev; - // if (𝑋𝑞̂[k] > 0) - X_hat_q_ari[k] += a << lev; - X_hat_q_ari[k + 1] += b << lev; - if (X_hat_q_ari[k] > 0) { - uint8_t bit = read_bit(bytes, &bp_side, &mask_side); - if (bit == 1) { - //𝑋𝑞̂[k] = -𝑋𝑞̂[k]; - X_hat_q_ari[k] = -X_hat_q_ari[k]; - } - } - // if (𝑋𝑞̂[k+1] > 0) - if (X_hat_q_ari[k + 1] > 0) { - uint8_t bit = read_bit(bytes, &bp_side, &mask_side); - if (bit == 1) { - //𝑋𝑞̂[k+1] = -𝑋𝑞̂[k+1]; - X_hat_q_ari[k + 1] = -X_hat_q_ari[k + 1]; - } - } - lev = std::min(lev, static_cast<uint8_t>(3)); - if (lev <= 1) { - t = 1 + (a + b) * (lev + 1); - } else { - t = 12 + lev; - } - c = (c & 15) * 16 + t; - // Note: specification of the following line hase been changed from d09r01 - // to d09r02_F2F - if (bp - bp_side > 3) { - BEC_detect = 1; - return; - } - } - // reset remaining fields in array X_hat_q_ari to simplify testing - for (int16_t k = lastnz; k < NE; k++) { - X_hat_q_ari[k] = 0; - } - - // 3.4.2.6 Residual data and finalization (d09r02_F2F) - /* Number of residual bits */ - int16_t nbits_side = nbits - (8 * bp_side + 8 - log2(mask_side)); - int16_t nbits_ari = (bp - 3) * 8; - nbits_ari += 25 - floor(log2(st.range)); - int16_t nbits_residual_tmp = nbits - (nbits_side + nbits_ari); - if (nbits_residual_tmp < 0) { - BEC_detect = 1; - return; - } - nbits_residual = nbits_residual_tmp; -} - -void ArithmeticDec::registerDatapoints(DatapointContainer* datapoints) { - if (nullptr != datapoints) { - datapoints->addDatapoint("rateFlag", &rateFlag, sizeof(rateFlag)); - datapoints->addDatapoint("tns_lpc_weighting", &tns_lpc_weighting, - sizeof(tns_lpc_weighting)); - datapoints->addDatapoint("rc_order_ari", &rc_order_ari[0], - sizeof(rc_order_ari)); - datapoints->addDatapoint("rc_i", &rc_i[0], sizeof(rc_i)); - datapoints->addDatapoint("X_hat_q_ari", &X_hat_q_ari[0], - sizeof(int16_t) * NE); - datapoints->addDatapoint("nbits_residual", &nbits_residual, - sizeof(nbits_residual)); - } -} - -} // namespace Lc3Dec diff --git a/system/embdrv/lc3_dec/Decoder/ArithmeticDec.hpp b/system/embdrv/lc3_dec/Decoder/ArithmeticDec.hpp deleted file mode 100644 index 3e5dd7dfe5..0000000000 --- a/system/embdrv/lc3_dec/Decoder/ArithmeticDec.hpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * ArithmeticDec.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef __ARITHMETIC_DEC_HPP_ -#define __ARITHMETIC_DEC_HPP_ - -#include <cstdint> - -#include "Datapoints.hpp" - -namespace Lc3Dec { - -struct ac_dec_state { - uint32_t low; - uint32_t range; -}; - -class ArithmeticDec { - public: - ArithmeticDec(uint16_t NF_, uint16_t NE_, uint16_t rateFlag_, - uint8_t tns_lpc_weighting_); - virtual ~ArithmeticDec(); - - void registerDatapoints(DatapointContainer* datapoints); - - double rc_q(uint8_t k, uint8_t f); - - void run(const uint8_t* bytes, uint16_t& bp, uint16_t& bp_side, - uint8_t& mask_side, int16_t& num_tns_filters, int16_t rc_order[], - const uint8_t& lsbMode, const int16_t& lastnz, uint16_t nbits, - uint8_t& BEC_detect); - - const uint16_t NF; - const uint16_t NE; - const uint16_t rateFlag; - const uint8_t tns_lpc_weighting; - - // states & outputs - int16_t* X_hat_q_ari; - uint8_t* save_lev; - int16_t nf_seed; - int16_t rc_order_ari[2]; - int16_t rc_i[2 * 8]; // [max(rc_order[f])=8][max(num_tns_filters)=2] - uint16_t nbits_residual; - - private: - struct ac_dec_state st; -}; - -} // namespace Lc3Dec - -#endif // __ARITHMETIC_DEC_HPP_ diff --git a/system/embdrv/lc3_dec/Decoder/BitReader.cpp b/system/embdrv/lc3_dec/Decoder/BitReader.cpp deleted file mode 100644 index 161dfb0e5e..0000000000 --- a/system/embdrv/lc3_dec/Decoder/BitReader.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * BitReader.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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 "BitReader.hpp" - -namespace Lc3Dec { - -uint8_t read_bit(const uint8_t bytes[], uint16_t* bp, uint8_t* mask) { - uint8_t bit; - if (bytes[*bp] & *mask) { - bit = 1; - } else { - bit = 0; - } - if (*mask == 0x80) { - *mask = 1; - *bp -= 1; - } else { - *mask <<= 1; - } - return bit; -} - -uint16_t read_uint(const uint8_t bytes[], uint16_t* bp, uint8_t* mask, - uint8_t numbits) { - uint16_t value = read_bit(bytes, bp, mask); - for (uint8_t i = 1; i < numbits; i++) { - uint16_t bit = read_bit(bytes, bp, mask); - value += bit << i; - } - return value; -} - -} // namespace Lc3Dec diff --git a/system/embdrv/lc3_dec/Decoder/BitReader.hpp b/system/embdrv/lc3_dec/Decoder/BitReader.hpp deleted file mode 100644 index a6def664c6..0000000000 --- a/system/embdrv/lc3_dec/Decoder/BitReader.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * BitReader.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef __BIT_READER_HPP_ -#define __BIT_READER_HPP_ - -#include <cstdint> - -namespace Lc3Dec { - -uint8_t read_bit(const uint8_t bytes[], uint16_t* bp, uint8_t* mask); -uint16_t read_uint(const uint8_t bytes[], uint16_t* bp, uint8_t* mask, - uint8_t numbits); - -} // namespace Lc3Dec - -#endif // __BIT_READER_HPP_ diff --git a/system/embdrv/lc3_dec/Decoder/DecoderFrame.cpp b/system/embdrv/lc3_dec/Decoder/DecoderFrame.cpp deleted file mode 100644 index 5ce8ff8377..0000000000 --- a/system/embdrv/lc3_dec/Decoder/DecoderFrame.cpp +++ /dev/null @@ -1,420 +0,0 @@ -/* - * DecoderFrame.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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 "DecoderFrame.hpp" - -#include <cmath> -#include <cstring> - -#include "BitReader.hpp" - -namespace Lc3Dec { - -DecoderFrame::DecoderFrame(ResidualSpectrum& residualSpectrum_, - SpectralNoiseShaping& spectralNoiseShaping_, - PacketLossConcealment& packetLossConcealment_, - MdctDec& mdctDec_, const Lc3Config& lc3Config_, - uint16_t nbytes_) - : nbytes(nbytes_), - nbits(nbytes_ * 8), - lc3Config(lc3Config_), - tns_lpc_weighting( - (nbits < - ((lc3Config.N_ms == Lc3Config::FrameDuration::d10ms) ? 480 : 360)) - ? 1 - : 0), - sideInformation(lc3Config.NF, lc3Config.NE, lc3Config.Fs_ind), - arithmeticDec(lc3Config.NF, lc3Config.NE, - (nbits > (160 + lc3Config.Fs_ind * 160)) ? 512 : 0, - tns_lpc_weighting), - residualSpectrum(residualSpectrum_), - spectralNoiseShaping(spectralNoiseShaping_), - packetLossConcealment(packetLossConcealment_), - mdctDec(mdctDec_), - longTermPostfilter(lc3Config, nbits), - - datapoints(nullptr), - - frameN(0), - lastnz(0), - P_BW(0), - lsbMode(0), - gg_ind(0), - num_tns_filters(0), - pitch_present(0), - pitch_index(0), - ltpf_active(0), - F_NF(0), - ind_LF(0), - ind_HF(0), - Gind(0), - LS_indA(0), - LS_indB(0), - idxA(0), - idxB(0), - nf_seed(0), - zeroFrame(0), - gg_off(0), - X_hat_q_nf(nullptr), - X_hat_f(nullptr), - X_s_tns(nullptr), - X_hat_ss(nullptr), - x_hat_clip(nullptr) { - rc_order[0] = 0; - rc_order[1] = 0; - - X_hat_q_nf = new double[lc3Config.NE]; - X_hat_f = new double[lc3Config.NE]; - X_s_tns = new double[lc3Config.NE]; - X_hat_ss = new double[lc3Config.NE]; -} - -DecoderFrame::~DecoderFrame() { - if (nullptr != X_hat_q_nf) { - delete[] X_hat_q_nf; - } - if (nullptr != X_hat_f) { - delete[] X_hat_f; - } - if (nullptr != X_s_tns) { - delete[] X_s_tns; - } - if (nullptr != X_hat_ss) { - delete[] X_hat_ss; - } - if (nullptr != x_hat_clip) { - delete[] x_hat_clip; - } -} - -void DecoderFrame::linkPreviousFrame(DecoderFrame* previousFrame) { - if (nullptr != previousFrame) { - longTermPostfilter = previousFrame->longTermPostfilter; - frameN = previousFrame->frameN; - } -} - -void DecoderFrame::noiseFilling() { - // 3.4.4 Noise filling (d09r02_F2F) - // including extensions according to: - // section 3.4.4. Noise filling (d09r04) - // Noise filling is performed only when zeroFrame is 0. - for (int16_t k = 0; k < lc3Config.NE; k++) { - X_hat_q_nf[k] = residualSpectrum.X_hat_q_residual[k]; - } - if (0 == zeroFrame) { - // bandwidth(𝑃𝑏𝑤) - // NB WB SSWB SWB FB - //𝑏𝑤_𝑠𝑡𝑜𝑝 80 160 240 320 400 - uint16_t bw_stop_table[5] = {80, 160, 240, 320, 400}; - uint16_t bw_stop = bw_stop_table[P_BW]; - if (lc3Config.N_ms == Lc3Config::FrameDuration::d7p5ms) { - bw_stop *= 3; - bw_stop /= 4; - } - - uint16_t NFstart = - (lc3Config.N_ms == Lc3Config::FrameDuration::d10ms) ? 24 : 18; - uint16_t NFwidth = - (lc3Config.N_ms == Lc3Config::FrameDuration::d10ms) ? 3 : 2; - - /* - 𝐿𝑁𝐹 ̂ = (8-𝐹𝑁𝐹)/16; - for k=0..bw_stop-1 - if 𝐼𝑁𝐹(k)==1 - nf_seed = (13849+nf_seed*31821) & 0xFFFF; - if nf_seed<0x8000 - 𝑋𝑞 ̂(𝑘) = 𝐿𝑁𝐹 ̂ ; - else - 𝑋𝑞 ̂(𝑘) = −𝐿𝑁𝐹 ̂ ; - */ - uint16_t nf_state = nf_seed; - double L_NF_hat = (8 - F_NF) / 16.0; - for (uint16_t k = 0; k < bw_stop; k++) { - /* - The indices for the relevant spectral coefficients are given by: - 𝐼𝑁𝐹 (𝑘) = { - 1 if 24 ≤ 𝑘 < 𝑏𝑤_𝑠𝑡𝑜𝑝 𝑎𝑛𝑑 𝑋𝑞 ̂(𝑖) == 0 𝑓𝑜𝑟 𝑎𝑙𝑙 𝑖 = 𝑘 − 3. . min(𝑏𝑤𝑠𝑡𝑜𝑝 - − 1, 𝑘 + 3) 0 otherwise # (109) where 𝑏𝑤_𝑠𝑡𝑜𝑝 depends on the bandwidth - information (see Section 3.4.2.4) as defined in Table 3.17. - */ - uint8_t I_NF_k = 0; - if ((NFstart <= k) && (k < bw_stop)) { - uint16_t limit = - ((bw_stop - 1) < (k + NFwidth)) ? (bw_stop - 1) : (k + NFwidth); - I_NF_k = 1; - for (uint16_t i = k - NFwidth; i <= limit; i++) { - if (0 != residualSpectrum.X_hat_q_residual[i]) { - I_NF_k = 0; - break; - } - } - } - - if (1 == I_NF_k) { - nf_state = (13849 + nf_state * 31821) & 0xFFFF; - if (nf_state < 0x8000) { - X_hat_q_nf[k] = L_NF_hat; - } else { - X_hat_q_nf[k] = -L_NF_hat; - } - } - } - } -} - -void DecoderFrame::applyGlobalGain() { - // 3.4.5 Global gain (d09r02_F2F) - // The global gain is applied to the spectrum after noise filling has been - // applied using the following formula (110) & (111) - int16_t v1 = nbits / (10 * (lc3Config.Fs_ind + 1)); - if (v1 > 115) { - gg_off = -115; - } else { - gg_off = -v1; - } - gg_off -= 105; - gg_off -= 5 * (lc3Config.Fs_ind + 1); - - double exponent = (gg_ind + gg_off) / 28.0; - double gg = pow(10.0, exponent); - for (int16_t k = 0; k < lc3Config.NE; k++) { - X_hat_f[k] = gg * X_hat_q_nf[k]; - } -} - -void DecoderFrame::temporalNoiseShaping() { - // 3.4.6 TNS DecoderFrame (d09r02_F2F) - /* - for 𝑘 = 0 to 𝑁𝐸 − 1 do { - 𝑋𝑠 ̂(𝑛) = 𝑋𝑓 ̂(𝑛) - } - s0 = s1 = s2 = s3 = s4 = s5 = s6 = s7 = 0 - for 𝑓 = 0 to num_tns_filters-1 do { - if (𝑟𝑐𝑜𝑟𝑑𝑒𝑟 (𝑓) > 0) - { - for 𝑛 = start_freq(𝑓) to stop_freq(f) − 1 do { - t = 𝑋𝑓 ̂ (𝑛) − 𝑟𝑐𝑞 (𝑟𝑐𝑜𝑟𝑑𝑒𝑟 (𝑓) − 1 , 𝑓) ∙ 𝑠𝑟𝑐𝑜𝑟𝑑𝑒𝑟(𝑓)−1 - for 𝑘 = 𝑟𝑐𝑜𝑟𝑑𝑒𝑟 (𝑓) − 2 to 0 do { - 𝑡 = 𝑡 − 𝑟𝑐𝑞 (𝑘, 𝑓) ∙ 𝑠𝑘 - 𝑠𝑘+1 = 𝑟𝑐𝑞 (𝑘, 𝑓) ∙ 𝑡 + 𝑠𝑘 - } - 𝑋𝑆 ̂(𝑛) = 𝑡 - 𝑠0 = 𝑡 - } - } - } - */ - uint16_t start_freq[2] = {12, 160}; - uint16_t stop_freq[2]; - if (lc3Config.N_ms == Lc3Config::FrameDuration::d10ms) { - if (4 == P_BW) start_freq[1] = 200; - switch (P_BW) { - case 0: - stop_freq[0] = 80; - break; - case 1: - stop_freq[0] = 160; - break; - case 2: - stop_freq[0] = 240; - break; - case 3: - stop_freq[0] = 160; - stop_freq[1] = 320; - break; - case 4: - stop_freq[0] = 200; - stop_freq[1] = 400; - break; - } - } else { - start_freq[0] = 9; - if (3 == P_BW) start_freq[1] = 120; // Errata 15098 implemented - if (4 == P_BW) start_freq[1] = 150; - switch (P_BW) { - case 0: - stop_freq[0] = 60; - break; - case 1: - stop_freq[0] = 120; - break; - case 2: - stop_freq[0] = 180; - break; - case 3: - // stop_freq[0] = 119; // this value is specified in Table 3.19 - // (d09r06_KLG_AY_NH_FhG, 2019-12-20), but gives poor match to 32kHz - // decoder tests compared to reference decoder - stop_freq[0] = 120; // this value gives good match to reference decoder - // and is more consistent to 10ms case - stop_freq[1] = 240; - break; - case 4: - stop_freq[0] = 150; - stop_freq[1] = 300; - break; - } - } - - for (int16_t k = 0; k < lc3Config.NE; k++) { - X_s_tns[k] = X_hat_f[k]; - } - double s[8]; - for (uint8_t k = 0; k < 8; k++) { - s[k] = 0.0; - } - for (uint8_t f = 0; f < num_tns_filters; f++) { - if (arithmeticDec.rc_order_ari[f] > 0) { - for (uint16_t n = start_freq[f]; n < stop_freq[f]; n++) { - double t = X_hat_f[n] - - arithmeticDec.rc_q(arithmeticDec.rc_order_ari[f] - 1, f) * - s[arithmeticDec.rc_order_ari[f] - 1]; - for (int8_t k = arithmeticDec.rc_order_ari[f] - 2; k >= 0; k--) { - t = t - arithmeticDec.rc_q(k, f) * s[k]; - s[k + 1] = arithmeticDec.rc_q(k, f) * t + s[k]; - } - X_s_tns[n] = t; - s[0] = t; - } - } - } -} - -void DecoderFrame::runFloat(const uint8_t* bytes, uint8_t BFI, - uint8_t& BEC_detect) { - // increment frame counter - frameN++; - - // 5.4.2.2 Initialization - uint16_t bp = 0; - uint16_t bp_side = nbytes - 1; - uint8_t mask_side = 1; - BEC_detect = BFI; // Note: the base specification initializes BEC_detect with - // zero, but initialization with BFI is more meaningful - - // 5.4.2.3 Side information - if (!BEC_detect) { - sideInformation.run(bytes, bp_side, mask_side, P_BW, lastnz, lsbMode, - gg_ind, num_tns_filters, rc_order, pitch_present, - pitch_index, ltpf_active, F_NF, ind_LF, ind_HF, Gind, - LS_indA, LS_indB, idxA, idxB, BEC_detect); - } - - // 3.4.2.4 Bandwidth interpretation (d09r02_F2F) - // ...included somewhere else? - - // 3.4.2.5 Arithmetic decoding (d09r02_F2F) - if (!BEC_detect) { - arithmeticDec.run(bytes, bp, bp_side, mask_side, num_tns_filters, rc_order, - lsbMode, lastnz, nbits, BEC_detect); - } - - if (!BEC_detect) { - /* Decode residual bits */ - // and 3.4.3 Residual decoding (d09r02_F2F) - residualSpectrum.run(bytes, bp_side, mask_side, lastnz, - arithmeticDec.X_hat_q_ari, - arithmeticDec.nbits_residual, arithmeticDec.save_lev, - lsbMode, nf_seed, zeroFrame, gg_ind, F_NF); - - // 3.4.4 Noise filling (d09r02_F2F) - noiseFilling(); - - // 3.4.5 Global gain (d09r02_F2F) - applyGlobalGain(); - - // 3.4.6 TNS decoder (d09r02_F2F) - temporalNoiseShaping(); - - // 3.4.7 SNS decoder (d09r02_F2F) - spectralNoiseShaping.run( - X_s_tns, X_hat_ss, ind_LF, ind_HF, sideInformation.submodeMSB, - sideInformation.submodeLSB, Gind, LS_indA, LS_indB, idxA, idxB); - } - - // Appendix B. Packet Loss Concealment (d09r02_F2F) - packetLossConcealment.run(BEC_detect, X_hat_ss, ltpf_active); - - // 3.4.8 Low delay MDCT synthesis (d09r02_F2F) - mdctDec.run(X_hat_ss); - - // 3.4.9 Long Term Postfilter (d09r02_F2F) - if (0 == pitch_present) { - pitch_index = 0; - ltpf_active = 0; - } - longTermPostfilter.setInputX(mdctDec.x_hat_mdct); - longTermPostfilter.run(ltpf_active, pitch_index); -} - -void DecoderFrame::registerDatapoints(DatapointContainer* datapoints_) { - datapoints = datapoints_; - if (nullptr != datapoints) { - datapoints->addDatapoint("fs_idx", &lc3Config.Fs_ind, - sizeof(lc3Config.Fs_ind)); - - datapoints->addDatapoint("frameN", &frameN, sizeof(frameN)); - - datapoints->addDatapoint("lastnz", &lastnz, sizeof(lastnz)); - datapoints->addDatapoint("P_BW", &P_BW, sizeof(P_BW)); - datapoints->addDatapoint("lsbMode", &lsbMode, sizeof(lsbMode)); - datapoints->addDatapoint("gg_ind", &gg_ind, sizeof(gg_ind)); - datapoints->addDatapoint("num_tns_filters", &num_tns_filters, - sizeof(num_tns_filters)); - datapoints->addDatapoint("rc_order", &rc_order[0], sizeof(rc_order)); - datapoints->addDatapoint("pitch_index", &pitch_index, sizeof(pitch_index)); - datapoints->addDatapoint("pitch_present", &pitch_present, - sizeof(pitch_present)); - datapoints->addDatapoint("ltpf_active", <pf_active, sizeof(ltpf_active)); - datapoints->addDatapoint("F_NF", &F_NF, sizeof(F_NF)); - datapoints->addDatapoint("ind_LF", &ind_LF, sizeof(ind_LF)); - datapoints->addDatapoint("ind_HF", &ind_HF, sizeof(ind_HF)); - datapoints->addDatapoint("Gind", &Gind, sizeof(Gind)); - datapoints->addDatapoint("LS_indA", &LS_indA, sizeof(LS_indA)); - datapoints->addDatapoint("idxA", &idxA, sizeof(idxA)); - datapoints->addDatapoint("idxB", &idxB, sizeof(idxB)); - - datapoints->addDatapoint("nf_seed", &nf_seed, sizeof(nf_seed)); - datapoints->addDatapoint("zeroFrame", &zeroFrame, sizeof(zeroFrame)); - - datapoints->addDatapoint("gg_off", &gg_off, sizeof(gg_off)); - datapoints->addDatapoint("rc_i_tns", &arithmeticDec.rc_i[0], - sizeof(arithmeticDec.rc_i[0]) * 8); - - datapoints->addDatapoint("X_hat_q_nf", &X_hat_q_nf[0], - sizeof(double) * lc3Config.NE); - datapoints->addDatapoint("X_s_tns", &X_s_tns[0], - sizeof(double) * lc3Config.NE); - datapoints->addDatapoint("X_hat_ss", &X_hat_ss[0], - sizeof(double) * lc3Config.NE); - - if (nullptr == x_hat_clip) { - x_hat_clip = new double[lc3Config.NF]; - } - datapoints->addDatapoint("x_hat_clip", &x_hat_clip[0], - sizeof(double) * lc3Config.NF); - - sideInformation.registerDatapoints(datapoints); - arithmeticDec.registerDatapoints(datapoints); - longTermPostfilter.registerDatapoints(datapoints); - } -} - -} // namespace Lc3Dec diff --git a/system/embdrv/lc3_dec/Decoder/DecoderFrame.hpp b/system/embdrv/lc3_dec/Decoder/DecoderFrame.hpp deleted file mode 100644 index 4ce1c86b66..0000000000 --- a/system/embdrv/lc3_dec/Decoder/DecoderFrame.hpp +++ /dev/null @@ -1,147 +0,0 @@ -/* - * DecoderFrame.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef __DECODER_FRAME_HPP_ -#define __DECODER_FRAME_HPP_ - -#include <cstdint> - -#include "ArithmeticDec.hpp" -#include "Datapoints.hpp" -#include "Lc3Config.hpp" -#include "LongTermPostfilter.hpp" -#include "MdctDec.hpp" -#include "PacketLossConcealment.hpp" -#include "ResidualSpectrum.hpp" -#include "SideInformation.hpp" -#include "SpectralNoiseShaping.hpp" - -namespace Lc3Dec { - -class DecoderFrame { - public: - DecoderFrame(ResidualSpectrum& residualSpectrum_, - SpectralNoiseShaping& spectralNoiseShaping_, - PacketLossConcealment& packetLossConcealment_, MdctDec& mdctDec_, - const Lc3Config& lc3Config_, uint16_t nbytes_); - virtual ~DecoderFrame(); - - void registerDatapoints(DatapointContainer* datapoints_); - - template <typename T> - void run(const uint8_t* bytes, uint8_t BFI, - uint16_t bits_per_audio_sample_dec, T* x_out, uint8_t& BEC_detect) { - if (!lc3Config.isValid()) { - return; - } - - // main decoder implementation: 3.4.1 until 3.4.9 (d09r06) - runFloat(bytes, BFI, BEC_detect); - - // 3.4.10 Output signal scaling and rounding (d09r06) - const uint32_t outputScale = 1UL << (-15 + bits_per_audio_sample_dec - 1); - for (uint16_t k = 0; k < lc3Config.NF; k++) { - double x_hat_clip_local; - if (longTermPostfilter.x_hat_ltpf[k] > 32767) { - x_hat_clip_local = 32767; - } else if (longTermPostfilter.x_hat_ltpf[k] < -32768) { - x_hat_clip_local = -32768; - } else { - x_hat_clip_local = longTermPostfilter.x_hat_ltpf[k]; - } - - // datapoint buffer for x_hat_clip only prepared when datapoints are - // available - if (nullptr != x_hat_clip) { - x_hat_clip[k] = x_hat_clip_local; - } - - // Round 𝑥 to nearest integer, e.g., ⌊−4.5⌉ = −5, ⌊−3.2⌉ = −3, ⌊3.2⌉ = 3, - // ⌊4.5⌉ = 5, - if (x_hat_clip_local > 0) { - x_out[k] = outputScale * x_hat_clip_local + 0.5; - } else { - x_out[k] = outputScale * x_hat_clip_local - 0.5; - } - } - - if (nullptr != datapoints) { - datapoints->log("x_out", &x_out[0], sizeof(T) * lc3Config.NF); - datapoints->log("BER_detect", &BEC_detect, sizeof(BEC_detect)); - } - } - - void linkPreviousFrame(DecoderFrame* previousFrame); - - // per instance constant parameter - const uint16_t nbytes; - const uint16_t nbits; - const Lc3Config& lc3Config; - const uint8_t tns_lpc_weighting; - - private: - void runFloat(const uint8_t* bytes, uint8_t BFI, uint8_t& BEC_detect); - - void noiseFilling(); - void applyGlobalGain(); - void temporalNoiseShaping(); - - SideInformation sideInformation; - ArithmeticDec arithmeticDec; - ResidualSpectrum& residualSpectrum; - SpectralNoiseShaping& spectralNoiseShaping; - PacketLossConcealment& packetLossConcealment; - MdctDec& mdctDec; - LongTermPostfilter longTermPostfilter; - - DatapointContainer* datapoints; - - // states & outputs - int16_t frameN; - - int16_t lastnz; - int16_t P_BW; - uint8_t lsbMode; - int16_t gg_ind; - int16_t num_tns_filters; - int16_t rc_order[2]; - uint8_t pitch_present; - int16_t pitch_index; - int16_t ltpf_active; - int16_t F_NF; - int16_t ind_LF; - int16_t ind_HF; - int16_t Gind; - int16_t LS_indA; - int16_t LS_indB; - int32_t idxA; - int16_t idxB; - uint16_t nf_seed; - uint16_t zeroFrame; - int16_t gg_off; - double* X_hat_q_nf; - double* X_hat_f; - double* X_s_tns; - double* X_hat_ss; - double* x_hat_clip; -}; - -} // namespace Lc3Dec - -#endif // __DECODER_FRAME_HPP_ diff --git a/system/embdrv/lc3_dec/Decoder/DecoderTop.cpp b/system/embdrv/lc3_dec/Decoder/DecoderTop.cpp deleted file mode 100644 index 5b7f6acb36..0000000000 --- a/system/embdrv/lc3_dec/Decoder/DecoderTop.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * DecoderTop.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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 "DecoderTop.hpp" - -namespace Lc3Dec { - -DecoderTop::DecoderTop(uint16_t fs_, DatapointContainer* datapoints_) - : DecoderTop(Lc3Config(fs_, Lc3Config::FrameDuration::d10ms, 1), - datapoints_) {} - -DecoderTop::DecoderTop(Lc3Config lc3Config_, DatapointContainer* datapoints_) - : lc3Config(lc3Config_), - datapoints(datapoints_), - decoderCurrentFrame(nullptr), - decoderPreviousFrame(nullptr), - residualSpectrum(lc3Config_.NE), - spectralNoiseShaping(lc3Config), - packetLossConcealment(lc3Config_.NE), - mdctDec(lc3Config) { - if (nullptr != datapoints) { - residualSpectrum.registerDatapoints(datapoints); - spectralNoiseShaping.registerDatapoints(datapoints); - packetLossConcealment.registerDatapoints(datapoints); - mdctDec.registerDatapoints(datapoints); - } -} - -DecoderTop::~DecoderTop() { - if (nullptr != decoderPreviousFrame) { - delete decoderPreviousFrame; - } - if (nullptr != decoderCurrentFrame) { - delete decoderCurrentFrame; - } -} - -} // namespace Lc3Dec diff --git a/system/embdrv/lc3_dec/Decoder/DecoderTop.hpp b/system/embdrv/lc3_dec/Decoder/DecoderTop.hpp deleted file mode 100644 index 268a574621..0000000000 --- a/system/embdrv/lc3_dec/Decoder/DecoderTop.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * DecoderTop.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef __DECODER_TOP_HPP_ -#define __DECODER_TOP_HPP_ - -#include <cstdint> - -#include "Datapoints.hpp" -#include "DecoderFrame.hpp" -#include "Lc3Config.hpp" -#include "MdctDec.hpp" -#include "PacketLossConcealment.hpp" -#include "ResidualSpectrum.hpp" -#include "SpectralNoiseShaping.hpp" - -namespace Lc3Dec { - -class DecoderTop { - public: - DecoderTop(uint16_t fs_, DatapointContainer* datapoints_ = nullptr); - DecoderTop(Lc3Config lc3Config_, DatapointContainer* datapoints_ = nullptr); - virtual ~DecoderTop(); - - template <typename T> - void run(const uint8_t* bytes, uint16_t nbytes, uint8_t BFI, - uint8_t bits_per_audio_sample_dec, T* x_out, uint8_t& BEC_detect) { - if ((nullptr == decoderCurrentFrame) || - (decoderCurrentFrame->nbytes != nbytes)) { - // We need to instantiate a new DecoderFrame only - // when byte_count has been changed. Thus, frequent - // dynamic memory allocation can be constrained to - // rate optimized operation. - if (nullptr != decoderPreviousFrame) { - delete decoderPreviousFrame; - } - decoderPreviousFrame = decoderCurrentFrame; - decoderCurrentFrame = - new DecoderFrame(residualSpectrum, spectralNoiseShaping, - packetLossConcealment, mdctDec, lc3Config, nbytes); - decoderCurrentFrame->linkPreviousFrame(decoderPreviousFrame); - if (nullptr != datapoints) { - // Another way to make to call optional would be to split run() into - // init(), registerDatapoints() & remaining run() -> we preferred the - // simpler - // API and thus designed this registration being dependent on the - // availability of datapoints. - decoderCurrentFrame->registerDatapoints(datapoints); - } - } - decoderCurrentFrame->run<T>(bytes, BFI, bits_per_audio_sample_dec, x_out, - BEC_detect); - } - - const Lc3Config lc3Config; - - private: - DatapointContainer* datapoints; - DecoderFrame* decoderCurrentFrame; - DecoderFrame* decoderPreviousFrame; - ResidualSpectrum residualSpectrum; - SpectralNoiseShaping spectralNoiseShaping; - PacketLossConcealment packetLossConcealment; - MdctDec mdctDec; -}; - -} // namespace Lc3Dec - -#endif // __DECODER_TOP_HPP_ diff --git a/system/embdrv/lc3_dec/Decoder/Lc3Decoder.cpp b/system/embdrv/lc3_dec/Decoder/Lc3Decoder.cpp deleted file mode 100644 index ccc7cf4fbc..0000000000 --- a/system/embdrv/lc3_dec/Decoder/Lc3Decoder.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Lc3Decoder.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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 "Lc3Decoder.hpp" - -#include <cstring> - -#include "DecoderTop.hpp" - -using namespace Lc3Dec; - -Lc3Decoder::Lc3Decoder(uint16_t Fs, Lc3Config::FrameDuration frameDuration) - : Lc3Decoder(Lc3Config(Fs, frameDuration, 1)) {} - -Lc3Decoder::Lc3Decoder(Lc3Config lc3Config_, uint8_t bits_per_audio_sample_dec_, - uint16_t byte_count_max_dec_, void* datapoints) - : lc3Config(lc3Config_), - bits_per_audio_sample_dec(bits_per_audio_sample_dec_), - byte_count_max_dec((byte_count_max_dec_ < 400) ? byte_count_max_dec_ - : 400), - decoderList(lc3Config.Nc) { - // proceed only with valid configuration - if (lc3Config.isValid()) { - for (uint8_t channelNr = 0; channelNr < lc3Config.Nc; channelNr++) { - decoderList[channelNr] = new DecoderTop( - lc3Config, reinterpret_cast<DatapointContainer*>(datapoints)); - } - } -} - -Lc3Decoder::~Lc3Decoder() { - for (uint8_t channelNr = 0; channelNr < lc3Config.Nc; channelNr++) { - DecoderTop* decoderTop = decoderList[channelNr]; - if (nullptr != decoderTop) { - delete decoderTop; - } - } -} - -uint8_t Lc3Decoder::run(const uint8_t* bytes, uint16_t byte_count, uint8_t BFI, - int16_t* x_out, uint16_t x_out_size, - uint8_t& BEC_detect, uint8_t channelNr) { - if (!lc3Config.isValid()) { - return INVALID_CONFIGURATION; - } - if ((byte_count < 20) || (byte_count > byte_count_max_dec)) { - return INVALID_BYTE_COUNT; - } - if (lc3Config.NF != x_out_size) { - return INVALID_X_OUT_SIZE; - } - if (bits_per_audio_sample_dec != 16) { - return INVALID_BITS_PER_AUDIO_SAMPLE; - } - if (nullptr == decoderList[channelNr]) { - return DECODER_ALLOCATION_ERROR; - } - - decoderList[channelNr]->run<int16_t>( - bytes, byte_count, BFI, bits_per_audio_sample_dec, x_out, BEC_detect); - return ERROR_FREE; -} - -uint8_t Lc3Decoder::run(const uint8_t* bytes, uint16_t byte_count, uint8_t BFI, - int32_t* x_out, uint16_t x_out_size, - uint8_t& BEC_detect, uint8_t channelNr) { - if (!lc3Config.isValid()) { - return INVALID_CONFIGURATION; - } - if ((byte_count < 20) || (byte_count > byte_count_max_dec)) { - return INVALID_BYTE_COUNT; - } - if (lc3Config.NF != x_out_size) { - return INVALID_X_OUT_SIZE; - } - if ((bits_per_audio_sample_dec != 16) && (bits_per_audio_sample_dec != 24) && - (bits_per_audio_sample_dec != 32)) { - return INVALID_BITS_PER_AUDIO_SAMPLE; - } - if (nullptr == decoderList[channelNr]) { - return DECODER_ALLOCATION_ERROR; - } - - decoderList[channelNr]->run<int32_t>( - bytes, byte_count, BFI, bits_per_audio_sample_dec, x_out, BEC_detect); - return ERROR_FREE; -} - -uint8_t Lc3Decoder::run(const uint8_t* bytes, - const uint16_t* byte_count_per_channel, - const uint8_t* BFI_per_channel, int16_t* x_out, - uint32_t x_out_size, uint8_t* BEC_detect_per_channel) { - if (!lc3Config.isValid()) { - return INVALID_CONFIGURATION; - } - if (lc3Config.NF * lc3Config.Nc != x_out_size) { - return INVALID_X_OUT_SIZE; - } - - uint8_t returnCode = ERROR_FREE; - uint32_t byteOffset = 0; - for (uint8_t channelNr = 0; channelNr < lc3Config.Nc; channelNr++) { - // Note: bitwise or of the single channel return code will not allow - // uniquely to decode - // the given error. The idea is to catch any error. This decision - // makes the API more simple. However, when the precise error code is - // needed, the single channel call has to be made separately. - returnCode |= - run(&bytes[byteOffset], byte_count_per_channel[channelNr], - BFI_per_channel[channelNr], &x_out[channelNr * lc3Config.NF], - lc3Config.NF, BEC_detect_per_channel[channelNr], channelNr); - byteOffset += byte_count_per_channel[channelNr]; - } - return returnCode; -} - -uint8_t Lc3Decoder::run(const uint8_t* bytes, - const uint16_t* byte_count_per_channel, - const uint8_t* BFI_per_channel, int32_t* x_out, - uint32_t x_out_size, uint8_t* BEC_detect_per_channel) { - if (!lc3Config.isValid()) { - return INVALID_CONFIGURATION; - } - if (lc3Config.NF * lc3Config.Nc != x_out_size) { - return INVALID_X_OUT_SIZE; - } - - uint8_t returnCode = ERROR_FREE; - uint32_t byteOffset = 0; - for (uint8_t channelNr = 0; channelNr < lc3Config.Nc; channelNr++) { - // Note: bitwise or of the single channel return code will not allow - // uniquely to decode - // the given error. The idea is to catch any error. This decision - // makes the API more simple. However, when the precise error code is - // needed, the single channel call has to be made separately. - returnCode |= - run(&bytes[byteOffset], byte_count_per_channel[channelNr], - BFI_per_channel[channelNr], &x_out[channelNr * lc3Config.NF], - lc3Config.NF, BEC_detect_per_channel[channelNr], channelNr); - byteOffset += byte_count_per_channel[channelNr]; - } - return returnCode; -} diff --git a/system/embdrv/lc3_dec/Decoder/LongTermPostfilter.cpp b/system/embdrv/lc3_dec/Decoder/LongTermPostfilter.cpp deleted file mode 100644 index 3838c7f7e7..0000000000 --- a/system/embdrv/lc3_dec/Decoder/LongTermPostfilter.cpp +++ /dev/null @@ -1,472 +0,0 @@ -/* - * LongTermPostfilter.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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 "LongTermPostfilter.hpp" - -#include <cmath> - -#include "LongTermPostfilterCoefficients.hpp" - -namespace Lc3Dec { - -LongTermPostfilter::LongTermPostfilter(const Lc3Config& lc3Config_, - uint16_t nbits) - : lc3Config(lc3Config_), - numMemBlocks((lc3Config.N_ms == Lc3Config::FrameDuration::d10ms) ? 2 : 3), - x_hat_ltpf(nullptr), - ltpf_active_prev(0), - blockStartIndex(0), - c_num(nullptr), - c_den(nullptr), - c_num_mem(nullptr), - c_den_mem(nullptr), - x_hat_ltpfin(nullptr), - x_hat_mem(nullptr), - x_hat_ltpf_mem(nullptr), - p_int(0), - p_fr(0), - p_int_mem(0), - p_fr_mem(0) { - x_hat_ltpfin = new double[lc3Config.NF]; - x_hat_mem = new double[lc3Config.NF * numMemBlocks]; - x_hat_ltpf = new double[lc3Config.NF]; - x_hat_ltpf_mem = new double[lc3Config.NF * numMemBlocks]; - - for (uint16_t n = 0; n < lc3Config.NF * numMemBlocks; n++) { - x_hat_mem[n] = 0.0; - x_hat_ltpf_mem[n] = 0.0; - } - - setGainParams(nbits); - - L_den = ceil(lc3Config.Fs / 4000.0); - if (L_den < 4) L_den = 4; - L_num = L_den - 2; - - c_num = new double[L_num + 1]; - c_den = new double[L_den + 1]; - c_num_mem = new double[L_num + 1]; - c_den_mem = new double[L_den + 1]; -} - -LongTermPostfilter::~LongTermPostfilter() { - if (nullptr != x_hat_ltpfin) { - delete[] x_hat_ltpfin; - } - if (nullptr != x_hat_mem) { - delete[] x_hat_mem; - } - if (nullptr != x_hat_ltpf) { - delete[] x_hat_ltpf; - } - if (nullptr != x_hat_ltpf_mem) { - delete[] x_hat_ltpf_mem; - } - if (nullptr != c_num) { - delete[] c_num; - } - if (nullptr != c_den) { - delete[] c_den; - } - if (nullptr != c_num_mem) { - delete[] c_num_mem; - } - if (nullptr != c_den_mem) { - delete[] c_den_mem; - } -} - -LongTermPostfilter& LongTermPostfilter::operator=( - const LongTermPostfilter& src) { - // TODO we should assert, that NF is equal in src and *this! - - ltpf_active_prev = src.ltpf_active_prev; - blockStartIndex = src.blockStartIndex; - p_int = src.p_int; - p_fr = src.p_fr; - p_int_mem = src.p_int_mem; - p_fr_mem = src.p_fr_mem; - - for (uint16_t k = 0; k < lc3Config.NF; k++) { - x_hat_ltpfin[k] = src.x_hat_ltpfin[k]; - x_hat_mem[k] = src.x_hat_mem[k]; - x_hat_mem[k + lc3Config.NF] = src.x_hat_mem[k + lc3Config.NF]; - if (numMemBlocks > 2) { - x_hat_mem[k + lc3Config.NF * 2] = src.x_hat_mem[k + lc3Config.NF * 2]; - } - x_hat_ltpf[k] = src.x_hat_ltpf[k]; - x_hat_ltpf_mem[k] = src.x_hat_ltpf_mem[k]; - x_hat_ltpf_mem[k + lc3Config.NF] = src.x_hat_ltpf_mem[k + lc3Config.NF]; - if (numMemBlocks > 2) { - x_hat_ltpf_mem[k + lc3Config.NF * 2] = - src.x_hat_ltpf_mem[k + lc3Config.NF * 2]; - } - } - for (uint8_t k = 0; k < L_num + 1; k++) { - c_num[k] = src.c_num[k]; - c_num_mem[k] = src.c_num_mem[k]; - } - for (uint8_t k = 0; k < L_den + 1; k++) { - c_den[k] = src.c_den[k]; - c_den_mem[k] = src.c_den_mem[k]; - } - - return *this; -} - -void LongTermPostfilter::setGainParams(uint16_t nbits) { - uint16_t t_nbits = (lc3Config.N_ms == Lc3Config::FrameDuration::d7p5ms) - ? round(nbits * 10 / 7.5) - : nbits; - - if (t_nbits < 320 + lc3Config.Fs_ind * 80) { - gain_ltpf = 0.4; - gain_ind = 0; - } else if (t_nbits < 400 + lc3Config.Fs_ind * 80) { - gain_ltpf = 0.35; - gain_ind = 1; - } else if (t_nbits < 480 + lc3Config.Fs_ind * 80) { - gain_ltpf = 0.3; - gain_ind = 2; - } else if (t_nbits < 560 + lc3Config.Fs_ind * 80) { - gain_ltpf = 0.25; - gain_ind = 3; - } else { - gain_ltpf = 0; - gain_ind = 4; // just a guess so far! - } -} - -void LongTermPostfilter::computeFilterCoeffs(uint16_t pitch_index) { - uint16_t pitch_int; - double pitch_fr; - if (pitch_index >= 440) { - pitch_int = pitch_index - 283; - pitch_fr = 0.0; - } else if (pitch_index >= 380) { - pitch_int = pitch_index / 2 - 63; - pitch_fr = 2 * pitch_index - 4 * pitch_int - 252; - } else { - pitch_int = pitch_index / 4 + 32; - pitch_fr = pitch_index - 4 * pitch_int + 128; - } - double pitch = pitch_int + pitch_fr / 4; - - double pitch_fs = pitch * (8000 * ceil(lc3Config.Fs / 8000.0) / 12800.0); - uint16_t p_up = (pitch_fs * 4) + 0.5; - - // update index parameters for current frame - p_int = p_up / 4; - p_fr = p_up - 4 * p_int; - - double* tab_ltpf_num_fs = - tab_ltpf_num_8000[gain_ind]; // default to avoid warnings - double* tab_ltpf_den_fs = - tab_ltpf_den_8000[p_fr]; // default to avoid warnings - switch (lc3Config.Fs) { - case 8000: - tab_ltpf_num_fs = tab_ltpf_num_8000[gain_ind]; - tab_ltpf_den_fs = tab_ltpf_den_8000[p_fr]; - break; - case 16000: - tab_ltpf_num_fs = tab_ltpf_num_16000[gain_ind]; - tab_ltpf_den_fs = tab_ltpf_den_16000[p_fr]; - break; - case 24000: - tab_ltpf_num_fs = tab_ltpf_num_24000[gain_ind]; - tab_ltpf_den_fs = tab_ltpf_den_24000[p_fr]; - break; - case 32000: - tab_ltpf_num_fs = tab_ltpf_num_32000[gain_ind]; - tab_ltpf_den_fs = tab_ltpf_den_32000[p_fr]; - break; - case 44100: - case 48000: - tab_ltpf_num_fs = tab_ltpf_num_48000[gain_ind]; - tab_ltpf_den_fs = tab_ltpf_den_48000[p_fr]; - break; - } - - for (uint8_t k = 0; k <= L_num; k++) { - c_num[k] = 0.85 * gain_ltpf * tab_ltpf_num_fs[k]; - } - for (uint8_t k = 0; k <= L_den; k++) { - c_den[k] = gain_ltpf * tab_ltpf_den_fs[k]; - } -} - -void LongTermPostfilter::setInputX(const double* const x_hat) { - for (uint16_t n = 0; n < lc3Config.NF; n++) { - x_hat_ltpfin[n] = x_hat[n]; - } -} - -void LongTermPostfilter::run(int16_t ltpf_active, int16_t pitch_index) { - // further register updates (maybe move to explicit registerUpdate method) - p_int_mem = p_int; - p_fr_mem = p_fr; - for (uint8_t k = 0; k <= L_num; k++) { - c_num_mem[k] = c_num[k]; - } - for (uint8_t k = 0; k <= L_den; k++) { - c_den_mem[k] = c_den[k]; - } - - // compute new coefficients - if (1 == ltpf_active) { - computeFilterCoeffs(pitch_index); - } else { - p_int = 0; - p_fr = 0; - for (uint8_t k = 0; k <= L_num; k++) { - c_num[k] = 0; - } - for (uint8_t k = 0; k <= L_den; k++) { - c_den[k] = 0; - } - } - - // start processing of input signal - for (uint16_t n = 0; n < lc3Config.NF; n++) { - x_hat_mem[blockStartIndex + n] = x_hat_ltpfin[n]; - } - double norm = (lc3Config.N_ms == Lc3Config::FrameDuration::d10ms) - ? lc3Config.NF / 4 - : lc3Config.NF / 3; - uint16_t sample2p5ms = - (lc3Config.Fs == 44100) ? 48000 / 400 : lc3Config.Fs / 400; - - if ((0 == ltpf_active) && (0 == ltpf_active_prev)) { - //*** transition case 1 ********************************************** - for (uint16_t n = 0; n < lc3Config.NF; n++) { - x_hat_ltpf_mem[blockStartIndex + n] = x_hat_mem[blockStartIndex + n]; - } - } else if ((1 == ltpf_active) && (0 == ltpf_active_prev)) { - //*** transition case 2 ********************************************** - for (uint16_t n = 0; n < sample2p5ms; n++) { - x_hat_ltpf_mem[blockStartIndex + n] = x_hat_mem[blockStartIndex + n]; - double filtOut = 0.0; - for (uint16_t k = 0; k <= L_num; k++) { - int16_t x_hat_index = blockStartIndex + n - k; - if (x_hat_index < 0) { - x_hat_index += numMemBlocks * lc3Config.NF; - } - filtOut += c_num[k] * x_hat_mem[x_hat_index]; - } - for (uint16_t k = 0; k <= L_den; k++) { - int16_t x_hat_ltpf_index = blockStartIndex + n - p_int + L_den / 2 - k; - if (x_hat_ltpf_index < 0) { - x_hat_ltpf_index += numMemBlocks * lc3Config.NF; - } - filtOut -= c_den[k] * x_hat_ltpf_mem[x_hat_ltpf_index]; - } - filtOut *= n / norm; - x_hat_ltpf_mem[blockStartIndex + n] -= filtOut; - } - - for (uint16_t n = sample2p5ms; n < lc3Config.NF; n++) { - x_hat_ltpf_mem[blockStartIndex + n] = x_hat_mem[blockStartIndex + n]; - double filtOut = 0.0; - for (uint16_t k = 0; k <= L_num; k++) { - int16_t x_hat_index = blockStartIndex + n - k; - if (x_hat_index < 0) { - x_hat_index += numMemBlocks * lc3Config.NF; - } - filtOut += c_num[k] * x_hat_mem[x_hat_index]; - } - for (uint16_t k = 0; k <= L_den; k++) { - int16_t x_hat_ltpf_index = - blockStartIndex + n - p_int + L_den / 2.0 - k; - if (x_hat_ltpf_index < 0) { - x_hat_ltpf_index += numMemBlocks * lc3Config.NF; - } - filtOut -= c_den[k] * x_hat_ltpf_mem[x_hat_ltpf_index]; - } - x_hat_ltpf_mem[blockStartIndex + n] -= filtOut; - } - - } else if ((0 == ltpf_active) && (1 == ltpf_active_prev)) { - //*** transition case 3 ********************************************** - for (uint16_t n = 0; n < sample2p5ms; n++) { - x_hat_ltpf_mem[blockStartIndex + n] = x_hat_mem[blockStartIndex + n]; - double filtOut = 0.0; - for (uint16_t k = 0; k <= L_num; k++) { - int16_t x_hat_index = blockStartIndex + n - k; - if (x_hat_index < 0) { - x_hat_index += numMemBlocks * lc3Config.NF; - } - filtOut += c_num_mem[k] * x_hat_mem[x_hat_index]; - } - for (uint16_t k = 0; k <= L_den; k++) { - int16_t x_hat_ltpf_index = - blockStartIndex + n - p_int_mem + L_den / 2 - k; - if (x_hat_ltpf_index < 0) { - x_hat_ltpf_index += numMemBlocks * lc3Config.NF; - } - filtOut -= c_den_mem[k] * x_hat_ltpf_mem[x_hat_ltpf_index]; - } - filtOut *= 1 - (n / norm); - x_hat_ltpf_mem[blockStartIndex + n] -= filtOut; - } - - for (uint16_t n = sample2p5ms; n < lc3Config.NF; n++) { - x_hat_ltpf_mem[blockStartIndex + n] = x_hat_mem[blockStartIndex + n]; - } - - } else { - if ((p_int == p_int_mem) && (p_fr == p_fr_mem)) { - //*** transition case 4 ********************************************** - for (uint16_t n = 0; n < lc3Config.NF; n++) { - x_hat_ltpf_mem[blockStartIndex + n] = x_hat_mem[blockStartIndex + n]; - double filtOut = 0.0; - for (uint16_t k = 0; k <= L_num; k++) { - int16_t x_hat_index = blockStartIndex + n - k; - if (x_hat_index < 0) { - x_hat_index += numMemBlocks * lc3Config.NF; - } - filtOut += c_num[k] * x_hat_mem[x_hat_index]; - } - for (uint16_t k = 0; k <= L_den; k++) { - int16_t x_hat_ltpf_index = - blockStartIndex + n - p_int + L_den / 2 - k; - if (x_hat_ltpf_index < 0) { - x_hat_ltpf_index += numMemBlocks * lc3Config.NF; - } - filtOut -= c_den[k] * x_hat_ltpf_mem[x_hat_ltpf_index]; - } - x_hat_ltpf_mem[blockStartIndex + n] -= filtOut; - } - - } else { - //*** transition case 5 ********************************************** - for (uint16_t n = 0; n < sample2p5ms; n++) { - x_hat_ltpf_mem[blockStartIndex + n] = x_hat_mem[blockStartIndex + n]; - double filtOut = 0.0; - for (uint16_t k = 0; k <= L_num; k++) { - int16_t x_hat_index = blockStartIndex + n - k; - if (x_hat_index < 0) { - x_hat_index += numMemBlocks * lc3Config.NF; - } - filtOut += c_num_mem[k] * x_hat_mem[x_hat_index]; - } - for (uint16_t k = 0; k <= L_den; k++) { - int16_t x_hat_ltpf_index = - blockStartIndex + n - p_int_mem + L_den / 2 - k; - if (x_hat_ltpf_index < 0) { - x_hat_ltpf_index += numMemBlocks * lc3Config.NF; - } - filtOut -= c_den_mem[k] * x_hat_ltpf_mem[x_hat_ltpf_index]; - } - filtOut *= 1 - (n / norm); - x_hat_ltpf_mem[blockStartIndex + n] -= filtOut; - } - - double x_hat_ltpf_temp[numMemBlocks * - lc3Config.NF]; // is it good to place such a - // buffer on the stack? - for (int16_t m = -L_num; m < norm; m++) { - int16_t idx = blockStartIndex + m; - if (idx < 0) { - idx += numMemBlocks * lc3Config.NF; - } - x_hat_ltpf_temp[idx] = x_hat_ltpf_mem[idx]; - } - - for (uint16_t n = 0; n < sample2p5ms; n++) { - x_hat_ltpf_mem[blockStartIndex + n] = - x_hat_ltpf_temp[blockStartIndex + n]; - double filtOut = 0.0; - for (uint16_t k = 0; k <= L_num; k++) { - int16_t x_hat_index = blockStartIndex + n - k; - if (x_hat_index < 0) { - x_hat_index += numMemBlocks * lc3Config.NF; - } - filtOut += c_num[k] * x_hat_ltpf_temp[x_hat_index]; - } - for (uint16_t k = 0; k <= L_den; k++) { - int16_t x_hat_ltpf_index = - blockStartIndex + n - p_int + L_den / 2 - k; - if (x_hat_ltpf_index < 0) { - x_hat_ltpf_index += numMemBlocks * lc3Config.NF; - } - filtOut -= c_den[k] * x_hat_ltpf_mem[x_hat_ltpf_index]; - } - filtOut *= (n / norm); - x_hat_ltpf_mem[blockStartIndex + n] -= filtOut; - } - - for (uint16_t n = sample2p5ms; n < lc3Config.NF; n++) { - x_hat_ltpf_mem[blockStartIndex + n] = x_hat_mem[blockStartIndex + n]; - double filtOut = 0.0; - for (uint16_t k = 0; k <= L_num; k++) { - int16_t x_hat_index = blockStartIndex + n - k; - if (x_hat_index < 0) { - x_hat_index += numMemBlocks * lc3Config.NF; - } - filtOut += c_num[k] * x_hat_mem[x_hat_index]; - } - for (uint16_t k = 0; k <= L_den; k++) { - int16_t x_hat_ltpf_index = - blockStartIndex + n - p_int + L_den / 2.0 - k; - if (x_hat_ltpf_index < 0) { - x_hat_ltpf_index += numMemBlocks * lc3Config.NF; - } - filtOut -= c_den[k] * x_hat_ltpf_mem[x_hat_ltpf_index]; - } - x_hat_ltpf_mem[blockStartIndex + n] -= filtOut; - } - } - } - - // copy to output x_hat_ltpf - for (uint16_t n = 0; n < lc3Config.NF; n++) { - x_hat_ltpf[n] = x_hat_ltpf_mem[blockStartIndex + n]; - } - - // increment current block in block-ringbuffer - blockStartIndex += lc3Config.NF; - if (blockStartIndex > (numMemBlocks - 1) * lc3Config.NF) { - blockStartIndex = 0; - } - - // register updates - ltpf_active_prev = ltpf_active; -} - -void LongTermPostfilter::registerDatapoints(DatapointContainer* datapoints) { - if (nullptr != datapoints) { - datapoints->addDatapoint("x_hat_ltpfin", x_hat_ltpfin, - sizeof(double) * lc3Config.NF); - datapoints->addDatapoint("x_hat_ltpf", x_hat_ltpf, - sizeof(double) * lc3Config.NF); - datapoints->addDatapoint("x_hat_ltpf_mem", x_hat_ltpf_mem, - sizeof(double) * lc3Config.NF * numMemBlocks); - datapoints->addDatapoint("x_hat_mem", x_hat_mem, - sizeof(double) * lc3Config.NF * numMemBlocks); - datapoints->addDatapoint("c_num", c_num, sizeof(double) * (L_num + 1)); - datapoints->addDatapoint("c_den", c_den, sizeof(double) * (L_den + 1)); - datapoints->addDatapoint("c_num_mem", c_num_mem, - sizeof(double) * (L_num + 1)); - datapoints->addDatapoint("c_den_mem", c_den_mem, - sizeof(double) * (L_den + 1)); - datapoints->addDatapoint("p_int", &p_int, sizeof(p_int)); - } -} - -} // namespace Lc3Dec diff --git a/system/embdrv/lc3_dec/Decoder/LongTermPostfilter.hpp b/system/embdrv/lc3_dec/Decoder/LongTermPostfilter.hpp deleted file mode 100644 index daeb31aa7d..0000000000 --- a/system/embdrv/lc3_dec/Decoder/LongTermPostfilter.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * LongTermPostfilter.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef LONG_TERM_POSTFILTER_H_ -#define LONG_TERM_POSTFILTER_H_ - -#include <cstdint> - -#include "Datapoints.hpp" -#include "Lc3Config.hpp" - -namespace Lc3Dec { - -class LongTermPostfilter { - public: - LongTermPostfilter(const Lc3Config& lc3Config_, uint16_t nbits); - ~LongTermPostfilter(); - - void registerDatapoints(DatapointContainer* datapoints); - - LongTermPostfilter& operator=(const LongTermPostfilter&); - - void setInputX(const double* const x_hat); - void run(int16_t ltpf_active, int16_t pitch_index); - - const Lc3Config& lc3Config; - const uint8_t numMemBlocks; - double* x_hat_ltpf; - - private: - void setGainParams(uint16_t nbits); - void computeFilterCoeffs(uint16_t pitch_index); - - int16_t ltpf_active_prev; - uint16_t blockStartIndex; - double* c_num; - double* c_den; - double* c_num_mem; - double* c_den_mem; - double* x_hat_ltpfin; - double* x_hat_mem; - double* x_hat_ltpf_mem; - - uint8_t L_num; - uint8_t L_den; - - double gain_ltpf; - uint8_t gain_ind; - - uint16_t p_int; - uint16_t p_fr; - uint16_t p_int_mem; - uint16_t p_fr_mem; -}; - -} // namespace Lc3Dec - -#endif // LONG_TERM_POSTFILTER_H_ diff --git a/system/embdrv/lc3_dec/Decoder/MPVQ.cpp b/system/embdrv/lc3_dec/Decoder/MPVQ.cpp deleted file mode 100644 index aa3d4d6b0a..0000000000 --- a/system/embdrv/lc3_dec/Decoder/MPVQ.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * MPVQ.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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 "MPVQ.hpp" - -#include <cstdbool> - -#include "SnsQuantizationTables.hpp" - -namespace Lc3Dec { - -// declare local helper functions -void mind2vec_tab(short dim_in, /* i: dimension */ - short k_max_local, /* i: nb unit pulses */ - short leading_sign, /* i: leading sign */ - unsigned int ind, /* i: MPVQ-index */ - short* vec_out, /* o: pulse train */ - unsigned int MPVQ_offsets[][11] /* i: offset matrix */ -); - -void mind2vec_one(short k_val_in, /* i: nb unit pulses */ - short leading_sign, /* i: leading sign -1, 1 */ - short* vec_out /* o: updated pulse train */ -); - -short setval_update_sign(short k_delta, /* i */ - short k_max_local_in, /* i */ - short* leading_sign, /* i/o */ - unsigned int* ind_in, /* i/o */ - short* vec_out /* i/o */ -); - -short get_lead_sign(unsigned int* ind_in); - -// -// Implementation -// - -void MPVQdeenum(uint8_t dim_in, /* i : dimension of vec_out */ - uint8_t k_val_in, /* i : number of unit pulses */ - int16_t LS_ind, /* i : leading sign index */ - int32_t MPVQ_ind, /* i : MPVQ shape index */ - int16_t* vec_out /* o : PVQ integer pulse train */ -) { - for (uint8_t i = 0; i < dim_in; i++) { - vec_out[i] = 0; - } - short leading_sign = 1; - if (LS_ind != 0) { - leading_sign = -1; - } - mind2vec_tab(dim_in, k_val_in, leading_sign, MPVQ_ind, vec_out, MPVQ_offsets); -} - -void mind2vec_tab(short dim_in, /* i: dimension */ - short k_max_local, /* i: nb unit pulses */ - short leading_sign, /* i: leading sign */ - unsigned int ind, /* i: MPVQ-index */ - short* vec_out, /* o: pulse train */ - unsigned int MPVQ_offsets[][11] /* i: offset matrix */ -) { - /* init */ - unsigned int* h_row_ptr = &(MPVQ_offsets[(dim_in - 1)][0]); - short k_acc = k_max_local; - /* loop over positions */ - for (uint8_t pos = 0; pos < dim_in; pos++) { - short k_delta; - if (ind != 0) { - k_acc = k_max_local; - ; - unsigned int UL_tmp_offset = h_row_ptr[k_acc]; - bool wrap_flag = (ind < UL_tmp_offset); - unsigned int UL_diff = 0; - if (!wrap_flag) { - // Note: due to android build using a integer-overflow sanitizer, we - // have to avoid - // computing the following difference when ind < UL_tmp_offset - UL_diff = ind - UL_tmp_offset; - } - while (wrap_flag) { - k_acc--; - wrap_flag = (ind < h_row_ptr[k_acc]); - if (!wrap_flag) { - // Note: due to android build using a integer-overflow sanitizer, we - // have to avoid - // computing the following difference when ind < UL_tmp_offset - UL_diff = ind - h_row_ptr[k_acc]; - } - } - ind = UL_diff; - k_delta = k_max_local - k_acc; - } else { - mind2vec_one(k_max_local, leading_sign, &vec_out[pos]); - break; - } - k_max_local = setval_update_sign(k_delta, k_max_local, &leading_sign, &ind, - &vec_out[pos]); - h_row_ptr -= 11; /* reduce dimension in MPVQ_offsets table */ - } -} - -void mind2vec_one(short k_val_in, /* i: nb unit pulses */ - short leading_sign, /* i: leading sign -1, 1 */ - short* vec_out /* o: updated pulse train */ -) { - short amp = k_val_in; - if (leading_sign < 0) { - amp = -k_val_in; - } - *vec_out = amp; -} - -short setval_update_sign( - short k_delta, /* i */ - short k_max_local_in, /* i */ - short* leading_sign, /* i/o */ - unsigned int* ind_in, /* i/o; needed to change type compared to spec */ - short* vec_out /* i/o */ -) { - short k_max_local_out = k_max_local_in; - if (k_delta != 0) { - mind2vec_one(k_delta, *leading_sign, vec_out); - *leading_sign = get_lead_sign(ind_in); - k_max_local_out -= k_delta; - } - return k_max_local_out; -} - -short get_lead_sign( - unsigned int* ind) // renamed "ind_in" from spec to just "ind" (as already - // found by yao.wang 28.06.2019) -{ - short leading_sign = +1; - if (((*ind) & 0x1) != 0) { - leading_sign = -1; - } - (*ind) = (*ind >> 1); - return leading_sign; -} - -} // namespace Lc3Dec diff --git a/system/embdrv/lc3_dec/Decoder/MPVQ.hpp b/system/embdrv/lc3_dec/Decoder/MPVQ.hpp deleted file mode 100644 index e015d65c2b..0000000000 --- a/system/embdrv/lc3_dec/Decoder/MPVQ.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * MPVQ.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef __MPVQ_HPP_ -#define __MPVQ_HPP_ - -#include <cstdint> - -namespace Lc3Dec { - -void MPVQdeenum(uint8_t dim_in, /* i : dimension of vec_out */ - uint8_t k_val_in, /* i : number of unit pulses */ - int16_t LS_ind, /* i : leading sign index */ - int32_t MPVQ_ind, /* i : MPVQ shape index */ - int16_t* vec_out /* o : PVQ integer pulse train */ -); - -} // namespace Lc3Dec - -#endif // __MPVQ_HPP_ diff --git a/system/embdrv/lc3_dec/Decoder/MdctDec.cpp b/system/embdrv/lc3_dec/Decoder/MdctDec.cpp deleted file mode 100644 index ba56b5d5d9..0000000000 --- a/system/embdrv/lc3_dec/Decoder/MdctDec.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* - * MdctDec.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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 "MdctDec.hpp" - -#include <cmath> - -#include "MdctWindows.hpp" - -namespace Lc3Dec { - -MdctDec::MdctDec(const Lc3Config& lc3Config_) - : lc3Config(lc3Config_), - x_hat_mdct(nullptr), - dctIVDbl(lc3Config.NF), - mem_ola_add(nullptr), - t_hat_mdct(nullptr), - wN(nullptr) { - mem_ola_add = new double[lc3Config.NF - lc3Config.Z]; - t_hat_mdct = new double[2 * lc3Config.NF]; - x_hat_mdct = new double[lc3Config.NF]; - for (uint16_t n = 0; n < (lc3Config.NF - lc3Config.Z); n++) { - mem_ola_add[n] = 0; - } - - // Note: we do not add additional configuration error checking at this level. - // We assume that there will be nor processing with invalid configuration, - // thus nonsense results for invalid lc3Config.N_ms and/or lc3Config.Fs_ind - // are accepted here. - wN = w_N80; // default initialization to avoid warnings - if (lc3Config.N_ms == Lc3Config::FrameDuration::d7p5ms) { - switch (lc3Config.NF) { - case 60: - wN = w_N60_7p5ms; - break; - case 120: - wN = w_N120_7p5ms; - break; - case 180: - wN = w_N180_7p5ms; - break; - case 240: - wN = w_N240_7p5ms; - break; - case 360: - wN = w_N360_7p5ms; - break; - } - } else { - // Lc3Config::FrameDuration::d10ms (and other as fallback) - switch (lc3Config.NF) { - case 80: - wN = w_N80; - break; - case 160: - wN = w_N160; - break; - case 240: - wN = w_N240; - break; - case 320: - wN = w_N320; - break; - case 480: - wN = w_N480; - break; - } - } -} - -MdctDec::~MdctDec() { - if (nullptr != mem_ola_add) { - delete[] mem_ola_add; - } - if (nullptr != t_hat_mdct) { - delete[] t_hat_mdct; - } - if (nullptr != x_hat_mdct) { - delete[] x_hat_mdct; - } -} - -void MdctDec::MdctInvFastDbl() { - dctIVDbl.run(); - - for (uint16_t n = 0; n < lc3Config.NF; n++) { - t_hat_mdct[n] = dctIVDbl.out[n]; - } - for (uint16_t n = lc3Config.NF; n < 2 * lc3Config.NF; n++) { - t_hat_mdct[n] = -dctIVDbl.out[2 * lc3Config.NF - 1 - n]; - } - - // TODO try to optimize out the mem-buffer - double mem[lc3Config.NF / 2]; - for (uint16_t n = 0; n < lc3Config.NF / 2; n++) { - mem[n] = t_hat_mdct[n]; - } - for (uint16_t n = 0; n < 3 * lc3Config.NF / 2; n++) { - t_hat_mdct[n] = t_hat_mdct[n + lc3Config.NF / 2]; - } - for (uint16_t n = 3 * lc3Config.NF / 2; n < 2 * lc3Config.NF; n++) { - t_hat_mdct[n] = -mem[n - 3 * lc3Config.NF / 2]; - } - - double gain = 1.0 / sqrt(2.0 * lc3Config.NF); - for (uint16_t n = 0; n < 2 * lc3Config.NF; n++) { - t_hat_mdct[n] *= gain; - } -} - -void MdctDec::run(const double* const X_hat) { - if (!lc3Config.isValid()) { - return; - } - - for (uint16_t k = 0; k < lc3Config.NE; k++) { - dctIVDbl.in[k] = X_hat[k]; - } - for (uint16_t k = lc3Config.NE; k < lc3Config.NF; k++) { - dctIVDbl.in[k] = 0; - } - - // 1. Generation of time domain aliasing buffer - MdctInvFastDbl(); - - // 2. Windowing of time-aliased buffer - for (uint16_t n = 0; n < 2 * lc3Config.NF; n++) { - t_hat_mdct[n] *= wN[2 * lc3Config.NF - 1 - n]; - } - - // 3. Conduct overlapp-add operation - for (uint16_t n = 0; n < lc3Config.NF - lc3Config.Z; n++) { - x_hat_mdct[n] = mem_ola_add[n] + t_hat_mdct[lc3Config.Z + n]; - mem_ola_add[n] = t_hat_mdct[lc3Config.NF + lc3Config.Z + n]; - } - for (uint16_t n = lc3Config.NF - lc3Config.Z; n < lc3Config.NF; n++) { - x_hat_mdct[n] = t_hat_mdct[lc3Config.Z + n]; - } -} - -void MdctDec::registerDatapoints(DatapointContainer* datapoints) { - if (nullptr != datapoints) { - datapoints->addDatapoint("X_hat_mdct", dctIVDbl.in, - sizeof(double) * lc3Config.NF); - datapoints->addDatapoint("t_hat_mdct", t_hat_mdct, - sizeof(double) * 2 * lc3Config.NF); - datapoints->addDatapoint("mem_ola_add", mem_ola_add, - sizeof(double) * (lc3Config.NF - lc3Config.Z)); - datapoints->addDatapoint("x_hat_mdct", x_hat_mdct, - sizeof(double) * lc3Config.NF); - } -} - -} // namespace Lc3Dec diff --git a/system/embdrv/lc3_dec/Decoder/MdctDec.hpp b/system/embdrv/lc3_dec/Decoder/MdctDec.hpp deleted file mode 100644 index 86e3ab654c..0000000000 --- a/system/embdrv/lc3_dec/Decoder/MdctDec.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * MdctDec.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef MDCT_DEC_H_ -#define MDCT_DEC_H_ - -#include <cstdint> - -#include "Datapoints.hpp" -#include "DctIV.hpp" -#include "Lc3Config.hpp" - -namespace Lc3Dec { - -class MdctDec { - public: - MdctDec(const Lc3Config& lc3Config_); - virtual ~MdctDec(); - - void registerDatapoints(DatapointContainer* datapoints); - - void run(const double* const X_hat); - - const Lc3Config& lc3Config; - double* x_hat_mdct; - - private: - void MdctInvFastDbl(); - - DctIVDbl dctIVDbl; - double* mem_ola_add; - double* t_hat_mdct; - double* wN; -}; - -} // namespace Lc3Dec - -#endif // MDCT_DEC_H_ diff --git a/system/embdrv/lc3_dec/Decoder/PacketLossConcealment.cpp b/system/embdrv/lc3_dec/Decoder/PacketLossConcealment.cpp deleted file mode 100644 index 0d038808d5..0000000000 --- a/system/embdrv/lc3_dec/Decoder/PacketLossConcealment.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * PacketLossConcealment.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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 "PacketLossConcealment.hpp" - -namespace Lc3Dec { - -PacketLossConcealment::PacketLossConcealment(uint16_t NE_) - : NE(NE_), - plc_seed(24607), // this initialization need not be done every frame as - // clarified by Errata 15114 - nbLostCmpt(0), - alpha(1), - X_hat_lastGood(nullptr) { - X_hat_lastGood = new double[NE]; - for (uint16_t k = 0; k < NE; k++) { - X_hat_lastGood[k] = 0.0; - } -} - -PacketLossConcealment::~PacketLossConcealment() { delete[] X_hat_lastGood; } - -void PacketLossConcealment::run(uint8_t BEC_detect, double* X_hat, - int16_t& ltpf_active) { - // Appendix B. Packet Loss Concealment (d09r02_F2F) - if (0 == BEC_detect) { - nbLostCmpt = 0; - alpha = 1; - for (uint16_t k = 0; k < NE; k++) { - X_hat_lastGood[k] = X_hat[k]; - } - } else { - ltpf_active = 0; // errata 15097 implemented - - if (nbLostCmpt < 0xFF) { - nbLostCmpt++; - } - - // Note: from (d09r02_F2F) its is not perfectly clear, - // whether alpha is modified before or after applying - // it to the spectrum -> we may have to check the - // given implementation with the LC3.exe reference - if (nbLostCmpt >= 8) { - alpha = 0.85 * alpha; - } else if (nbLostCmpt >= 4) { - alpha = 0.9 * alpha; - } - - for (uint16_t k = 0; k < NE; k++) { - plc_seed = (16831 + plc_seed * 12821) & 0xFFFF; - if (plc_seed < 0x8000) { - X_hat[k] = alpha * X_hat_lastGood[k]; - } else { - X_hat[k] = -alpha * X_hat_lastGood[k]; - } - } - } -} - -void PacketLossConcealment::registerDatapoints(DatapointContainer* datapoints) { - if (nullptr != datapoints) { - datapoints->addDatapoint("X_hat_lastGood", &X_hat_lastGood[0], - sizeof(double) * NE); - } -} - -} // namespace Lc3Dec diff --git a/system/embdrv/lc3_dec/Decoder/PacketLossConcealment.hpp b/system/embdrv/lc3_dec/Decoder/PacketLossConcealment.hpp deleted file mode 100644 index e3eb0679bd..0000000000 --- a/system/embdrv/lc3_dec/Decoder/PacketLossConcealment.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * PacketLossConcealment.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef PACKET_LOSS_CONCEALMENT_H_ -#define PACKET_LOSS_CONCEALMENT_H_ - -#include <cstdint> - -#include "Datapoints.hpp" - -namespace Lc3Dec { - -class PacketLossConcealment { - public: - PacketLossConcealment(uint16_t NE_); - virtual ~PacketLossConcealment(); - - void registerDatapoints(DatapointContainer* datapoints); - - void run(uint8_t BER_DETECT, double* X_hat, int16_t& ltpf_active); - - const uint16_t NE; - - private: - uint16_t plc_seed; - uint8_t nbLostCmpt; - double alpha; - double* X_hat_lastGood; -}; - -} // namespace Lc3Dec - -#endif // PACKET_LOSS_CONCEALMENT_H_ diff --git a/system/embdrv/lc3_dec/Decoder/ResidualSpectrum.cpp b/system/embdrv/lc3_dec/Decoder/ResidualSpectrum.cpp deleted file mode 100644 index 55453ad32f..0000000000 --- a/system/embdrv/lc3_dec/Decoder/ResidualSpectrum.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * ResidualSpectrum.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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 "ResidualSpectrum.hpp" - -#include <cmath> - -#include "BitReader.hpp" - -namespace Lc3Dec { - -ResidualSpectrum::ResidualSpectrum(uint16_t NE_) - : NE(NE_), X_hat_q_residual(nullptr), nResBits(0) { - X_hat_q_residual = new double[NE]; -} - -ResidualSpectrum::~ResidualSpectrum() { delete[] X_hat_q_residual; } - -void ResidualSpectrum::run( - const uint8_t* bytes, uint16_t& bp_side, uint8_t& mask_side, - const uint16_t lastnz, const int16_t* const X_hat_q_ari, - uint16_t const nbits_residual, // the const is implementation dependent and - // thus not repeated in header declaration - uint8_t* save_lev, const uint8_t& lsbMode, uint16_t& nf_seed, - uint16_t& zeroFrame, const int16_t gg_ind, int16_t F_NF) { - // 3.4.2.6 Residual data and finalization (d09r02_F2F) - /* Decode residual bits */ - for (uint16_t k = 0; k < lastnz; k++) { - X_hat_q_residual[k] = X_hat_q_ari[k]; - } - // for (k = lastnz; k < 𝑁𝐸; k++) - for (uint16_t k = lastnz; k < NE; k++) { - //𝑋𝑞 ̂[k] = 0; - X_hat_q_residual[k] = 0; - } - uint8_t resBits[nbits_residual]; - uint16_t remaining_nbits_residual = - nbits_residual; // changed relative to specification to ensure const - // input into array allocation - nResBits = 0; - if (lsbMode == 0) { - // for (k = 0; k < 𝑁𝐸; k++) - for (uint16_t k = 0; k < NE; k++) { - // if (𝑋𝑞 ̂[k] != 0) - if (X_hat_q_residual[k] != 0) { - if (nResBits == remaining_nbits_residual) { - break; - } - resBits[nResBits++] = read_bit(bytes, &bp_side, &mask_side); - } - } - } else { - for (uint16_t k = 0; k < lastnz; k += 2) { - if (save_lev[k] > 0) { - if (remaining_nbits_residual == 0) { - break; - } - uint8_t bit = read_bit(bytes, &bp_side, &mask_side); - remaining_nbits_residual--; - if (bit == 1) { - // if (𝑋𝑞 ̂[k] > 0) - if (X_hat_q_residual[k] > 0) { - //𝑋𝑞 ̂[k] += 1; - X_hat_q_residual[k] += 1; - } - // else if (𝑋𝑞 ̂[k] < 0) - else if (X_hat_q_residual[k] < 0) { - //𝑋𝑞 ̂[k] -= 1; - X_hat_q_residual[k] -= 1; - } else { - if (remaining_nbits_residual == 0) { - break; - } - bit = read_bit(bytes, &bp_side, &mask_side); - remaining_nbits_residual--; - if (bit == 0) { - //𝑋𝑞 ̂[k] = 1; - X_hat_q_residual[k] = 1; - } else { - //𝑋𝑞 ̂[k] = -1; - X_hat_q_residual[k] = -1; - } - } - } - if (remaining_nbits_residual == 0) { - break; - } - bit = read_bit(bytes, &bp_side, &mask_side); - remaining_nbits_residual--; - if (bit == 1) { - // if (𝑋𝑞 ̂[k+1] > 0) - if (X_hat_q_residual[k + 1] > 0) { - //𝑋𝑞 ̂[k+1] += 1; - X_hat_q_residual[k + 1] += 1; - } - // else if (𝑋𝑞 ̂[k+1] < 0) - else if (X_hat_q_residual[k + 1] < 0) { - //𝑋𝑞 ̂[k+1] -= 1; - X_hat_q_residual[k + 1] -= 1; - } else { - if (remaining_nbits_residual == 0) { - break; - } - bit = read_bit(bytes, &bp_side, &mask_side); - remaining_nbits_residual--; - if (bit == 0) { - //𝑋𝑞 ̂[k+1] = 1; - X_hat_q_residual[k + 1] = 1; - } else { - //𝑋𝑞 ̂[k+1] = -1; - X_hat_q_residual[k + 1] = -1; - } - } - } - } - } - } - - /* Noise Filling Seed */ - int16_t tmp = 0; - // for (k = 0; k < 𝑁𝐸; k++) - for (uint16_t k = 0; k < NE; k++) { - // tmp += abs(𝑋𝑞 ̂[k]) * k; - tmp += abs(X_hat_q_residual[k]) * k; - } - nf_seed = tmp & 0xFFFF; /* Note that both tmp and nf_seed are 32-bit int*/ - /* Zero frame flag */ - // if (lastnz == 2 && 𝑋𝑞 ̂[0] == 0 && 𝑋𝑞 ̂[1] == 0 && 𝑔𝑔𝑖𝑛𝑑 == 0 && 𝐹𝑁𝐹 == 7) - if ((lastnz == 2) && (X_hat_q_residual[0] == 0.0) && - (X_hat_q_residual[1] == 0.0) && (gg_ind == 0) && (F_NF == 7)) { - zeroFrame = 1; - } else { - zeroFrame = 0; - } - - // 3.4.3 Residual decoding (d09r02_F2F) - // Residual decoding is performed only when lsbMode is 0. - if (lsbMode == 0) { - uint16_t k, n; - k = n = 0; - // while (k < 𝑁𝐸 && n < nResBits) - while (k < NE && n < nResBits) { - // if (𝑋𝑞 ̂[k] != 0) - if (X_hat_q_residual[k] != 0) { - if (resBits[n++] == 0) { - // if (𝑋𝑞 ̂[k] > 0) - if (X_hat_q_residual[k] > 0) { - //𝑋𝑞 ̂[k] -= 0.1875; - X_hat_q_residual[k] -= 0.1875; - } else { - //𝑋𝑞 ̂[k] -= 0.3125; - X_hat_q_residual[k] -= 0.3125; - } - } else { - // if (𝑋𝑞 ̂[k] > 0) - if (X_hat_q_residual[k] > 0) { - //𝑋𝑞 ̂[k] += 0.3125; - X_hat_q_residual[k] += 0.3125; - } else { - //𝑋𝑞 ̂[k] += 0.1875; - X_hat_q_residual[k] += 0.1875; - } - } - } - k++; - } - } -} - -void ResidualSpectrum::registerDatapoints(DatapointContainer* datapoints) { - if (nullptr != datapoints) { - datapoints->addDatapoint("X_hat_q_residual", &X_hat_q_residual[0], - sizeof(double) * NE); - } -} - -} // namespace Lc3Dec diff --git a/system/embdrv/lc3_dec/Decoder/ResidualSpectrum.hpp b/system/embdrv/lc3_dec/Decoder/ResidualSpectrum.hpp deleted file mode 100644 index 2f13a57023..0000000000 --- a/system/embdrv/lc3_dec/Decoder/ResidualSpectrum.hpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * ResidualSpectrum.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef RESIDUAL_SPECTRUM_H_ -#define RESIDUAL_SPECTRUM_H_ - -#include <cstdint> - -#include "Datapoints.hpp" - -namespace Lc3Dec { - -class ResidualSpectrum { - public: - ResidualSpectrum(uint16_t NE_); - - virtual ~ResidualSpectrum(); - - void registerDatapoints(DatapointContainer* datapoints); - - void run(const uint8_t* bytes, uint16_t& bp_side, uint8_t& mask_side, - const uint16_t lastnz, const int16_t* const X_hat_q_ari, - uint16_t nbits_residual, uint8_t* save_lev, const uint8_t& lsbMode, - uint16_t& nf_seed, uint16_t& zeroFrame, const int16_t gg_ind, - int16_t F_NF); - - const uint16_t NE; - - double* X_hat_q_residual; - uint16_t nResBits; - - private: -}; - -} // namespace Lc3Dec - -#endif // RESIDUAL_SPECTRUM_H_ diff --git a/system/embdrv/lc3_dec/Decoder/SideInformation.cpp b/system/embdrv/lc3_dec/Decoder/SideInformation.cpp deleted file mode 100644 index 4516aabf60..0000000000 --- a/system/embdrv/lc3_dec/Decoder/SideInformation.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/* - * SideInformation.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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 "SideInformation.hpp" - -#include <cmath> - -#include "BitReader.hpp" - -namespace Lc3Dec { - -static const uint8_t nbits_bw_table[5] = { - 0, 1, 2, 2, 3}; // see 3.4.2.4 Bandwidth interpretation (d09r02_F2F) - -SideInformation::SideInformation(uint16_t NF_, uint16_t NE_, uint8_t fs_ind_) - : NF(NF_), - NE(NE_), - fs_ind(fs_ind_), - nbits_bw(nbits_bw_table[fs_ind]), - submodeMSB(0), - submodeLSB(0) {} - -SideInformation::~SideInformation() {} - -void SideInformation::dec_split_st2VQ_CW(uint32_t cwRx, uint32_t szA, - uint32_t szB, uint8_t& BEC_detect, - int16_t& submodeLSB, int32_t& idxA, - int32_t& idxBorGainLSB) { - if (cwRx >= szB * szA) { - idxA = 0; - idxBorGainLSB = 0; - submodeLSB = 0; - BEC_detect = 1; - return; - } - idxBorGainLSB = floor(cwRx / szA); - idxA = cwRx - idxBorGainLSB * szA; - submodeLSB = 0; - idxBorGainLSB = idxBorGainLSB - 2; - if (idxBorGainLSB < 0) { - submodeLSB = 1; - } - - idxBorGainLSB = idxBorGainLSB + 2 * submodeLSB; - // BEC_detect = 0; // changed in comparision to specification -> variable is - // handles as reference to overall BEC_detect -} - -void SideInformation::run(const uint8_t* bytes, uint16_t& bp_side, - uint8_t& mask_side, int16_t& P_BW, int16_t& lastnz, - uint8_t& lsbMode, int16_t& gg_ind, - int16_t& num_tns_filters, int16_t* rc_order, - uint8_t& pitch_present, int16_t& pitch_index, - int16_t& ltpf_active, int16_t& F_NF, int16_t& ind_LF, - int16_t& ind_HF, int16_t& Gind, int16_t& LS_indA, - int16_t& LS_indB, int32_t& idxA, int16_t& idxB, - - uint8_t& BEC_detect) { - // 5.4.2.3 Side information - /* Bandwidth */ - if (nbits_bw > 0) { - P_BW = read_uint(bytes, &bp_side, &mask_side, nbits_bw); - if (fs_ind < P_BW) { - BEC_detect = 1; - return; - } - } else { - P_BW = 0; - } - /* Last non-zero tuple */ - nbits_lastnz = ceil(log2(NE / 2)); - int16_t tmp_lastnz = read_uint(bytes, &bp_side, &mask_side, nbits_lastnz); - lastnz = (tmp_lastnz + 1) << 1; - if (lastnz > NE) { - /* consider this as bit error (BEC) */ - BEC_detect = 1; - return; - } - /* LSB mode bit */ - lsbMode = read_bit(bytes, &bp_side, &mask_side); - /* Global Gain */ - gg_ind = read_uint(bytes, &bp_side, &mask_side, 8); - /* TNS activation flag */ - if (P_BW < 3) { - num_tns_filters = 1; - } else { - num_tns_filters = 2; - } - rc_order[0] = 0; // not specified, but on the safe side - rc_order[1] = 0; // not specified, but on the safe side - for (uint8_t f = 0; f < num_tns_filters; f++) { - rc_order[f] = read_bit(bytes, &bp_side, &mask_side); - } - /* Pitch present flag */ - pitch_present = read_bit(bytes, &bp_side, &mask_side); - /* SNS-VQ integer bits */ - /* Read 5+5 bits of SNQ VQ decoding stage 1 according to Section 5.4.7.2.1 - * (d09r01) */ - /* Read 5+5 bits of SNQ VQ decoding stage 1 according to Section 3.4.7.2.1 - * (d09r02)(d09r02_F2F) */ - ind_LF = read_uint(bytes, &bp_side, &mask_side, 5); /* stage1 LF */ - ind_HF = read_uint(bytes, &bp_side, &mask_side, 5); /* stage1 HF */ - - /* Read 28 bits of SNS VQ decoding stage 2 according to section 5.4.7.2.2 - * (d09r01) */ - // 3.4.7.2.2 Stage 2 SNS VQ decoding (d09r02_F2F) - submodeMSB = read_bit(bytes, &bp_side, &mask_side); - if (submodeMSB == 0) { - Gind = read_uint(bytes, &bp_side, &mask_side, 1); - } else { - Gind = read_uint(bytes, &bp_side, &mask_side, 2); - } - LS_indA = read_bit(bytes, &bp_side, &mask_side); /* LS_indA 1 bit */ - if (submodeMSB == 0) { - /* ‘regular’/’regular_lf’ demultiplexing, establish if shape_j is 0 or 1 */ - uint32_t tmp = read_uint(bytes, &bp_side, &mask_side, 13); - tmp |= (read_uint(bytes, &bp_side, &mask_side, 12) << 13); - int32_t idxBorGainLSB; - //[ BEC_detect, submodeLSB, idxA, idxBorGainLSB ] = dec_split_st2VQ_CW(tmp, - // 4780008U>>1, 14 ); - dec_split_st2VQ_CW(tmp, 4780008U >> 1, 14, BEC_detect, submodeLSB, idxA, - idxBorGainLSB); - if (BEC_detect) { - // early exit to avoid unpredictable side-effects - return; - } - if (submodeLSB != 0) { - Gind = (Gind << 1) + idxBorGainLSB; /* for regular_lf */ - // just set some defined values (although nothing is specified for this - // case) - idxB = 0; - LS_indB = 0; - } else { - idxB = idxBorGainLSB >> 1; /* for regular */ - LS_indB = idxBorGainLSB & 0x1; - } - } else { - // Attention: the given reference intermediate results do not cover - // this case -> tested with conformance tests only! (successful operation - // observed already) - /* outlier_* demultiplexing, establish if shape_j is 2 or 3 */ - int32_t tmp = read_uint(bytes, &bp_side, &mask_side, 12); - tmp |= - static_cast<int32_t>(read_uint(bytes, &bp_side, &mask_side, 12) << 12); - idxA = tmp; - // idxB = -1; // removed in pseudo-code of d09r02_F2F - submodeLSB = 0; - // this intialization does not seem to be correct here - // (just from code reading; context of pseudo-code in specification is not - // clear) - // BEC_detect = 0; - if (tmp >= static_cast<int32_t>((30316544U >> 1) + 1549824U)) { - BEC_detect = 1; - return; - } else { - tmp -= static_cast<int32_t>(30316544U >> 1); - if (tmp >= 0) { - submodeLSB = 1; - Gind = (Gind << 1) + (tmp & 0x1); - idxA = tmp >> 1; - } - } - } - - /* LTPF data */ - if (pitch_present != 0) { - ltpf_active = read_uint(bytes, &bp_side, &mask_side, 1); - pitch_index = read_uint(bytes, &bp_side, &mask_side, 9); - } - - /* Noise Level */ - F_NF = read_uint(bytes, &bp_side, &mask_side, 3); -} - -void SideInformation::registerDatapoints(DatapointContainer* datapoints) { - if (nullptr != datapoints) { - datapoints->addDatapoint("nbits_lastnz", &nbits_lastnz, - sizeof(nbits_lastnz)); - datapoints->addDatapoint("submodeMSB", &submodeMSB, sizeof(submodeMSB)); - } -} - -} // namespace Lc3Dec diff --git a/system/embdrv/lc3_dec/Decoder/SideInformation.hpp b/system/embdrv/lc3_dec/Decoder/SideInformation.hpp deleted file mode 100644 index e6df7e4960..0000000000 --- a/system/embdrv/lc3_dec/Decoder/SideInformation.hpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * SideInformation.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef SIDE_INFORMATION_H_ -#define SIDE_INFORMATION_H_ - -#include <cstdint> - -#include "Datapoints.hpp" - -namespace Lc3Dec { - -class SideInformation { - public: - SideInformation(uint16_t NF_, uint16_t NE_, uint8_t fs_ind_); - - virtual ~SideInformation(); - - void registerDatapoints(DatapointContainer* datapoints); - - void run(const uint8_t* bytes, uint16_t& bp_side, uint8_t& mask_side, - int16_t& P_BW, int16_t& lastnz, uint8_t& lsbMode, int16_t& gg_ind, - int16_t& num_tns_filters, int16_t* rc_order, uint8_t& pitch_present, - int16_t& pitch_index, int16_t& ltpf_active, int16_t& F_NF, - int16_t& ind_LF, int16_t& ind_HF, int16_t& Gind, int16_t& LS_indA, - int16_t& LS_indB, int32_t& idxA, int16_t& idxB, - - uint8_t& BEC_detect); - - const uint16_t NF; - const uint16_t NE; - const uint8_t fs_ind; - const uint8_t nbits_bw; - - int16_t submodeMSB; - int16_t submodeLSB; - - private: - uint8_t nbits_lastnz; - - void dec_split_st2VQ_CW(uint32_t cwRx, uint32_t szA, uint32_t szB, - uint8_t& BEC_detect, int16_t& submodeLSB, - int32_t& idxA, int32_t& idxBorGainLSB); -}; - -} // namespace Lc3Dec - -#endif // SIDE_INFORMATION_H_ diff --git a/system/embdrv/lc3_dec/Decoder/SpectralNoiseShaping.cpp b/system/embdrv/lc3_dec/Decoder/SpectralNoiseShaping.cpp deleted file mode 100644 index b07de9d6a3..0000000000 --- a/system/embdrv/lc3_dec/Decoder/SpectralNoiseShaping.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - * SpectralNoiseShaping.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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 "SpectralNoiseShaping.hpp" - -#include <cmath> - -#include "BandIndexTables.hpp" -#include "MPVQ.hpp" -#include "SnsQuantizationTables.hpp" - -namespace Lc3Dec { - -SpectralNoiseShaping::SpectralNoiseShaping(const Lc3Config& lc3Config_) - : lc3Config(lc3Config_), I_fs(nullptr) { - // Note: we do not add additional configuration error checking at this level. - // We assume that there will be nor processing with invalid configuration, - // thus nonsense results for invalid lc3Config.N_ms and/or lc3Config.Fs_ind - // are accepted here. - if (lc3Config.N_ms == Lc3Config::FrameDuration::d7p5ms) { - switch (lc3Config.Fs_ind) { - case 0: - I_fs = &I_8000_7p5ms[0]; - break; - case 1: - I_fs = &I_16000_7p5ms[0]; - break; - case 2: - I_fs = &I_24000_7p5ms[0]; - break; - case 3: - I_fs = &I_32000_7p5ms[0]; - break; - case 4: - I_fs = &I_48000_7p5ms[0]; - break; - } - } else { - // Lc3Config::FrameDuration::d10ms (and other as fallback) - switch (lc3Config.Fs_ind) { - case 0: - I_fs = &I_8000[0]; - break; - case 1: - I_fs = &I_16000[0]; - break; - case 2: - I_fs = &I_24000[0]; - break; - case 3: - I_fs = &I_32000[0]; - break; - case 4: - I_fs = &I_48000[0]; - break; - } - } -} - -SpectralNoiseShaping::~SpectralNoiseShaping() {} - -void SpectralNoiseShaping::run(const double* const X_s_tns, - double* const X_hat_ss, int16_t ind_LF, - int16_t ind_HF, int16_t submodeMSB, - int16_t submodeLSB, int16_t Gind, - int16_t LS_indA, int16_t LS_indB, int32_t idxA, - int16_t idxB) { - if (!lc3Config.isValid()) { - return; - } - - // 3.4.7 SNS decoder (d09r02_F2F) - // 3.4.7.2 SNS scale factor decoding (d09r02_F2F) - // 3.4.7.2.1 Stage 1 SNS VQ decoding (d09r02_F2F) - // already done earlier (see SideInformation) - - // The first stage vector is composed as: - //𝑠𝑡1(𝑛) = 𝐿𝐹𝐶𝐵𝑖𝑛𝑑_𝐿𝐹 (𝑛), 𝑓𝑜𝑟 𝑛 = [0 … 7], # (33) - //𝑠𝑡1(𝑛 + 8) = 𝐻𝐹𝐶𝐵𝑖𝑛𝑑_𝐻𝐹(𝑛), 𝑓𝑜𝑟 𝑛 = [0 … 7], # (34) - double st1[16]; - for (uint8_t n = 0; n < 8; n++) { - st1[n] = LFCB[ind_LF][n]; - st1[n + 8] = HFCB[ind_HF][n]; - } - - // 3.4.7.2.2 Stage 2 SNS VQ decoding (d09r02_F2F) - // already done earlier -> submodeMSB, Gind, LS_indA, LS_indB, idxA, idxB - int16_t shape_j = (submodeMSB << 1) + submodeLSB; - int16_t gain_i = Gind; - - int16_t y[16]; - int16_t z[16]; - - switch (shape_j) { - case 0: - MPVQdeenum(10, 10, LS_indA, idxA, y); - MPVQdeenum(6, 1, LS_indB, idxB, z); - for (uint8_t n = 10; n <= 15; n++) { - y[n] = z[n - 10]; - } - break; - case 1: - MPVQdeenum(10, 10, LS_indA, idxA, y); - for (uint8_t n = 10; n <= 15; n++) { - y[n] = 0; - } - break; - case 2: - MPVQdeenum(16, 8, LS_indA, idxA, y); - break; - case 3: - MPVQdeenum(16, 6, LS_indA, idxA, y); - break; - } - - double yNorm = 0; - for (uint8_t n = 0; n < 16; n++) { - // yNorm += y[n]*(y[n]*1.0); - yNorm += y[n] * y[n]; - } - yNorm = std::sqrt(yNorm); - // Note: we skipped intermediate signal xq_shape_j and applied yNorm - // directly together with G_gain_i_shape_j - - double G_gain_i_shape_j = - sns_vq_far_adj_gains[gain_i]; // default initialization to avoid warnings - switch (shape_j) { - case 0: - G_gain_i_shape_j = sns_vq_reg_adj_gains[gain_i]; - break; - case 1: - G_gain_i_shape_j = sns_vq_reg_lf_adj_gains[gain_i]; - break; - case 2: - G_gain_i_shape_j = sns_vq_near_adj_gains[gain_i]; - break; - case 3: - G_gain_i_shape_j = sns_vq_far_adj_gains[gain_i]; - break; - } - if (0.0 != yNorm) // do we have to make this even more robust??? - { - G_gain_i_shape_j /= yNorm; - } - - // Synthesis of the Quantized SNS scale factor vector - double scfQ[16]; - for (uint8_t n = 0; n < 16; n++) { - double factor = 0; - for (uint8_t col = 0; col < 16; col++) { - factor += y[col] * D[n][col]; - } - scfQ[n] = st1[n] + G_gain_i_shape_j * factor; - } - - // 3.4.7.3 SNS scale factors interpolation (d09r02_F2F) - double scfQint[64]; - scfQint[0] = scfQ[0]; - scfQint[1] = scfQ[0]; - for (uint8_t n = 0; n <= 14; n++) { - scfQint[4 * n + 2] = scfQ[n] + (1.0 / 8.0 * (scfQ[n + 1] - scfQ[n])); - scfQint[4 * n + 3] = scfQ[n] + (3.0 / 8.0 * (scfQ[n + 1] - scfQ[n])); - scfQint[4 * n + 4] = scfQ[n] + (5.0 / 8.0 * (scfQ[n + 1] - scfQ[n])); - scfQint[4 * n + 5] = scfQ[n] + (7.0 / 8.0 * (scfQ[n + 1] - scfQ[n])); - } - scfQint[62] = scfQ[15] + 1 / 8.0 * (scfQ[15] - scfQ[14]); - scfQint[63] = scfQ[15] + 3 / 8.0 * (scfQ[15] - scfQ[14]); - - // add special handling for lc3Config.N_b=60 (happens for 7.5ms and fs=8kHz) - // see section 3.4.7.3 SNS scale factors interpolation (d1.0r03 including - // Errata 15036) - const uint8_t n2 = 64 - lc3Config.N_b; - if (n2 != 0) { - for (uint8_t i = 0; i < n2; i++) { - scfQint[i] = (scfQint[2 * i] + scfQint[2 * i + 1]) / 2; - } - for (uint8_t i = n2; i < lc3Config.N_b; i++) { - scfQint[i] = scfQint[i + n2]; - } - } - - double g_SNS[64]; - for (uint8_t b = 0; b < lc3Config.N_b; b++) { - g_SNS[b] = exp2(scfQint[b]); - } - - // 3.4.7.4 Spectral Shaping (d09r02_F2F) - // for (b=0; b<𝑁𝑏; b++) - for (uint8_t b = 0; b < lc3Config.N_b; b++) { - // for (k=𝐼𝑓𝑠 (𝑏); k< 𝐼𝑓𝑠 (𝑏 + 1); k++) - for (uint16_t k = I_fs[b]; k < I_fs[b + 1]; k++) { - //𝑋 ̂(𝑘) = 𝑋𝑆 ̂(𝑘) ∙ 𝑔𝑆𝑁𝑆 (𝑏) - X_hat_ss[k] = X_s_tns[k] * g_SNS[b]; - } - } -} - -void SpectralNoiseShaping::registerDatapoints(DatapointContainer* datapoints) {} - -} // namespace Lc3Dec diff --git a/system/embdrv/lc3_dec/Decoder/SpectralNoiseShaping.hpp b/system/embdrv/lc3_dec/Decoder/SpectralNoiseShaping.hpp deleted file mode 100644 index 939e50367f..0000000000 --- a/system/embdrv/lc3_dec/Decoder/SpectralNoiseShaping.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SpectralNoiseShaping.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef SPECTRAL_NOISE_SHAPING_H_ -#define SPECTRAL_NOISE_SHAPING_H_ - -#include <cstdint> - -#include "Datapoints.hpp" -#include "Lc3Config.hpp" - -namespace Lc3Dec { - -class SpectralNoiseShaping { - public: - SpectralNoiseShaping(const Lc3Config& lc3Config_); - - virtual ~SpectralNoiseShaping(); - - void registerDatapoints(DatapointContainer* datapoints); - - void run(const double* const X_s_tns, double* const X_hat_ss, int16_t ind_LF, - int16_t ind_HF, int16_t submodeMSB, int16_t submodeLSB, int16_t Gind, - int16_t LS_indA, int16_t LS_indB, int32_t idxA, int16_t idxB); - - const Lc3Config& lc3Config; - - private: - int* I_fs; -}; - -} // namespace Lc3Dec - -#endif // SPECTRAL_NOISE_SHAPING_H_ diff --git a/system/embdrv/lc3_dec/Readme.txt b/system/embdrv/lc3_dec/Readme.txt deleted file mode 100644 index 859d9bb49c..0000000000 --- a/system/embdrv/lc3_dec/Readme.txt +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Readme.txt - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com - * - * 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. - */ - -Contents -======== - (1) Introduction - (2) Directory Structure - (3) Naming Conventions - (4) General Code Structure - (5) Test and Debug Support - -(1) Introduction -================ -(derived from Bluetooth SIG LC3 specification dr09r06) -The Low Complexity Communication Codec (LC3) is an efficient Bluetooth Audio Codec for use in -audio profiles. This codec can encode speech and music at a variety of bitrates. The LC3 can -be incorporated in any Bluetooth audio profile. - -The LC3 specification allows floating point and fixed point implementations as long as the -resulting decoded audio signals are sufficiently close in quality. The given implementation -exploits floating point operation in the majority of the code. - -To deliver satisfactory audio quality under all channel conditions, it is strongly recommended -that some form of Packet Loss Concealment (PLC) should be implemented on the receiving ends of -audio connections. The purpose of packet loss concealment is to conceal the effect of unavailable -or corrupted frame data for decoding. The given code implements the example PLC algorithm provided -in the informative Appendix B of the LC3 specification. Alternative PLC schemes are possible, but have -to meet or exceed the performance of the given implementation. - -The initial implementation of this codec has been made in year 2019 in parallel to final -improvements and extensions to the LC3 specification. The final implementation has been matched -to the specification, however, references in the code to the specification are not adapted to -the latest formal changes in the specification. Thus, the revision of the specification referenced -is given with each reference, so that it should be possible to track the links to the specification. - -(2) Directory Structure -======================= - |- Api -> include files needed by calling application code - |- Common | -> implementation needed by LC3 encoder and decoder - | |-- KissFft -> source code of kissfft library used for fast transforms - | |-- Tables -> tables as given in Section 3.7 "Tables and constants" (dr09r06) - |- Decoder -> implementation of LC3 decoder (*.hpp and *.cpp) - |- Encoder -> implementation of LC3 encoder (*.hpp and *.cpp) - |- TestSupport -> interface and dummy/demo implementation of "datapoint" access - for test and debug support - -(3) Naming Conventions and Coding Style -======================================= - Names of variables/objects have been chosen to be as close as possible -to the naming within the LC3 specification. This applies not only to the -selected wording, but also to the chosen case and concatenation of words. - Thus, variable naming may appear somewhat unorthodox to a standard C/C++ developer -and is not always consistent in style. Nevertheless, the close link to the specification -document is considered most valuable so that this approach has been followed. - The LC3 specification contains textual descriptions, equations, pseudo-code, tables -and reference intermediate outputs. The naming of variables is not perfectly consistent, -particularly in the case of names for intermediate outputs in relation to the -specification text. Thus, there are situations where we had to select one name out of -different options or had to choose different names for internal variables and -"datapoints" provided for test and debug support. - - Some parts of the code are directly converted from pseudo-code given in -the specification document. Changes compared to the specification are made only -when supported by technical arguments. Again, the close link to the specification -is considered most valuable. Note that this implies in some situations that code -is not optimized in terms of computation effort, memory usage and/or clarity of its structure. - -Further Conventions: - - indentation using 4 spaces; no TABS at all - - directory, file and class names are camel-case starting with a capital letter - - -(4) General Code Structure -========================== - The implementation is in C++ where object oriented programming is mainly used to - formulate the relations of higher level modules/classes. The code of the lower level - modules is syntactically C++, but the style is more like plain old procedural - programming. The latter is mainly due to the goal of formulating the code very close - to the specification - not only with respect to its overall behaviour but also with - respect to the organization. This is particularly true for the modules depending - heavily on converted pseudo-code from the LC3 specification. - - A brief overview on the main class relationships is summarized in the following - basic diagrams. - - Encoder: - -------- - Lc3Encoder : main API and handling of multi-channel sessions - | |(1)------(1) Lc3Config : configuration instance - | - |(1)-------(lc3Config.Nc) EncoderTop : toplevel class for single channel session; - | | dynamically reallocates EncoderFrame instance in case - | | of bitrate changes - | | - | |--- holds all sub-modules directly that are not dependent - | on variable bitrate; - | - |(1)-----(1) EncoderFrame : toplevel processing per frame and - reallocation of sub-modules in case - of bitrate changes - - Decoder: - -------- - Lc3Decoder : main API and handling of multi-channel sessions - | |(1)------(1) Lc3Config : configuration instance - | - |(1)-------(lc3Config.Nc) DecoderTop : toplevel class for single channel session; - | | dynamically reallocates DecoderFrame instance in case - | | of bitrate changes - | | - | |--- holds all sub-modules directly that are not dependent - | on variable bitrate; - | - |(1)-----(1) DecoderFrame : toplevel processing per frame and - reallocation of sub-modules in case - of bitrate changes - - -(5) Test and Debug Support -========================== -The development of the codec implementation has been strongly based on close match of -intermediate values with specified reference values. To be able to access the proper -values in a standardized manner a simple "datapoint" API has been created. - Note: this API is not fully optimized for usage within in android but may be extended -for this purpose in future. - The given API can be found in "TestSupport/Datapoints.hpp" with a basic (mainly dummy) implementation -given in "TestSupport/DatapointsAndroid.cpp". - To use this API an instance of "DatapointContainer" has to be created and provided to the -Lc3Encoder and Lc3Decoder constructors when needed. Note: that this is not intended for final releases -due to the additional resources needed. diff --git a/system/embdrv/lc3_dec/TestSupport/Datapoints.hpp b/system/embdrv/lc3_dec/TestSupport/Datapoints.hpp deleted file mode 100644 index 5817c96a60..0000000000 --- a/system/embdrv/lc3_dec/TestSupport/Datapoints.hpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Datapoints.hpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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. - */ - -#ifndef __DATAPOINTS_HPP_ -#define __DATAPOINTS_HPP_ - -#include <cstdint> - -class Datapoint; -class ContainerRealization; - -class DatapointContainer { - public: - DatapointContainer(); - virtual ~DatapointContainer(); - - void addDatapoint(const char* label, void* pData, uint16_t sizeInBytes); - void addDatapoint(const char* label, const void* pData, uint16_t sizeInBytes); - void log(const char* label, const void* pData, uint16_t sizeInBytes); - - uint16_t getDatapointSize(const char* label); - bool getDatapointValue(const char* label, void* pDataBuffer, - uint16_t bufferSize); - bool setDatapointValue(const char* label, const void* pDataBuffer, - uint16_t bufferSize); - - private: - void addDatapoint(const char* label, Datapoint* pDatapoint); - ContainerRealization* m_pContainer; -}; - -#endif // __DATAPOINTS_HPP_ diff --git a/system/embdrv/lc3_dec/TestSupport/DatapointsAndroid.cpp b/system/embdrv/lc3_dec/TestSupport/DatapointsAndroid.cpp deleted file mode 100644 index 2caa9628f2..0000000000 --- a/system/embdrv/lc3_dec/TestSupport/DatapointsAndroid.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * DatapointsDummy.cpp - * - * Copyright 2021 HIMSA II K/S - www.himsa.com. Represented by EHIMA - - * www.ehima.com - * - * 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 <base/logging.h> - -#include <iomanip> -#include <iostream> -#include <sstream> - -#include "Datapoints.hpp" - -class ContainerRealization {}; - -DatapointContainer::DatapointContainer() : m_pContainer(nullptr) { - // nothing stored yet; we may integrate a complete datapoint container when - // more debugging is needed in the android context - (void)m_pContainer; -} - -DatapointContainer::~DatapointContainer() {} - -void DatapointContainer::addDatapoint(const char* label, - Datapoint* pDatapoint) {} - -void DatapointContainer::addDatapoint(const char* label, void* pData, - uint16_t sizeInBytes) {} - -void DatapointContainer::addDatapoint(const char* label, const void* pData, - uint16_t sizeInBytes) {} - -void DatapointContainer::log(const char* label, const void* pData, - uint16_t sizeInBytes) { - // Note: this is just a first simple step to demonstrate the possibilities we - // have. - // In this case the datapoint label its size in bytes and its content as - // hex-byte-stream is send to the android LOG. - const uint8_t* pByteData = reinterpret_cast<const uint8_t*>(pData); - std::string valueAsHexString("0x"); - std::ostringstream vStream; - vStream << "0x"; - for (uint16_t byteNr = 0; byteNr < sizeInBytes; byteNr++) { - vStream << std::right << std::setw(2) << std::setfill('0') << std::hex - << static_cast<int>(pByteData[byteNr]); - } - // TODO: uncomment for testing - // LOG(INFO) << label << "[" << sizeInBytes << "]:" << vStream.str(); -} - -uint16_t DatapointContainer::getDatapointSize(const char* label) { return 0; } - -bool DatapointContainer::getDatapointValue(const char* label, void* pDataBuffer, - uint16_t bufferSize) { - return false; -} - -bool DatapointContainer::setDatapointValue(const char* label, - const void* pDataBuffer, - uint16_t bufferSize) { - return false; -} diff --git a/system/embdrv/lc3_dec/fuzzer/liblc3codec_decoder_fuzzer.cpp b/system/embdrv/lc3_dec/fuzzer/liblc3codec_decoder_fuzzer.cpp deleted file mode 100644 index e453e6e8cb..0000000000 --- a/system/embdrv/lc3_dec/fuzzer/liblc3codec_decoder_fuzzer.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2021 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 <fuzzer/FuzzedDataProvider.h> - -#include "../Api/Lc3Decoder.hpp" - -using FrameDuration = Lc3Config::FrameDuration; - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp(data, size); - - uint16_t fs = fdp.PickValueInArray({8000, 16000, 24000, 32000, 44100, 48000}); - FrameDuration fd = - fdp.PickValueInArray({FrameDuration::d10ms, FrameDuration::d7p5ms}); - uint8_t bfi = fdp.ConsumeIntegralInRange(0, 1); - uint8_t bec_detect = fdp.ConsumeIntegralInRange(0, 1); - - uint16_t input_byte_count = fdp.ConsumeIntegralInRange(20, 400); - - if (fdp.remaining_bytes() < input_byte_count) { - return 0; - } - - std::vector<uint8_t> encoded_bytes(input_byte_count); - - fdp.ConsumeData(encoded_bytes.data(), encoded_bytes.size()); - - uint16_t output_frame_count = Lc3Config(fs, fd, 1).NF; - std::vector<uint16_t> decoded_data(output_frame_count * 2); - - Lc3Decoder decoder(fs, fd); - decoder.run(encoded_bytes.data(), encoded_bytes.size(), bfi, - (int16_t*)decoded_data.data(), output_frame_count, bec_detect, 0); - - return 0; -}
\ No newline at end of file diff --git a/system/embdrv/lc3_dec/fuzzer/liblc3codec_encoder_fuzzer.cpp b/system/embdrv/lc3_dec/fuzzer/liblc3codec_encoder_fuzzer.cpp deleted file mode 100644 index e1014f7ce0..0000000000 --- a/system/embdrv/lc3_dec/fuzzer/liblc3codec_encoder_fuzzer.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2021 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 <fuzzer/FuzzedDataProvider.h> - -#include "../Api/Lc3Encoder.hpp" - -using FrameDuration = Lc3Config::FrameDuration; - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - FuzzedDataProvider fdp(data, size); - - uint16_t fs = fdp.PickValueInArray({8000, 16000, 24000, 32000, 44100, 48000}); - FrameDuration fd = - fdp.PickValueInArray({FrameDuration::d10ms, FrameDuration::d7p5ms}); - uint16_t output_byte_count = fdp.ConsumeIntegralInRange(20, 400); - - Lc3Config config(fs, fd, 1); - if (config.getErrorStatus() != Lc3Config::ERROR_FREE) { - return 0; - } - - uint16_t num_frames = config.NF * config.Nc; - - if (fdp.remaining_bytes() < num_frames * 2) { - return 0; - } - - std::vector<uint16_t> input_frames(num_frames); - - fdp.ConsumeData(input_frames.data(), - input_frames.size() * 2 /* each frame is 2 bytes */); - - Lc3Encoder encoder(config); - - std::vector<uint8_t> output(output_byte_count); - encoder.run((const int16_t*)input_frames.data(), output_byte_count, - output.data()); - return 0; -}
\ No newline at end of file diff --git a/system/gd/Android.bp b/system/gd/Android.bp index cbb475f5fe..449639bb70 100644 --- a/system/gd/Android.bp +++ b/system/gd/Android.bp @@ -183,6 +183,7 @@ cc_defaults { ":BluetoothL2capSources", ":BluetoothMetricsSources", ":BluetoothNeighborSources", + ":BluetoothOsSources", ":BluetoothPacketSources", ":BluetoothShimSources", ":BluetoothSecuritySources", @@ -354,6 +355,7 @@ cc_test { ":BluetoothHciUnitTestSources", ":BluetoothL2capUnitTestSources", ":BluetoothMetricsTestSources", + ":BluetoothOsTestSources", ":BluetoothPacketTestSources", ":BluetoothShimTestSources", ":BluetoothSecurityUnitTestSources", diff --git a/system/gd/att/att_module.h b/system/gd/att/att_module.h index a04993c8b3..1322394e6e 100644 --- a/system/gd/att/att_module.h +++ b/system/gd/att/att_module.h @@ -25,6 +25,9 @@ namespace att { class AttModule : public bluetooth::Module { public: AttModule() = default; + AttModule(const AttModule&) = delete; + AttModule& operator=(const AttModule&) = delete; + ~AttModule() = default; static const ModuleFactory Factory; @@ -41,7 +44,6 @@ class AttModule : public bluetooth::Module { private: struct impl; std::unique_ptr<impl> pimpl_; - DISALLOW_COPY_AND_ASSIGN(AttModule); }; } // namespace att diff --git a/system/gd/btaa/activity_attribution.h b/system/gd/btaa/activity_attribution.h index e2861286d9..93f5549dd3 100644 --- a/system/gd/btaa/activity_attribution.h +++ b/system/gd/btaa/activity_attribution.h @@ -50,6 +50,9 @@ class ActivityAttributionCallback { class ActivityAttribution : public bluetooth::Module { public: ActivityAttribution() = default; + ActivityAttribution(const ActivityAttribution&) = delete; + ActivityAttribution& operator=(const ActivityAttribution&) = delete; + ~ActivityAttribution() = default; void Capture(const hal::HciPacket& packet, hal::SnoopLogger::PacketType type); @@ -71,8 +74,6 @@ class ActivityAttribution : public bluetooth::Module { private: struct impl; std::unique_ptr<impl> pimpl_; - - DISALLOW_COPY_AND_ASSIGN(ActivityAttribution); }; } // namespace activity_attribution diff --git a/system/gd/cert/run b/system/gd/cert/run index c15d621f86..a71e42671e 100755 --- a/system/gd/cert/run +++ b/system/gd/cert/run @@ -79,6 +79,7 @@ CERT_TEST_VENV=${ANDROID_BUILD_TOP}/out/dist/bluetooth_venv OUT_TARGET="${ANDROID_BUILD_TOP}/out/target" TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd/host_config.yaml" TEST_FILTER="--presubmit" +TEST_RUNNER="blueberry/tests/gd/gd_test_runner.py" CPP_BUILD_TARGET="bluetooth_stack_with_facade root-canal bluetooth_packets_python3" RUST_BUILD_TARGET="bluetooth_with_facades root-canal bluetooth_packets_python3 bt_topshim_facade" BUILD_TARGET=$CPP_BUILD_TARGET @@ -89,6 +90,7 @@ NUM_REPETITIONS="1" SKIP_SOONG_BUILD=false USE_ASHMEM_VENV=true VERBOSE_MODE=false +DEVICE_TEST=false ## Verify devices connected and valid DUT_SERIAL="DUT Not Set" @@ -120,6 +122,9 @@ function parse_options { echo -e " Makes use of ashmem as best as possible for targeted speed increases." echo -e "${BLUE} --device${NOCOLOR}" echo -e " Run the test on the 2 real devices." + echo -e "${BLUE} --sl4a${NOCOLOR}" + echo -e " Run GD Sl4A combination tests using the default gd_sl4a config." + echo -e " Please install the correct SL4A build to DUT manually before running tests." echo -e "${BLUE} --rust${NOCOLOR}" echo -e " Run the test using the rust implementation on the 2 real devices." echo -e "${BLUE} --rhost${NOCOLOR}" @@ -152,27 +157,8 @@ function parse_options { shift # past argument ;; --device) + DEVICE_TEST=true TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd/devices_config.yaml" - RR="$(cat ${TEST_CONFIG}|grep \'CERT\\\|DUT\')" - if [ "$RR" != "" ]; then - DUT_SERIAL="$(menu-adb DUT)" - DUT_ADB="adb -s ${DUT_SERIAL}" - DUT_NAME="$(adb devices -l | grep -v "List of device" | grep ${DUT_SERIAL} | awk '{ print $6 }' | cut -d ':' -f 2)" - CERT_SERIAL="$(menu-adb CERT)" - CERT_ADB="adb -s ${CERT_SERIAL}" - CERT_NAME="$(adb devices -l | grep -v "List of device" | grep ${CERT_SERIAL} | awk '{ print $6 }' | cut -d ':' -f 2)" - - if [ "${CERT_SERIAL}" == "${DUT_SERIAL}" ]; then - echo - echo -e "${RED}ERROR: CERT and DUT cannot be the same device, or you only have one device connected!${NOCOLOR}" - echo - exit 1 - fi - - ## Set android devices in config - sed -i "s/'DUT'/'${DUT_SERIAL}'/g" ${TEST_CONFIG} - sed -i "s/'CERT'/'${CERT_SERIAL}'/g" ${TEST_CONFIG} - fi shift # past argument ;; # Repeat running the specified test cases by N times in one single setup @@ -192,6 +178,7 @@ function parse_options { BUILD_TARGET=$RUST_BUILD_TARGET export RUST_BACKTRACE=1 TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd/rust_devices_config.yaml" + DEVICE_TEST=true shift # past argument ;; --rhost) @@ -200,6 +187,12 @@ function parse_options { TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd/rust_host_config.yaml" shift # past argument ;; + --sl4a) + TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd_sl4a/gd_sl4a_device_config.yaml" + TEST_RUNNER="blueberry/tests/gd_sl4a/gd_sl4a_test_runner.py" + DEVICE_TEST=true + shift # past argument + ;; # This will log everything to both log file and stdout --verbose) VERBOSE_MODE=true @@ -237,6 +230,31 @@ function parse_options { } +function select_devices { + if [ "$DEVICE_TEST" == true ] ; then + RR="$(cat ${TEST_CONFIG}|grep \'CERT\\\|DUT\')" + if [ "$RR" != "" ]; then + DUT_SERIAL="$(menu-adb DUT)" + DUT_ADB="adb -s ${DUT_SERIAL}" + DUT_NAME="$(adb devices -l | grep -v "List of device" | grep ${DUT_SERIAL} | awk '{ print $6 }' | cut -d ':' -f 2)" + CERT_SERIAL="$(menu-adb CERT)" + CERT_ADB="adb -s ${CERT_SERIAL}" + CERT_NAME="$(adb devices -l | grep -v "List of device" | grep ${CERT_SERIAL} | awk '{ print $6 }' | cut -d ':' -f 2)" + + if [ "${CERT_SERIAL}" == "${DUT_SERIAL}" ]; then + echo + echo -e "${RED}ERROR: CERT and DUT cannot be the same device, or you only have one device connected!${NOCOLOR}" + echo + exit 1 + fi + + ## Set android devices in config + sed -i "s/'DUT'/'${DUT_SERIAL}'/g" ${TEST_CONFIG} + sed -i "s/'CERT'/'${CERT_SERIAL}'/g" ${TEST_CONFIG} + fi + fi +} + function soong_build { if [ "$CLEAN_VENV" == true ] ; then $ANDROID_BUILD_TOP/build/soong/soong_ui.bash --build-mode --"modules-in-a-dir" --dir="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system" dist $BUILD_TARGET -j20 @@ -410,7 +428,7 @@ function gotta_go_fast { function run_tests { for n in $(seq "${NUM_REPETITIONS}"); do - $(echo "${CERT_TEST_VENV}/bin/python" "${CERT_TEST_VENV}/sources/blueberry/tests/gd/gd_test_runner.py" \ + $(echo "${CERT_TEST_VENV}/bin/python" "${CERT_TEST_VENV}/sources/${TEST_RUNNER}" \ "-c ${TEST_CONFIG}" "${TEST_FILTER}") done @@ -475,6 +493,7 @@ function menu-adb() { function main { check_environment parse_options $@ + select_devices if [[ "${SKIP_SOONG_BUILD}" != true ]] ; then soong_build fi diff --git a/system/gd/cert/run_topshim b/system/gd/cert/run_topshim index 50a01343df..a2c04848c4 100755 --- a/system/gd/cert/run_topshim +++ b/system/gd/cert/run_topshim @@ -20,7 +20,8 @@ import os import argparse TEST_SUITES = [ - "blueberry.tests.gd.rust.topshim.facade.adapter_test" + "blueberry.tests.gd.rust.topshim.facade.adapter_test", + "blueberry.tests.gd.rust.topshim.facade.suspend_test" ] SOONG_UI_BASH = 'build/soong/soong_ui.bash' @@ -135,7 +136,7 @@ def main(): if not all(test_results): failures = [i for i, x in enumerate(test_results) if not x] for index in failures: - print('TEST FAILLED: ' + TEST_SUITES[index]) + print('TEST FAILED: ' + TEST_SUITES[index]) sys.exit(0) print('TEST PASSED ' + str(len(test_results)) + ' tests were run') diff --git a/system/gd/common/callback_list.h b/system/gd/common/callback_list.h index a3ad6b1f18..441a5fa3ef 100644 --- a/system/gd/common/callback_list.h +++ b/system/gd/common/callback_list.h @@ -68,6 +68,9 @@ class CallbackList<void(Args...)> : public base::internal::CallbackListBase<Call public: using CallbackType = CallbackWithHandler<void(Args...)>; CallbackList() = default; + CallbackList(const CallbackList&) = delete; + CallbackList& operator=(const CallbackList&) = delete; + template <typename... RunArgs> void Notify(RunArgs&&... args) { auto it = this->GetIterator(); @@ -76,9 +79,6 @@ class CallbackList<void(Args...)> : public base::internal::CallbackListBase<Call cb->handler->Post(base::Bind(cb->callback, args...)); } } - - private: - DISALLOW_COPY_AND_ASSIGN(CallbackList); }; } // namespace common diff --git a/system/gd/common/contextual_callback.h b/system/gd/common/contextual_callback.h index 539352945f..ba78ed6ba1 100644 --- a/system/gd/common/contextual_callback.h +++ b/system/gd/common/contextual_callback.h @@ -39,8 +39,8 @@ class ContextualOnceCallback<R(Args...)> { : callback_(std::move(callback)), context_(context) {} constexpr ContextualOnceCallback() = default; - - DISALLOW_COPY_AND_ASSIGN(ContextualOnceCallback); + ContextualOnceCallback(const ContextualOnceCallback&) = delete; + ContextualOnceCallback& operator=(const ContextualOnceCallback&) = delete; ContextualOnceCallback(ContextualOnceCallback&&) noexcept = default; ContextualOnceCallback& operator=(ContextualOnceCallback&&) noexcept = default; diff --git a/system/gd/hal/snoop_logger.cc b/system/gd/hal/snoop_logger.cc index f517c8e0e9..8de479a05f 100644 --- a/system/gd/hal/snoop_logger.cc +++ b/system/gd/hal/snoop_logger.cc @@ -67,15 +67,14 @@ constexpr SnoopLogger::FileHeaderType kBtSnoopFileHeader = { // the relevant system property constexpr size_t kDefaultBtSnoopMaxPacketsPerFile = 0xffff; -// We want to use at most 256 KB memory for btsnooz log -constexpr size_t kDefaultBtsnoozMaxMemoryUsageBytes = 256 * 1024; // We restrict the maximum packet size to 150 bytes constexpr size_t kDefaultBtSnoozMaxBytesPerPacket = 150; constexpr size_t kDefaultBtSnoozMaxPayloadBytesPerPacket = kDefaultBtSnoozMaxBytesPerPacket - sizeof(SnoopLogger::PacketHeaderType); -// Calculate max number of packets based on max memory usage and max packet size -constexpr size_t kDefaultBtSnoozMaxPacketsPerBuffer = - kDefaultBtsnoozMaxMemoryUsageBytes / kDefaultBtSnoozMaxBytesPerPacket; + +using namespace std::chrono_literals; +constexpr std::chrono::hours kBtSnoozLogLifeTime = 12h; +constexpr std::chrono::hours kBtSnoozLogDeleteRepeatingAlarmInterval = 1h; std::string get_btsnoop_log_path(std::string log_dir, bool filtered) { if (filtered) { @@ -107,6 +106,20 @@ void delete_btsnoop_files(const std::string& log_path) { } } +void delete_old_btsnooz_files(const std::string& log_path, const std::chrono::milliseconds log_life_time) { + auto opt_created_ts = os::FileCreatedTime(log_path); + if (!opt_created_ts) return; + + using namespace std::chrono; + auto created_tp = opt_created_ts.value(); + auto current_tp = std::chrono::system_clock::now(); + + auto diff = duration_cast<milliseconds>(current_tp - created_tp); + if (diff >= log_life_time) { + delete_btsnoop_files(log_path); + } +} + size_t get_btsnooz_packet_length_to_write(const HciPacket& packet, SnoopLogger::PacketType type) { static const size_t kAclHeaderSize = 4; static const size_t kL2capHeaderSize = 4; @@ -172,11 +185,16 @@ SnoopLogger::SnoopLogger( std::string snoop_log_path, std::string snooz_log_path, size_t max_packets_per_file, - const std::string& btsnoop_mode) + size_t max_packets_per_buffer, + const std::string& btsnoop_mode, + const std::chrono::milliseconds snooz_log_life_time, + const std::chrono::milliseconds snooz_log_delete_alarm_interval) : snoop_log_path_(std::move(snoop_log_path)), snooz_log_path_(std::move(snooz_log_path)), max_packets_per_file_(max_packets_per_file), - btsnooz_buffer_(kDefaultBtSnoozMaxPacketsPerBuffer) { + btsnooz_buffer_(max_packets_per_buffer), + snooz_log_life_time_(snooz_log_life_time), + snooz_log_delete_alarm_interval_(snooz_log_delete_alarm_interval) { if (false && btsnoop_mode == kBtSnoopLogModeFiltered) { // TODO(b/163733538): implement filtered snoop log in GD, currently filtered == disabled LOG_INFO("Filtered Snoop Logs enabled"); @@ -360,14 +378,20 @@ void SnoopLogger::Start() { if (is_enabled_) { OpenNextSnoopLogFile(); } + alarm_ = std::make_unique<os::RepeatingAlarm>(GetHandler()); + alarm_->Schedule( + common::Bind(&delete_old_btsnooz_files, snooz_log_path_, snooz_log_life_time_), snooz_log_delete_alarm_interval_); } void SnoopLogger::Stop() { std::lock_guard<std::recursive_mutex> lock(file_mutex_); - LOG_DEBUG("Dumping btsnooz log data to %s", snooz_log_path_.c_str()); - DumpSnoozLogToFile(btsnooz_buffer_.Drain()); LOG_DEBUG("Closing btsnoop log data at %s", snoop_log_path_.c_str()); CloseCurrentSnoopLogFile(); + // Cancel the alarm + alarm_->Cancel(); + alarm_.reset(); + // delete any existing snooz logs + delete_btsnoop_files(snooz_log_path_); } DumpsysDataFinisher SnoopLogger::GetDumpsysData(flatbuffers::FlatBufferBuilder* builder) const { @@ -391,6 +415,16 @@ size_t SnoopLogger::GetMaxPacketsPerFile() { return max_packets_per_file; } +size_t SnoopLogger::GetMaxPacketsPerBuffer() { + // We want to use at most 256 KB memory for btsnooz log for release builds + // and 512 KB memory for userdebug/eng builds + auto is_debuggable = os::GetSystemProperty(kIsDebuggableProperty); + size_t btsnooz_max_memory_usage_bytes = + ((is_debuggable.has_value() && common::StringTrim(is_debuggable.value()) == "1") ? 512 : 256) * 1024; + // Calculate max number of packets based on max memory usage and max packet size + return btsnooz_max_memory_usage_bytes / kDefaultBtSnoozMaxBytesPerPacket; +} + std::string SnoopLogger::GetBtSnoopMode() { // Default mode is DISABLED on user build. // In userdebug/eng build, it can also be overwritten by modifying the global setting @@ -421,7 +455,10 @@ const ModuleFactory SnoopLogger::Factory = ModuleFactory([]() { os::ParameterProvider::SnoopLogFilePath(), os::ParameterProvider::SnoozLogFilePath(), GetMaxPacketsPerFile(), - GetBtSnoopMode()); + GetMaxPacketsPerBuffer(), + GetBtSnoopMode(), + kBtSnoozLogLifeTime, + kBtSnoozLogDeleteRepeatingAlarmInterval); }); } // namespace hal diff --git a/system/gd/hal/snoop_logger.h b/system/gd/hal/snoop_logger.h index 22e88d8873..3ec96fb705 100644 --- a/system/gd/hal/snoop_logger.h +++ b/system/gd/hal/snoop_logger.h @@ -24,6 +24,7 @@ #include "common/circular_buffer.h" #include "hal/hci_hal.h" #include "module.h" +#include "os/repeating_alarm.h" namespace bluetooth { namespace hal { @@ -62,6 +63,8 @@ class SnoopLogger : public ::bluetooth::Module { // Changes to this value is only effective after restarting Bluetooth static size_t GetMaxPacketsPerFile(); + static size_t GetMaxPacketsPerBuffer(); + // Get snoop logger mode based on current system setup // Changes to this values is only effective after restarting Bluetooth static std::string GetBtSnoopMode(); @@ -96,7 +99,10 @@ class SnoopLogger : public ::bluetooth::Module { std::string snoop_log_path, std::string snooz_log_path, size_t max_packets_per_file, - const std::string& btsnoop_mode); + size_t max_packets_per_buffer, + const std::string& btsnoop_mode, + const std::chrono::milliseconds snooz_log_life_time, + const std::chrono::milliseconds snooz_log_delete_alarm_interval); void CloseCurrentSnoopLogFile(); void OpenNextSnoopLogFile(); void DumpSnoozLogToFile(const std::vector<std::string>& data) const; @@ -111,6 +117,9 @@ class SnoopLogger : public ::bluetooth::Module { common::CircularBuffer<std::string> btsnooz_buffer_; size_t packet_counter_ = 0; mutable std::recursive_mutex file_mutex_; + std::unique_ptr<os::RepeatingAlarm> alarm_; + std::chrono::milliseconds snooz_log_life_time_; + std::chrono::milliseconds snooz_log_delete_alarm_interval_; }; } // namespace hal diff --git a/system/gd/hal/snoop_logger_test.cc b/system/gd/hal/snoop_logger_test.cc index dcfe92d79b..f945cb5253 100644 --- a/system/gd/hal/snoop_logger_test.cc +++ b/system/gd/hal/snoop_logger_test.cc @@ -51,6 +51,7 @@ std::vector<uint8_t> kHfpAtNrec0 = {0x02, 0x02, 0x20, 0x13, 0x00, 0x0f, 0x00, 0x using bluetooth::TestModuleRegistry; using bluetooth::hal::SnoopLogger; +using namespace std::chrono_literals; // Expose protected constructor for test class TestSnoopLoggerModule : public SnoopLogger { @@ -60,14 +61,28 @@ class TestSnoopLoggerModule : public SnoopLogger { std::string snooz_log_path, size_t max_packets_per_file, const std::string& btsnoop_mode) - : SnoopLogger(std::move(snoop_log_path), std::move(snooz_log_path), max_packets_per_file, btsnoop_mode) {} + : SnoopLogger( + std::move(snoop_log_path), + std::move(snooz_log_path), + max_packets_per_file, + SnoopLogger::GetMaxPacketsPerBuffer(), + btsnoop_mode, + 20ms, + 5ms) {} std::string ToString() const override { return std::string("TestSnoopLoggerModule"); } + + void CallGetDumpsysData(flatbuffers::FlatBufferBuilder* builder) { + GetDumpsysData(builder); + } }; class SnoopLoggerModuleTest : public Test { + public: + flatbuffers::FlatBufferBuilder* builder_; + protected: void SetUp() override { temp_dir_ = std::filesystem::temp_directory_path(); @@ -75,6 +90,8 @@ class SnoopLoggerModuleTest : public Test { temp_snoop_log_last_ = temp_dir_ / "btsnoop_hci.log.last"; temp_snooz_log_ = temp_dir_ / "btsnooz_hci.log"; temp_snooz_log_last_ = temp_dir_ / "btsnooz_hci.log.last"; + builder_ = new flatbuffers::FlatBufferBuilder(); + DeleteSnoopLogFiles(); ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_)); ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_)); @@ -84,6 +101,7 @@ class SnoopLoggerModuleTest : public Test { void TearDown() override { DeleteSnoopLogFiles(); + delete builder_; } void DeleteSnoopLogFiles() { @@ -133,7 +151,7 @@ TEST_F(SnoopLoggerModuleTest, disable_snoop_log_test) { // Verify states after test ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_)); ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_)); - ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_)); + ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_)); } TEST_F(SnoopLoggerModuleTest, capture_one_packet_test) { @@ -163,16 +181,19 @@ TEST_F(SnoopLoggerModuleTest, capture_hci_cmd_btsnooz_test) { test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger); snoop_looger->Capture(kInformationRequest, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::CMD); + snoop_looger->CallGetDumpsysData(builder_); + + ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_)); + ASSERT_EQ( + std::filesystem::file_size(temp_snooz_log_), + sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + kInformationRequest.size()); test_registry.StopAll(); // Verify states after test ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_)); ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_)); - ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_)); - ASSERT_EQ( - std::filesystem::file_size(temp_snooz_log_), - sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + kInformationRequest.size()); + ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_)); } TEST_F(SnoopLoggerModuleTest, capture_l2cap_signal_packet_btsnooz_test) { @@ -183,16 +204,19 @@ TEST_F(SnoopLoggerModuleTest, capture_l2cap_signal_packet_btsnooz_test) { test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger); snoop_looger->Capture(kSdpConnectionRequest, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL); + snoop_looger->CallGetDumpsysData(builder_); + + ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_)); + ASSERT_EQ( + std::filesystem::file_size(temp_snooz_log_), + sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + kSdpConnectionRequest.size()); test_registry.StopAll(); // Verify states after test ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_)); ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_)); - ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_)); - ASSERT_EQ( - std::filesystem::file_size(temp_snooz_log_), - sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + kSdpConnectionRequest.size()); + ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_)); } TEST_F(SnoopLoggerModuleTest, capture_l2cap_short_data_packet_btsnooz_test) { @@ -203,16 +227,19 @@ TEST_F(SnoopLoggerModuleTest, capture_l2cap_short_data_packet_btsnooz_test) { test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger); snoop_looger->Capture(kAvdtpSuspend, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL); + snoop_looger->CallGetDumpsysData(builder_); + + ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_)); + ASSERT_EQ( + std::filesystem::file_size(temp_snooz_log_), + sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + kAvdtpSuspend.size()); test_registry.StopAll(); // Verify states after test ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_)); ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_)); - ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_)); - ASSERT_EQ( - std::filesystem::file_size(temp_snooz_log_), - sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + kAvdtpSuspend.size()); + ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_)); } TEST_F(SnoopLoggerModuleTest, capture_l2cap_long_data_packet_btsnooz_test) { @@ -223,16 +250,36 @@ TEST_F(SnoopLoggerModuleTest, capture_l2cap_long_data_packet_btsnooz_test) { test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger); snoop_looger->Capture(kHfpAtNrec0, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL); + snoop_looger->CallGetDumpsysData(builder_); + + ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_)); + ASSERT_EQ( + std::filesystem::file_size(temp_snooz_log_), + sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + 14); test_registry.StopAll(); // Verify states after test ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_)); ASSERT_FALSE(std::filesystem::exists(temp_snoop_log_last_)); + ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_)); +} + +TEST_F(SnoopLoggerModuleTest, delete_old_snooz_log_files) { + // Actual test + auto* snoop_looger = new TestSnoopLoggerModule( + temp_snoop_log_.string(), temp_snooz_log_.string(), 10, SnoopLogger::kBtSnoopLogModeDisabled); + TestModuleRegistry test_registry; + test_registry.InjectTestModule(&SnoopLogger::Factory, snoop_looger); + + std::filesystem::create_directories(temp_snooz_log_); + ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_)); - ASSERT_EQ( - std::filesystem::file_size(temp_snooz_log_), - sizeof(SnoopLogger::FileHeaderType) + sizeof(SnoopLogger::PacketHeaderType) + 14); + std::this_thread::sleep_for(10ms); + ASSERT_TRUE(std::filesystem::exists(temp_snooz_log_)); + std::this_thread::sleep_for(15ms); + ASSERT_FALSE(std::filesystem::exists(temp_snooz_log_)); + test_registry.StopAll(); } TEST_F(SnoopLoggerModuleTest, rotate_file_at_new_session_test) { diff --git a/system/gd/hci/acl_manager.h b/system/gd/hci/acl_manager.h index 72426bdafa..9c008013bb 100644 --- a/system/gd/hci/acl_manager.h +++ b/system/gd/hci/acl_manager.h @@ -57,6 +57,9 @@ class AclManager : public Module { public: AclManager(); + AclManager(const AclManager&) = delete; + AclManager& operator=(const AclManager&) = delete; + // NOTE: It is necessary to forward declare a default destructor that overrides the base class one, because // "struct impl" is forwarded declared in .cc and compiler needs a concrete definition of "struct impl" when // compiling AclManager's destructor. Hence we need to forward declare the destructor for AclManager to delay @@ -148,8 +151,6 @@ private: struct impl; std::unique_ptr<impl> pimpl_; - - DISALLOW_COPY_AND_ASSIGN(AclManager); }; } // namespace hci diff --git a/system/gd/hci/acl_manager/acl_connection.h b/system/gd/hci/acl_manager/acl_connection.h index c396b1833a..1347c8232a 100644 --- a/system/gd/hci/acl_manager/acl_connection.h +++ b/system/gd/hci/acl_manager/acl_connection.h @@ -28,6 +28,9 @@ namespace acl_manager { class AclConnection { public: AclConnection() : queue_up_end_(nullptr), handle_(0){}; + AclConnection(const AclConnection&) = delete; + AclConnection& operator=(const AclConnection&) = delete; + virtual ~AclConnection() = default; uint16_t GetHandle() const { @@ -47,7 +50,6 @@ class AclConnection { AclConnection(QueueUpEnd* queue_up_end, uint16_t handle) : queue_up_end_(queue_up_end), handle_(handle) {} QueueUpEnd* queue_up_end_; uint16_t handle_; - DISALLOW_COPY_AND_ASSIGN(AclConnection); }; } // namespace acl_manager diff --git a/system/gd/hci/acl_manager/classic_acl_connection.cc b/system/gd/hci/acl_manager/classic_acl_connection.cc index 5fd5eaf866..f80dbffda8 100644 --- a/system/gd/hci/acl_manager/classic_acl_connection.cc +++ b/system/gd/hci/acl_manager/classic_acl_connection.cc @@ -353,7 +353,7 @@ ClassicAclConnection::ClassicAclConnection(std::shared_ptr<Queue> queue, } ClassicAclConnection::~ClassicAclConnection() { - pimpl_->PutEventCallbacks(); + if (pimpl_) pimpl_->PutEventCallbacks(); delete pimpl_; } diff --git a/system/gd/hci/acl_manager/classic_acl_connection.h b/system/gd/hci/acl_manager/classic_acl_connection.h index 328cbb1eb4..6870114e06 100644 --- a/system/gd/hci/acl_manager/classic_acl_connection.h +++ b/system/gd/hci/acl_manager/classic_acl_connection.h @@ -33,6 +33,9 @@ class ClassicAclConnection : public AclConnection { ClassicAclConnection(); ClassicAclConnection(std::shared_ptr<Queue> queue, AclConnectionInterface* acl_connection_interface, uint16_t handle, Address address); + ClassicAclConnection(const ClassicAclConnection&) = delete; + ClassicAclConnection& operator=(const ClassicAclConnection&) = delete; + ~ClassicAclConnection(); virtual Address GetAddress() const { @@ -86,7 +89,6 @@ class ClassicAclConnection : public AclConnection { private: struct impl; struct impl* pimpl_ = nullptr; - DISALLOW_COPY_AND_ASSIGN(ClassicAclConnection); }; } // namespace acl_manager diff --git a/system/gd/hci/acl_manager/le_acl_connection.cc b/system/gd/hci/acl_manager/le_acl_connection.cc index d57aab2db4..8763cee396 100644 --- a/system/gd/hci/acl_manager/le_acl_connection.cc +++ b/system/gd/hci/acl_manager/le_acl_connection.cc @@ -117,7 +117,7 @@ LeAclConnection::LeAclConnection( } LeAclConnection::~LeAclConnection() { - pimpl_->PutEventCallbacks(); + if (pimpl_) pimpl_->PutEventCallbacks(); delete pimpl_; } diff --git a/system/gd/hci/acl_manager/le_acl_connection.h b/system/gd/hci/acl_manager/le_acl_connection.h index fd81111ba6..0fc14a9585 100644 --- a/system/gd/hci/acl_manager/le_acl_connection.h +++ b/system/gd/hci/acl_manager/le_acl_connection.h @@ -39,6 +39,9 @@ class LeAclConnection : public AclConnection { AddressWithType local_address, AddressWithType remote_address, Role role); + LeAclConnection(const LeAclConnection&) = delete; + LeAclConnection& operator=(const LeAclConnection&) = delete; + ~LeAclConnection(); virtual AddressWithType GetLocalAddress() const { @@ -84,7 +87,6 @@ class LeAclConnection : public AclConnection { AddressWithType local_address_; AddressWithType remote_address_; Role role_; - DISALLOW_COPY_AND_ASSIGN(LeAclConnection); }; } // namespace acl_manager diff --git a/system/gd/hci/acl_manager/le_impl.h b/system/gd/hci/acl_manager/le_impl.h index b666fbd705..599cd8b607 100644 --- a/system/gd/hci/acl_manager/le_impl.h +++ b/system/gd/hci/acl_manager/le_impl.h @@ -452,15 +452,6 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { address_with_type.ToConnectListAddressType(), address_with_type.GetAddress()); } - void clear_connect_list() { - if (!address_manager_registered) { - le_address_manager_->Register(this); - address_manager_registered = true; - } - pause_connection = true; - le_address_manager_->ClearConnectList(); - } - void remove_device_from_connect_list(AddressWithType address_with_type) { direct_connections_.erase(address_with_type); register_with_address_manager(); @@ -468,6 +459,11 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { address_with_type.ToConnectListAddressType(), address_with_type.GetAddress()); } + void clear_connect_list() { + register_with_address_manager(); + le_address_manager_->ClearConnectList(); + } + void add_device_to_resolving_list( AddressWithType address_with_type, const std::array<uint8_t, 16>& peer_irk, diff --git a/system/gd/hci/command_interface.h b/system/gd/hci/command_interface.h index eba01dbe07..28fa6273f2 100644 --- a/system/gd/hci/command_interface.h +++ b/system/gd/hci/command_interface.h @@ -28,8 +28,10 @@ template <typename T> class CommandInterface { public: CommandInterface() = default; + CommandInterface(const CommandInterface&) = delete; + CommandInterface& operator=(const CommandInterface&) = delete; + virtual ~CommandInterface() = default; - DISALLOW_COPY_AND_ASSIGN(CommandInterface); virtual void EnqueueCommand(std::unique_ptr<T> command, common::ContextualOnceCallback<void(CommandCompleteView)> on_complete) = 0; diff --git a/system/gd/hci/controller.h b/system/gd/hci/controller.h index ea45aef729..573c695ad6 100644 --- a/system/gd/hci/controller.h +++ b/system/gd/hci/controller.h @@ -28,8 +28,10 @@ namespace hci { class Controller : public Module { public: Controller(); + Controller(const Controller&) = delete; + Controller& operator=(const Controller&) = delete; + virtual ~Controller(); - DISALLOW_COPY_AND_ASSIGN(Controller); using CompletedAclPacketsCallback = common::ContextualCallback<void(uint16_t /* handle */, uint16_t /* num_packets */)>; diff --git a/system/gd/hci/hci_layer.h b/system/gd/hci/hci_layer.h index 8ff74d3867..bde991508d 100644 --- a/system/gd/hci/hci_layer.h +++ b/system/gd/hci/hci_layer.h @@ -43,8 +43,10 @@ class HciLayer : public Module, public CommandInterface<CommandBuilder> { // LINT.IfChange public: HciLayer(); + HciLayer(const HciLayer&) = delete; + HciLayer& operator=(const HciLayer&) = delete; + virtual ~HciLayer(); - DISALLOW_COPY_AND_ASSIGN(HciLayer); void EnqueueCommand( std::unique_ptr<CommandBuilder> command, diff --git a/system/gd/hci/le_advertising_manager.h b/system/gd/hci/le_advertising_manager.h index 75040fbc1f..557b110d8d 100644 --- a/system/gd/hci/le_advertising_manager.h +++ b/system/gd/hci/le_advertising_manager.h @@ -102,6 +102,8 @@ class LeAdvertisingManager : public bluetooth::Module { static constexpr uint16_t kLeMaximumFragmentLength = 251; static constexpr FragmentPreference kFragment_preference = FragmentPreference::CONTROLLER_SHOULD_NOT; LeAdvertisingManager(); + LeAdvertisingManager(const LeAdvertisingManager&) = delete; + LeAdvertisingManager& operator=(const LeAdvertisingManager&) = delete; size_t GetNumberOfAdvertisingInstances() const; @@ -153,7 +155,6 @@ class LeAdvertisingManager : public bluetooth::Module { os::Handler* handler); struct impl; std::unique_ptr<impl> pimpl_; - DISALLOW_COPY_AND_ASSIGN(LeAdvertisingManager); }; } // namespace hci diff --git a/system/gd/hci/le_scanning_manager.h b/system/gd/hci/le_scanning_manager.h index 8e58fb5cb0..2bc5180e8d 100644 --- a/system/gd/hci/le_scanning_manager.h +++ b/system/gd/hci/le_scanning_manager.h @@ -42,6 +42,8 @@ class LeScanningManager : public bluetooth::Module { static constexpr uint8_t kNotPeriodicAdvertisement = 0x00; static constexpr ScannerId kInvalidScannerId = 0xFF; LeScanningManager(); + LeScanningManager(const LeScanningManager&) = delete; + LeScanningManager& operator=(const LeScanningManager&) = delete; virtual void RegisterScanner(const Uuid app_uuid); @@ -92,7 +94,6 @@ class LeScanningManager : public bluetooth::Module { private: struct impl; std::unique_ptr<impl> pimpl_; - DISALLOW_COPY_AND_ASSIGN(LeScanningManager); }; } // namespace hci diff --git a/system/gd/hci/vendor_specific_event_manager.h b/system/gd/hci/vendor_specific_event_manager.h index 7e0f3334dc..3dba563847 100644 --- a/system/gd/hci/vendor_specific_event_manager.h +++ b/system/gd/hci/vendor_specific_event_manager.h @@ -24,6 +24,8 @@ namespace hci { class VendorSpecificEventManager : public bluetooth::Module { public: VendorSpecificEventManager(); + VendorSpecificEventManager(const VendorSpecificEventManager&) = delete; + VendorSpecificEventManager& operator=(const VendorSpecificEventManager&) = delete; void RegisterEventHandler(VseSubeventCode event, common::ContextualCallback<void(VendorSpecificEventView)> handler); @@ -43,7 +45,6 @@ class VendorSpecificEventManager : public bluetooth::Module { private: struct impl; std::unique_ptr<impl> pimpl_; - DISALLOW_COPY_AND_ASSIGN(VendorSpecificEventManager); }; } // namespace hci diff --git a/system/gd/iso/iso_manager.h b/system/gd/iso/iso_manager.h index d38405c4e8..b40d6f5175 100644 --- a/system/gd/iso/iso_manager.h +++ b/system/gd/iso/iso_manager.h @@ -37,6 +37,9 @@ using IsoDataCallback = common::ContextualCallback<void(std::unique_ptr<hci::Iso */ class IsoManager { public: + IsoManager(const IsoManager&) = delete; + IsoManager& operator=(const IsoManager&) = delete; + friend class IsoModule; void RegisterIsoEstablishedCallback(CisEstablishedCallback cb); @@ -80,7 +83,6 @@ class IsoManager { private: os::Handler* iso_handler_ = nullptr; internal::IsoManagerImpl* iso_manager_impl_; - DISALLOW_COPY_AND_ASSIGN(IsoManager); }; } // namespace iso diff --git a/system/gd/iso/iso_module.h b/system/gd/iso/iso_module.h index 6db880c109..d767620b31 100644 --- a/system/gd/iso/iso_module.h +++ b/system/gd/iso/iso_module.h @@ -26,6 +26,9 @@ namespace iso { class IsoModule : public bluetooth::Module { public: IsoModule() = default; + IsoModule(const IsoModule&) = delete; + IsoModule& operator=(const IsoModule&) = delete; + ~IsoModule() = default; /** @@ -47,7 +50,6 @@ class IsoModule : public bluetooth::Module { private: struct impl; std::unique_ptr<impl> pimpl_; - DISALLOW_COPY_AND_ASSIGN(IsoModule); }; } // namespace iso diff --git a/system/gd/l2cap/classic/dynamic_channel_manager.h b/system/gd/l2cap/classic/dynamic_channel_manager.h index 66e3aeec58..ab240ff0d3 100644 --- a/system/gd/l2cap/classic/dynamic_channel_manager.h +++ b/system/gd/l2cap/classic/dynamic_channel_manager.h @@ -122,6 +122,9 @@ class DynamicChannelManager { friend class L2capClassicModule; + DynamicChannelManager(const DynamicChannelManager&) = delete; + DynamicChannelManager& operator=(const DynamicChannelManager&) = delete; + virtual ~DynamicChannelManager() = default; protected: @@ -139,7 +142,6 @@ class DynamicChannelManager { internal::DynamicChannelServiceManagerImpl* service_manager_ = nullptr; internal::LinkManager* link_manager_ = nullptr; os::Handler* l2cap_layer_handler_ = nullptr; - DISALLOW_COPY_AND_ASSIGN(DynamicChannelManager); }; } // namespace classic diff --git a/system/gd/l2cap/classic/dynamic_channel_service.h b/system/gd/l2cap/classic/dynamic_channel_service.h index f098db1a03..40ead1f6ad 100644 --- a/system/gd/l2cap/classic/dynamic_channel_service.h +++ b/system/gd/l2cap/classic/dynamic_channel_service.h @@ -32,6 +32,8 @@ class DynamicChannelServiceManagerImpl; class DynamicChannelService { public: DynamicChannelService() = default; + DynamicChannelService(const DynamicChannelService&) = delete; + DynamicChannelService& operator=(const DynamicChannelService&) = delete; using OnUnregisteredCallback = common::ContextualOnceCallback<void()>; @@ -59,7 +61,6 @@ class DynamicChannelService { Psm psm_ = kDefaultPsm; internal::DynamicChannelServiceManagerImpl* manager_ = nullptr; os::Handler* l2cap_layer_handler_; - DISALLOW_COPY_AND_ASSIGN(DynamicChannelService); }; } // namespace classic diff --git a/system/gd/l2cap/classic/fixed_channel_manager.h b/system/gd/l2cap/classic/fixed_channel_manager.h index a3285e7d3e..9c40bd1e54 100644 --- a/system/gd/l2cap/classic/fixed_channel_manager.h +++ b/system/gd/l2cap/classic/fixed_channel_manager.h @@ -129,6 +129,9 @@ class FixedChannelManager { virtual bool RegisterService(Cid cid, OnRegistrationCompleteCallback on_registration_complete, OnConnectionOpenCallback on_connection_open, os::Handler* handler); + FixedChannelManager(const FixedChannelManager&) = delete; + FixedChannelManager& operator=(const FixedChannelManager&) = delete; + virtual ~FixedChannelManager() = default; friend class L2capClassicModule; @@ -143,7 +146,6 @@ class FixedChannelManager { internal::FixedChannelServiceManagerImpl* service_manager_ = nullptr; internal::LinkManager* link_manager_ = nullptr; os::Handler* l2cap_layer_handler_ = nullptr; - DISALLOW_COPY_AND_ASSIGN(FixedChannelManager); }; } // namespace classic diff --git a/system/gd/l2cap/classic/fixed_channel_service.h b/system/gd/l2cap/classic/fixed_channel_service.h index d5d213b62a..447d3a80bd 100644 --- a/system/gd/l2cap/classic/fixed_channel_service.h +++ b/system/gd/l2cap/classic/fixed_channel_service.h @@ -32,6 +32,8 @@ class FixedChannelServiceManagerImpl; class FixedChannelService { public: FixedChannelService() = default; + FixedChannelService(const FixedChannelService&) = delete; + FixedChannelService& operator=(const FixedChannelService&) = delete; using OnUnregisteredCallback = common::OnceCallback<void()>; @@ -51,7 +53,6 @@ class FixedChannelService { Cid cid_ = kInvalidCid; internal::FixedChannelServiceManagerImpl* manager_ = nullptr; os::Handler* l2cap_layer_handler_; - DISALLOW_COPY_AND_ASSIGN(FixedChannelService); }; } // namespace classic diff --git a/system/gd/l2cap/classic/internal/fixed_channel_impl.h b/system/gd/l2cap/classic/internal/fixed_channel_impl.h index 4c4e9f17fb..37efa1db84 100644 --- a/system/gd/l2cap/classic/internal/fixed_channel_impl.h +++ b/system/gd/l2cap/classic/internal/fixed_channel_impl.h @@ -35,6 +35,9 @@ class FixedChannelImpl : public l2cap::internal::ChannelImpl { public: FixedChannelImpl(Cid cid, Link* link, os::Handler* l2cap_handler); + FixedChannelImpl(const FixedChannelImpl&) = delete; + FixedChannelImpl& operator=(const FixedChannelImpl&) = delete; + virtual ~FixedChannelImpl() = default; hci::Address GetDevice() const { @@ -96,8 +99,6 @@ class FixedChannelImpl : public l2cap::internal::ChannelImpl { static constexpr size_t kChannelQueueSize = 10; common::BidiQueue<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder> channel_queue_{ kChannelQueueSize}; - - DISALLOW_COPY_AND_ASSIGN(FixedChannelImpl); }; } // namespace internal diff --git a/system/gd/l2cap/classic/internal/link.h b/system/gd/l2cap/classic/internal/link.h index a5b17a9dc8..2b61aaebf0 100644 --- a/system/gd/l2cap/classic/internal/link.h +++ b/system/gd/l2cap/classic/internal/link.h @@ -51,6 +51,9 @@ class Link : public l2cap::internal::ILink, public hci::acl_manager::ConnectionM DynamicChannelServiceManagerImpl* dynamic_service_manager, FixedChannelServiceManagerImpl* fixed_service_manager, LinkManager* link_manager); + Link(const Link&) = delete; + Link& operator=(const Link&) = delete; + hci::AddressWithType GetDevice() const override { return {acl_connection_->GetAddress(), hci::AddressType::PUBLIC_DEVICE_ADDRESS}; } @@ -234,7 +237,6 @@ class Link : public l2cap::internal::ILink, public hci::acl_manager::ConnectionM bool has_requested_authentication_ = false; std::list<EncryptionChangeListener> encryption_change_listener_; std::atomic_int remaining_packets_to_be_sent_ = 0; - DISALLOW_COPY_AND_ASSIGN(Link); }; } // namespace internal diff --git a/system/gd/l2cap/classic/internal/link_manager.h b/system/gd/l2cap/classic/internal/link_manager.h index a81b0f5aad..4d327ea5bf 100644 --- a/system/gd/l2cap/classic/internal/link_manager.h +++ b/system/gd/l2cap/classic/internal/link_manager.h @@ -52,6 +52,9 @@ class LinkManager : public hci::acl_manager::ConnectionCallbacks { acl_manager_->RegisterCallbacks(this, l2cap_handler_); } + LinkManager(const LinkManager&) = delete; + LinkManager& operator=(const LinkManager&) = delete; + struct PendingFixedChannelConnection { os::Handler* handler_; FixedChannelManager::OnConnectionFailureCallback on_fail_callback_; @@ -147,8 +150,6 @@ class LinkManager : public hci::acl_manager::ConnectionCallbacks { os::Handler* link_property_callback_handler_ = nullptr; std::unordered_set<hci::Address> disconnected_links_; std::unordered_set<hci::Address> links_with_pending_packets_; - - DISALLOW_COPY_AND_ASSIGN(LinkManager); }; } // namespace internal diff --git a/system/gd/l2cap/classic/l2cap_classic_module.h b/system/gd/l2cap/classic/l2cap_classic_module.h index f22f039768..407de38dc4 100644 --- a/system/gd/l2cap/classic/l2cap_classic_module.h +++ b/system/gd/l2cap/classic/l2cap_classic_module.h @@ -36,6 +36,9 @@ namespace classic { class L2capClassicModule : public bluetooth::Module { public: L2capClassicModule(); + L2capClassicModule(const L2capClassicModule&) = delete; + L2capClassicModule& operator=(const L2capClassicModule&) = delete; + virtual ~L2capClassicModule(); /** @@ -86,8 +89,6 @@ class L2capClassicModule : public bluetooth::Module { private: struct impl; std::unique_ptr<impl> pimpl_; - - DISALLOW_COPY_AND_ASSIGN(L2capClassicModule); }; } // namespace classic diff --git a/system/gd/l2cap/internal/dynamic_channel_impl.h b/system/gd/l2cap/internal/dynamic_channel_impl.h index a012fff2de..4ae959f2e6 100644 --- a/system/gd/l2cap/internal/dynamic_channel_impl.h +++ b/system/gd/l2cap/internal/dynamic_channel_impl.h @@ -36,6 +36,9 @@ class DynamicChannelImpl : public l2cap::internal::ChannelImpl { public: DynamicChannelImpl(Psm psm, Cid cid, Cid remote_cid, l2cap::internal::ILink* link, os::Handler* l2cap_handler); + DynamicChannelImpl(const DynamicChannelImpl&) = delete; + DynamicChannelImpl& operator=(const DynamicChannelImpl&) = delete; + virtual ~DynamicChannelImpl() = default; hci::AddressWithType GetDevice() const; @@ -90,8 +93,6 @@ class DynamicChannelImpl : public l2cap::internal::ChannelImpl { static constexpr size_t kChannelQueueSize = 5; common::BidiQueue<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder> channel_queue_{ kChannelQueueSize}; - - DISALLOW_COPY_AND_ASSIGN(DynamicChannelImpl); }; } // namespace internal diff --git a/system/gd/l2cap/le/dynamic_channel_manager.h b/system/gd/l2cap/le/dynamic_channel_manager.h index e5334ef13e..2d1b24f069 100644 --- a/system/gd/l2cap/le/dynamic_channel_manager.h +++ b/system/gd/l2cap/le/dynamic_channel_manager.h @@ -40,6 +40,9 @@ class DynamicChannelServiceManagerImpl; class DynamicChannelManager { public: + DynamicChannelManager(const DynamicChannelManager&) = delete; + DynamicChannelManager& operator=(const DynamicChannelManager&) = delete; + enum class ConnectionResultCode { SUCCESS = 0, FAIL_NO_SERVICE_REGISTERED = 1, // No service is registered @@ -138,7 +141,6 @@ class DynamicChannelManager { internal::DynamicChannelServiceManagerImpl* service_manager_ = nullptr; internal::LinkManager* link_manager_ = nullptr; os::Handler* l2cap_layer_handler_ = nullptr; - DISALLOW_COPY_AND_ASSIGN(DynamicChannelManager); }; } // namespace le diff --git a/system/gd/l2cap/le/dynamic_channel_service.h b/system/gd/l2cap/le/dynamic_channel_service.h index 898c885eca..4294e59aea 100644 --- a/system/gd/l2cap/le/dynamic_channel_service.h +++ b/system/gd/l2cap/le/dynamic_channel_service.h @@ -32,6 +32,8 @@ class DynamicChannelServiceManagerImpl; class DynamicChannelService { public: DynamicChannelService() = default; + DynamicChannelService(const DynamicChannelService&) = delete; + DynamicChannelService& operator=(const DynamicChannelService&) = delete; using OnUnregisteredCallback = common::OnceCallback<void()>; @@ -58,7 +60,6 @@ class DynamicChannelService { Psm psm_ = kDefaultPsm; internal::DynamicChannelServiceManagerImpl* manager_ = nullptr; os::Handler* l2cap_layer_handler_; - DISALLOW_COPY_AND_ASSIGN(DynamicChannelService); }; } // namespace le diff --git a/system/gd/l2cap/le/fixed_channel_manager.h b/system/gd/l2cap/le/fixed_channel_manager.h index 1b059ac342..9bd2c70cd8 100644 --- a/system/gd/l2cap/le/fixed_channel_manager.h +++ b/system/gd/l2cap/le/fixed_channel_manager.h @@ -36,6 +36,9 @@ class FixedChannelServiceManagerImpl; class FixedChannelManager { public: + FixedChannelManager(const FixedChannelManager&) = delete; + FixedChannelManager& operator=(const FixedChannelManager&) = delete; + enum class ConnectionResultCode { SUCCESS = 0, FAIL_NO_SERVICE_REGISTERED = 1, // No service is registered @@ -136,7 +139,6 @@ class FixedChannelManager { internal::FixedChannelServiceManagerImpl* service_manager_ = nullptr; internal::LinkManager* link_manager_ = nullptr; os::Handler* l2cap_layer_handler_ = nullptr; - DISALLOW_COPY_AND_ASSIGN(FixedChannelManager); }; } // namespace le diff --git a/system/gd/l2cap/le/fixed_channel_service.h b/system/gd/l2cap/le/fixed_channel_service.h index 0c4556e230..7660e31ec5 100644 --- a/system/gd/l2cap/le/fixed_channel_service.h +++ b/system/gd/l2cap/le/fixed_channel_service.h @@ -32,6 +32,8 @@ class FixedChannelServiceManagerImpl; class FixedChannelService { public: FixedChannelService() = default; + FixedChannelService(const FixedChannelService&) = delete; + FixedChannelService& operator=(const FixedChannelService&) = delete; using OnUnregisteredCallback = common::OnceCallback<void()>; @@ -51,7 +53,6 @@ class FixedChannelService { Cid cid_ = kInvalidCid; internal::FixedChannelServiceManagerImpl* manager_ = nullptr; os::Handler* l2cap_layer_handler_; - DISALLOW_COPY_AND_ASSIGN(FixedChannelService); }; } // namespace le diff --git a/system/gd/l2cap/le/internal/fixed_channel_impl.h b/system/gd/l2cap/le/internal/fixed_channel_impl.h index d4fb3a3708..59a68add89 100644 --- a/system/gd/l2cap/le/internal/fixed_channel_impl.h +++ b/system/gd/l2cap/le/internal/fixed_channel_impl.h @@ -36,6 +36,9 @@ class FixedChannelImpl : public l2cap::internal::ChannelImpl { public: FixedChannelImpl(Cid cid, Link* link, os::Handler* l2cap_handler); + FixedChannelImpl(const FixedChannelImpl&) = delete; + FixedChannelImpl& operator=(const FixedChannelImpl&) = delete; + virtual ~FixedChannelImpl() = default; hci::AddressWithType GetDevice() const { @@ -98,8 +101,6 @@ class FixedChannelImpl : public l2cap::internal::ChannelImpl { static constexpr size_t kChannelQueueSize = 10; common::BidiQueue<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder> channel_queue_{ kChannelQueueSize}; - - DISALLOW_COPY_AND_ASSIGN(FixedChannelImpl); }; } // namespace internal diff --git a/system/gd/l2cap/le/internal/link.h b/system/gd/l2cap/le/internal/link.h index 518793eb32..a17ea33b6d 100644 --- a/system/gd/l2cap/le/internal/link.h +++ b/system/gd/l2cap/le/internal/link.h @@ -49,6 +49,9 @@ class Link : public l2cap::internal::ILink, public hci::acl_manager::LeConnectio DynamicChannelServiceManagerImpl* dynamic_service_manager, FixedChannelServiceManagerImpl* fixed_service_manager, LinkManager* link_manager); + Link(const Link&) = delete; + Link& operator=(const Link&) = delete; + ~Link() = default; inline hci::AddressWithType GetDevice() const override { @@ -170,7 +173,6 @@ class Link : public l2cap::internal::ILink, public hci::acl_manager::LeConnectio uint16_t update_request_latency_; uint16_t update_request_supervision_timeout_; std::atomic_int remaining_packets_to_be_sent_ = 0; - DISALLOW_COPY_AND_ASSIGN(Link); // Received connection update complete from ACL manager. SignalId is bound to a valid number when we need to send a // response to remote. If SignalId is bound to an invalid number, we don't send a response to remote, because the diff --git a/system/gd/l2cap/le/internal/link_manager.h b/system/gd/l2cap/le/internal/link_manager.h index c6ec046ec4..836a3f6e8c 100644 --- a/system/gd/l2cap/le/internal/link_manager.h +++ b/system/gd/l2cap/le/internal/link_manager.h @@ -56,6 +56,9 @@ class LinkManager : public hci::acl_manager::LeConnectionCallbacks { acl_manager_->RegisterLeCallbacks(this, l2cap_handler_); } + LinkManager(const LinkManager&) = delete; + LinkManager& operator=(const LinkManager&) = delete; + struct PendingFixedChannelConnection { os::Handler* handler_; FixedChannelManager::OnConnectionFailureCallback on_fail_callback_; @@ -116,8 +119,6 @@ class LinkManager : public hci::acl_manager::LeConnectionCallbacks { LinkPropertyListener* link_property_listener_ = nullptr; std::unordered_set<hci::AddressWithType> disconnected_links_; std::unordered_set<hci::AddressWithType> links_with_pending_packets_; - - DISALLOW_COPY_AND_ASSIGN(LinkManager); }; } // namespace internal diff --git a/system/gd/l2cap/le/l2cap_le_module.h b/system/gd/l2cap/le/l2cap_le_module.h index 05cabd21ff..28352c0c68 100644 --- a/system/gd/l2cap/le/l2cap_le_module.h +++ b/system/gd/l2cap/le/l2cap_le_module.h @@ -39,6 +39,9 @@ namespace le { class L2capLeModule : public bluetooth::Module { public: L2capLeModule(); + L2capLeModule(const L2capLeModule&) = delete; + L2capLeModule& operator=(const L2capLeModule&) = delete; + virtual ~L2capLeModule(); /** @@ -81,8 +84,6 @@ class L2capLeModule : public bluetooth::Module { * This is not synchronized. */ virtual void SetLinkPropertyListener(os::Handler* handler, LinkPropertyListener* listener); - - DISALLOW_COPY_AND_ASSIGN(L2capLeModule); }; } // namespace le diff --git a/system/gd/neighbor/connectability.h b/system/gd/neighbor/connectability.h index eebf741104..00858059dd 100644 --- a/system/gd/neighbor/connectability.h +++ b/system/gd/neighbor/connectability.h @@ -29,6 +29,9 @@ class ConnectabilityModule : public bluetooth::Module { bool IsConnectable() const; ConnectabilityModule(); + ConnectabilityModule(const ConnectabilityModule&) = delete; + ConnectabilityModule& operator=(const ConnectabilityModule&) = delete; + ~ConnectabilityModule(); static const ModuleFactory Factory; @@ -44,8 +47,6 @@ class ConnectabilityModule : public bluetooth::Module { private: struct impl; std::unique_ptr<impl> pimpl_; - - DISALLOW_COPY_AND_ASSIGN(ConnectabilityModule); }; } // namespace neighbor diff --git a/system/gd/neighbor/discoverability.h b/system/gd/neighbor/discoverability.h index cce4b87965..4c118c293e 100644 --- a/system/gd/neighbor/discoverability.h +++ b/system/gd/neighbor/discoverability.h @@ -35,6 +35,9 @@ class DiscoverabilityModule : public bluetooth::Module { static const ModuleFactory Factory; DiscoverabilityModule(); + DiscoverabilityModule(const DiscoverabilityModule&) = delete; + DiscoverabilityModule& operator=(const DiscoverabilityModule&) = delete; + ~DiscoverabilityModule(); protected: @@ -48,8 +51,6 @@ class DiscoverabilityModule : public bluetooth::Module { private: struct impl; std::unique_ptr<impl> pimpl_; - - DISALLOW_COPY_AND_ASSIGN(DiscoverabilityModule); }; } // namespace neighbor diff --git a/system/gd/neighbor/inquiry.h b/system/gd/neighbor/inquiry.h index 1482af521a..5304be5327 100644 --- a/system/gd/neighbor/inquiry.h +++ b/system/gd/neighbor/inquiry.h @@ -67,6 +67,9 @@ class InquiryModule : public bluetooth::Module { static const ModuleFactory Factory; InquiryModule(); + InquiryModule(const InquiryModule&) = delete; + InquiryModule& operator=(const InquiryModule&) = delete; + ~InquiryModule(); protected: @@ -80,8 +83,6 @@ class InquiryModule : public bluetooth::Module { private: struct impl; std::unique_ptr<impl> pimpl_; - - DISALLOW_COPY_AND_ASSIGN(InquiryModule); }; } // namespace neighbor diff --git a/system/gd/neighbor/name.h b/system/gd/neighbor/name.h index 233757ddd4..48d8eadd2a 100644 --- a/system/gd/neighbor/name.h +++ b/system/gd/neighbor/name.h @@ -45,6 +45,9 @@ class NameModule : public bluetooth::Module { static const ModuleFactory Factory; NameModule(); + NameModule(const NameModule&) = delete; + NameModule& operator=(const NameModule&) = delete; + ~NameModule(); protected: @@ -58,8 +61,6 @@ class NameModule : public bluetooth::Module { private: struct impl; std::unique_ptr<impl> pimpl_; - - DISALLOW_COPY_AND_ASSIGN(NameModule); }; } // namespace neighbor diff --git a/system/gd/neighbor/name_db.h b/system/gd/neighbor/name_db.h index 1180cff9bb..5164f721dd 100644 --- a/system/gd/neighbor/name_db.h +++ b/system/gd/neighbor/name_db.h @@ -40,6 +40,9 @@ class NameDbModule : public bluetooth::Module { static const ModuleFactory Factory; NameDbModule(); + NameDbModule(const NameDbModule&) = delete; + NameDbModule& operator=(const NameDbModule&) = delete; + ~NameDbModule(); protected: @@ -53,8 +56,6 @@ class NameDbModule : public bluetooth::Module { private: struct impl; std::unique_ptr<impl> pimpl_; - - DISALLOW_COPY_AND_ASSIGN(NameDbModule); }; } // namespace neighbor diff --git a/system/gd/neighbor/page.h b/system/gd/neighbor/page.h index 14c3ae606b..19c55b9b92 100644 --- a/system/gd/neighbor/page.h +++ b/system/gd/neighbor/page.h @@ -43,6 +43,9 @@ class PageModule : public bluetooth::Module { static const ModuleFactory Factory; PageModule(); + PageModule(const PageModule&) = delete; + PageModule& operator=(const PageModule&) = delete; + ~PageModule(); protected: @@ -56,8 +59,6 @@ class PageModule : public bluetooth::Module { private: struct impl; std::unique_ptr<impl> pimpl_; - - DISALLOW_COPY_AND_ASSIGN(PageModule); }; } // namespace neighbor diff --git a/system/gd/neighbor/scan.h b/system/gd/neighbor/scan.h index e1699b4e05..6cea59595d 100644 --- a/system/gd/neighbor/scan.h +++ b/system/gd/neighbor/scan.h @@ -25,6 +25,9 @@ namespace neighbor { class ScanModule : public bluetooth::Module { public: ScanModule(); + ScanModule(const ScanModule&) = delete; + ScanModule& operator=(const ScanModule&) = delete; + ~ScanModule(); void SetInquiryScan(); @@ -48,8 +51,6 @@ class ScanModule : public bluetooth::Module { private: struct impl; std::unique_ptr<impl> pimpl_; - - DISALLOW_COPY_AND_ASSIGN(ScanModule); }; } // namespace neighbor diff --git a/system/gd/os/Android.bp b/system/gd/os/Android.bp index fb4c50c2b9..b2916c58a8 100644 --- a/system/gd/os/Android.bp +++ b/system/gd/os/Android.bp @@ -8,6 +8,13 @@ package { } filegroup { + name: "BluetoothOsSources", + srcs: [ + "handler.cc", + ], +} + +filegroup { name: "BluetoothOsSources_android", srcs: [ "android/metrics.cc", @@ -36,6 +43,13 @@ filegroup { } filegroup { + name: "BluetoothOsTestSources", + srcs: [ + "handler_unittest.cc", + ], +} + +filegroup { name: "BluetoothOsTestSources_host", srcs: [ "host/system_properties_test.cc", @@ -48,7 +62,6 @@ filegroup { srcs: [ "linux_generic/alarm.cc", "linux_generic/files.cc", - "linux_generic/handler.cc", "linux_generic/reactor.cc", "linux_generic/repeating_alarm.cc", "linux_generic/reactive_semaphore.cc", @@ -62,7 +75,6 @@ filegroup { srcs: [ "linux_generic/alarm_unittest.cc", "linux_generic/files_test.cc", - "linux_generic/handler_unittest.cc", "linux_generic/queue_unittest.cc", "linux_generic/reactor_unittest.cc", "linux_generic/repeating_alarm_unittest.cc", diff --git a/system/gd/os/BUILD.gn b/system/gd/os/BUILD.gn index 790da5ed6b..48337e14e8 100644 --- a/system/gd/os/BUILD.gn +++ b/system/gd/os/BUILD.gn @@ -27,9 +27,9 @@ source_set("BluetoothOsSources_linux") { source_set("BluetoothOsSources_linux_generic") { sources = [ + "handler.cc", "linux_generic/alarm.cc", "linux_generic/files.cc", - "linux_generic/handler.cc", "linux_generic/reactive_semaphore.cc", "linux_generic/reactor.cc", "linux_generic/repeating_alarm.cc", diff --git a/system/gd/os/alarm.h b/system/gd/os/alarm.h index 773c36f4ac..4a689da48b 100644 --- a/system/gd/os/alarm.h +++ b/system/gd/os/alarm.h @@ -36,11 +36,12 @@ class Alarm { // Create and register a single-shot alarm on a given handler explicit Alarm(Handler* handler); + Alarm(const Alarm&) = delete; + Alarm& operator=(const Alarm&) = delete; + // Unregister this alarm from the thread and release resource ~Alarm(); - DISALLOW_COPY_AND_ASSIGN(Alarm); - // Schedule the alarm with given delay void Schedule(common::OnceClosure task, std::chrono::milliseconds delay); diff --git a/system/gd/os/files.h b/system/gd/os/files.h index 5a6721b1ef..5802aa1e67 100644 --- a/system/gd/os/files.h +++ b/system/gd/os/files.h @@ -16,6 +16,7 @@ #pragma once +#include <chrono> #include <iterator> #include <optional> @@ -45,5 +46,9 @@ bool WriteToFile(const std::string& path, const std::string& data); // Return true on success, false on failure (e.g. file not exist, failed to remove, etc) bool RemoveFile(const std::string& path); +// Returns created time_point of given file, return std::nullopt on failure +std::optional<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> FileCreatedTime( + const std::string& path); + } // namespace os } // namespace bluetooth
\ No newline at end of file diff --git a/system/gd/os/linux_generic/handler.cc b/system/gd/os/handler.cc index 2f996f91e6..ff1ee8802c 100644 --- a/system/gd/os/linux_generic/handler.cc +++ b/system/gd/os/handler.cc @@ -16,9 +16,6 @@ #include "os/handler.h" -#include <sys/eventfd.h> -#include <unistd.h> - #include <cstring> #include "common/bind.h" @@ -27,19 +24,14 @@ #include "os/reactor.h" #include "os/utils.h" -#ifndef EFD_SEMAPHORE -#define EFD_SEMAPHORE 1 -#endif - namespace bluetooth { namespace os { using common::OnceClosure; -Handler::Handler(Thread* thread) - : tasks_(new std::queue<OnceClosure>()), thread_(thread), fd_(eventfd(0, EFD_SEMAPHORE | EFD_NONBLOCK)) { - ASSERT(fd_ != -1); +Handler::Handler(Thread* thread) : tasks_(new std::queue<OnceClosure>()), thread_(thread) { + event_ = thread_->GetReactor()->NewEvent(); reactable_ = thread_->GetReactor()->Register( - fd_, common::Bind(&Handler::handle_next_event, common::Unretained(this)), common::Closure()); + event_->Id(), common::Bind(&Handler::handle_next_event, common::Unretained(this)), common::Closure()); } Handler::~Handler() { @@ -47,10 +39,7 @@ Handler::~Handler() { std::lock_guard<std::mutex> lock(mutex_); ASSERT_LOG(was_cleared(), "Handlers must be cleared before they are destroyed"); } - - int close_status; - RUN_NO_INTR(close_status = close(fd_)); - ASSERT(close_status != -1); + event_->Close(); } void Handler::Post(OnceClosure closure) { @@ -62,9 +51,7 @@ void Handler::Post(OnceClosure closure) { } tasks_->emplace(std::move(closure)); } - uint64_t val = 1; - auto write_result = eventfd_write(fd_, val); - ASSERT(write_result != -1); + event_->Notify(); } void Handler::Clear() { @@ -76,9 +63,7 @@ void Handler::Clear() { } delete tmp; - uint64_t val; - while (eventfd_read(fd_, &val) == 0) { - } + event_->Clear(); thread_->GetReactor()->Unregister(reactable_); reactable_ = nullptr; @@ -93,13 +78,12 @@ void Handler::handle_next_event() { common::OnceClosure closure; { std::lock_guard<std::mutex> lock(mutex_); - uint64_t val = 0; - auto read_result = eventfd_read(fd_, &val); + bool has_data = event_->Read(); if (was_cleared()) { return; } - ASSERT_LOG(read_result != -1, "eventfd read error %d %s", errno, strerror(errno)); + ASSERT_LOG(has_data, "Notified for work but no work available"); closure = std::move(tasks_->front()); tasks_->pop(); diff --git a/system/gd/os/handler.h b/system/gd/os/handler.h index 9e530bc36e..1dabbde7ff 100644 --- a/system/gd/os/handler.h +++ b/system/gd/os/handler.h @@ -38,11 +38,12 @@ class Handler : public common::IPostableContext { // Create and register a handler on given thread explicit Handler(Thread* thread); + Handler(const Handler&) = delete; + Handler& operator=(const Handler&) = delete; + // Unregister this handler from the thread and release resource. Unhandled events will be discarded and not executed. virtual ~Handler(); - DISALLOW_COPY_AND_ASSIGN(Handler); - // Enqueue a closure to the queue of this handler virtual void Post(common::OnceClosure closure) override; @@ -102,7 +103,7 @@ class Handler : public common::IPostableContext { }; std::queue<common::OnceClosure>* tasks_; Thread* thread_; - int fd_; + std::unique_ptr<Reactor::Event> event_; Reactor::Reactable* reactable_; mutable std::mutex mutex_; void handle_next_event(); diff --git a/system/gd/os/linux_generic/handler_unittest.cc b/system/gd/os/handler_unittest.cc index cea030ef1d..b8c580f4c9 100644 --- a/system/gd/os/linux_generic/handler_unittest.cc +++ b/system/gd/os/handler_unittest.cc @@ -16,8 +16,6 @@ #include "os/handler.h" -#include <sys/eventfd.h> - #include <future> #include <thread> diff --git a/system/gd/os/linux_generic/files.cc b/system/gd/os/linux_generic/files.cc index bb018bf374..cf1a4aade8 100644 --- a/system/gd/os/linux_generic/files.cc +++ b/system/gd/os/linux_generic/files.cc @@ -195,5 +195,19 @@ bool RemoveFile(const std::string& path) { return true; } +std::optional<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> FileCreatedTime( + const std::string& path) { + struct stat file_info; + if (stat(path.c_str(), &file_info) != 0) { + LOG_ERROR("unable to read '%s' file metadata, error: %s", path.c_str(), strerror(errno)); + return std::nullopt; + } + using namespace std::chrono; + using namespace std::chrono_literals; + auto created_ts = file_info.st_ctim; + auto d = seconds{created_ts.tv_sec} + nanoseconds{created_ts.tv_nsec}; + return time_point<system_clock>(duration_cast<system_clock::duration>(d)); +} + } // namespace os } // namespace bluetooth
\ No newline at end of file diff --git a/system/gd/os/linux_generic/reactive_semaphore.h b/system/gd/os/linux_generic/reactive_semaphore.h index 718666c69c..dd54b1a9dc 100644 --- a/system/gd/os/linux_generic/reactive_semaphore.h +++ b/system/gd/os/linux_generic/reactive_semaphore.h @@ -26,6 +26,10 @@ class ReactiveSemaphore { public: // Creates a new ReactiveSemaphore with an initial value of |value|. explicit ReactiveSemaphore(unsigned int value); + + ReactiveSemaphore(const ReactiveSemaphore&) = delete; + ReactiveSemaphore& operator=(const ReactiveSemaphore&) = delete; + ~ReactiveSemaphore(); // Decrements the value of |fd_|, this will cause a crash if |fd_| unreadable. void Decrease(); @@ -33,8 +37,6 @@ class ReactiveSemaphore { void Increase(); int GetFd(); - DISALLOW_COPY_AND_ASSIGN(ReactiveSemaphore); - private: int fd_; }; diff --git a/system/gd/os/linux_generic/reactor.cc b/system/gd/os/linux_generic/reactor.cc index 5722c61392..f0c7b1509e 100644 --- a/system/gd/os/linux_generic/reactor.cc +++ b/system/gd/os/linux_generic/reactor.cc @@ -41,6 +41,47 @@ namespace bluetooth { namespace os { using common::Closure; +struct Reactor::Event::impl { + impl() { + fd_ = eventfd(0, EFD_SEMAPHORE | EFD_NONBLOCK); + ASSERT_LOG(fd_ != -1, "Unable to create nonblocking event file descriptor semaphore"); + } + ~impl() { + ASSERT_LOG(fd_ != -1, "Unable to close a never-opened event file descriptor"); + close(fd_); + fd_ = -1; + } + int fd_ = -1; +}; + +Reactor::Event::Event() : pimpl_(new impl()) {} +Reactor::Event::~Event() { + delete pimpl_; +} + +bool Reactor::Event::Read() { + uint64_t val = 0; + return eventfd_read(pimpl_->fd_, &val) == 0; +} +int Reactor::Event::Id() const { + return pimpl_->fd_; +} +void Reactor::Event::Clear() { + uint64_t val; + while (eventfd_read(pimpl_->fd_, &val) == 0) { + } +} +void Reactor::Event::Close() { + int close_status; + RUN_NO_INTR(close_status = close(pimpl_->fd_)); + ASSERT(close_status != -1); +} +void Reactor::Event::Notify() { + uint64_t val = 1; + auto write_result = eventfd_write(pimpl_->fd_, val); + ASSERT(write_result != -1); +} + class Reactor::Reactable { public: Reactable(int fd, Closure on_read_ready, Closure on_write_ready) @@ -165,6 +206,10 @@ void Reactor::Stop() { ASSERT(control != -1); } +std::unique_ptr<Reactor::Event> Reactor::NewEvent() const { + return std::make_unique<Reactor::Event>(); +} + Reactor::Reactable* Reactor::Register(int fd, Closure on_read_ready, Closure on_write_ready) { uint32_t poll_event_type = 0; if (!on_read_ready.is_null()) { diff --git a/system/gd/os/reactor.h b/system/gd/os/reactor.h index e61f4f5aec..c85625c339 100644 --- a/system/gd/os/reactor.h +++ b/system/gd/os/reactor.h @@ -22,6 +22,7 @@ #include <functional> #include <future> #include <list> +#include <memory> #include <mutex> #include <thread> @@ -43,11 +44,12 @@ class Reactor { // Construct a reactor on the current thread Reactor(); + Reactor(const Reactor&) = delete; + Reactor& operator=(const Reactor&) = delete; + // Destruct this reactor and release its resources ~Reactor(); - DISALLOW_COPY_AND_ASSIGN(Reactor); - // Start the reactor. The current thread will be blocked until Stop() is invoked and handled. void Run(); @@ -71,6 +73,23 @@ class Reactor { // Modify the registration for a reactable with given reactable void ModifyRegistration(Reactable* reactable, common::Closure on_read_ready, common::Closure on_write_ready); + class Event { + public: + Event(); + ~Event(); + bool Read(); + int Id() const; + void Clear(); + void Close(); + void Notify(); + + private: + Event(const Event& handler) = default; + struct impl; + impl* pimpl_{nullptr}; + }; + std::unique_ptr<Reactor::Event> NewEvent() const; + private: mutable std::mutex mutex_; int epoll_fd_; diff --git a/system/gd/os/repeating_alarm.h b/system/gd/os/repeating_alarm.h index 6b37162cf1..b261b5e7fd 100644 --- a/system/gd/os/repeating_alarm.h +++ b/system/gd/os/repeating_alarm.h @@ -36,11 +36,12 @@ class RepeatingAlarm { // Create and register a repeating alarm on a given handler explicit RepeatingAlarm(Handler* handler); + RepeatingAlarm(const RepeatingAlarm&) = delete; + RepeatingAlarm& operator=(const RepeatingAlarm&) = delete; + // Unregister this alarm from the thread and release resource ~RepeatingAlarm(); - DISALLOW_COPY_AND_ASSIGN(RepeatingAlarm); - // Schedule a repeating alarm with given period void Schedule(common::Closure task, std::chrono::milliseconds period); diff --git a/system/gd/os/thread.h b/system/gd/os/thread.h index d14d75ea21..4be792d3cc 100644 --- a/system/gd/os/thread.h +++ b/system/gd/os/thread.h @@ -43,11 +43,12 @@ class Thread { // priority: priority for kernel scheduler Thread(const std::string& name, Priority priority); + Thread(const Thread&) = delete; + Thread& operator=(const Thread&) = delete; + // Stop and destroy this thread ~Thread(); - DISALLOW_COPY_AND_ASSIGN(Thread); - // Stop this thread. Must be invoked from another thread. After this thread is stopped, it cannot be started again. bool Stop(); diff --git a/system/gd/rust/facade/src/main.rs b/system/gd/rust/facade/src/main.rs index 55cfb0ca8d..3ce456cdff 100644 --- a/system/gd/rust/facade/src/main.rs +++ b/system/gd/rust/facade/src/main.rs @@ -14,10 +14,7 @@ use futures::stream::StreamExt; use grpcio::*; use log::debug; use nix::sys::signal; -use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::sync::{Arc, Mutex}; -use tokio::io::AsyncWriteExt; -use tokio::net::TcpStream; use tokio::runtime::Runtime; fn main() { @@ -51,7 +48,6 @@ async fn async_main(rt: Arc<Runtime>, mut sigint: mpsc::UnboundedReceiver<()>) { let root_server_port = value_t!(matches, "root-server-port", u16).unwrap(); let grpc_port = value_t!(matches, "grpc-port", u16).unwrap(); - let signal_port = value_t!(matches, "signal-port", u16).unwrap(); let rootcanal_port = value_t!(matches, "rootcanal-port", u16).ok(); let env = Arc::new(Environment::new(2)); let mut server = ServerBuilder::new(env) @@ -66,17 +62,10 @@ async fn async_main(rt: Arc<Runtime>, mut sigint: mpsc::UnboundedReceiver<()>) { .unwrap(); server.start(); - indicate_started(signal_port).await; sigint.next().await; block_on(server.shutdown()).unwrap(); } -async fn indicate_started(signal_port: u16) { - let address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), signal_port); - let mut stream = TcpStream::connect(address).await.unwrap(); - stream.shutdown().await.unwrap(); -} - // TODO: remove as this is a temporary nix-based hack to catch SIGINT fn install_sigint() -> mpsc::UnboundedReceiver<()> { let (tx, rx) = mpsc::unbounded(); diff --git a/system/gd/rust/facade_proto/build.rs b/system/gd/rust/facade_proto/build.rs index 7c9bc4c40f..bb6bf46289 100644 --- a/system/gd/rust/facade_proto/build.rs +++ b/system/gd/rust/facade_proto/build.rs @@ -58,19 +58,21 @@ fn main() { _ => (), } - // Proto root is //platform2/bt/gd + // Proto root is //platform2/bt/system let proto_root = match env::var("PLATFORM_SUBDIR") { - Ok(dir) => PathBuf::from(dir).join("bt/gd"), - // Currently at //platform2/gd/rust/facade_proto - Err(_) => PathBuf::from(env::current_dir().unwrap()).join("../..").canonicalize().unwrap(), + Ok(dir) => PathBuf::from(dir).join("bt/system"), + // Currently at //platform2/bt/system/gd/rust/facade_proto + Err(_) => { + PathBuf::from(env::current_dir().unwrap()).join("../../..").canonicalize().unwrap() + } }; // // Generate protobuf output // - let facade_dir = proto_root.join("facade"); + let facade_dir = proto_root.join("blueberry/facade"); let proto_input_files = [facade_dir.join("common.proto")]; - let proto_include_dirs = [facade_dir]; + let proto_include_dirs = [facade_dir.clone()]; protoc_rust::Codegen::new() .out_dir(proto_out_dir.as_os_str().to_str().unwrap()) @@ -84,17 +86,13 @@ fn main() { // Generate grpc output // let grpc_proto_input_files = [ - proto_root.join("hci/facade/hci_facade.proto"), - proto_root.join("hci/facade/controller_facade.proto"), - proto_root.join("hal/hal_facade.proto"), - proto_root.join("facade/rootservice.proto"), - ]; - let grpc_proto_include_dirs = [ - proto_root.join("hci/facade"), - proto_root.join("hal"), - proto_root.join("facade"), - proto_root, + facade_dir.join("hci/hci_facade.proto"), + facade_dir.join("hci/controller_facade.proto"), + facade_dir.join("hal/hal_facade.proto"), + facade_dir.join("rootservice.proto"), ]; + let grpc_proto_include_dirs = + [facade_dir.join("hci"), facade_dir.join("hal"), facade_dir, proto_root]; protoc_grpcio::compile_grpc_protos( &grpc_proto_input_files, diff --git a/system/gd/rust/linux/client/src/command_handler.rs b/system/gd/rust/linux/client/src/command_handler.rs index f789eaa93b..9f9f280c85 100644 --- a/system/gd/rust/linux/client/src/command_handler.rs +++ b/system/gd/rust/linux/client/src/command_handler.rs @@ -85,7 +85,8 @@ fn build_commands() -> HashMap<String, CommandOption> { String::from("adapter"), CommandOption { description: String::from( - "Enable/Disable/Show default bluetooth adapter. (e.g. adapter enable)", + "Enable/Disable/Show default bluetooth adapter. (e.g. adapter enable)\n + Discoverable On/Off (e.g. adapter discoverable on)", ), function_pointer: CommandHandler::cmd_adapter, }, @@ -244,47 +245,84 @@ impl CommandHandler { } let default_adapter = self.context.lock().unwrap().default_adapter; - enforce_arg_len(args, 1, "adapter <enable|disable|show>", || match &args[0][0..] { - "enable" => { - self.context.lock().unwrap().manager_dbus.start(default_adapter); - } - "disable" => { - self.context.lock().unwrap().manager_dbus.stop(default_adapter); - } - "show" => { - if !self.context.lock().unwrap().adapter_ready { - self.adapter_not_ready(); - return; + enforce_arg_len(args, 1, "adapter <enable|disable|show|discoverable>", || { + match &args[0][0..] { + "enable" => { + self.context.lock().unwrap().manager_dbus.start(default_adapter); + } + "disable" => { + self.context.lock().unwrap().manager_dbus.stop(default_adapter); } + "show" => { + if !self.context.lock().unwrap().adapter_ready { + self.adapter_not_ready(); + return; + } - let enabled = self.context.lock().unwrap().enabled; - let address = match self.context.lock().unwrap().adapter_address.as_ref() { - Some(x) => x.clone(), - None => String::from(""), - }; - let name = self.context.lock().unwrap().adapter_dbus.as_ref().unwrap().get_name(); - let uuids = self.context.lock().unwrap().adapter_dbus.as_ref().unwrap().get_uuids(); - let cod = self - .context - .lock() - .unwrap() - .adapter_dbus - .as_ref() - .unwrap() - .get_bluetooth_class(); - print_info!("Address: {}", address); - print_info!("Name: {}", name); - print_info!("State: {}", if enabled { "enabled" } else { "disabled" }); - print_info!("Class: {:#06x}", cod); - print_info!( - "Uuids: {}", - DisplayList( - uuids.iter().map(|&x| UuidHelper::to_string(&x)).collect::<Vec<String>>() - ) - ); - } - _ => { - println!("Invalid argument '{}'", args[0]); + let enabled = self.context.lock().unwrap().enabled; + let address = match self.context.lock().unwrap().adapter_address.as_ref() { + Some(x) => x.clone(), + None => String::from(""), + }; + let context = self.context.lock().unwrap(); + let adapter_dbus = context.adapter_dbus.as_ref().unwrap(); + let name = adapter_dbus.get_name(); + let uuids = adapter_dbus.get_uuids(); + let is_discoverable = adapter_dbus.get_discoverable(); + let cod = adapter_dbus.get_bluetooth_class(); + let multi_adv_supported = adapter_dbus.is_multi_advertisement_supported(); + let le_ext_adv_supported = adapter_dbus.is_le_extended_advertising_supported(); + print_info!("Address: {}", address); + print_info!("Name: {}", name); + print_info!("State: {}", if enabled { "enabled" } else { "disabled" }); + print_info!("Discoverable: {}", is_discoverable); + print_info!("Class: {:#06x}", cod); + print_info!("IsMultiAdvertisementSupported: {}", multi_adv_supported); + print_info!("IsLeExtendedAdvertisingSupported: {}", le_ext_adv_supported); + print_info!( + "Uuids: {}", + DisplayList( + uuids + .iter() + .map(|&x| UuidHelper::to_string(&x)) + .collect::<Vec<String>>() + ) + ); + } + "discoverable" => match &args[1][0..] { + "on" => { + let discoverable = self + .context + .lock() + .unwrap() + .adapter_dbus + .as_ref() + .unwrap() + .set_discoverable(true, 60); + print_info!( + "Set discoverable for 60s: {}", + if discoverable { "succeeded" } else { "failed" } + ); + } + "off" => { + let discoverable = self + .context + .lock() + .unwrap() + .adapter_dbus + .as_ref() + .unwrap() + .set_discoverable(false, 60); + print_info!( + "Turn discoverable off: {}", + if discoverable { "succeeded" } else { "failed" } + ); + } + _ => println!("Invalid argument for adapter discoverable '{}'", args[1]), + }, + _ => { + println!("Invalid argument '{}'", args[0]); + } } }); } diff --git a/system/gd/rust/linux/client/src/dbus_iface.rs b/system/gd/rust/linux/client/src/dbus_iface.rs index d3afcd0441..1a5c42a7b2 100644 --- a/system/gd/rust/linux/client/src/dbus_iface.rs +++ b/system/gd/rust/linux/client/src/dbus_iface.rs @@ -309,6 +309,22 @@ impl IBluetooth for BluetoothDBus { self.client_proxy.method("SetBluetoothClass", (cod,)) } + fn get_discoverable(&self) -> bool { + self.client_proxy.method("GetDiscoverable", ()) + } + + fn set_discoverable(&self, mode: bool, duration: u32) -> bool { + self.client_proxy.method("SetDiscoverable", (mode, duration)) + } + + fn is_multi_advertisement_supported(&self) -> bool { + self.client_proxy.method("IsMultiAdvertisementSupported", ()) + } + + fn is_le_extended_advertising_supported(&self) -> bool { + self.client_proxy.method("IsLeExtendedAdvertisingSupported", ()) + } + fn start_discovery(&self) -> bool { self.client_proxy.method("StartDiscovery", ()) } diff --git a/system/gd/rust/linux/service/src/iface_bluetooth.rs b/system/gd/rust/linux/service/src/iface_bluetooth.rs index 005de3e656..c413bda632 100644 --- a/system/gd/rust/linux/service/src/iface_bluetooth.rs +++ b/system/gd/rust/linux/service/src/iface_bluetooth.rs @@ -130,6 +130,26 @@ impl IBluetooth for IBluetoothDBus { true } + #[dbus_method("GetDiscoverable")] + fn get_discoverable(&self) -> bool { + true + } + + #[dbus_method("SetDiscoverable")] + fn set_discoverable(&self, mode: bool, duration: u32) -> bool { + true + } + + #[dbus_method("IsMultiAdvertisementSupported")] + fn is_multi_advertisement_supported(&self) -> bool { + true + } + + #[dbus_method("IsLeExtendedAdvertisingSupported")] + fn is_le_extended_advertising_supported(&self) -> bool { + true + } + #[dbus_method("StartDiscovery")] fn start_discovery(&self) -> bool { true diff --git a/system/gd/rust/linux/stack/src/bluetooth.rs b/system/gd/rust/linux/stack/src/bluetooth.rs index ee0578c958..c3b1d3218f 100644 --- a/system/gd/rust/linux/stack/src/bluetooth.rs +++ b/system/gd/rust/linux/stack/src/bluetooth.rs @@ -2,8 +2,8 @@ use bt_topshim::btif::{ BaseCallbacks, BaseCallbacksDispatcher, BluetoothInterface, BluetoothProperty, BtAclState, - BtBondState, BtDiscoveryState, BtHciErrorCode, BtPinCode, BtPropertyType, BtSspVariant, - BtState, BtStatus, BtTransport, RawAddress, Uuid, Uuid128Bit, + BtBondState, BtDiscoveryState, BtHciErrorCode, BtLocalLeFeatures, BtPinCode, BtPropertyType, + BtScanMode, BtSspVariant, BtState, BtStatus, BtTransport, RawAddress, Uuid, Uuid128Bit, }; use bt_topshim::{ profiles::hid_host::{HHCallbacksDispatcher, HidHost}, @@ -25,6 +25,9 @@ use crate::bluetooth_media::{BluetoothMedia, IBluetoothMedia, MediaActions}; use crate::uuid::{Profile, UuidHelper}; use crate::{BluetoothCallbackType, Message, RPCProxy}; +const DEFAULT_DISCOVERY_TIMEOUT_MS: u64 = 12800; +const MIN_ADV_INSTANCES_FOR_MULTI_ADV: u8 = 5; + /// Defines the adapter API. pub trait IBluetooth { /// Adds a callback from a client who wishes to observe adapter events. @@ -67,6 +70,19 @@ pub trait IBluetooth { /// Sets the bluetooth class. fn set_bluetooth_class(&self, cod: u32) -> bool; + /// Returns whether the adapter is discoverable. + fn get_discoverable(&self) -> bool; + + /// Sets discoverability. If discoverable, limits the duration with given value. + fn set_discoverable(&self, mode: bool, duration: u32) -> bool; + + /// Returns whether multi-advertisement is supported. + /// A minimum number of 5 advertising instances is required for multi-advertisment support. + fn is_multi_advertisement_supported(&self) -> bool; + + /// Returns whether LE extended advertising is supported. + fn is_le_extended_advertising_supported(&self) -> bool; + /// Starts BREDR Inquiry. fn start_discovery(&self) -> bool; @@ -243,6 +259,7 @@ pub struct Bluetooth { state: BtState, tx: Sender<Message>, uuid_helper: UuidHelper, + is_connectable: bool, } impl Bluetooth { @@ -269,6 +286,7 @@ impl Bluetooth { state: BtState::Off, tx, uuid_helper: UuidHelper::new(), + is_connectable: false, } } @@ -322,6 +340,29 @@ impl Bluetooth { } } + fn get_connectable(&self) -> bool { + match self.properties.get(&BtPropertyType::AdapterScanMode) { + Some(prop) => match prop { + BluetoothProperty::AdapterScanMode(mode) => match *mode { + BtScanMode::Connectable | BtScanMode::ConnectableDiscoverable => true, + _ => false, + }, + _ => false, + }, + _ => false, + } + } + + fn set_connectable(&mut self, mode: bool) -> bool { + self.is_connectable = mode; + if mode && self.get_discoverable() { + return true; + } + self.intf.lock().unwrap().set_adapter_property(BluetoothProperty::AdapterScanMode( + if mode { BtScanMode::Connectable } else { BtScanMode::None_ }, + )) == 0 + } + pub(crate) fn callback_disconnected(&mut self, id: u32, cb_type: BluetoothCallbackType) { match cb_type { BluetoothCallbackType::Adapter => { @@ -786,6 +827,59 @@ impl IBluetooth for Bluetooth { self.intf.lock().unwrap().set_adapter_property(BluetoothProperty::ClassOfDevice(cod)) == 0 } + fn get_discoverable(&self) -> bool { + match self.properties.get(&BtPropertyType::AdapterScanMode) { + Some(prop) => match prop { + BluetoothProperty::AdapterScanMode(mode) => match mode { + BtScanMode::ConnectableDiscoverable => true, + _ => false, + }, + _ => false, + }, + _ => false, + } + } + + fn set_discoverable(&self, mode: bool, duration: u32) -> bool { + self.intf + .lock() + .unwrap() + .set_adapter_property(BluetoothProperty::AdapterDiscoverableTimeout(duration)); + self.intf.lock().unwrap().set_adapter_property(BluetoothProperty::AdapterScanMode( + if mode { + BtScanMode::ConnectableDiscoverable + } else { + if self.is_connectable { + BtScanMode::Connectable + } else { + BtScanMode::None_ + } + }, + )) == 0 + } + + fn is_multi_advertisement_supported(&self) -> bool { + match self.properties.get(&BtPropertyType::LocalLeFeatures) { + Some(prop) => match prop { + BluetoothProperty::LocalLeFeatures(llf) => { + llf.max_adv_instance >= MIN_ADV_INSTANCES_FOR_MULTI_ADV + } + _ => false, + }, + _ => false, + } + } + + fn is_le_extended_advertising_supported(&self) -> bool { + match self.properties.get(&BtPropertyType::LocalLeFeatures) { + Some(prop) => match prop { + BluetoothProperty::LocalLeFeatures(llf) => llf.le_extended_advertising_supported, + _ => false, + }, + _ => false, + } + } + fn start_discovery(&self) -> bool { self.intf.lock().unwrap().start_discovery() == 0 } @@ -803,20 +897,11 @@ impl IBluetooth for Bluetooth { return 0; } - match self.properties.get(&BtPropertyType::AdapterDiscoveryTimeout) { - Some(variant) => match variant { - BluetoothProperty::AdapterDiscoveryTimeout(timeout) => { - let seconds: u64 = (*timeout).into(); - let elapsed = self.discovering_started.elapsed(); - if elapsed.as_secs() >= seconds { - 0 - } else { - seconds * 1000 - elapsed.as_millis() as u64 - } - } - _ => 0, - }, - _ => 0, + let elapsed_ms = self.discovering_started.elapsed().as_millis() as u64; + if elapsed_ms >= DEFAULT_DISCOVERY_TIMEOUT_MS { + 0 + } else { + DEFAULT_DISCOVERY_TIMEOUT_MS - elapsed_ms } } diff --git a/system/gd/rust/linux/stack/src/lib.rs b/system/gd/rust/linux/stack/src/lib.rs index 160363e88a..ad21e6e617 100644 --- a/system/gd/rust/linux/stack/src/lib.rs +++ b/system/gd/rust/linux/stack/src/lib.rs @@ -1,7 +1,7 @@ -//! Fluoride/GD Bluetooth stack. +//! Floss Bluetooth stack. //! -//! This crate provides the API implementation of the Fluoride/GD Bluetooth stack, independent of -//! any RPC projection. +//! This crate provides the API implementation of the Fluoride/GD Bluetooth +//! stack, independent of any RPC projection. #[macro_use] extern crate num_derive; @@ -27,9 +27,6 @@ use bt_topshim::{ }, }; -/// Represents a Bluetooth address. -// TODO: Add support for LE random addresses. - #[derive(Clone, Debug)] pub enum BluetoothCallbackType { Adapter, diff --git a/system/gd/rust/topshim/facade/Android.bp b/system/gd/rust/topshim/facade/Android.bp index c97cca8972..95648c71ea 100644 --- a/system/gd/rust/topshim/facade/Android.bp +++ b/system/gd/rust/topshim/facade/Android.bp @@ -45,7 +45,6 @@ rust_binary_host { "libbt-sbc-encoder", "libFraunhoferAAC", "libg722codec", - "liblc3codec", "liblc3", "libudrv-uipc", "libbluetooth_gd", // Gabeldorsche diff --git a/system/gd/rust/topshim/facade/src/adapter_service.rs b/system/gd/rust/topshim/facade/src/adapter_service.rs index efd96eebd4..1243b07b16 100644 --- a/system/gd/rust/topshim/facade/src/adapter_service.rs +++ b/system/gd/rust/topshim/facade/src/adapter_service.rs @@ -3,6 +3,7 @@ use bt_topshim::btif; use bt_topshim::btif::{BaseCallbacks, BaseCallbacksDispatcher, BluetoothInterface}; +use bt_topshim_facade_protobuf::empty::Empty; use bt_topshim_facade_protobuf::facade::{ EventType, FetchEventsRequest, FetchEventsResponse, SetDiscoveryModeRequest, SetDiscoveryModeResponse, ToggleStackRequest, ToggleStackResponse, @@ -118,4 +119,11 @@ impl AdapterService for AdapterServiceImpl { sink.success(SetDiscoveryModeResponse::default()).await.unwrap(); }) } + + fn clear_event_filter(&mut self, ctx: RpcContext<'_>, _req: Empty, sink: UnarySink<Empty>) { + self.btif_intf.lock().unwrap().clear_event_filter(); + ctx.spawn(async move { + sink.success(Empty::default()).await.unwrap(); + }) + } } diff --git a/system/gd/rust/topshim/gatt/gatt_ble_scanner_shim.cc b/system/gd/rust/topshim/gatt/gatt_ble_scanner_shim.cc index 9b34b612ef..65cdb8456c 100644 --- a/system/gd/rust/topshim/gatt/gatt_ble_scanner_shim.cc +++ b/system/gd/rust/topshim/gatt/gatt_ble_scanner_shim.cc @@ -16,13 +16,20 @@ #include "gd/rust/topshim/gatt/gatt_ble_scanner_shim.h" +#include <base/bind.h> +#include <base/callback.h> + #include <algorithm> #include <iterator> +#include <memory> #include <vector> +#include "bind_helpers.h" #include "gd/rust/topshim/common/utils.h" +#include "include/hardware/bt_common_types.h" #include "rust/cxx.h" #include "src/profiles/gatt.rs.h" +#include "types/bluetooth/uuid.h" #include "types/raw_address.h" namespace bluetooth { @@ -31,12 +38,65 @@ namespace rust { namespace rusty = ::bluetooth::topshim::rust; -void BleScannerIntf::RegisterCallbacks() { - // Register self as a callback handler. We will dispatch to Rust callbacks. - scanner_intf_->RegisterCallbacks(this); +namespace internal { +ApcfCommand ConvertApcfFromRust(const RustApcfCommand& command) { + RawAddress address = rusty::CopyFromRustAddress(command.address); + + // Copy vectors + arrays + std::vector<uint8_t> name, data, data_mask; + std::array<uint8_t, 16> irk; + std::copy(command.name.begin(), command.name.end(), std::back_inserter(name)); + std::copy(command.data.begin(), command.data.end(), std::back_inserter(data)); + std::copy(command.data_mask.begin(), command.data_mask.end(), std::back_inserter(data_mask)); + std::copy(command.irk.begin(), command.irk.end(), std::begin(irk)); + + ApcfCommand converted = { + .type = command.type_, + .address = address, + .addr_type = command.addr_type, + .uuid = bluetooth::Uuid::From128BitBE(command.uuid.uu), + .uuid_mask = bluetooth::Uuid::From128BitBE(command.uuid_mask.uu), + .name = name, + .company = command.company, + .company_mask = command.company_mask, + .data = data, + .data_mask = data_mask, + .irk = irk, + }; + + return converted; } -// ScanningCallbacks overrides +std::vector<ApcfCommand> ConvertApcfVec(const ::rust::Vec<RustApcfCommand>& rustvec) { + std::vector<ApcfCommand> converted; + + for (const RustApcfCommand& command : rustvec) { + converted.push_back(ConvertApcfFromRust(command)); + } + + return converted; +} + +::btgatt_filt_param_setup_t ConvertRustFilterParam(const RustGattFilterParam& param) { + ::btgatt_filt_param_setup_t converted = { + .feat_seln = param.feat_seln, + .list_logic_type = param.list_logic_type, + .filt_logic_type = param.filt_logic_type, + .rssi_high_thres = param.rssi_high_thres, + .rssi_low_thres = param.rssi_low_thres, + .dely_mode = param.delay_mode, + .found_timeout = param.found_timeout, + .lost_timeout = param.lost_timeout, + .found_timeout_cnt = param.found_timeout_count, + .num_of_tracking_entries = param.num_of_tracking_entries, + }; + + return converted; +} +} // namespace internal + +// ScanningCallbacks implementations + void BleScannerIntf::OnScannerRegistered(const bluetooth::Uuid app_uuid, uint8_t scannerId, uint8_t status) { rusty::gdscan_on_scanner_registered(reinterpret_cast<const signed char*>(&app_uuid), scannerId, status); } @@ -89,8 +149,8 @@ void BleScannerIntf::OnTrackAdvFoundLost(AdvertisingTrackInfo ati) { // .scan_response is copied below }; - std::copy(ati.adv_packet.begin(), ati.adv_packet.end(), std::back_inserter(rust_info.adv_packet)); - std::copy(ati.scan_response.begin(), ati.scan_response.end(), std::back_inserter(rust_info.scan_response)); + std::copy(rust_info.adv_packet.begin(), rust_info.adv_packet.end(), std::back_inserter(ati.adv_packet)); + std::copy(rust_info.scan_response.begin(), rust_info.scan_response.end(), std::back_inserter(ati.scan_response)); rusty::gdscan_on_track_adv_found_lost(rust_info); } @@ -104,6 +164,185 @@ void BleScannerIntf::OnBatchScanThresholdCrossed(int client_if) { rusty::gdscan_on_batch_scan_threshold_crossed(client_if); } +// BleScannerInterface implementations + +void BleScannerIntf::RegisterScanner(RustUuid uuid) { + bluetooth::Uuid converted = bluetooth::Uuid::From128BitBE(uuid.uu); + scanner_intf_->RegisterScanner( + converted, base::Bind(&BleScannerIntf::OnRegisterCallback, base::Unretained(this), uuid)); +} + +void BleScannerIntf::Unregister(uint8_t scanner_id) { + scanner_intf_->Unregister(scanner_id); +} + +void BleScannerIntf::Scan(bool start) { + scanner_intf_->Scan(start); +} + +void BleScannerIntf::ScanFilterParamSetup( + uint8_t scanner_id, uint8_t action, uint8_t filter_index, RustGattFilterParam filter_param) { + std::unique_ptr<::btgatt_filt_param_setup_t> converted = + std::make_unique<::btgatt_filt_param_setup_t>(std::move(internal::ConvertRustFilterParam(filter_param))); + + scanner_intf_->ScanFilterParamSetup( + scanner_id, + action, + filter_index, + std::move(converted), + base::Bind(&BleScannerIntf::OnFilterParamSetupCallback, base::Unretained(this), scanner_id)); +} + +void BleScannerIntf::ScanFilterAdd(uint8_t filter_index, ::rust::Vec<RustApcfCommand> filters) { + auto converted = internal::ConvertApcfVec(filters); + scanner_intf_->ScanFilterAdd( + filter_index, + converted, + base::Bind(&BleScannerIntf::OnFilterConfigCallback, base::Unretained(this), filter_index)); +} + +void BleScannerIntf::ScanFilterClear(uint8_t filter_index) { + scanner_intf_->ScanFilterClear( + filter_index, base::Bind(&BleScannerIntf::OnFilterConfigCallback, base::Unretained(this), filter_index)); +} + +void BleScannerIntf::ScanFilterEnable(bool enable) { + scanner_intf_->ScanFilterEnable(enable, base::Bind(&BleScannerIntf::OnEnableCallback, base::Unretained(this))); +} + +void BleScannerIntf::SetScanParameters(uint8_t scanner_id, uint16_t scan_interval, uint16_t scan_window) { + scanner_intf_->SetScanParameters( + scanner_id, + scan_interval, + scan_window, + base::Bind(&BleScannerIntf::OnStatusCallback, base::Unretained(this), scanner_id)); +} + +void BleScannerIntf::BatchscanConfigStorage( + uint8_t scanner_id, + int32_t batch_scan_full_max, + int32_t batch_scan_trunc_max, + int32_t batch_scan_notify_threshold) { + scanner_intf_->BatchscanConfigStorage( + scanner_id, + batch_scan_full_max, + batch_scan_trunc_max, + batch_scan_notify_threshold, + base::Bind(&BleScannerIntf::OnStatusCallback, base::Unretained(this), scanner_id)); +} + +void BleScannerIntf::BatchscanEnable( + int32_t scan_mode, uint16_t scan_interval, uint16_t scan_window, int32_t addr_type, int32_t discard_rule) { + scanner_intf_->BatchscanEnable( + scan_mode, + scan_interval, + scan_window, + addr_type, + discard_rule, + base::Bind(&BleScannerIntf::OnStatusCallback, base::Unretained(this), 0)); +} + +void BleScannerIntf::BatchscanDisable() { + scanner_intf_->BatchscanDisable(base::Bind(&BleScannerIntf::OnStatusCallback, base::Unretained(this), 0)); +} + +void BleScannerIntf::BatchscanReadReports(uint8_t scanner_id, int32_t scan_mode) { + scanner_intf_->BatchscanReadReports(scanner_id, scan_mode); +} + +void BleScannerIntf::StartSync(uint8_t sid, RustRawAddress address, uint16_t skip, uint16_t timeout) { + RawAddress converted = rusty::CopyFromRustAddress(address); + scanner_intf_->StartSync( + sid, + converted, + skip, + timeout, + base::Bind(&BleScannerIntf::OnStartSyncCb, base::Unretained(this)), + base::Bind(&BleScannerIntf::OnSyncReportCb, base::Unretained(this)), + base::Bind(&BleScannerIntf::OnSyncLostCb, base::Unretained(this))); +} + +void BleScannerIntf::StopSync(uint16_t handle) { + scanner_intf_->StopSync(handle); +} + +void BleScannerIntf::CancelCreateSync(uint8_t sid, RustRawAddress address) { + RawAddress converted = rusty::CopyFromRustAddress(address); + scanner_intf_->CancelCreateSync(sid, converted); +} + +void BleScannerIntf::TransferSync(RustRawAddress address, uint16_t service_data, uint16_t sync_handle) { + RawAddress converted = rusty::CopyFromRustAddress(address); + scanner_intf_->TransferSync( + converted, service_data, sync_handle, base::Bind(&BleScannerIntf::OnSyncTransferCb, base::Unretained(this))); +} + +void BleScannerIntf::TransferSetInfo(RustRawAddress address, uint16_t service_data, uint8_t adv_handle) { + RawAddress converted = rusty::CopyFromRustAddress(address); + scanner_intf_->TransferSetInfo( + converted, service_data, adv_handle, base::Bind(&BleScannerIntf::OnSyncTransferCb, base::Unretained(this))); +} + +void BleScannerIntf::SyncTxParameters(RustRawAddress address, uint8_t mode, uint16_t skip, uint16_t timeout) { + RawAddress converted = rusty::CopyFromRustAddress(address); + scanner_intf_->SyncTxParameters( + converted, mode, skip, timeout, base::Bind(&BleScannerIntf::OnStartSyncCb, base::Unretained(this))); +} + +void BleScannerIntf::OnRegisterCallback(RustUuid uuid, uint8_t scanner_id, uint8_t btm_status) { + rusty::gdscan_register_callback(uuid, scanner_id, btm_status); +} + +void BleScannerIntf::OnStatusCallback(uint8_t scanner_id, uint8_t btm_status) { + rusty::gdscan_status_callback(scanner_id, btm_status); +} + +void BleScannerIntf::OnEnableCallback(uint8_t action, uint8_t btm_status) { + rusty::gdscan_enable_callback(action, btm_status); +} + +void BleScannerIntf::OnFilterParamSetupCallback( + uint8_t scanner_id, uint8_t avbl_space, uint8_t action_type, uint8_t btm_status) { + rusty::gdscan_filter_param_setup_callback(scanner_id, avbl_space, action_type, btm_status); +} + +void BleScannerIntf::OnFilterConfigCallback( + uint8_t filter_index, uint8_t filt_type, uint8_t avbl_space, uint8_t action, uint8_t btm_status) { + rusty::gdscan_filter_config_callback(filter_index, filt_type, avbl_space, action, btm_status); +} + +void BleScannerIntf::OnStartSyncCb( + uint8_t status, + uint16_t sync_handle, + uint8_t advertising_sid, + uint8_t address_type, + RawAddress address, + uint8_t phy, + uint16_t interval) { + RustRawAddress converted = rusty::CopyToRustAddress(address); + rusty::gdscan_start_sync_callback(status, sync_handle, advertising_sid, address_type, &converted, phy, interval); +} + +void BleScannerIntf::OnSyncReportCb( + uint16_t sync_handle, int8_t tx_power, int8_t rssi, uint8_t status, std::vector<uint8_t> data) { + rusty::gdscan_sync_report_callback(sync_handle, tx_power, rssi, status, data.data(), data.size()); +} + +void BleScannerIntf::OnSyncLostCb(uint16_t sync_handle) { + rusty::gdscan_sync_lost_callback(sync_handle); +} + +void BleScannerIntf::OnSyncTransferCb(uint8_t status, RawAddress address) { + RustRawAddress converted = rusty::CopyToRustAddress(address); + rusty::gdscan_sync_transfer_callback(status, &converted); +} + +void BleScannerIntf::RegisterCallbacks() { + // Register self as a callback handler. We will dispatch to Rust callbacks. + scanner_intf_->RegisterCallbacks(this); +} + +// ScanningCallbacks overrides std::unique_ptr<BleScannerIntf> GetBleScannerIntf(const unsigned char* gatt_intf) { return std::make_unique<BleScannerIntf>(reinterpret_cast<const btgatt_interface_t*>(gatt_intf)->scanner); } diff --git a/system/gd/rust/topshim/gatt/gatt_ble_scanner_shim.h b/system/gd/rust/topshim/gatt/gatt_ble_scanner_shim.h index eb89d12015..86fe902a62 100644 --- a/system/gd/rust/topshim/gatt/gatt_ble_scanner_shim.h +++ b/system/gd/rust/topshim/gatt/gatt_ble_scanner_shim.h @@ -26,13 +26,16 @@ namespace bluetooth { namespace topshim { namespace rust { +struct RustApcfCommand; +struct RustGattFilterParam; +struct RustRawAddress; +struct RustUuid; + class BleScannerIntf : public ScanningCallbacks { public: BleScannerIntf(BleScannerInterface* scanner_intf) : scanner_intf_(scanner_intf){}; ~BleScannerIntf() = default; - void RegisterCallbacks(); - // ScanningCallbacks overrides void OnScannerRegistered(const bluetooth::Uuid app_uuid, uint8_t scannerId, uint8_t status) override; @@ -57,7 +60,106 @@ class BleScannerIntf : public ScanningCallbacks { void OnBatchScanThresholdCrossed(int client_if) override; + // Implementations of BleScannerInterface. These don't inherit from + // BleScannerInterface because the Rust FFI boundary requires some clever + // modifications. + + // Register a scanner for a Uuid. Response comes back via + // |OnRegisterCallback|. + void RegisterScanner(RustUuid uuid); + + // Unregister a scanner with a |scanner_id|. + void Unregister(uint8_t scanner_id); + + // Start/Stop LE scanning. + void Scan(bool start); + + // Setup scan filter parameters. Get responses via + // |OnFilterParamSetupCallback|. + void ScanFilterParamSetup(uint8_t scanner_id, uint8_t action, uint8_t filter_index, RustGattFilterParam filter_param); + + // Adds filters to given filter index. Gets responses via + // |OnFilterConfigCallback|. + void ScanFilterAdd(uint8_t filter_index, ::rust::Vec<RustApcfCommand> filters); + + // Clear scan filter conditions for a specific index. + void ScanFilterClear(uint8_t filter_index); + + // Enable/disable scan filter. Gets responses via |OnEnableCallback|. + void ScanFilterEnable(bool enable); + + // Sets the LE scan interval and window in units of N * 0.625 msec. The result + // of this action is returned via |OnStatusCallback|. + void SetScanParameters(uint8_t scanner_id, uint16_t scan_interval, uint16_t scan_window); + + // Configure the batchscan storage and get a response via |OnStatusCallback|. + void BatchscanConfigStorage( + uint8_t scanner_id, + int32_t batch_scan_full_max, + int32_t batch_scan_trunc_max, + int32_t batch_scan_notify_threshold); + + // Enable batchscan. Gets responses via |OnStatusCallback| with scanner id + // = 0 (since multiple scanners can be registered). + void BatchscanEnable( + int32_t scan_mode, uint16_t scan_interval, uint16_t scan_window, int32_t addr_type, int32_t discard_rule); + + // Disable batchscan. Gets responses via |OnStatusCallback| with a scanner id + // = 0 (since multiple scanners can be registered). + void BatchscanDisable(); + + // Read out batchscan report for a specific scanner. Gets responses via + // |ScanningCallbacks::OnBatchScanReports|. + void BatchscanReadReports(uint8_t scanner_id, int32_t scan_mode); + + // Start periodic sync. Gets responses via |OnStartSyncCb|. Periodic reports + // come via |OnSyncReportCb| and |OnSyncLostCb|. + void StartSync(uint8_t sid, RustRawAddress address, uint16_t skip, uint16_t timeout); + + // Stop periodic sync. + void StopSync(uint16_t handle); + + // Cancel creating a periodic sync. + void CancelCreateSync(uint8_t sid, RustRawAddress address); + + // Transfer sync data to target address. Gets responses via + // |OnSyncTransferCb|. + void TransferSync(RustRawAddress address, uint16_t service_data, uint16_t sync_handle); + + // Transfer set info to target address. Gets responses via |OnSyncTransferCb|. + void TransferSetInfo(RustRawAddress address, uint16_t service_data, uint8_t adv_handle); + + // Sync tx parameters to target address. Gets responses via |OnStartSyncCb|. + void SyncTxParameters(RustRawAddress address, uint8_t mode, uint16_t skip, uint16_t timeout); + + // Register scanning callbacks to be dispatched to the Rust layer via static + // methods. + void RegisterCallbacks(); + private: + // The callback functions below will get base::Bind to the apis that need it + // and will call the same Rust function with all the parameters. Some of these + // callbacks don't have all the parameters coming back in the original + // callback and will need the values to be base::Bind at the callsite. + + void OnRegisterCallback(RustUuid uuid, uint8_t scanner_id, uint8_t btm_status); + void OnStatusCallback(uint8_t scanner_id, uint8_t btm_status); + void OnEnableCallback(uint8_t action, uint8_t btm_status); + void OnFilterParamSetupCallback(uint8_t scanner_id, uint8_t avbl_space, uint8_t action_type, uint8_t btm_status); + void OnFilterConfigCallback( + uint8_t filt_index, uint8_t filt_type, uint8_t avbl_space, uint8_t action, uint8_t btm_status); + void OnStartSyncCb( + uint8_t status, + uint16_t sync_handle, + uint8_t advertising_sid, + uint8_t address_type, + RawAddress address, + uint8_t phy, + uint16_t interval); + void OnSyncReportCb(uint16_t sync_handle, int8_t tx_power, int8_t rssi, uint8_t status, std::vector<uint8_t> data); + void OnSyncLostCb(uint16_t sync_handle); + void OnSyncTransferCb(uint8_t status, RawAddress address); + BleScannerInterface* scanner_intf_; }; diff --git a/system/gd/rust/topshim/macros/src/lib.rs b/system/gd/rust/topshim/macros/src/lib.rs index d042408f2e..3ae2a9d11f 100644 --- a/system/gd/rust/topshim/macros/src/lib.rs +++ b/system/gd/rust/topshim/macros/src/lib.rs @@ -73,22 +73,24 @@ impl Parse for CbVariant { /// Implement C function to convert callback into enum variant. /// /// Expected syntax: +/// ```compile_fail /// cb_variant(DispatcherType, function_name -> EnumType::Variant, args..., { /// // Statements (maybe converting types) /// // Args in order will be _0, _1, etc. /// }) +/// ``` /// -/// args can do conversions inline as well. In order for conversions to work, the relevant -/// From<T> trait should also be implemented. +/// args can do conversions inline as well. In order for conversions to work, the relevant +/// From<T> trait should also be implemented. /// -/// Example: -/// u32 -> BtStatus (requires impl From<u32> for BtStatus) +/// Example: +/// u32 -> BtStatus (requires impl From<u32> for BtStatus) /// -/// To consume a value during conversion, you can use `Type -> _`. This is useful when you want -/// to convert a pointer + size into a single Vec (i.e. using ptr_to_vec). +/// To consume a value during conversion, you can use "Type -> _". This is useful when you want +/// to convert a pointer + size into a single Vec (i.e. using ptr_to_vec). /// -/// Example: -/// u32 -> _ +/// Example: +/// u32 -> _ pub fn cb_variant(input: TokenStream) -> TokenStream { let parsed_cptr = parse_macro_input!(input as CbVariant); diff --git a/system/gd/rust/topshim/src/btif.rs b/system/gd/rust/topshim/src/btif.rs index dc7eaabdde..9febbaca3c 100644 --- a/system/gd/rust/topshim/src/btif.rs +++ b/system/gd/rust/topshim/src/btif.rs @@ -1,7 +1,6 @@ -//! Bluetooth interface shim +//! Shim for `bt_interface_t`, providing access to libbluetooth. //! //! This is a shim interface for calling the C++ bluetooth interface via Rust. -//! use crate::bindings::root as bindings; use crate::topstack::get_dispatchers; @@ -135,7 +134,7 @@ pub enum BtPropertyType { ServiceRecord, AdapterScanMode, AdapterBondedDevices, - AdapterDiscoveryTimeout, + AdapterDiscoverableTimeout, RemoteFriendlyName, RemoteRssi, RemoteVersionInfo, @@ -300,7 +299,7 @@ pub enum BluetoothProperty { ServiceRecord(BtServiceRecord), AdapterScanMode(BtScanMode), AdapterBondedDevices(Vec<RawAddress>), - AdapterDiscoveryTimeout(u32), + AdapterDiscoverableTimeout(u32), RemoteFriendlyName(String), RemoteRssi(i8), RemoteVersionInfo(BtRemoteVersion), @@ -328,8 +327,8 @@ impl BluetoothProperty { BluetoothProperty::ServiceRecord(_) => BtPropertyType::ServiceRecord, BluetoothProperty::AdapterScanMode(_) => BtPropertyType::AdapterScanMode, BluetoothProperty::AdapterBondedDevices(_) => BtPropertyType::AdapterBondedDevices, - BluetoothProperty::AdapterDiscoveryTimeout(_) => { - BtPropertyType::AdapterDiscoveryTimeout + BluetoothProperty::AdapterDiscoverableTimeout(_) => { + BtPropertyType::AdapterDiscoverableTimeout } BluetoothProperty::RemoteFriendlyName(_) => BtPropertyType::RemoteFriendlyName, BluetoothProperty::RemoteRssi(_) => BtPropertyType::RemoteRssi, @@ -357,7 +356,7 @@ impl BluetoothProperty { BluetoothProperty::AdapterBondedDevices(devlist) => { devlist.len() * mem::size_of::<RawAddress>() } - BluetoothProperty::AdapterDiscoveryTimeout(_) => mem::size_of::<u32>(), + BluetoothProperty::AdapterDiscoverableTimeout(_) => mem::size_of::<u32>(), BluetoothProperty::RemoteFriendlyName(name) => { cmp::min(PROPERTY_NAME_MAX, name.len() + 1) } @@ -374,10 +373,10 @@ impl BluetoothProperty { } } - // Given a mutable array, this will copy the data to that array and return a - // pointer to it. - // - // The lifetime of the returned pointer is tied to that of the slice given. + /// Given a mutable array, this will copy the data to that array and return a + /// pointer to it. + /// + /// The lifetime of the returned pointer is tied to that of the slice given. fn get_data_ptr<'a>(&'a self, data: &'a mut [u8]) -> *mut u8 { let len = self.get_len(); match &*self { @@ -424,7 +423,7 @@ impl BluetoothProperty { data[start..end].copy_from_slice(&dev.val); } } - BluetoothProperty::AdapterDiscoveryTimeout(timeout) => { + BluetoothProperty::AdapterDiscoverableTimeout(timeout) => { data.copy_from_slice(&timeout.to_ne_bytes()); } BluetoothProperty::RemoteFriendlyName(name) => { @@ -498,8 +497,8 @@ impl From<bindings::bt_property_t> for BluetoothProperty { count, )) } - BtPropertyType::AdapterDiscoveryTimeout => { - BluetoothProperty::AdapterDiscoveryTimeout(u32_from_bytes(slice)) + BtPropertyType::AdapterDiscoverableTimeout => { + BluetoothProperty::AdapterDiscoverableTimeout(u32_from_bytes(slice)) } BtPropertyType::RemoteFriendlyName => { BluetoothProperty::RemoteFriendlyName(ascii_to_string(slice, len)) @@ -685,6 +684,7 @@ macro_rules! cast_to_const_ffi_address { }; } +/// An enum representing `bt_callbacks_t` from btif. #[derive(Clone, Debug)] pub enum BaseCallbacks { AdapterState(BtState), @@ -761,13 +761,14 @@ struct RawInterfaceWrapper { unsafe impl Send for RawInterfaceWrapper {} -pub struct BluetoothInterface { - internal: RawInterfaceWrapper, - pub is_init: bool, - // Need to take ownership of callbacks so it doesn't get freed after init - callbacks: Option<Box<bindings::bt_callbacks_t>>, -} - +/// Macro to call functions via function pointers. Expects the self object to +/// have a raw interface wrapper at `self.internal`. The actual function call is +/// marked unsafe since it will need to dereference a C object. This can cause +/// segfaults if not validated beforehand. +/// +/// Example: +/// ccall!(self, foobar, arg1, arg2) +/// Expands to: unsafe {((*self.internal.raw).foobar.unwrap())(arg1, arg2)} #[macro_export] macro_rules! ccall { ($self:ident,$fn_name:ident) => { @@ -779,7 +780,51 @@ macro_rules! ccall { unsafe { ((*$self.internal.raw).$fn_name.unwrap())($($args),*) } - } + }; +} + +/// Macro to call const functions via cxx. Expects the self object to have the +/// cxx object to be called at `self.internal_cxx`. +/// +/// Example: +/// cxxcall!(self, foobar, arg1, arg2) +/// Expands to: self.internal_cxx.foobar(arg1, arg2) +#[macro_export] +macro_rules! cxxcall { + ($self:expr,$fn_name:ident) => { + $self.internal_cxx.$fn_name() + }; + ($self:expr,$fn_name:ident, $($args:expr),*) => { + $self.internal_cxx.$fn_name($($args),*) + }; +} + +/// Macro to call mutable functions via cxx. Mutable functions are always +/// required to be defined with `self: Pin<&mut Self>`. The self object must +/// have the cxx object at `self.internal_cxx`. +/// +/// Example: +/// mutcxxcall!(self, foobar, arg1, arg2) +/// Expands to: self.internal_cxx.pin_mut().foobar(arg1, arg2) +#[macro_export] +macro_rules! mutcxxcall { + ($self:expr,$fn_name:ident) => { + $self.internal_cxx.pin_mut().$fn_name() + }; + ($self:expr,$fn_name:ident, $($args:expr),*) => { + $self.internal_cxx.pin_mut().$fn_name($($args),*) + }; +} + +/// Rust wrapper around `bt_interface_t`. +pub struct BluetoothInterface { + internal: RawInterfaceWrapper, + + /// Set to true after `initialize` is called. + pub is_init: bool, + + // Need to take ownership of callbacks so it doesn't get freed after init + callbacks: Option<Box<bindings::bt_callbacks_t>>, } impl BluetoothInterface { @@ -787,6 +832,12 @@ impl BluetoothInterface { self.is_init } + /// Initialize the Bluetooth interface by setting up the underlying interface. + /// + /// # Arguments + /// + /// * `callbacks` - Dispatcher struct that accepts [`BaseCallbacks`] + /// * `init_flags` - List of flags sent to libbluetooth for init. pub fn initialize( &mut self, callbacks: BaseCallbacksDispatcher, @@ -953,6 +1004,10 @@ impl BluetoothInterface { ccall!(self, ssp_reply, ffi_addr, cvariant, accept, passkey) } + pub fn clear_event_filter(&self) -> i32 { + ccall!(self, clear_event_filter) + } + pub(crate) fn get_profile_interface( &self, profile: SupportedProfiles, diff --git a/system/gd/rust/topshim/src/lib.rs b/system/gd/rust/topshim/src/lib.rs index c240ba8118..74b622f90d 100644 --- a/system/gd/rust/topshim/src/lib.rs +++ b/system/gd/rust/topshim/src/lib.rs @@ -1,4 +1,16 @@ -//! The main entry point for Rust to C++. +//! Topshim is the main entry point from Rust code to C++. +//! +//! The Bluetooth stack is split into two parts: libbluetooth and the framework +//! above it. Libbluetooth is a combination of C/C++ and Rust that provides the +//! core Bluetooth functionality. It exposes top level apis in `bt_interface_t` +//! which can be used to drive the underlying implementation. Topshim provides +//! Rust apis to access this C/C++ interface and other top level interfaces in +//! order to use libbluetooth. +//! +//! The expected users of Topshim: +//! * Floss (ChromeOS + Linux Bluetooth stack; uses D-Bus) +//! * Topshim facade (used for testing) + #[macro_use] extern crate lazy_static; #[macro_use] @@ -6,8 +18,14 @@ extern crate num_derive; #[macro_use] extern crate bitflags; +/// Bindgen bindings for accessing libbluetooth. pub mod bindings; + pub mod btif; + +/// Helper module for the topshim facade. pub mod controller; + pub mod profiles; + pub mod topstack; diff --git a/system/gd/rust/topshim/src/profiles/gatt.rs b/system/gd/rust/topshim/src/profiles/gatt.rs index ebb6bed748..2a71b282a5 100644 --- a/system/gd/rust/topshim/src/profiles/gatt.rs +++ b/system/gd/rust/topshim/src/profiles/gatt.rs @@ -8,7 +8,7 @@ use crate::profiles::gatt::bindings::{ BleAdvertiserInterface, BleScannerInterface, }; use crate::topstack::get_dispatchers; -use crate::{cast_to_ffi_address, ccall, deref_ffi_address}; +use crate::{cast_to_ffi_address, ccall, deref_ffi_address, mutcxxcall}; use num_traits::cast::FromPrimitive; @@ -29,6 +29,11 @@ pub mod ffi { address: [u8; 6], } + #[derive(Debug, Copy, Clone)] + pub struct RustUuid { + uu: [u8; 16], + } + #[derive(Debug, Clone)] pub struct RustAdvertisingTrackInfo { scanner_id: u8, @@ -46,6 +51,37 @@ pub mod ffi { scan_response: Vec<u8>, } + // Original definition exists in C++. + #[derive(Debug, Clone)] + pub struct RustGattFilterParam { + feat_seln: u16, + list_logic_type: u16, + filt_logic_type: u8, + rssi_high_thres: u8, + rssi_low_thres: u8, + delay_mode: u8, + found_timeout: u16, + lost_timeout: u16, + found_timeout_count: u8, + num_of_tracking_entries: u16, + } + + // Defined in C++ and needs a translation in shim. + #[derive(Debug, Clone)] + pub struct RustApcfCommand { + type_: u8, + address: RustRawAddress, + addr_type: u8, + uuid: RustUuid, + uuid_mask: RustUuid, + name: Vec<u8>, + company: u16, + company_mask: u16, + data: Vec<u8>, + data_mask: Vec<u8>, + irk: [u8; 16], + } + unsafe extern "C++" { include!("gatt/gatt_shim.h"); @@ -75,7 +111,76 @@ pub mod ffi { unsafe fn GetBleScannerIntf(gatt: *const u8) -> UniquePtr<BleScannerIntf>; - // TODO - Implement the rest of the BleScannerIntf + fn RegisterScanner(self: Pin<&mut BleScannerIntf>, uuid: RustUuid); + fn Unregister(self: Pin<&mut BleScannerIntf>, scanner_id: u8); + fn Scan(self: Pin<&mut BleScannerIntf>, start: bool); + fn ScanFilterParamSetup( + self: Pin<&mut BleScannerIntf>, + scanner_id: u8, + action: u8, + filter_index: u8, + filt_param: RustGattFilterParam, + ); + fn ScanFilterAdd( + self: Pin<&mut BleScannerIntf>, + filter_index: u8, + filters: Vec<RustApcfCommand>, + ); + fn ScanFilterClear(self: Pin<&mut BleScannerIntf>, filter_index: u8); + fn ScanFilterEnable(self: Pin<&mut BleScannerIntf>, enable: bool); + fn SetScanParameters( + self: Pin<&mut BleScannerIntf>, + scanner_id: u8, + scan_interval: u16, + scan_window: u16, + ); + + fn BatchscanConfigStorage( + self: Pin<&mut BleScannerIntf>, + scanner_id: u8, + batch_scan_full_max: i32, + batch_scan_trunc_max: i32, + batch_scan_notify_threshold: i32, + ); + fn BatchscanEnable( + self: Pin<&mut BleScannerIntf>, + scan_mode: i32, + scan_interval: u16, + scan_window: u16, + addr_type: i32, + discard_rule: i32, + ); + fn BatchscanDisable(self: Pin<&mut BleScannerIntf>); + fn BatchscanReadReports(self: Pin<&mut BleScannerIntf>, scanner_id: u8, scan_mode: i32); + + fn StartSync( + self: Pin<&mut BleScannerIntf>, + sid: u8, + address: RustRawAddress, + skip: u16, + timeout: u16, + ); + fn StopSync(self: Pin<&mut BleScannerIntf>, handle: u16); + fn CancelCreateSync(self: Pin<&mut BleScannerIntf>, sid: u8, address: RustRawAddress); + fn TransferSync( + self: Pin<&mut BleScannerIntf>, + address: RustRawAddress, + service_data: u16, + sync_handle: u16, + ); + fn TransferSetInfo( + self: Pin<&mut BleScannerIntf>, + address: RustRawAddress, + service_data: u16, + adv_handle: u8, + ); + fn SyncTxParameters( + self: Pin<&mut BleScannerIntf>, + address: RustRawAddress, + mode: u8, + skip: u16, + timeout: u16, + ); /// Registers a C++ |ScanningCallbacks| implementation with the BleScanner. /// The shim implementation will call all the callbacks defined via |cb_variant!|. @@ -83,7 +188,6 @@ pub mod ffi { } extern "Rust" { - // All callbacks below are generated by cb_variant! and will be called // by the ScanningCallbacks handler in shim. unsafe fn gdscan_on_scanner_registered(uuid: *const i8, scannerId: u8, status: u8); @@ -111,10 +215,61 @@ pub mod ffi { data_len: usize, ); unsafe fn gdscan_on_batch_scan_threshold_crossed(client_if: i32); + + // Static cb_variant! callbacks using base::Callback + unsafe fn gdscan_register_callback(uuid: RustUuid, scanner_id: u8, btm_status: u8); + unsafe fn gdscan_status_callback(scanner_id: u8, btm_status: u8); + unsafe fn gdscan_enable_callback(action: u8, btm_status: u8); + unsafe fn gdscan_filter_param_setup_callback( + scanner_id: u8, + available_space: u8, + action: u8, + btm_status: u8, + ); + unsafe fn gdscan_filter_config_callback( + filter_index: u8, + filter_type: u8, + available_space: u8, + action: u8, + btm_status: u8, + ); + unsafe fn gdscan_start_sync_callback( + status: u8, + sync_handle: u16, + advertising_sid: u8, + addr_type: u8, + address: *const RustRawAddress, + phy: u8, + interval: u16, + ); + unsafe fn gdscan_sync_report_callback( + sync_handle: u16, + tx_power: i8, + rssi: i8, + status: u8, + data: *const u8, + len: usize, + ); + unsafe fn gdscan_sync_lost_callback(sync_handle: u16); + unsafe fn gdscan_sync_transfer_callback(status: u8, address: *const RustRawAddress); } } pub type AdvertisingTrackInfo = ffi::RustAdvertisingTrackInfo; +pub type GattFilterParam = ffi::RustGattFilterParam; +pub type ApcfCommand = ffi::RustApcfCommand; + +impl From<ffi::RustUuid> for Uuid { + fn from(item: ffi::RustUuid) -> Self { + Uuid { uu: item.uu } + } +} + +impl From<Uuid> for ffi::RustUuid { + fn from(item: Uuid) -> Self { + ffi::RustUuid { uu: item.uu } + } +} #[derive(Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)] #[repr(u32)] @@ -532,6 +687,72 @@ cb_variant!( cb_variant!(GDScannerCb, gdscan_on_batch_scan_threshold_crossed -> GattScannerCallbacks::OnBatchScanThresholdCrossed, i32); +/// In-band callbacks from the various |BleScannerInterface| methods. Rather than +/// store closures for each registered callback, we instead bind and return an +/// identifier for the callback instead (such as scanner id or Uuid). +#[derive(Debug)] +pub enum GattScannerInbandCallbacks { + /// Params: App Uuid, Scanner Id, BTM Status + RegisterCallback(Uuid, u8, u8), + + /// Params: Scanner Id, BTM Status + StatusCallback(u8, u8), + + /// Params: Action (enable/disable), BTM Status + EnableCallback(u8, u8), + + /// Params: Scanner Id, Available Space, Action Type, BTM Status + FilterParamSetupCallback(u8, u8, u8, u8), + + /// Params: Filter Index, Filter Type, Available Space, Action, BTM Status + FilterConfigCallback(u8, u8, u8, u8, u8), + + /// Params: Status, Sync Handle, Advertising Sid, Address Type, Address, Phy, Interval + StartSyncCallback(u8, u16, u8, u8, RawAddress, u8, u16), + + /// Params: Sync Handle, Tx Power, RSSI, Status, Data + SyncReportCallback(u16, i8, i8, u8, Vec<u8>), + + /// Params: Sync Handle + SyncLostCallback(u16), + + /// Params: Status, Address + SyncTransferCallback(u8, RawAddress), +} + +pub struct GattScannerInbandCallbacksDispatcher { + pub dispatch: Box<dyn Fn(GattScannerInbandCallbacks) + Send>, +} + +type GDScannerInbandCb = Arc<Mutex<GattScannerInbandCallbacksDispatcher>>; + +cb_variant!(GDScannerInbandCb, gdscan_register_callback -> GattScannerInbandCallbacks::RegisterCallback, + ffi::RustUuid -> Uuid, u8, u8); + +cb_variant!(GDScannerInbandCb, gdscan_status_callback -> GattScannerInbandCallbacks::StatusCallback, u8, u8); +cb_variant!(GDScannerInbandCb, gdscan_enable_callback -> GattScannerInbandCallbacks::EnableCallback, u8, u8); +cb_variant!(GDScannerInbandCb, + gdscan_filter_param_setup_callback -> GattScannerInbandCallbacks::FilterParamSetupCallback, + u8, u8, u8, u8); +cb_variant!(GDScannerInbandCb, + gdscan_filter_config_callback -> GattScannerInbandCallbacks::FilterConfigCallback, + u8, u8, u8, u8, u8); +cb_variant!(GDScannerInbandCb, +gdscan_start_sync_callback -> GattScannerInbandCallbacks::StartSyncCallback, +u8, u16, u8, u8, *const ffi::RustRawAddress, u8, u16, { + let _4 = unsafe { deref_ffi_address!(_4) }; +}); +cb_variant!(GDScannerInbandCb, +gdscan_sync_report_callback -> GattScannerInbandCallbacks::SyncReportCallback, +u16, i8, i8, u8, *const u8, usize -> _, { + let _4 = ptr_to_vec(_4, _5 as usize); +}); +cb_variant!(GDScannerInbandCb, gdscan_sync_lost_callback -> GattScannerInbandCallbacks::SyncLostCallback, u16); +cb_variant!(GDScannerInbandCb, gdscan_sync_transfer_callback -> GattScannerInbandCallbacks::SyncTransferCallback, +u8, *const ffi::RustRawAddress, { + let _1 = unsafe { deref_ffi_address!(_1) }; +}); + struct RawGattWrapper { raw: *const btgatt_interface_t, } @@ -761,11 +982,12 @@ impl GattClient { } pub fn read_phy(&mut self, client_if: i32, addr: &RawAddress) -> BtStatus { - BtStatus::from_i32( - self.internal_cxx - .pin_mut() - .read_phy(client_if, ffi::RustRawAddress { address: addr.val }), - ) + BtStatus::from_i32(mutcxxcall!( + self, + read_phy, + client_if, + ffi::RustRawAddress { address: addr.val } + )) .unwrap() } @@ -863,7 +1085,6 @@ impl GattServer { // TODO(b/193916778): Figure out how to shim read_phy which accepts base::Callback } -// TODO(b/193916778): Underlying FFI is C++, implement using cxx. pub struct BleScanner { internal: RawBleScannerWrapper, internal_cxx: cxx::UniquePtr<ffi::BleScannerIntf>, @@ -881,6 +1102,125 @@ impl BleScanner { internal_cxx, } } + + fn register_scanner(&mut self, app_uuid: Uuid) { + mutcxxcall!(self, RegisterScanner, app_uuid.into()); + } + + fn unregister(&mut self, scanner_id: u8) { + mutcxxcall!(self, Unregister, scanner_id); + } + + fn start_scan(&mut self) { + mutcxxcall!(self, Scan, true); + } + + fn stop_scan(&mut self) { + mutcxxcall!(self, Scan, false); + } + + fn scan_filter_setup( + &mut self, + scanner_id: u8, + action: u8, + filter_index: u8, + param: GattFilterParam, + ) { + mutcxxcall!(self, ScanFilterParamSetup, scanner_id, action, filter_index, param); + } + + fn scan_filter_add(&mut self, filter_index: u8, filters: Vec<ApcfCommand>) { + mutcxxcall!(self, ScanFilterAdd, filter_index, filters); + } + + fn scan_filter_clear(&mut self, filter_index: u8) { + mutcxxcall!(self, ScanFilterClear, filter_index); + } + + fn scan_filter_enable(&mut self) { + mutcxxcall!(self, ScanFilterEnable, true); + } + + fn scan_filter_disable(&mut self) { + mutcxxcall!(self, ScanFilterEnable, false); + } + + fn set_scan_parameters(&mut self, scanner_id: u8, scan_interval: u16, scan_window: u16) { + mutcxxcall!(self, SetScanParameters, scanner_id, scan_interval, scan_window); + } + + fn batchscan_config_storage( + &mut self, + scanner_id: u8, + full_max: i32, + trunc_max: i32, + notify_threshold: i32, + ) { + mutcxxcall!( + self, + BatchscanConfigStorage, + scanner_id, + full_max, + trunc_max, + notify_threshold + ); + } + + fn batchscan_enable( + &mut self, + scan_mode: i32, + scan_interval: u16, + scan_window: u16, + addr_type: i32, + discard_rule: i32, + ) { + mutcxxcall!( + self, + BatchscanEnable, + scan_mode, + scan_interval, + scan_window, + addr_type, + discard_rule + ); + } + + fn batchscan_disable(&mut self) { + mutcxxcall!(self, BatchscanDisable); + } + + fn batchscan_read_reports(&mut self, scanner_id: u8, scan_mode: i32) { + mutcxxcall!(self, BatchscanReadReports, scanner_id, scan_mode); + } + + fn start_sync(&mut self, sid: u8, address: RawAddress, skip: u16, timeout: u16) { + let addr = unsafe { *((&address as *const RawAddress) as *const ffi::RustRawAddress) }; + mutcxxcall!(self, StartSync, sid, addr, skip, timeout); + } + + fn stop_sync(&mut self, handle: u16) { + mutcxxcall!(self, StopSync, handle); + } + + fn cancel_create_sync(&mut self, sid: u8, address: RawAddress) { + let addr = unsafe { *((&address as *const RawAddress) as *const ffi::RustRawAddress) }; + mutcxxcall!(self, CancelCreateSync, sid, addr); + } + + fn transfer_sync(&mut self, address: RawAddress, service_data: u16, sync_handle: u16) { + let addr = unsafe { *((&address as *const RawAddress) as *const ffi::RustRawAddress) }; + mutcxxcall!(self, TransferSync, addr, service_data, sync_handle); + } + + fn transfer_set_info(&mut self, address: RawAddress, service_data: u16, adv_handle: u8) { + let addr = unsafe { *((&address as *const RawAddress) as *const ffi::RustRawAddress) }; + mutcxxcall!(self, TransferSetInfo, addr, service_data, adv_handle); + } + + fn sync_tx_parameters(&mut self, address: RawAddress, mode: u8, skip: u16, timeout: u16) { + let addr = unsafe { *((&address as *const RawAddress) as *const ffi::RustRawAddress) }; + mutcxxcall!(self, SyncTxParameters, addr, mode, skip, timeout); + } } // TODO(b/193916778): Underlying FFI is C++, implement using cxx. @@ -1053,7 +1393,7 @@ impl Gatt { self.gatt_scanner_callbacks = Some(gatt_scanner_callbacks); // Register callbacks for gatt scanner - self.scanner.internal_cxx.pin_mut().RegisterCallbacks(); + mutcxxcall!(self.scanner, RegisterCallbacks); return self.is_init; } diff --git a/system/gd/rust/topshim/src/profiles/mod.rs b/system/gd/rust/topshim/src/profiles/mod.rs index a12e7c5048..283ae9b294 100644 --- a/system/gd/rust/topshim/src/profiles/mod.rs +++ b/system/gd/rust/topshim/src/profiles/mod.rs @@ -1,3 +1,5 @@ +//! Various libraries to access the profile interfaces. + pub mod a2dp; pub mod avrcp; pub mod gatt; diff --git a/system/gd/rust/topshim/src/topstack.rs b/system/gd/rust/topshim/src/topstack.rs index 7553863ec3..18edf5d2e3 100644 --- a/system/gd/rust/topshim/src/topstack.rs +++ b/system/gd/rust/topshim/src/topstack.rs @@ -29,13 +29,53 @@ lazy_static! { Arc::new(Mutex::new(DispatchContainer { instances: HashMap::new() })); } -type InstanceBox = Box<dyn Any + Send + Sync>; +/// A Box-ed struct that implements a `dispatch` fn. +/// +/// Example: +/// ``` +/// use std::sync::Arc; +/// use std::sync::Mutex; +/// +/// #[derive(Debug)] +/// enum Foo { +/// First(i16), +/// Second(i32), +/// } +/// +/// struct FooDispatcher { +/// dispatch: Box<dyn Fn(Foo) + Send>, +/// } +/// +/// fn main() { +/// let foo_dispatcher = FooDispatcher { +/// dispatch: Box::new(move |value| { +/// println!("Dispatch {:?}", value); +/// }) +/// }; +/// let value = Arc::new(Mutex::new(foo_dispatcher)); +/// let instance_box = Box::new(value); +/// } +/// ``` +pub type InstanceBox = Box<dyn Any + Send + Sync>; +/// Manage enum dispatches for emulating callbacks. +/// +/// Libbluetooth is highly callback based but our Rust code prefers using +/// channels. To reconcile these two systems, we pass static callbacks to +/// libbluetooth that convert callback args into an enum variant and call the +/// dispatcher for that enum. The dispatcher will then queue that enum into the +/// channel (using a captured channel tx in the closure). pub struct DispatchContainer { instances: HashMap<TypeId, InstanceBox>, } impl DispatchContainer { + /// Find registered dispatcher for enum specialization. + /// + /// # Return + /// + /// Returns an Option with a dispatcher object (the contents of + /// [`InstanceBox`]). pub fn get<T: 'static + Clone + Send + Sync>(&self) -> Option<T> { let typeid = TypeId::of::<T>(); @@ -46,11 +86,22 @@ impl DispatchContainer { None } + /// Set dispatcher for an enum specialization. + /// + /// # Arguments + /// + /// * `obj` - The contents of [`InstanceBox`], usually `Arc<Mutex<U>>`. See + /// the [`InstanceBox`] documentation for examples. + /// + /// # Returns + /// + /// True if this is replacing an existing enum dispatcher. pub fn set<T: 'static + Clone + Send + Sync>(&mut self, obj: T) -> bool { self.instances.insert(TypeId::of::<T>(), Box::new(obj)).is_some() } } +/// Take a clone of the static dispatcher container. pub fn get_dispatchers() -> Arc<Mutex<DispatchContainer>> { CB_DISPATCHER.clone() } diff --git a/system/gd/security/facade_configuration_api.h b/system/gd/security/facade_configuration_api.h index d6bab79579..9feb8a4600 100644 --- a/system/gd/security/facade_configuration_api.h +++ b/system/gd/security/facade_configuration_api.h @@ -35,6 +35,9 @@ namespace security { */ class FacadeConfigurationApi { public: + FacadeConfigurationApi(const FacadeConfigurationApi&) = delete; + FacadeConfigurationApi& operator=(const FacadeConfigurationApi&) = delete; + friend class internal::SecurityManagerImpl; friend class SecurityModule; @@ -63,7 +66,6 @@ class FacadeConfigurationApi { private: os::Handler* security_handler_ = nullptr; internal::SecurityManagerImpl* security_manager_impl_; - DISALLOW_COPY_AND_ASSIGN(FacadeConfigurationApi); }; } // namespace security diff --git a/system/gd/security/security_manager.h b/system/gd/security/security_manager.h index 627cc2ac89..1842761187 100644 --- a/system/gd/security/security_manager.h +++ b/system/gd/security/security_manager.h @@ -36,6 +36,9 @@ namespace security { */ class SecurityManager : public UICallbacks { public: + SecurityManager(const SecurityManager&) = delete; + SecurityManager& operator=(const SecurityManager&) = delete; + friend class SecurityModule; /** @@ -133,7 +136,6 @@ class SecurityManager : public UICallbacks { private: os::Handler* security_handler_ = nullptr; internal::SecurityManagerImpl* security_manager_impl_; - DISALLOW_COPY_AND_ASSIGN(SecurityManager); }; } // namespace security diff --git a/system/gd/security/security_module.h b/system/gd/security/security_module.h index 889073388a..68ba2dacd1 100644 --- a/system/gd/security/security_module.h +++ b/system/gd/security/security_module.h @@ -27,6 +27,9 @@ namespace security { class SecurityModule : public bluetooth::Module { public: SecurityModule() = default; + SecurityModule(const SecurityModule&) = delete; + SecurityModule& operator=(const SecurityModule&) = delete; + ~SecurityModule() = default; /** @@ -55,7 +58,6 @@ class SecurityModule : public bluetooth::Module { private: struct impl; std::unique_ptr<impl> pimpl_; - DISALLOW_COPY_AND_ASSIGN(SecurityModule); }; } // namespace security diff --git a/system/gd/security/test/mocks.h b/system/gd/security/test/mocks.h index 3ddc909f4c..dc8d3254db 100644 --- a/system/gd/security/test/mocks.h +++ b/system/gd/security/test/mocks.h @@ -30,6 +30,9 @@ namespace security { class UIMock : public UI { public: UIMock() = default; + UIMock(const UIMock&) = delete; + UIMock& operator=(const UIMock&) = delete; + ~UIMock() = default; // Convert these to accept ConfirmationData @@ -40,9 +43,6 @@ class UIMock : public UI { MOCK_METHOD1(DisplayEnterPasskeyDialog, void(ConfirmationData)); MOCK_METHOD1(DisplayPasskey, void(ConfirmationData)); MOCK_METHOD1(DisplayEnterPinDialog, void(ConfirmationData)); - - private: - DISALLOW_COPY_AND_ASSIGN(UIMock); }; class LeSecurityInterfaceMock : public hci::LeSecurityInterface { diff --git a/system/gd/shim/dumpsys.h b/system/gd/shim/dumpsys.h index 35c1936d77..04be062793 100644 --- a/system/gd/shim/dumpsys.h +++ b/system/gd/shim/dumpsys.h @@ -36,6 +36,10 @@ class Dumpsys : public bluetooth::Module { os::Handler* GetGdShimHandler(); Dumpsys(const std::string& pre_bundled_schema); + + Dumpsys(const Dumpsys&) = delete; + Dumpsys& operator=(const Dumpsys&) = delete; + ~Dumpsys() = default; static const ModuleFactory Factory; @@ -51,7 +55,6 @@ class Dumpsys : public bluetooth::Module { struct impl; std::unique_ptr<impl> pimpl_; const dumpsys::ReflectionSchema reflection_schema_; - DISALLOW_COPY_AND_ASSIGN(Dumpsys); }; } // namespace shim diff --git a/system/gd/storage/config_cache.h b/system/gd/storage/config_cache.h index f0e1fe456b..44229e473d 100644 --- a/system/gd/storage/config_cache.h +++ b/system/gd/storage/config_cache.h @@ -52,10 +52,13 @@ class Mutation; class ConfigCache { public: ConfigCache(size_t temp_device_capacity, std::unordered_set<std::string_view> persistent_property_names); + + ConfigCache(const ConfigCache&) = delete; + ConfigCache& operator=(const ConfigCache&) = delete; + virtual ~ConfigCache() = default; // no copy - DISALLOW_COPY_AND_ASSIGN(ConfigCache); // can move ConfigCache(ConfigCache&& other) noexcept; diff --git a/system/gd/storage/storage_module.h b/system/gd/storage/storage_module.h index 8853a4e76f..ba41b1a5eb 100644 --- a/system/gd/storage/storage_module.h +++ b/system/gd/storage/storage_module.h @@ -47,6 +47,9 @@ class StorageModule : public bluetooth::Module { static const std::string kAdapterSection; + StorageModule(const StorageModule&) = delete; + StorageModule& operator=(const StorageModule&) = delete; + ~StorageModule(); static const ModuleFactory Factory; @@ -146,8 +149,6 @@ class StorageModule : public bluetooth::Module { bool is_restricted_mode_; bool is_single_user_mode_; static bool is_config_checksum_pass(int check_bit); - - DISALLOW_COPY_AND_ASSIGN(StorageModule); }; } // namespace storage diff --git a/system/include/hardware/bluetooth.h b/system/include/hardware/bluetooth.h index 65c9db2f33..16130873a9 100644 --- a/system/include/hardware/bluetooth.h +++ b/system/include/hardware/bluetooth.h @@ -282,11 +282,11 @@ typedef enum { */ BT_PROPERTY_ADAPTER_BONDED_DEVICES, /** - * Description - Bluetooth Adapter Discovery timeout (in seconds) + * Description - Bluetooth Adapter Discoverable timeout (in seconds) * Access mode - GET and SET * Data type - uint32_t */ - BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT, + BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT, /* Properties unique to remote device */ /** @@ -472,8 +472,7 @@ typedef void (*link_quality_report_callback)( int negative_acknowledgement_count); /** Switch the buffer size callback */ -typedef void (*switch_buffer_size_callback)(RawAddress* remote_addr, - bool is_low_latency_buffer_size); +typedef void (*switch_buffer_size_callback)(bool is_low_latency_buffer_size); typedef enum { ASSOCIATE_JVM, DISASSOCIATE_JVM } bt_cb_thread_evt; @@ -772,6 +771,11 @@ typedef struct { * @return true if audio low latency is successfully allowed or disallowed */ bool (*allow_low_latency_audio)(bool allowed, const RawAddress& address); + + /** + * Set the event filter for the controller + */ + int (*clear_event_filter)(); } bt_interface_t; #define BLUETOOTH_INTERFACE_STRING "bluetoothInterface" diff --git a/system/include/hardware/bt_has.h b/system/include/hardware/bt_has.h index 4fdd316852..739edc041f 100644 --- a/system/include/hardware/bt_has.h +++ b/system/include/hardware/bt_has.h @@ -36,9 +36,10 @@ enum class ConnectionState : uint8_t { /** Results codes for the failed preset operations */ enum class ErrorCode : uint8_t { NO_ERROR = 0, - SET_NAME_NOT_ALLOWED, - OPERATION_NOT_SUPPORTED, - OPERATION_NOT_POSSIBLE, + SET_NAME_NOT_ALLOWED, // Preset cannot be written (read only preset) + OPERATION_NOT_SUPPORTED, // If theres no optional characteristic, + // or request opcode is invalid or not supported + OPERATION_NOT_POSSIBLE, // Operation cannot be performed at this time INVALID_PRESET_NAME_LENGTH, INVALID_PRESET_INDEX, GROUP_OPERATION_NOT_SUPPORTED, diff --git a/system/include/hardware/bt_vc.h b/system/include/hardware/bt_vc.h index fb0b725fac..e7f498b6cb 100644 --- a/system/include/hardware/bt_vc.h +++ b/system/include/hardware/bt_vc.h @@ -42,11 +42,11 @@ class VolumeControlCallbacks { /* Callback for the volume change changed on the device */ virtual void OnVolumeStateChanged(const RawAddress& address, uint8_t volume, - bool mute) = 0; + bool mute, bool isAutonomous) = 0; /* Callback for the volume change changed on the group*/ virtual void OnGroupVolumeStateChanged(int group_id, uint8_t volume, - bool mute) = 0; + bool mute, bool isAutonomous) = 0; }; class VolumeControlInterface { diff --git a/system/main/Android.bp b/system/main/Android.bp index bd331e62f4..812340d79b 100644 --- a/system/main/Android.bp +++ b/system/main/Android.bp @@ -99,7 +99,6 @@ cc_library_shared { "libbt-sbc-encoder", "libFraunhoferAAC", "libg722codec", - "liblc3codec", "liblc3", "libudrv-uipc", "libprotobuf-cpp-lite", @@ -125,7 +124,6 @@ cc_library_shared { "android.hardware.bluetooth.a2dp@1.0", "android.hardware.bluetooth.audio@2.0", "android.hardware.bluetooth.audio@2.1", - "android.hardware.bluetooth.audio@2.2", "android.hardware.bluetooth.audio-V1-ndk", "android.hardware.bluetooth@1.0", "android.hardware.bluetooth@1.1", @@ -156,6 +154,10 @@ cc_library_shared { required: [ "bt_did.conf", "bt_stack.conf", + "audio_set_scenarios_bfbs", + "audio_set_scenarios_json", + "audio_set_configurations_bfbs", + "audio_set_configurations_json", ], cflags: [ "-DBUILDCFG", diff --git a/system/main/shim/acl.h b/system/main/shim/acl.h index d156f85d46..f90e641455 100644 --- a/system/main/shim/acl.h +++ b/system/main/shim/acl.h @@ -43,6 +43,10 @@ class Acl : public hci::acl_manager::ConnectionCallbacks, public: Acl(os::Handler* handler, const acl_interface_t& acl_interface, uint8_t max_acceptlist_size, uint8_t max_address_resolution_size); + + Acl(const Acl&) = delete; + Acl& operator=(const Acl&) = delete; + ~Acl(); // hci::acl_manager::ConnectionCallbacks @@ -120,7 +124,6 @@ class Acl : public hci::acl_manager::ConnectionCallbacks, struct impl; std::unique_ptr<impl> pimpl_; - DISALLOW_COPY_AND_ASSIGN(Acl); }; } // namespace legacy diff --git a/system/main/shim/btm.cc b/system/main/shim/btm.cc index b79292c72c..29827208d3 100644 --- a/system/main/shim/btm.cc +++ b/system/main/shim/btm.cc @@ -55,8 +55,8 @@ static constexpr bool kPassiveScanning = false; using BtmRemoteDeviceName = tBTM_REMOTE_DEV_NAME; -extern void btm_process_cancel_complete(uint8_t status, uint8_t mode); -extern void btm_process_inq_complete(uint8_t status, uint8_t result_type); +extern void btm_process_cancel_complete(tHCI_STATUS status, uint8_t mode); +extern void btm_process_inq_complete(tHCI_STATUS status, uint8_t result_type); extern void btm_ble_process_adv_addr(RawAddress& raw_address, tBLE_ADDR_TYPE* address_type); extern void btm_ble_process_adv_pkt_cont( diff --git a/system/main/shim/btm_api.cc b/system/main/shim/btm_api.cc index a4ad2f913f..d5f3023c4e 100644 --- a/system/main/shim/btm_api.cc +++ b/system/main/shim/btm_api.cc @@ -71,7 +71,7 @@ extern void btm_clear_all_pending_le_entry(void); extern void btm_clr_inq_result_flt(void); extern void btm_set_eir_uuid(const uint8_t* p_eir, tBTM_INQ_RESULTS* p_results); extern void btm_sort_inq_result(void); -extern void btm_process_inq_complete(uint8_t status, uint8_t result_type); +extern void btm_process_inq_complete(tHCI_STATUS status, uint8_t result_type); static bool is_classic_device(tBT_DEVICE_TYPE device_type) { return device_type == BT_DEVICE_TYPE_BREDR; @@ -1341,3 +1341,8 @@ tBTM_STATUS bluetooth::shim::BTM_SetDeviceClass(DEV_CLASS dev_class) { LOG_WARN("Unimplemented"); return BTM_SUCCESS; } + +tBTM_STATUS bluetooth::shim::BTM_ClearEventFilter() { + controller_get_interface()->clear_event_filter(); + return BTM_SUCCESS; +} diff --git a/system/main/shim/btm_api.h b/system/main/shim/btm_api.h index 5a4f42f081..3f864b4c0f 100644 --- a/system/main/shim/btm_api.h +++ b/system/main/shim/btm_api.h @@ -1840,6 +1840,17 @@ bool BTM_BleLocalPrivacyEnabled(void); ******************************************************************************/ tBTM_STATUS BTM_BleGetEnergyInfo(tBTM_BLE_ENERGY_INFO_CBACK* p_ener_cback); +/******************************************************************************* + * + * Function BTM_ClearEventFilter + * + * Description Clears the event filter in the controller + * + * Returns Return btm status + * + ******************************************************************************/ +tBTM_STATUS BTM_ClearEventFilter(void); + /** * Send remote name request to GD shim Name module */ diff --git a/system/main/shim/controller.cc b/system/main/shim/controller.cc index 0b3edb34df..1ac4d79053 100644 --- a/system/main/shim/controller.cc +++ b/system/main/shim/controller.cc @@ -313,6 +313,12 @@ static uint8_t get_le_resolving_list_size(void) { static uint8_t get_le_all_initiating_phys() { return data_.phy; } +static uint8_t controller_clear_event_filter() { + LOG_VERBOSE("Called!"); + bluetooth::shim::GetController()->SetEventFilterClearAll(); + return BTM_SUCCESS; +} + static const controller_t interface = { .get_is_ready = get_is_ready, @@ -410,7 +416,8 @@ static const controller_t interface = { .get_ble_resolving_list_max_size = get_le_resolving_list_size, .set_ble_resolving_list_max_size = set_ble_resolving_list_max_size, .get_local_supported_codecs = get_local_supported_codecs, - .get_le_all_initiating_phys = get_le_all_initiating_phys}; + .get_le_all_initiating_phys = get_le_all_initiating_phys, + .clear_event_filter = controller_clear_event_filter}; const controller_t* bluetooth::shim::controller_get_interface() { static bool loaded = false; diff --git a/system/main/shim/le_scanning_manager.cc b/system/main/shim/le_scanning_manager.cc index bcc8b1a647..7bd81e30bc 100644 --- a/system/main/shim/le_scanning_manager.cc +++ b/system/main/shim/le_scanning_manager.cc @@ -132,7 +132,9 @@ void BleScannerInterfaceImpl::Scan(bool start) { BTM_LogHistory( kBtmLogTag, RawAddress::kEmpty, base::StringPrintf("Le scan %s", (start) ? "started" : "stopped")); - address_cache_.init(); + do_in_jni_thread(FROM_HERE, + base::Bind(&BleScannerInterfaceImpl::AddressCache::init, + base::Unretained(&address_cache_))); } /** Setup scan filter params */ @@ -496,6 +498,11 @@ bool BleScannerInterfaceImpl::parse_filter_command( void BleScannerInterfaceImpl::handle_remote_properties( RawAddress bd_addr, tBLE_ADDR_TYPE addr_type, std::vector<uint8_t> advertising_data) { + if (!bluetooth::shim::is_gd_stack_started_up()) { + LOG_WARN("Gd stack is stopped, return"); + return; + } + // skip anonymous advertisment if (addr_type == BLE_ADDR_ANONYMOUS) { return; @@ -543,11 +550,6 @@ void BleScannerInterfaceImpl::handle_remote_properties( } } } - if (!bluetooth::shim::is_gd_stack_started_up()) { - LOG_WARN("Gd stack is stopped, return"); - return; - } - auto* storage_module = bluetooth::shim::GetStorage(); bluetooth::hci::Address address = ToGdAddress(bd_addr); diff --git a/system/main/shim/stack.h b/system/main/shim/stack.h index b105866b18..f32db434a1 100644 --- a/system/main/shim/stack.h +++ b/system/main/shim/stack.h @@ -39,6 +39,9 @@ class Stack { static Stack* GetInstance(); Stack() = default; + Stack(const Stack&) = delete; + Stack& operator=(const Stack&) = delete; + ~Stack() = default; // Idle mode, config is loaded, but controller is not enabled @@ -64,8 +67,6 @@ class Stack { return rust_controller_; } - DISALLOW_COPY_AND_ASSIGN(Stack); - private: mutable std::recursive_mutex mutex_; StackManager stack_manager_; diff --git a/system/packet/avrcp/avrcp_browse_packet.h b/system/packet/avrcp/avrcp_browse_packet.h index 038f576426..f6bd72e225 100644 --- a/system/packet/avrcp/avrcp_browse_packet.h +++ b/system/packet/avrcp/avrcp_browse_packet.h @@ -17,7 +17,6 @@ #pragma once #include <base/logging.h> -#include <base/macros.h> #include <iostream> #include "hardware/avrcp/avrcp_common.h" @@ -52,6 +51,9 @@ class BrowsePacketBuilder : public ::bluetooth::PacketBuilder { class BrowsePacket : public ::bluetooth::Packet { public: + BrowsePacket(const BrowsePacket&) = delete; + BrowsePacket& operator=(const BrowsePacket&) = delete; + virtual ~BrowsePacket() = default; static std::shared_ptr<BrowsePacket> Parse( @@ -76,8 +78,7 @@ class BrowsePacket : public ::bluetooth::Packet { private: virtual std::pair<size_t, size_t> GetPayloadIndecies() const override; - DISALLOW_COPY_AND_ASSIGN(BrowsePacket); }; } // namespace avrcp -} // namespace bluetooth
\ No newline at end of file +} // namespace bluetooth diff --git a/system/packet/avrcp/avrcp_packet.h b/system/packet/avrcp/avrcp_packet.h index ee0e0d5ad1..7a44dc57bb 100644 --- a/system/packet/avrcp/avrcp_packet.h +++ b/system/packet/avrcp/avrcp_packet.h @@ -17,7 +17,6 @@ #pragma once #include <base/logging.h> -#include <base/macros.h> #include <iostream> #include "hardware/avrcp/avrcp_common.h" @@ -62,6 +61,9 @@ class PacketBuilder : public ::bluetooth::PacketBuilder { class Packet : public ::bluetooth::Packet { public: + Packet(const Packet&) = delete; + Packet& operator=(const Packet&) = delete; + virtual ~Packet() = default; // TODO (apanicke): Right now we can use this to build an AvrcpPacket from @@ -104,7 +106,6 @@ class Packet : public ::bluetooth::Packet { private: virtual std::pair<size_t, size_t> GetPayloadIndecies() const override; - DISALLOW_COPY_AND_ASSIGN(Packet); }; } // namespace avrcp diff --git a/system/profile/avrcp/connection_handler.h b/system/profile/avrcp/connection_handler.h index 5320b63a47..67445a8df5 100644 --- a/system/profile/avrcp/connection_handler.h +++ b/system/profile/avrcp/connection_handler.h @@ -158,6 +158,9 @@ class ConnectionHandler { tAVRC_MSG* p_msg); ConnectionHandler() : weak_ptr_factory_(this){}; + ConnectionHandler(const ConnectionHandler&) = delete; + ConnectionHandler& operator=(const ConnectionHandler&) = delete; + virtual ~ConnectionHandler() = default; // Callback for when sending a response to a device @@ -165,7 +168,6 @@ class ConnectionHandler { std::unique_ptr<::bluetooth::PacketBuilder> message); base::WeakPtrFactory<ConnectionHandler> weak_ptr_factory_; - DISALLOW_COPY_AND_ASSIGN(ConnectionHandler); }; } // namespace avrcp diff --git a/system/profile/avrcp/device.h b/system/profile/avrcp/device.h index fc5d7364b0..07e1cac7d2 100644 --- a/system/profile/avrcp/device.h +++ b/system/profile/avrcp/device.h @@ -65,6 +65,10 @@ class Device { std::unique_ptr<::bluetooth::PacketBuilder> message)> send_msg_cb, uint16_t ctrl_mtu, uint16_t browse_mtu); + + Device(const Device&) = delete; + Device& operator=(const Device&) = delete; + virtual ~Device() = default; /** @@ -339,7 +343,6 @@ class Device { std::set<uint8_t> active_labels_; int8_t volume_ = -1; - DISALLOW_COPY_AND_ASSIGN(Device); }; } // namespace avrcp diff --git a/system/service/a2dp_sink.h b/system/service/a2dp_sink.h index 7bf59026ac..7b6f3ce7e0 100644 --- a/system/service/a2dp_sink.h +++ b/system/service/a2dp_sink.h @@ -16,8 +16,6 @@ #pragma once -#include <base/macros.h> - #include <atomic> #include <mutex> #include <string> @@ -47,6 +45,9 @@ class A2dpSink : public BluetoothInstance, virtual ~Delegate() = default; }; + A2dpSink(const A2dpSink&) = delete; + A2dpSink& operator=(const A2dpSink&) = delete; + ~A2dpSink() override; void SetDelegate(Delegate* delegate); @@ -84,21 +85,19 @@ class A2dpSink : public BluetoothInstance, std::mutex mutex_; std::mutex delegate_mutex_; Delegate* delegate_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(A2dpSink); }; class A2dpSinkFactory : public BluetoothInstanceFactory { public: A2dpSinkFactory(); + A2dpSinkFactory(const A2dpSinkFactory&) = delete; + A2dpSinkFactory& operator=(const A2dpSinkFactory&) = delete; + ~A2dpSinkFactory() override; // BluetoothInstanceFactory override: bool RegisterInstance(const Uuid& uuid, const RegisterCallback& callback) override; - - private: - DISALLOW_COPY_AND_ASSIGN(A2dpSinkFactory); }; } // namespace bluetooth diff --git a/system/service/a2dp_source.h b/system/service/a2dp_source.h index 801393f4d1..5b1b554606 100644 --- a/system/service/a2dp_source.h +++ b/system/service/a2dp_source.h @@ -16,8 +16,6 @@ #pragma once -#include <base/macros.h> - #include <atomic> #include <mutex> #include <string> @@ -50,6 +48,9 @@ class A2dpSource : public BluetoothInstance, virtual ~Delegate() = default; }; + A2dpSource(const A2dpSource&) = delete; + A2dpSource& operator=(const A2dpSource&) = delete; + ~A2dpSource() override; void SetDelegate(Delegate* delegate); @@ -99,21 +100,19 @@ class A2dpSource : public BluetoothInstance, // delegate function which attempts to take 'clock'. std::mutex delegate_mutex_; Delegate* delegate_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(A2dpSource); }; class A2dpSourceFactory : public BluetoothInstanceFactory { public: A2dpSourceFactory(); + A2dpSourceFactory(const A2dpSourceFactory&) = delete; + A2dpSourceFactory& operator=(const A2dpSourceFactory&) = delete; + ~A2dpSourceFactory() override; // BluetoothInstanceFactory override: bool RegisterInstance(const Uuid& uuid, const RegisterCallback& callback) override; - - private: - DISALLOW_COPY_AND_ASSIGN(A2dpSourceFactory); }; } // namespace bluetooth diff --git a/system/service/adapter.cc b/system/service/adapter.cc index 9c0468899a..19e7400a62 100644 --- a/system/service/adapter.cc +++ b/system/service/adapter.cc @@ -215,6 +215,9 @@ class AdapterImpl : public Adapter, public hal::BluetoothInterface::Observer { hal::BluetoothInterface::Get()->GetHALInterface()->get_adapter_properties(); } + AdapterImpl(const AdapterImpl&) = delete; + AdapterImpl& operator=(const AdapterImpl&) = delete; + ~AdapterImpl() override { hal::BluetoothInterface::Get()->RemoveObserver(this); } @@ -800,8 +803,6 @@ class AdapterImpl : public Adapter, public hal::BluetoothInterface::Observer { // Factory used to create per-app GattServer instances. std::unique_ptr<GattServerFactory> gatt_server_factory_; - - DISALLOW_COPY_AND_ASSIGN(AdapterImpl); }; // static diff --git a/system/service/adapter.h b/system/service/adapter.h index a4e517c2cc..e3fa306cf1 100644 --- a/system/service/adapter.h +++ b/system/service/adapter.h @@ -20,8 +20,6 @@ #include <string> #include <vector> -#include <base/macros.h> - #include "service/common/bluetooth/adapter_state.h" #include "service/common/bluetooth/remote_device_props.h" @@ -102,6 +100,9 @@ class Adapter { // in tests; use MockAdapter instead. static std::unique_ptr<Adapter> Create(); + Adapter(const Adapter&) = delete; + Adapter& operator=(const Adapter&) = delete; + virtual ~Adapter() = default; // Add or remove an observer. @@ -221,9 +222,6 @@ class Adapter { protected: Adapter() = default; - - private: - DISALLOW_COPY_AND_ASSIGN(Adapter); }; } // namespace bluetooth diff --git a/system/service/avrcp_control.h b/system/service/avrcp_control.h index eef36f8927..47950e335d 100644 --- a/system/service/avrcp_control.h +++ b/system/service/avrcp_control.h @@ -19,7 +19,6 @@ #include <atomic> #include <mutex> -#include "base/macros.h" #include "bluetooth/uuid.h" #include "service/bluetooth_instance.h" #include "service/common/bluetooth/avrcp_media_attr.h" @@ -50,6 +49,9 @@ class AvrcpControl : public BluetoothInstance, virtual ~Delegate() = default; }; + AvrcpControl(const AvrcpControl&) = delete; + AvrcpControl& operator=(const AvrcpControl&) = delete; + // The destructor automatically unregisters this instance from the stack. ~AvrcpControl() override; @@ -106,8 +108,6 @@ class AvrcpControl : public BluetoothInstance, // Raw handle to the Delegate, which must outlive this AvrcpControl instance. std::mutex delegate_mutex_; Delegate* delegate_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(AvrcpControl); }; // AvrcpControlFactory is used to register and obtain a per-application @@ -121,6 +121,9 @@ class AvrcpControlFactory // Don't construct/destruct directly except in tests. Instead, obtain a handle // from an Adapter instance. AvrcpControlFactory(); + AvrcpControlFactory(const AvrcpControlFactory&) = delete; + AvrcpControlFactory& operator=(const AvrcpControlFactory&) = delete; + ~AvrcpControlFactory() override; // BluetoothInstanceFactory override: @@ -129,7 +132,6 @@ class AvrcpControlFactory private: std::atomic<int> next_control_id_{0}; - DISALLOW_COPY_AND_ASSIGN(AvrcpControlFactory); }; } // namespace bluetooth diff --git a/system/service/avrcp_target.cc b/system/service/avrcp_target.cc index f5d21b72a5..9a39b412f4 100644 --- a/system/service/avrcp_target.cc +++ b/system/service/avrcp_target.cc @@ -23,7 +23,6 @@ #include "array_utils.h" #include "base/logging.h" -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "service/logging_helpers.h" #include "stack/include/avrc_defs.h" diff --git a/system/service/avrcp_target.h b/system/service/avrcp_target.h index e0ee57bb5a..76c5be0db8 100644 --- a/system/service/avrcp_target.h +++ b/system/service/avrcp_target.h @@ -20,7 +20,6 @@ #include <string> #include <vector> -#include "base/macros.h" #include "service/bluetooth_instance.h" #include "service/common/bluetooth/avrcp_int_value.h" #include "service/common/bluetooth/avrcp_register_notification_response.h" @@ -68,6 +67,9 @@ class AvrcpTarget : public BluetoothInstance, virtual ~Delegate() = default; }; + AvrcpTarget(const AvrcpTarget&) = delete; + AvrcpTarget& operator=(const AvrcpTarget&) = delete; + // The destructor automatically unregisters this instance from the stack. ~AvrcpTarget() override; @@ -150,8 +152,6 @@ class AvrcpTarget : public BluetoothInstance, // Raw handle to the Delegate, which must outlive this AvrcpTarget instance. std::mutex delegate_mutex_; Delegate* delegate_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(AvrcpTarget); }; // AvrcpTargetFactory is used to register and obtain a per-application @@ -165,14 +165,14 @@ class AvrcpTargetFactory // Don't construct/destruct directly except in tests. Instead, obtain a handle // from an Adapter instance. AvrcpTargetFactory(); + AvrcpTargetFactory(const AvrcpTargetFactory&) = delete; + AvrcpTargetFactory& operator=(const AvrcpTargetFactory&) = delete; + ~AvrcpTargetFactory() override; // BluetoothInstanceFactory override: bool RegisterInstance(const Uuid& uuid, const RegisterCallback& callback) override; - - private: - DISALLOW_COPY_AND_ASSIGN(AvrcpTargetFactory); }; } // namespace bluetooth diff --git a/system/service/bluetooth_instance.h b/system/service/bluetooth_instance.h index d0146c585a..5728d5e02b 100644 --- a/system/service/bluetooth_instance.h +++ b/system/service/bluetooth_instance.h @@ -19,7 +19,6 @@ #include <functional> #include <memory> -#include <base/macros.h> #include <bluetooth/uuid.h> #include "service/common/bluetooth/low_energy_constants.h" @@ -31,6 +30,9 @@ namespace bluetooth { // stack-assigned integer "instance_id" ID associated with it. class BluetoothInstance { public: + BluetoothInstance(const BluetoothInstance&) = delete; + BluetoothInstance& operator=(const BluetoothInstance&) = delete; + virtual ~BluetoothInstance() = default; // Returns the app-specific unique ID used while registering this instance. @@ -43,9 +45,6 @@ class BluetoothInstance { // Constructor shouldn't be called directly as instances are meant to be // obtained from the factory. BluetoothInstance() = default; - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothInstance); }; // A BluetoothInstanceFactory provides a common interface for factory @@ -54,6 +53,9 @@ class BluetoothInstance { class BluetoothInstanceFactory { public: BluetoothInstanceFactory() = default; + BluetoothInstanceFactory(const BluetoothInstanceFactory&) = delete; + BluetoothInstanceFactory& operator=(const BluetoothInstanceFactory&) = delete; + virtual ~BluetoothInstanceFactory() = default; // Callback invoked as a result of a call to RegisterInstance. @@ -67,9 +69,6 @@ class BluetoothInstanceFactory { // the case of an error, the pointer will contain nullptr. virtual bool RegisterInstance(const Uuid& app_uuid, const RegisterCallback& callback) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothInstanceFactory); }; } // namespace bluetooth diff --git a/system/service/bluetooth_interface.cc b/system/service/bluetooth_interface.cc index aafa04fa3f..1c178bdc00 100644 --- a/system/service/bluetooth_interface.cc +++ b/system/service/bluetooth_interface.cc @@ -239,7 +239,7 @@ static int set_adapter_property(const bt_property_t* property) { switch (property->type) { case BT_PROPERTY_BDNAME: case BT_PROPERTY_ADAPTER_SCAN_MODE: - case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT: + case BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT: case BT_PROPERTY_CLASS_OF_DEVICE: case BT_PROPERTY_LOCAL_IO_CAPS: case BT_PROPERTY_LOCAL_IO_CAPS_BLE: diff --git a/system/service/client/main.cc b/system/service/client/main.cc index b4ab06e382..b08136997a 100644 --- a/system/service/client/main.cc +++ b/system/service/client/main.cc @@ -20,7 +20,6 @@ #include <base/at_exit.h> #include <base/command_line.h> #include <base/logging.h> -#include <base/macros.h> #include <base/strings/string_number_conversions.h> #include <base/strings/string_split.h> #include <base/strings/string_util.h> @@ -147,6 +146,8 @@ inline void EndAsyncOut() { class CLIBluetoothCallback : public android::bluetooth::BnBluetoothCallback { public: CLIBluetoothCallback() = default; + CLIBluetoothCallback(const CLIBluetoothCallback&) = delete; + CLIBluetoothCallback& operator=(const CLIBluetoothCallback&) = delete; ~CLIBluetoothCallback() override = default; // IBluetoothCallback overrides: @@ -216,15 +217,15 @@ class CLIBluetoothCallback : public android::bluetooth::BnBluetoothCallback { // no-op return Status::ok(); } - - private: - DISALLOW_COPY_AND_ASSIGN(CLIBluetoothCallback); }; class CLIBluetoothLowEnergyCallback : public android::bluetooth::BnBluetoothLowEnergyCallback { public: CLIBluetoothLowEnergyCallback() = default; + CLIBluetoothLowEnergyCallback(const CLIBluetoothLowEnergyCallback&) = delete; + CLIBluetoothLowEnergyCallback& operator=( + const CLIBluetoothLowEnergyCallback&) = delete; ~CLIBluetoothLowEnergyCallback() override = default; // IBluetoothLowEnergyCallback overrides: @@ -262,15 +263,16 @@ class CLIBluetoothLowEnergyCallback EndAsyncOut(); return Status::ok(); } - - private: - DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLowEnergyCallback); }; class CLIBluetoothLeAdvertiserCallback : public android::bluetooth::BnBluetoothLeAdvertiserCallback { public: CLIBluetoothLeAdvertiserCallback() = default; + CLIBluetoothLeAdvertiserCallback(const CLIBluetoothLeAdvertiserCallback&) = + delete; + CLIBluetoothLeAdvertiserCallback& operator=( + const CLIBluetoothLeAdvertiserCallback&) = delete; ~CLIBluetoothLeAdvertiserCallback() override = default; // IBluetoothLowEnergyCallback overrides: @@ -299,15 +301,15 @@ class CLIBluetoothLeAdvertiserCallback EndAsyncOut(); return Status::ok(); } - - private: - DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLeAdvertiserCallback); }; class CLIBluetoothLeScannerCallback : public android::bluetooth::BnBluetoothLeScannerCallback { public: CLIBluetoothLeScannerCallback() = default; + CLIBluetoothLeScannerCallback(const CLIBluetoothLeScannerCallback&) = delete; + CLIBluetoothLeScannerCallback& operator=( + const CLIBluetoothLeScannerCallback&) = delete; ~CLIBluetoothLeScannerCallback() override = default; // IBluetoothLowEnergyCallback overrides: @@ -341,15 +343,14 @@ class CLIBluetoothLeScannerCallback EndAsyncOut(); return Status::ok(); } - - private: - DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLeScannerCallback); }; class CLIGattClientCallback : public android::bluetooth::BnBluetoothGattClientCallback { public: CLIGattClientCallback() = default; + CLIGattClientCallback(const CLIGattClientCallback&) = delete; + CLIGattClientCallback& operator=(const CLIGattClientCallback&) = delete; ~CLIGattClientCallback() override = default; // IBluetoothGattClientCallback overrides: @@ -367,9 +368,6 @@ class CLIGattClientCallback gatt_registering = false; return Status::ok(); } - - private: - DISALLOW_COPY_AND_ASSIGN(CLIGattClientCallback); }; void PrintCommandStatus(bool status) { PrintOpStatus("Command", status); } @@ -1051,6 +1049,8 @@ bool ExecuteCommand(const sp<IBluetooth>& bt_iface, std::string& command) { class BluetoothDeathRecipient : public android::IBinder::DeathRecipient { public: BluetoothDeathRecipient() = default; + BluetoothDeathRecipient(const BluetoothDeathRecipient&) = delete; + BluetoothDeathRecipient& operator=(const BluetoothDeathRecipient&) = delete; ~BluetoothDeathRecipient() override = default; // android::IBinder::DeathRecipient override: @@ -1063,9 +1063,6 @@ class BluetoothDeathRecipient : public android::IBinder::DeathRecipient { android::IPCThreadState::self()->stopProcess(); should_exit = true; } - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothDeathRecipient); }; int main(int argc, char* argv[]) { diff --git a/system/service/common/bluetooth/advertise_data.h b/system/service/common/bluetooth/advertise_data.h index bae83ee334..796f7dcc15 100644 --- a/system/service/common/bluetooth/advertise_data.h +++ b/system/service/common/bluetooth/advertise_data.h @@ -20,8 +20,6 @@ #include <vector> -#include <base/macros.h> - namespace bluetooth { // Represents a data packet for Bluetooth Low Energy advertisements. This is the diff --git a/system/service/common/bluetooth/advertise_settings.h b/system/service/common/bluetooth/advertise_settings.h index 4aff4c92dd..e4aee5377a 100644 --- a/system/service/common/bluetooth/advertise_settings.h +++ b/system/service/common/bluetooth/advertise_settings.h @@ -16,7 +16,6 @@ #pragma once -#include <base/macros.h> #include <base/time/time.h> namespace bluetooth { diff --git a/system/service/common/bluetooth/util/atomic_string.h b/system/service/common/bluetooth/util/atomic_string.h index 46d4588ed2..f5ed1c3ba4 100644 --- a/system/service/common/bluetooth/util/atomic_string.h +++ b/system/service/common/bluetooth/util/atomic_string.h @@ -19,14 +19,16 @@ #include <mutex> #include <string> -#include <base/macros.h> - namespace util { // A simple atomic container class for std::string. class AtomicString final { public: explicit AtomicString(const std::string& str); + + AtomicString(const AtomicString&) = delete; + AtomicString& operator=(const AtomicString&) = delete; + ~AtomicString() = default; std::string Get() const; @@ -35,8 +37,6 @@ class AtomicString final { private: std::mutex lock_; std::string str_; - - DISALLOW_COPY_AND_ASSIGN(AtomicString); }; } // namespace util diff --git a/system/service/daemon.cc b/system/service/daemon.cc index 4cd384285b..11bfae1722 100644 --- a/system/service/daemon.cc +++ b/system/service/daemon.cc @@ -42,6 +42,9 @@ class DaemonImpl : public Daemon, public ipc::IPCManager::Delegate { public: DaemonImpl() : initialized_(false) {} + DaemonImpl(const DaemonImpl&) = delete; + DaemonImpl& operator=(const DaemonImpl&) = delete; + ~DaemonImpl() override { if (!initialized_) return; @@ -161,8 +164,6 @@ class DaemonImpl : public Daemon, public ipc::IPCManager::Delegate { std::unique_ptr<Settings> settings_; std::unique_ptr<Adapter> adapter_; std::unique_ptr<ipc::IPCManager> ipc_manager_; - - DISALLOW_COPY_AND_ASSIGN(DaemonImpl); }; } // namespace diff --git a/system/service/daemon.h b/system/service/daemon.h index 06afe91008..a1f26a07e2 100644 --- a/system/service/daemon.h +++ b/system/service/daemon.h @@ -16,7 +16,6 @@ #pragma once -#include <base/macros.h> #include "abstract_message_loop.h" namespace ipc { @@ -62,13 +61,14 @@ class Daemon { protected: Daemon() = default; + Daemon(const Daemon&) = delete; + Daemon& operator=(const Daemon&) = delete; + virtual ~Daemon() = default; private: // Internal instance helper called by Initialize(). virtual bool Init() = 0; - - DISALLOW_COPY_AND_ASSIGN(Daemon); }; } // namespace bluetooth diff --git a/system/service/example/heart_rate/heart_rate_server.cc b/system/service/example/heart_rate/heart_rate_server.cc index 170042a70f..9777c203f8 100644 --- a/system/service/example/heart_rate/heart_rate_server.cc +++ b/system/service/example/heart_rate/heart_rate_server.cc @@ -41,6 +41,11 @@ class CLIBluetoothLeAdvertiserCallback android::sp<android::bluetooth::IBluetooth> bt) : bt_(bt) {} + CLIBluetoothLeAdvertiserCallback(const CLIBluetoothLeAdvertiserCallback&) = + delete; + CLIBluetoothLeAdvertiserCallback& operator=( + const CLIBluetoothLeAdvertiserCallback&) = delete; + // IBluetoothLeAdvertiserCallback overrides: Status OnAdvertiserRegistered(int status, int advertiser_id) { if (status != bluetooth::BLE_STATUS_SUCCESS) { @@ -90,7 +95,6 @@ class CLIBluetoothLeAdvertiserCallback private: android::sp<android::bluetooth::IBluetooth> bt_; - DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLeAdvertiserCallback); }; HeartRateServer::HeartRateServer( diff --git a/system/service/example/heart_rate/heart_rate_server.h b/system/service/example/heart_rate/heart_rate_server.h index e78c58aecf..1b716fd193 100644 --- a/system/service/example/heart_rate/heart_rate_server.h +++ b/system/service/example/heart_rate/heart_rate_server.h @@ -19,7 +19,6 @@ #include <mutex> #include <unordered_map> -#include <base/macros.h> #include <base/memory/ref_counted.h> #include <base/memory/weak_ptr.h> #if BASE_VER < 930627 @@ -44,6 +43,9 @@ class HeartRateServer HeartRateServer(android::sp<android::bluetooth::IBluetooth> bluetooth, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, bool advertise); + HeartRateServer(const HeartRateServer&) = delete; + HeartRateServer& operator=(const HeartRateServer&) = delete; + ~HeartRateServer() override; // Set up the server and register the GATT services with the stack. This @@ -141,8 +143,6 @@ class HeartRateServer // Note: This should remain the last member so that it'll be destroyed and // invalidate its weak pointers before any other members are destroyed. base::WeakPtrFactory<HeartRateServer> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(HeartRateServer); }; } // namespace heart_rate diff --git a/system/service/gatt_client.h b/system/service/gatt_client.h index 5a0322d2da..4ed1143e4e 100644 --- a/system/service/gatt_client.h +++ b/system/service/gatt_client.h @@ -19,7 +19,6 @@ #include <mutex> #include <unordered_map> -#include <base/macros.h> #include <bluetooth/uuid.h> #include "service/bluetooth_instance.h" @@ -32,6 +31,9 @@ namespace bluetooth { // obtained through the factory. class GattClient : public BluetoothInstance { public: + GattClient(const GattClient&) = delete; + GattClient& operator=(const GattClient&) = delete; + ~GattClient() override; // BluetoothClientInstace overrides: @@ -48,8 +50,6 @@ class GattClient : public BluetoothInstance { // See getters above for documentation. Uuid app_identifier_; int client_id_; - - DISALLOW_COPY_AND_ASSIGN(GattClient); }; // GattClientFactory is used to register and obtain a per-application GattClient @@ -61,6 +61,9 @@ class GattClientFactory : public BluetoothInstanceFactory, // Don't construct/destruct directly except in tests. Instead, obtain a handle // from an Adapter instance. GattClientFactory(); + GattClientFactory(const GattClientFactory&) = delete; + GattClientFactory& operator=(const GattClientFactory&) = delete; + ~GattClientFactory() override; // BluetoothInstanceFactory override: @@ -76,8 +79,6 @@ class GattClientFactory : public BluetoothInstanceFactory, // Map of pending calls to register. std::mutex pending_calls_lock_; std::unordered_map<Uuid, RegisterCallback> pending_calls_; - - DISALLOW_COPY_AND_ASSIGN(GattClientFactory); }; } // namespace bluetooth diff --git a/system/service/gatt_server.h b/system/service/gatt_server.h index c46e8d00c4..7d670aed91 100644 --- a/system/service/gatt_server.h +++ b/system/service/gatt_server.h @@ -16,7 +16,6 @@ #pragma once -#include <base/macros.h> #include <bluetooth/uuid.h> #include <deque> @@ -45,6 +44,9 @@ class GattServer : public BluetoothInstance, class Delegate { public: Delegate() = default; + Delegate(const Delegate&) = delete; + Delegate& operator=(const Delegate&) = delete; + virtual ~Delegate() = default; // Called when there is an incoming read request for the characteristic with @@ -104,12 +106,12 @@ class GattServer : public BluetoothInstance, virtual void OnConnectionStateChanged(GattServer* gatt_server, const std::string& device_addres, bool connected) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(Delegate); }; // The desctructor automatically unregisters this instance from the stack. + GattServer(const GattServer&) = delete; + GattServer& operator=(const GattServer&) = delete; + ~GattServer() override; // Assigns a delegate to this instance. |delegate| must out-live this @@ -262,8 +264,6 @@ class GattServer : public BluetoothInstance, // Raw handle to the Delegate, which must outlive this GattServer instance. Delegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(GattServer); }; // GattServerFactory is used to register and obtain a per-application GattServer @@ -275,6 +275,9 @@ class GattServerFactory : public BluetoothInstanceFactory, // Don't construct/destruct directly except in tests. Instead, obtain a handle // from an Adapter instance. GattServerFactory(); + GattServerFactory(const GattServerFactory&) = delete; + GattServerFactory& operator=(const GattServerFactory&) = delete; + ~GattServerFactory() override; // BluetoothInstanceFactory override: @@ -290,8 +293,6 @@ class GattServerFactory : public BluetoothInstanceFactory, // Map of pending calls to register. std::mutex pending_calls_lock_; std::unordered_map<Uuid, RegisterCallback> pending_calls_; - - DISALLOW_COPY_AND_ASSIGN(GattServerFactory); }; } // namespace bluetooth diff --git a/system/service/hal/bluetooth_av_interface.cc b/system/service/hal/bluetooth_av_interface.cc index e4a759dd9f..beabd968f2 100644 --- a/system/service/hal/bluetooth_av_interface.cc +++ b/system/service/hal/bluetooth_av_interface.cc @@ -147,6 +147,9 @@ btav_sink_callbacks_t av_sink_callbacks = { class BluetoothAvInterfaceImpl : public BluetoothAvInterface { public: BluetoothAvInterfaceImpl() = default; + BluetoothAvInterfaceImpl(const BluetoothAvInterfaceImpl&) = delete; + BluetoothAvInterfaceImpl& operator=(const BluetoothAvInterfaceImpl&) = delete; + ~BluetoothAvInterfaceImpl() override { A2dpSinkDisable(); A2dpSourceDisable(); @@ -274,8 +277,6 @@ class BluetoothAvInterfaceImpl : public BluetoothAvInterface { bool source_enabled_ = false; bool sink_enabled_ = false; - - DISALLOW_COPY_AND_ASSIGN(BluetoothAvInterfaceImpl); }; namespace { diff --git a/system/service/hal/bluetooth_av_interface.h b/system/service/hal/bluetooth_av_interface.h index 2b444b2b67..4f0b4773e8 100644 --- a/system/service/hal/bluetooth_av_interface.h +++ b/system/service/hal/bluetooth_av_interface.h @@ -16,7 +16,6 @@ #pragma once -#include <base/macros.h> #include <hardware/bluetooth.h> #include <hardware/bt_av.h> @@ -90,10 +89,10 @@ class BluetoothAvInterface { protected: BluetoothAvInterface() = default; - virtual ~BluetoothAvInterface() = default; + BluetoothAvInterface(const BluetoothAvInterface&) = delete; + BluetoothAvInterface& operator=(const BluetoothAvInterface&) = delete; - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothAvInterface); + virtual ~BluetoothAvInterface() = default; }; } // namespace hal diff --git a/system/service/hal/bluetooth_avrcp_interface.cc b/system/service/hal/bluetooth_avrcp_interface.cc index 42ac0a6372..cbb0317041 100644 --- a/system/service/hal/bluetooth_avrcp_interface.cc +++ b/system/service/hal/bluetooth_avrcp_interface.cc @@ -490,6 +490,10 @@ class BluetoothAvrcpInterfaceImpl : public BluetoothAvrcpInterface { public: BluetoothAvrcpInterfaceImpl() : control_iface_(nullptr) {} + BluetoothAvrcpInterfaceImpl(const BluetoothAvrcpInterfaceImpl&) = delete; + BluetoothAvrcpInterfaceImpl& operator=(const BluetoothAvrcpInterfaceImpl&) = + delete; + ~BluetoothAvrcpInterfaceImpl() override { if (control_iface_) control_iface_->cleanup(); } @@ -614,8 +618,6 @@ class BluetoothAvrcpInterfaceImpl : public BluetoothAvrcpInterface { bool control_enabled_ = false; bool target_enabled_ = false; - - DISALLOW_COPY_AND_ASSIGN(BluetoothAvrcpInterfaceImpl); }; namespace { diff --git a/system/service/hal/bluetooth_avrcp_interface.h b/system/service/hal/bluetooth_avrcp_interface.h index fc67c3c41f..4646880169 100644 --- a/system/service/hal/bluetooth_avrcp_interface.h +++ b/system/service/hal/bluetooth_avrcp_interface.h @@ -16,7 +16,6 @@ #pragma once -#include <base/macros.h> #include <hardware/bluetooth.h> #include <hardware/bt_rc.h> @@ -130,6 +129,9 @@ class BluetoothAvrcpInterface { uint8_t status); }; + BluetoothAvrcpInterface(const BluetoothAvrcpInterface&) = delete; + BluetoothAvrcpInterface& operator=(const BluetoothAvrcpInterface&) = delete; + // Initialize and clean up the BluetoothInterface singleton. Returns false if // the underlying HAL interface failed to initialize, and true on success. static bool Initialize(); @@ -172,9 +174,6 @@ class BluetoothAvrcpInterface { protected: BluetoothAvrcpInterface() = default; virtual ~BluetoothAvrcpInterface() = default; - - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothAvrcpInterface); }; } // namespace hal diff --git a/system/service/hal/bluetooth_gatt_interface.cc b/system/service/hal/bluetooth_gatt_interface.cc index c9d165b0c3..76cf5c9361 100644 --- a/system/service/hal/bluetooth_gatt_interface.cc +++ b/system/service/hal/bluetooth_gatt_interface.cc @@ -443,6 +443,10 @@ class BluetoothGattInterfaceImpl : public BluetoothGattInterface { public: BluetoothGattInterfaceImpl() : hal_iface_(nullptr) {} + BluetoothGattInterfaceImpl(const BluetoothGattInterfaceImpl&) = delete; + BluetoothGattInterfaceImpl& operator=(const BluetoothGattInterfaceImpl&) = + delete; + ~BluetoothGattInterfaceImpl() override { if (hal_iface_) hal_iface_->cleanup(); } @@ -536,8 +540,6 @@ class BluetoothGattInterfaceImpl : public BluetoothGattInterface { // The HAL handle obtained from the shared library. We hold a weak reference // to this since the actual data resides in the shared Bluetooth library. const btgatt_interface_t* hal_iface_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothGattInterfaceImpl); }; namespace { diff --git a/system/service/hal/bluetooth_gatt_interface.h b/system/service/hal/bluetooth_gatt_interface.h index 471dfc4d03..ad3f851554 100644 --- a/system/service/hal/bluetooth_gatt_interface.h +++ b/system/service/hal/bluetooth_gatt_interface.h @@ -16,7 +16,6 @@ #pragma once -#include <base/macros.h> #include <hardware/bluetooth.h> #include <hardware/bt_gatt.h> @@ -254,14 +253,15 @@ class BluetoothGattInterface { protected: BluetoothGattInterface() = default; + BluetoothGattInterface(const BluetoothGattInterface&) = delete; + BluetoothGattInterface& operator=(const BluetoothGattInterface&) = delete; + virtual ~BluetoothGattInterface() = default; private: // Used to keep a reference count for the different BLE scan clients. std::mutex scan_clients_lock_; std::unordered_set<int> scan_client_set_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothGattInterface); }; } // namespace hal diff --git a/system/service/hal/bluetooth_interface.cc b/system/service/hal/bluetooth_interface.cc index c47a3edf35..3acb5725d0 100644 --- a/system/service/hal/bluetooth_interface.cc +++ b/system/service/hal/bluetooth_interface.cc @@ -217,14 +217,13 @@ void LinkQualityReportCallback(uint64_t timestamp, int report_id, int rssi, packets_not_receive_count, negative_acknowledgement_count)); } -void SwitchBufferSizeCallback(RawAddress* remote_addr, - bool is_low_latency_buffer_size) { +void SwitchBufferSizeCallback(bool is_low_latency_buffer_size) { shared_lock<shared_mutex_impl> lock(g_instance_lock); VERIFY_INTERFACE_OR_RETURN(); LOG(WARNING) << __func__ << " - is_low_latency_buffer_size: " << is_low_latency_buffer_size; FOR_EACH_BLUETOOTH_OBSERVER( - SwitchBufferSizeCallback(remote_addr, is_low_latency_buffer_size)); + SwitchBufferSizeCallback(is_low_latency_buffer_size)); } // The HAL Bluetooth DM callbacks. @@ -246,7 +245,7 @@ bt_callbacks_t bt_callbacks = { nullptr, /* energy_info_cb */ LinkQualityReportCallback, nullptr /* generate_local_oob_data_cb */, - SwitchBufferSizeCallback + SwitchBufferSizeCallback, }; bt_os_callouts_t bt_os_callouts = {sizeof(bt_os_callouts_t), @@ -297,6 +296,9 @@ class BluetoothInterfaceImpl : public BluetoothInterface { public: BluetoothInterfaceImpl() : hal_iface_(nullptr) {} + BluetoothInterfaceImpl(const BluetoothInterfaceImpl&) = delete; + BluetoothInterfaceImpl& operator=(const BluetoothInterfaceImpl&) = delete; + ~BluetoothInterfaceImpl() override { if (hal_iface_) hal_iface_->cleanup(); } @@ -358,8 +360,6 @@ class BluetoothInterfaceImpl : public BluetoothInterface { // The HAL handle obtained from the shared library. We hold a weak reference // to this since the actual data resides in the shared Bluetooth library. const bt_interface_t* hal_iface_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothInterfaceImpl); }; namespace { @@ -437,7 +437,7 @@ void BluetoothInterface::Observer::LinkQualityReportCallback( } void BluetoothInterface::Observer::SwitchBufferSizeCallback( - RawAddress* /* remote_addr */, bool /* is_low_latency_buffer_size */) { + bool /* is_low_latency_buffer_size */) { // Do nothing. } diff --git a/system/service/hal/bluetooth_interface.h b/system/service/hal/bluetooth_interface.h index 50c35f656d..da68c9ce09 100644 --- a/system/service/hal/bluetooth_interface.h +++ b/system/service/hal/bluetooth_interface.h @@ -16,7 +16,6 @@ #pragma once -#include <base/macros.h> #include <hardware/bluetooth.h> #include "types/raw_address.h" @@ -83,8 +82,7 @@ class BluetoothInterface { int retransmission_count, int packets_not_receive_count, int negative_acknowledgement_count); - virtual void SwitchBufferSizeCallback(RawAddress* remote_addr, - bool is_low_latency_buffer_size); + virtual void SwitchBufferSizeCallback(bool is_low_latency_buffer_size); // TODO(armansito): Complete the list of callbacks. }; @@ -127,10 +125,10 @@ class BluetoothInterface { protected: BluetoothInterface() = default; - virtual ~BluetoothInterface() = default; + BluetoothInterface(const BluetoothInterface&) = delete; + BluetoothInterface& operator=(const BluetoothInterface&) = delete; - private: - DISALLOW_COPY_AND_ASSIGN(BluetoothInterface); + virtual ~BluetoothInterface() = default; }; } // namespace hal diff --git a/system/service/hal/fake_bluetooth_av_interface.h b/system/service/hal/fake_bluetooth_av_interface.h index c97c9a3180..e4a45ceeed 100644 --- a/system/service/hal/fake_bluetooth_av_interface.h +++ b/system/service/hal/fake_bluetooth_av_interface.h @@ -16,7 +16,6 @@ #pragma once -#include <base/macros.h> #include <base/observer_list.h> #include "abstract_observer_list.h" @@ -56,6 +55,10 @@ class FakeBluetoothAvInterface : public BluetoothAvInterface { std::shared_ptr<TestA2dpSourceHandler> a2dp_source_handler); FakeBluetoothAvInterface( std::shared_ptr<TestA2dpSinkHandler> a2dp_sink_handler); + + FakeBluetoothAvInterface(const FakeBluetoothAvInterface&) = delete; + FakeBluetoothAvInterface& operator=(const FakeBluetoothAvInterface&) = delete; + ~FakeBluetoothAvInterface(); // The methods below can be used to notify observers with certain events and @@ -92,8 +95,6 @@ class FakeBluetoothAvInterface : public BluetoothAvInterface { private: btbase::AbstractObserverList<A2dpSourceObserver> a2dp_source_observers_; btbase::AbstractObserverList<A2dpSinkObserver> a2dp_sink_observers_; - - DISALLOW_COPY_AND_ASSIGN(FakeBluetoothAvInterface); }; } // namespace hal diff --git a/system/service/hal/fake_bluetooth_gatt_interface.h b/system/service/hal/fake_bluetooth_gatt_interface.h index d6e917fb9b..eb3b9bf342 100644 --- a/system/service/hal/fake_bluetooth_gatt_interface.h +++ b/system/service/hal/fake_bluetooth_gatt_interface.h @@ -16,7 +16,6 @@ #pragma once -#include <base/macros.h> #include <base/observer_list.h> #include <vector> @@ -75,6 +74,11 @@ class FakeBluetoothGattInterface : public BluetoothGattInterface { std::shared_ptr<BleScannerInterface> scanner_handler, std::shared_ptr<TestClientHandler> client_handler, std::shared_ptr<TestServerHandler> server_handler); + + FakeBluetoothGattInterface(const FakeBluetoothGattInterface&) = delete; + FakeBluetoothGattInterface& operator=(const FakeBluetoothGattInterface&) = + delete; + ~FakeBluetoothGattInterface(); // The methods below can be used to notify observers with certain events and @@ -148,8 +152,6 @@ class FakeBluetoothGattInterface : public BluetoothGattInterface { std::shared_ptr<BleScannerInterface> scanner_handler_; std::shared_ptr<TestClientHandler> client_handler_; std::shared_ptr<TestServerHandler> server_handler_; - - DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattInterface); }; } // namespace hal diff --git a/system/service/hal/fake_bluetooth_interface.cc b/system/service/hal/fake_bluetooth_interface.cc index 729778d4cd..33209b494a 100644 --- a/system/service/hal/fake_bluetooth_interface.cc +++ b/system/service/hal/fake_bluetooth_interface.cc @@ -81,6 +81,7 @@ bt_interface_t fake_bt_iface = { nullptr, /* set_dynamic_audio_buffer_size */ nullptr, /* generate_local_oob_data */ nullptr, /* allow_low_latency_audio */ + nullptr, /* clear_event_filter */ }; } // namespace diff --git a/system/service/hal/fake_bluetooth_interface.h b/system/service/hal/fake_bluetooth_interface.h index 9ea99b50c4..08f189a737 100644 --- a/system/service/hal/fake_bluetooth_interface.h +++ b/system/service/hal/fake_bluetooth_interface.h @@ -14,7 +14,6 @@ // limitations under the License. // -#include <base/macros.h> #include <base/observer_list.h> #include "abstract_observer_list.h" @@ -44,6 +43,9 @@ class FakeBluetoothInterface : public BluetoothInterface { static Manager* GetManager(); FakeBluetoothInterface() = default; + FakeBluetoothInterface(const FakeBluetoothInterface&) = delete; + FakeBluetoothInterface& operator=(const FakeBluetoothInterface&) = delete; + ~FakeBluetoothInterface() override = default; // Notifies the observers that the adapter state changed to |state|. @@ -70,8 +72,6 @@ class FakeBluetoothInterface : public BluetoothInterface { private: btbase::AbstractObserverList<Observer> observers_; - - DISALLOW_COPY_AND_ASSIGN(FakeBluetoothInterface); }; } // namespace hal diff --git a/system/service/ipc/binder/bluetooth_a2dp_sink_binder_server.h b/system/service/ipc/binder/bluetooth_a2dp_sink_binder_server.h index e18af54788..f54733cfa0 100644 --- a/system/service/ipc/binder/bluetooth_a2dp_sink_binder_server.h +++ b/system/service/ipc/binder/bluetooth_a2dp_sink_binder_server.h @@ -19,8 +19,6 @@ #include <map> #include <string> -#include <base/macros.h> - #include <android/bluetooth/BnBluetoothA2dpSink.h> #include <android/bluetooth/IBluetoothA2dpSinkCallback.h> @@ -40,6 +38,10 @@ class BluetoothA2dpSinkBinderServer public bluetooth::A2dpSink::Delegate { public: explicit BluetoothA2dpSinkBinderServer(bluetooth::Adapter* adapter); + BluetoothA2dpSinkBinderServer(const BluetoothA2dpSinkBinderServer&) = delete; + BluetoothA2dpSinkBinderServer& operator=( + const BluetoothA2dpSinkBinderServer&) = delete; + ~BluetoothA2dpSinkBinderServer() override = default; // IBluetoothA2dpSink implementation: @@ -78,8 +80,6 @@ class BluetoothA2dpSinkBinderServer bluetooth::BluetoothInstance* instance) override; bluetooth::Adapter* adapter_; // weak - - DISALLOW_COPY_AND_ASSIGN(BluetoothA2dpSinkBinderServer); }; } // namespace binder diff --git a/system/service/ipc/binder/bluetooth_a2dp_source_binder_server.h b/system/service/ipc/binder/bluetooth_a2dp_source_binder_server.h index 160a38adc1..3800a962ec 100644 --- a/system/service/ipc/binder/bluetooth_a2dp_source_binder_server.h +++ b/system/service/ipc/binder/bluetooth_a2dp_source_binder_server.h @@ -20,8 +20,6 @@ #include <string> #include <vector> -#include <base/macros.h> - #include <android/bluetooth/BnBluetoothA2dpSource.h> #include <android/bluetooth/IBluetoothA2dpSourceCallback.h> @@ -41,6 +39,11 @@ class BluetoothA2dpSourceBinderServer public bluetooth::A2dpSource::Delegate { public: explicit BluetoothA2dpSourceBinderServer(bluetooth::Adapter* adapter); + BluetoothA2dpSourceBinderServer(const BluetoothA2dpSourceBinderServer&) = + delete; + BluetoothA2dpSourceBinderServer& operator=( + const BluetoothA2dpSourceBinderServer&) = delete; + ~BluetoothA2dpSourceBinderServer() override; bool HasInstance(); @@ -87,8 +90,6 @@ class BluetoothA2dpSourceBinderServer bluetooth::BluetoothInstance* instance) override; bluetooth::Adapter* const adapter_; // weak - - DISALLOW_COPY_AND_ASSIGN(BluetoothA2dpSourceBinderServer); }; } // namespace binder diff --git a/system/service/ipc/binder/bluetooth_avrcp_control_binder_server.h b/system/service/ipc/binder/bluetooth_avrcp_control_binder_server.h index 11cf1f3d3e..00b5921b8e 100644 --- a/system/service/ipc/binder/bluetooth_avrcp_control_binder_server.h +++ b/system/service/ipc/binder/bluetooth_avrcp_control_binder_server.h @@ -19,8 +19,6 @@ #include <map> #include <string> -#include "base/macros.h" - #include "android/bluetooth/BnBluetoothAvrcpControl.h" #include "android/bluetooth/IBluetoothAvrcpControlCallback.h" @@ -40,6 +38,11 @@ class BluetoothAvrcpControlBinderServer public bluetooth::AvrcpControl::Delegate { public: explicit BluetoothAvrcpControlBinderServer(bluetooth::Adapter* adapter); + BluetoothAvrcpControlBinderServer(const BluetoothAvrcpControlBinderServer&) = + delete; + BluetoothAvrcpControlBinderServer& operator=( + const BluetoothAvrcpControlBinderServer&) = delete; + ~BluetoothAvrcpControlBinderServer() override = default; // IBluetoothAvrcpControl implementation: @@ -81,8 +84,6 @@ class BluetoothAvrcpControlBinderServer std::shared_ptr<bluetooth::AvrcpControl> GetAvrcpControl(int id); bluetooth::Adapter* adapter_; // weak - - DISALLOW_COPY_AND_ASSIGN(BluetoothAvrcpControlBinderServer); }; } // namespace binder diff --git a/system/service/ipc/binder/bluetooth_avrcp_target_binder_server.h b/system/service/ipc/binder/bluetooth_avrcp_target_binder_server.h index 9d2bba03c3..aeab315978 100644 --- a/system/service/ipc/binder/bluetooth_avrcp_target_binder_server.h +++ b/system/service/ipc/binder/bluetooth_avrcp_target_binder_server.h @@ -20,8 +20,6 @@ #include <string> #include <vector> -#include "base/macros.h" - #include "android/bluetooth/BnBluetoothAvrcpTarget.h" #include "android/bluetooth/IBluetoothAvrcpTargetCallback.h" @@ -41,6 +39,11 @@ class BluetoothAvrcpTargetBinderServer public bluetooth::AvrcpTarget::Delegate { public: explicit BluetoothAvrcpTargetBinderServer(bluetooth::Adapter* adapter); + BluetoothAvrcpTargetBinderServer(const BluetoothAvrcpTargetBinderServer&) = + delete; + BluetoothAvrcpTargetBinderServer& operator=( + const BluetoothAvrcpTargetBinderServer&) = delete; + ~BluetoothAvrcpTargetBinderServer() override; bool HasInstance(); @@ -123,8 +126,6 @@ class BluetoothAvrcpTargetBinderServer std::shared_ptr<bluetooth::AvrcpTarget> GetAvrcpTarget(); bluetooth::Adapter* const adapter_; // weak - - DISALLOW_COPY_AND_ASSIGN(BluetoothAvrcpTargetBinderServer); }; } // namespace binder diff --git a/system/service/ipc/binder/bluetooth_binder_server.h b/system/service/ipc/binder/bluetooth_binder_server.h index 7131e8b430..a389d3f6af 100644 --- a/system/service/ipc/binder/bluetooth_binder_server.h +++ b/system/service/ipc/binder/bluetooth_binder_server.h @@ -19,7 +19,6 @@ #include <string> #include <vector> -#include <base/macros.h> #include <utils/String16.h> #include <utils/Vector.h> @@ -66,6 +65,10 @@ class BluetoothBinderServer : public BnBluetooth, public bluetooth::Adapter::Observer { public: explicit BluetoothBinderServer(bluetooth::Adapter* adapter); + + BluetoothBinderServer(const BluetoothBinderServer&) = delete; + BluetoothBinderServer& operator=(const BluetoothBinderServer&) = delete; + ~BluetoothBinderServer() override; // IBluetooth overrides: @@ -188,8 +191,6 @@ class BluetoothBinderServer : public BnBluetooth, // The IBluetoothAvrcpTarget interface handle. This is lazily initialized on // the first call to GetAvrcpTargetInterface(). android::sp<BluetoothAvrcpTargetBinderServer> avrcp_target_interface_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothBinderServer); }; } // namespace binder diff --git a/system/service/ipc/binder/bluetooth_gatt_client_binder_server.h b/system/service/ipc/binder/bluetooth_gatt_client_binder_server.h index 65b8b60e82..28fa325545 100644 --- a/system/service/ipc/binder/bluetooth_gatt_client_binder_server.h +++ b/system/service/ipc/binder/bluetooth_gatt_client_binder_server.h @@ -16,8 +16,6 @@ #pragma once -#include <base/macros.h> - #include <android/bluetooth/BnBluetoothGattClient.h> #include <android/bluetooth/IBluetoothGattClientCallback.h> @@ -41,6 +39,12 @@ class BluetoothGattClientBinderServer : public BnBluetoothGattClient, public InterfaceWithInstancesBase { public: explicit BluetoothGattClientBinderServer(bluetooth::Adapter* adapter); + + BluetoothGattClientBinderServer(const BluetoothGattClientBinderServer&) = + delete; + BluetoothGattClientBinderServer& operator=( + const BluetoothGattClientBinderServer&) = delete; + ~BluetoothGattClientBinderServer() override = default; // IBluetoothGattClient overrides: @@ -67,8 +71,6 @@ class BluetoothGattClientBinderServer : public BnBluetoothGattClient, bluetooth::BluetoothInstance* instance) override; bluetooth::Adapter* adapter_; // weak - - DISALLOW_COPY_AND_ASSIGN(BluetoothGattClientBinderServer); }; } // namespace binder diff --git a/system/service/ipc/binder/bluetooth_gatt_server_binder_server.h b/system/service/ipc/binder/bluetooth_gatt_server_binder_server.h index 925339af17..34fb7c5843 100644 --- a/system/service/ipc/binder/bluetooth_gatt_server_binder_server.h +++ b/system/service/ipc/binder/bluetooth_gatt_server_binder_server.h @@ -16,8 +16,6 @@ #pragma once -#include <base/macros.h> - #include <android/bluetooth/BnBluetoothGattServer.h> #include <android/bluetooth/IBluetoothGattServerCallback.h> @@ -42,6 +40,12 @@ class BluetoothGattServerBinderServer : public BnBluetoothGattServer, public bluetooth::GattServer::Delegate { public: explicit BluetoothGattServerBinderServer(bluetooth::Adapter* adapter); + + BluetoothGattServerBinderServer(const BluetoothGattServerBinderServer&) = + delete; + BluetoothGattServerBinderServer& operator=( + const BluetoothGattServerBinderServer&) = delete; + ~BluetoothGattServerBinderServer() override = default; // IBluetoothGattServer overrides: @@ -109,8 +113,6 @@ class BluetoothGattServerBinderServer : public BnBluetoothGattServer, bluetooth::BluetoothInstance* instance) override; bluetooth::Adapter* adapter_; // weak - - DISALLOW_COPY_AND_ASSIGN(BluetoothGattServerBinderServer); }; } // namespace binder diff --git a/system/service/ipc/binder/bluetooth_le_advertiser_binder_server.h b/system/service/ipc/binder/bluetooth_le_advertiser_binder_server.h index 6602f5afb9..a8fca24d42 100644 --- a/system/service/ipc/binder/bluetooth_le_advertiser_binder_server.h +++ b/system/service/ipc/binder/bluetooth_le_advertiser_binder_server.h @@ -18,8 +18,6 @@ #include <memory> -#include <base/macros.h> - #include <android/bluetooth/IBluetoothLeAdvertiserCallback.h> #include "android/bluetooth/BnBluetoothLeAdvertiser.h" @@ -45,6 +43,12 @@ class BluetoothLeAdvertiserBinderServer : public BnBluetoothLeAdvertiser, public InterfaceWithInstancesBase { public: explicit BluetoothLeAdvertiserBinderServer(bluetooth::Adapter* adapter); + + BluetoothLeAdvertiserBinderServer(const BluetoothLeAdvertiserBinderServer&) = + delete; + BluetoothLeAdvertiserBinderServer& operator=( + const BluetoothLeAdvertiserBinderServer&) = delete; + ~BluetoothLeAdvertiserBinderServer() override; // IBluetoothLowEnergy overrides: @@ -77,8 +81,6 @@ class BluetoothLeAdvertiserBinderServer : public BnBluetoothLeAdvertiser, bluetooth::BluetoothInstance* instance) override; bluetooth::Adapter* adapter_; // weak - - DISALLOW_COPY_AND_ASSIGN(BluetoothLeAdvertiserBinderServer); }; } // namespace binder diff --git a/system/service/ipc/binder/bluetooth_le_scanner_binder_server.h b/system/service/ipc/binder/bluetooth_le_scanner_binder_server.h index 0cc3ae94a6..3288a4cc93 100644 --- a/system/service/ipc/binder/bluetooth_le_scanner_binder_server.h +++ b/system/service/ipc/binder/bluetooth_le_scanner_binder_server.h @@ -18,8 +18,6 @@ #include <memory> -#include <base/macros.h> - #include <android/bluetooth/IBluetoothLeScannerCallback.h> #include "android/bluetooth/BnBluetoothLeScanner.h" @@ -47,6 +45,11 @@ class BluetoothLeScannerBinderServer public bluetooth::LowEnergyScanner::Delegate { public: explicit BluetoothLeScannerBinderServer(bluetooth::Adapter* adapter); + BluetoothLeScannerBinderServer(const BluetoothLeScannerBinderServer&) = + delete; + BluetoothLeScannerBinderServer& operator=( + const BluetoothLeScannerBinderServer&) = delete; + ~BluetoothLeScannerBinderServer() override; // IBluetoothLowEnergy overrides: @@ -79,8 +82,6 @@ class BluetoothLeScannerBinderServer bluetooth::BluetoothInstance* instance) override; bluetooth::Adapter* adapter_; // weak - - DISALLOW_COPY_AND_ASSIGN(BluetoothLeScannerBinderServer); }; } // namespace binder diff --git a/system/service/ipc/binder/bluetooth_low_energy_binder_server.h b/system/service/ipc/binder/bluetooth_low_energy_binder_server.h index 4508b3497f..0db2312fb8 100644 --- a/system/service/ipc/binder/bluetooth_low_energy_binder_server.h +++ b/system/service/ipc/binder/bluetooth_low_energy_binder_server.h @@ -18,8 +18,6 @@ #include <memory> -#include <base/macros.h> - #include <android/bluetooth/IBluetoothLowEnergyCallback.h> #include "android/bluetooth/BnBluetoothLowEnergy.h" @@ -47,6 +45,11 @@ class BluetoothLowEnergyBinderServer public bluetooth::LowEnergyClient::Delegate { public: explicit BluetoothLowEnergyBinderServer(bluetooth::Adapter* adapter); + BluetoothLowEnergyBinderServer(const BluetoothLowEnergyBinderServer&) = + delete; + BluetoothLowEnergyBinderServer& operator=( + const BluetoothLowEnergyBinderServer&) = delete; + ~BluetoothLowEnergyBinderServer() override; // IBluetoothLowEnergy overrides: @@ -83,8 +86,6 @@ class BluetoothLowEnergyBinderServer bluetooth::BluetoothInstance* instance) override; bluetooth::Adapter* adapter_; // weak - - DISALLOW_COPY_AND_ASSIGN(BluetoothLowEnergyBinderServer); }; } // namespace binder diff --git a/system/service/ipc/binder/interface_with_instances_base.h b/system/service/ipc/binder/interface_with_instances_base.h index 05f2817b1f..4501b00456 100644 --- a/system/service/ipc/binder/interface_with_instances_base.h +++ b/system/service/ipc/binder/interface_with_instances_base.h @@ -19,8 +19,6 @@ #include <memory> #include <unordered_map> -#include <base/macros.h> - #include "bluetooth/uuid.h" #include "service/bluetooth_instance.h" #include "service/ipc/binder/remote_callback_map.h" @@ -40,6 +38,10 @@ class InterfaceWithInstancesBase virtual public android::RefBase { public: InterfaceWithInstancesBase() = default; + InterfaceWithInstancesBase(const InterfaceWithInstancesBase&) = delete; + InterfaceWithInstancesBase& operator=(const InterfaceWithInstancesBase&) = + delete; + ~InterfaceWithInstancesBase() override = default; protected: @@ -99,8 +101,6 @@ class InterfaceWithInstancesBase RemoteCallbackMap<int, IInterface> id_to_cb_; std::unordered_map<int, std::shared_ptr<bluetooth::BluetoothInstance>> id_to_instance_; - - DISALLOW_COPY_AND_ASSIGN(InterfaceWithInstancesBase); }; } // namespace binder diff --git a/system/service/ipc/binder/ipc_handler_binder.h b/system/service/ipc/binder/ipc_handler_binder.h index 2edd323d87..e59aef4765 100644 --- a/system/service/ipc/binder/ipc_handler_binder.h +++ b/system/service/ipc/binder/ipc_handler_binder.h @@ -16,8 +16,6 @@ #pragma once -#include <base/macros.h> - #include "service/ipc/ipc_handler.h" #include "service/ipc/ipc_manager.h" @@ -27,6 +25,10 @@ namespace ipc { class IPCHandlerBinder : public IPCHandler { public: IPCHandlerBinder(bluetooth::Adapter* adapter, IPCManager::Delegate* delegate); + + IPCHandlerBinder(const IPCHandlerBinder&) = delete; + IPCHandlerBinder& operator=(const IPCHandlerBinder&) = delete; + ~IPCHandlerBinder() override; // IPCHandler overrides: @@ -38,8 +40,6 @@ class IPCHandlerBinder : public IPCHandler { // Notify the delegate that IPC has started. void NotifyStarted(); - - DISALLOW_COPY_AND_ASSIGN(IPCHandlerBinder); }; } // namespace ipc diff --git a/system/service/ipc/binder/remote_callback_list.h b/system/service/ipc/binder/remote_callback_list.h index e25e550593..f78bc60855 100644 --- a/system/service/ipc/binder/remote_callback_list.h +++ b/system/service/ipc/binder/remote_callback_list.h @@ -21,7 +21,6 @@ #include <unordered_map> #include <base/logging.h> -#include <base/macros.h> #include <binder/IBinder.h> #include <binder/IInterface.h> @@ -53,6 +52,9 @@ template <typename T> class RemoteCallbackList final { public: RemoteCallbackList() = default; + RemoteCallbackList(const RemoteCallbackList&) = delete; + RemoteCallbackList& operator=(const RemoteCallbackList&) = delete; + ~RemoteCallbackList(); // Register and unregister a callback interface. Registering will @@ -91,8 +93,6 @@ class RemoteCallbackList final { std::mutex map_lock_; CallbackMap callbacks_; - - DISALLOW_COPY_AND_ASSIGN(RemoteCallbackList); }; // Template Implementation details below diff --git a/system/service/ipc/binder/remote_callback_map.h b/system/service/ipc/binder/remote_callback_map.h index 7f31b5390a..96a717b7f0 100644 --- a/system/service/ipc/binder/remote_callback_map.h +++ b/system/service/ipc/binder/remote_callback_map.h @@ -20,7 +20,6 @@ #include <unordered_map> #include <base/logging.h> -#include <base/macros.h> #include <binder/IBinder.h> #include <binder/IInterface.h> @@ -38,6 +37,9 @@ template <typename K, typename V> class RemoteCallbackMap final { public: RemoteCallbackMap() = default; + RemoteCallbackMap(const RemoteCallbackMap&) = delete; + RemoteCallbackMap& operator=(const RemoteCallbackMap&) = delete; + ~RemoteCallbackMap(); // The Delegate interface is used to notify when a registered callback is @@ -104,8 +106,6 @@ class RemoteCallbackMap final { std::mutex map_lock_; CallbackMap map_; - - DISALLOW_COPY_AND_ASSIGN(RemoteCallbackMap); }; // Template Implementation details below diff --git a/system/service/ipc/dbus/ipc_handler_dbus.h b/system/service/ipc/dbus/ipc_handler_dbus.h index 2a83369cf8..4c0a7e9fea 100644 --- a/system/service/ipc/dbus/ipc_handler_dbus.h +++ b/system/service/ipc/dbus/ipc_handler_dbus.h @@ -29,6 +29,10 @@ namespace ipc { class IPCHandlerDBus : public IPCHandler { public: IPCHandlerDBus(bluetooth::Adapter* adapter, IPCManager::Delegate* delegate); + + IPCHandlerDBus(const IPCHandlerDBus&) = delete; + IPCHandlerDBus& operator=(const IPCHandlerDBus&) = delete; + ~IPCHandlerDBus() override; void InitDbus(); @@ -41,8 +45,6 @@ class IPCHandlerDBus : public IPCHandler { base::Thread* dbus_thread_; IPCHandlerDBus() = default; - - DISALLOW_COPY_AND_ASSIGN(IPCHandlerDBus); }; } // namespace ipc diff --git a/system/service/ipc/ipc_handler.h b/system/service/ipc/ipc_handler.h index 9b7994cf37..473d6e0f31 100644 --- a/system/service/ipc/ipc_handler.h +++ b/system/service/ipc/ipc_handler.h @@ -16,7 +16,6 @@ #pragma once -#include <base/macros.h> #include <base/memory/ref_counted.h> #include "service/ipc/ipc_manager.h" @@ -32,6 +31,10 @@ namespace ipc { class IPCHandler : public base::RefCountedThreadSafe<IPCHandler> { public: IPCHandler(bluetooth::Adapter* adapter, IPCManager::Delegate* delegate); + + IPCHandler(const IPCHandler&) = delete; + IPCHandler& operator=(const IPCHandler&) = delete; + virtual ~IPCHandler(); // Initializes and runs the IPC mechanism. Returns true on success, false @@ -55,8 +58,6 @@ class IPCHandler : public base::RefCountedThreadSafe<IPCHandler> { // The delegate that is interested in notifications from us. IPCManager::Delegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(IPCHandler); }; } // namespace ipc diff --git a/system/service/ipc/ipc_handler_linux.h b/system/service/ipc/ipc_handler_linux.h index 7cd6efabee..765dda2e21 100644 --- a/system/service/ipc/ipc_handler_linux.h +++ b/system/service/ipc/ipc_handler_linux.h @@ -19,7 +19,6 @@ #include <atomic> #include <base/files/file_path.h> #include <base/files/scoped_file.h> -#include <base/macros.h> #include <base/threading/thread.h> #include "service/ipc/ipc_handler.h" @@ -35,6 +34,10 @@ namespace ipc { class IPCHandlerLinux : public IPCHandler { public: IPCHandlerLinux(bluetooth::Adapter* adapter, IPCManager::Delegate* delegate); + + IPCHandlerLinux(const IPCHandlerLinux&) = delete; + IPCHandlerLinux& operator=(const IPCHandlerLinux&) = delete; + ~IPCHandlerLinux() override; // IPCHandler overrides: @@ -81,8 +84,6 @@ class IPCHandlerLinux : public IPCHandler { // The origin thread's task runner. scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_; - - DISALLOW_COPY_AND_ASSIGN(IPCHandlerLinux); }; } // namespace ipc diff --git a/system/service/ipc/ipc_manager.h b/system/service/ipc/ipc_manager.h index ee960ba6f5..bc5a104e3b 100644 --- a/system/service/ipc/ipc_manager.h +++ b/system/service/ipc/ipc_manager.h @@ -18,7 +18,6 @@ #include <memory> -#include <base/macros.h> #include <base/memory/ref_counted.h> namespace bluetooth { @@ -47,6 +46,9 @@ class IPCManager { class Delegate { public: Delegate() = default; + Delegate(const Delegate&) = delete; + Delegate& operator=(const Delegate&) = delete; + virtual ~Delegate() = default; // Called when an IPC mechanism has successfully started and is ready for @@ -56,12 +58,12 @@ class IPCManager { // Called when an IPC mechanism has stopped. This may happen due to an error // in initialization or due to a regular shut down routine. virtual void OnIPCHandlerStopped(Type type) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(Delegate); }; explicit IPCManager(bluetooth::Adapter* adapter); + IPCManager(const IPCManager&) = delete; + IPCManager& operator=(const IPCManager&) = delete; + ~IPCManager(); // Initialize the underlying IPC handler based on |type|, if that type has not @@ -96,8 +98,6 @@ class IPCManager { // The Bluetooth adapter instance. This is owned by Daemon so we keep a raw // pointer to it. bluetooth::Adapter* adapter_; - - DISALLOW_COPY_AND_ASSIGN(IPCManager); }; } // namespace ipc diff --git a/system/service/logging_helpers.cc b/system/service/logging_helpers.cc index 8b53033cc6..78a24e600f 100644 --- a/system/service/logging_helpers.cc +++ b/system/service/logging_helpers.cc @@ -112,7 +112,7 @@ const char* BtPropertyText(const bt_property_type_t prop) { CASE_RETURN_TEXT(BT_PROPERTY_SERVICE_RECORD); CASE_RETURN_TEXT(BT_PROPERTY_ADAPTER_SCAN_MODE); CASE_RETURN_TEXT(BT_PROPERTY_ADAPTER_BONDED_DEVICES); - CASE_RETURN_TEXT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT); + CASE_RETURN_TEXT(BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT); CASE_RETURN_TEXT(BT_PROPERTY_REMOTE_FRIENDLY_NAME); CASE_RETURN_TEXT(BT_PROPERTY_REMOTE_RSSI); CASE_RETURN_TEXT(BT_PROPERTY_REMOTE_VERSION_INFO); diff --git a/system/service/low_energy_advertiser.h b/system/service/low_energy_advertiser.h index ec0dd748b0..46d5316965 100644 --- a/system/service/low_energy_advertiser.h +++ b/system/service/low_energy_advertiser.h @@ -21,7 +21,6 @@ #include <map> #include <mutex> -#include <base/macros.h> #include <bluetooth/uuid.h> #include "service/bluetooth_instance.h" @@ -42,6 +41,9 @@ class Adapter; // should be obtained through the factory. class LowEnergyAdvertiser : public BluetoothInstance { public: + LowEnergyAdvertiser(const LowEnergyAdvertiser&) = delete; + LowEnergyAdvertiser& operator=(const LowEnergyAdvertiser&) = delete; + // The destructor automatically unregisters this client instance from the // stack. ~LowEnergyAdvertiser() override; @@ -107,8 +109,6 @@ class LowEnergyAdvertiser : public BluetoothInstance { std::atomic_bool adv_started_; std::unique_ptr<StatusCallback> adv_start_callback_; std::unique_ptr<StatusCallback> adv_stop_callback_; - - DISALLOW_COPY_AND_ASSIGN(LowEnergyAdvertiser); }; // LowEnergyAdvertiserFactory is used to register and obtain a per-application @@ -121,6 +121,10 @@ class LowEnergyAdvertiserFactory : public BluetoothInstanceFactory { // Don't construct/destruct directly except in tests. Instead, obtain a handle // from an Adapter instance. explicit LowEnergyAdvertiserFactory(); + LowEnergyAdvertiserFactory(const LowEnergyAdvertiserFactory&) = delete; + LowEnergyAdvertiserFactory& operator=(const LowEnergyAdvertiserFactory&) = + delete; + ~LowEnergyAdvertiserFactory() override; // BluetoothInstanceFactory override: @@ -138,8 +142,6 @@ class LowEnergyAdvertiserFactory : public BluetoothInstanceFactory { // Map of pending calls to register. std::mutex pending_calls_lock_; std::unordered_set<Uuid> pending_calls_; - - DISALLOW_COPY_AND_ASSIGN(LowEnergyAdvertiserFactory); }; } // namespace bluetooth diff --git a/system/service/low_energy_client.h b/system/service/low_energy_client.h index a4b60c61e0..ba39357fe7 100644 --- a/system/service/low_energy_client.h +++ b/system/service/low_energy_client.h @@ -16,7 +16,6 @@ #pragma once -#include <base/macros.h> #include <bluetooth/uuid.h> #include <atomic> @@ -53,6 +52,9 @@ class LowEnergyClient : private hal::BluetoothGattInterface::ClientObserver, class Delegate { public: Delegate() = default; + Delegate(const Delegate&) = delete; + Delegate& operator=(const Delegate&) = delete; + virtual ~Delegate() = default; // Called asynchronously to notify the delegate of connection state change @@ -62,11 +64,11 @@ class LowEnergyClient : private hal::BluetoothGattInterface::ClientObserver, // Called asynchronously to notify the delegate of mtu change virtual void OnMtuChanged(LowEnergyClient* client, int status, const char* address, int mtu) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(Delegate); }; + LowEnergyClient(const LowEnergyClient&) = delete; + LowEnergyClient& operator=(const LowEnergyClient&) = delete; + // The destructor automatically unregisters this client instance from the // stack. ~LowEnergyClient() override; @@ -134,8 +136,6 @@ class LowEnergyClient : private hal::BluetoothGattInterface::ClientObserver, // Maps bluetooth address to connection id // TODO(jpawlowski): change type to bimap std::map<const RawAddress, int, ConnComparator> connection_ids_; - - DISALLOW_COPY_AND_ASSIGN(LowEnergyClient); }; // LowEnergyClientFactory is used to register and obtain a per-application @@ -149,6 +149,9 @@ class LowEnergyClientFactory // Don't construct/destruct directly except in tests. Instead, obtain a handle // from an Adapter instance. explicit LowEnergyClientFactory(Adapter& adapter); + LowEnergyClientFactory(const LowEnergyClientFactory&) = delete; + LowEnergyClientFactory& operator=(const LowEnergyClientFactory&) = delete; + ~LowEnergyClientFactory() override; // BluetoothInstanceFactory override: @@ -169,8 +172,6 @@ class LowEnergyClientFactory // Raw pointer to the Adapter that owns this factory. Adapter& adapter_; - - DISALLOW_COPY_AND_ASSIGN(LowEnergyClientFactory); }; } // namespace bluetooth diff --git a/system/service/low_energy_scanner.h b/system/service/low_energy_scanner.h index 6325c41cf2..627f287f83 100644 --- a/system/service/low_energy_scanner.h +++ b/system/service/low_energy_scanner.h @@ -16,7 +16,6 @@ #pragma once -#include <base/macros.h> #include <bluetooth/uuid.h> #include <atomic> @@ -49,17 +48,20 @@ class LowEnergyScanner : private hal::BluetoothGattInterface::ScannerObserver, class Delegate { public: Delegate() = default; + Delegate(const Delegate&) = delete; + Delegate& operator=(const Delegate&) = delete; + virtual ~Delegate() = default; // Called asynchronously to notify the delegate of nearby BLE advertisers // found during a device scan. virtual void OnScanResult(LowEnergyScanner* client, const ScanResult& scan_result) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(Delegate); }; + LowEnergyScanner(const LowEnergyScanner&) = delete; + LowEnergyScanner& operator=(const LowEnergyScanner&) = delete; + // The destructor automatically unregisters this client instance from the // stack. ~LowEnergyScanner() override; @@ -120,8 +122,6 @@ class LowEnergyScanner : private hal::BluetoothGattInterface::ScannerObserver, // instance. std::mutex delegate_mutex_; Delegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(LowEnergyScanner); }; // LowEnergyScannerFactory is used to register and obtain a per-application @@ -135,6 +135,9 @@ class LowEnergyScannerFactory // Don't construct/destruct directly except in tests. Instead, obtain a handle // from an Adapter instance. explicit LowEnergyScannerFactory(Adapter& adapter); + LowEnergyScannerFactory(const LowEnergyScannerFactory&) = delete; + LowEnergyScannerFactory& operator=(const LowEnergyScannerFactory&) = delete; + ~LowEnergyScannerFactory() override; // BluetoothInstanceFactory override: @@ -155,8 +158,6 @@ class LowEnergyScannerFactory // Raw pointer to the Adapter that owns this factory. Adapter& adapter_; - - DISALLOW_COPY_AND_ASSIGN(LowEnergyScannerFactory); }; } // namespace bluetooth diff --git a/system/service/settings.h b/system/service/settings.h index 1f298d6c0e..38e5ca98b2 100644 --- a/system/service/settings.h +++ b/system/service/settings.h @@ -19,7 +19,6 @@ #include <string> #include <base/files/file_path.h> -#include <base/macros.h> namespace bluetooth { @@ -32,6 +31,9 @@ class Settings { static const char kHelp[]; Settings(); + Settings(const Settings&) = delete; + Settings& operator=(const Settings&) = delete; + ~Settings(); // TODO(armansito): Write an instance method for storing things into a file. @@ -67,8 +69,6 @@ class Settings { bool enable_on_start_; std::string android_ipc_socket_suffix_; base::FilePath create_ipc_socket_path_; - - DISALLOW_COPY_AND_ASSIGN(Settings); }; } // namespace bluetooth diff --git a/system/service/test/a2dp_sink_unittest.cc b/system/service/test/a2dp_sink_unittest.cc index f51e11292d..69545c29c8 100644 --- a/system/service/test/a2dp_sink_unittest.cc +++ b/system/service/test/a2dp_sink_unittest.cc @@ -32,15 +32,15 @@ class MockA2dpSinkHandler : public hal::FakeBluetoothAvInterface::TestA2dpSinkHandler { public: MockA2dpSinkHandler() = default; + MockA2dpSinkHandler(const MockA2dpSinkHandler&) = delete; + MockA2dpSinkHandler& operator=(const MockA2dpSinkHandler&) = delete; + ~MockA2dpSinkHandler() override = default; MOCK_METHOD1(Connect, bt_status_t(RawAddress)); MOCK_METHOD1(Disconnect, bt_status_t(RawAddress)); MOCK_METHOD1(SetAudioFocusState, void(int)); MOCK_METHOD1(SetAudioTrackGain, void(float)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockA2dpSinkHandler); }; class TestDelegate : public A2dpSink::Delegate { @@ -89,6 +89,9 @@ class TestDelegate : public A2dpSink::Delegate { class A2dpSinkTest : public ::testing::Test { public: A2dpSinkTest() = default; + A2dpSinkTest(const A2dpSinkTest&) = delete; + A2dpSinkTest& operator=(const A2dpSinkTest&) = delete; + ~A2dpSinkTest() override = default; void SetUp() override { @@ -107,14 +110,14 @@ class A2dpSinkTest : public ::testing::Test { hal::FakeBluetoothAvInterface* fake_hal_av_iface_; std::shared_ptr<MockA2dpSinkHandler> mock_handler_; std::unique_ptr<A2dpSinkFactory> factory_; - - private: - DISALLOW_COPY_AND_ASSIGN(A2dpSinkTest); }; class A2dpSinkPostRegisterTest : public A2dpSinkTest { public: A2dpSinkPostRegisterTest() = default; + A2dpSinkPostRegisterTest(const A2dpSinkPostRegisterTest&) = delete; + A2dpSinkPostRegisterTest& operator=(const A2dpSinkPostRegisterTest&) = delete; + ~A2dpSinkPostRegisterTest() override = default; void SetUp() override { @@ -160,9 +163,6 @@ class A2dpSinkPostRegisterTest : public A2dpSinkTest { } std::unique_ptr<A2dpSink> a2dp_sink_; - - private: - DISALLOW_COPY_AND_ASSIGN(A2dpSinkPostRegisterTest); }; TEST_F(A2dpSinkTest, RegisterA2dpSink) { diff --git a/system/service/test/a2dp_source_unittest.cc b/system/service/test/a2dp_source_unittest.cc index 5aede818fb..b29172754c 100644 --- a/system/service/test/a2dp_source_unittest.cc +++ b/system/service/test/a2dp_source_unittest.cc @@ -32,13 +32,13 @@ class MockA2dpSourceHandler : public hal::FakeBluetoothAvInterface::TestA2dpSourceHandler { public: MockA2dpSourceHandler() = default; + MockA2dpSourceHandler(const MockA2dpSourceHandler&) = delete; + MockA2dpSourceHandler& operator=(const MockA2dpSourceHandler&) = delete; + ~MockA2dpSourceHandler() override = default; MOCK_METHOD1(Connect, bt_status_t(RawAddress)); MOCK_METHOD1(Disconnect, bt_status_t(RawAddress)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockA2dpSourceHandler); }; class TestDelegate : public A2dpSource::Delegate { @@ -86,6 +86,9 @@ class TestDelegate : public A2dpSource::Delegate { class A2dpSourceTest : public ::testing::Test { public: A2dpSourceTest() = default; + A2dpSourceTest(const A2dpSourceTest&) = delete; + A2dpSourceTest& operator=(const A2dpSourceTest&) = delete; + ~A2dpSourceTest() override = default; void SetUp() override { @@ -104,14 +107,15 @@ class A2dpSourceTest : public ::testing::Test { hal::FakeBluetoothAvInterface* fake_hal_av_iface_; std::shared_ptr<MockA2dpSourceHandler> mock_handler_; std::unique_ptr<A2dpSourceFactory> factory_; - - private: - DISALLOW_COPY_AND_ASSIGN(A2dpSourceTest); }; class A2dpSourcePostRegisterTest : public A2dpSourceTest { public: A2dpSourcePostRegisterTest() = default; + A2dpSourcePostRegisterTest(const A2dpSourcePostRegisterTest&) = delete; + A2dpSourcePostRegisterTest& operator=(const A2dpSourcePostRegisterTest&) = + delete; + ~A2dpSourcePostRegisterTest() override = default; void SetUp() override { @@ -157,9 +161,6 @@ class A2dpSourcePostRegisterTest : public A2dpSourceTest { } std::unique_ptr<A2dpSource> a2dp_source_; - - private: - DISALLOW_COPY_AND_ASSIGN(A2dpSourcePostRegisterTest); }; TEST_F(A2dpSourceTest, RegisterA2dpSource) { diff --git a/system/service/test/adapter_unittest.cc b/system/service/test/adapter_unittest.cc index 37b0abbeb5..6c736097dc 100644 --- a/system/service/test/adapter_unittest.cc +++ b/system/service/test/adapter_unittest.cc @@ -16,7 +16,6 @@ #include "service/adapter.h" -#include <base/macros.h> #include <gtest/gtest.h> #include "service/hal/fake_bluetooth_gatt_interface.h" @@ -30,6 +29,9 @@ namespace { class AdapterTest : public ::testing::Test { public: AdapterTest() = default; + AdapterTest(const AdapterTest&) = delete; + AdapterTest& operator=(const AdapterTest&) = delete; + ~AdapterTest() override = default; void SetUp() override { @@ -55,9 +57,6 @@ class AdapterTest : public ::testing::Test { hal::FakeBluetoothInterface* fake_hal_iface_; hal::FakeBluetoothInterface::Manager* fake_hal_manager_; std::unique_ptr<Adapter> adapter_; - - private: - DISALLOW_COPY_AND_ASSIGN(AdapterTest); }; class TestObserver final : public bluetooth::Adapter::Observer { @@ -71,6 +70,9 @@ class TestObserver final : public bluetooth::Adapter::Observer { adapter_->AddObserver(this); } + TestObserver(const TestObserver&) = delete; + TestObserver& operator=(const TestObserver&) = delete; + ~TestObserver() override { adapter_->RemoveObserver(this); } bluetooth::AdapterState prev_state() const { return prev_state_; } @@ -106,8 +108,6 @@ class TestObserver final : public bluetooth::Adapter::Observer { bluetooth::AdapterState prev_state_, cur_state_; std::string last_connection_state_address_; bool last_device_connected_state_; - - DISALLOW_COPY_AND_ASSIGN(TestObserver); }; TEST_F(AdapterTest, IsEnabled) { diff --git a/system/service/test/gatt_client_unittest.cc b/system/service/test/gatt_client_unittest.cc index 71850cdea9..c7c02091a8 100644 --- a/system/service/test/gatt_client_unittest.cc +++ b/system/service/test/gatt_client_unittest.cc @@ -16,7 +16,6 @@ #include "service/gatt_client.h" -#include <base/macros.h> #include <gmock/gmock.h> #include <gtest/gtest.h> @@ -33,6 +32,9 @@ class MockGattHandler : public hal::FakeBluetoothGattInterface::TestClientHandler { public: MockGattHandler() = default; + MockGattHandler(const MockGattHandler&) = delete; + MockGattHandler& operator=(const MockGattHandler&) = delete; + ~MockGattHandler() override = default; MOCK_METHOD2(RegisterClient, @@ -41,14 +43,14 @@ class MockGattHandler MOCK_METHOD1(Scan, bt_status_t(bool)); MOCK_METHOD4(Connect, bt_status_t(int, const RawAddress&, bool, int)); MOCK_METHOD3(Disconnect, bt_status_t(int, const RawAddress&, int)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockGattHandler); }; class GattClientTest : public ::testing::Test { public: GattClientTest() = default; + GattClientTest(const GattClientTest&) = delete; + GattClientTest& operator=(const GattClientTest&) = delete; + ~GattClientTest() override = default; void SetUp() override { @@ -74,9 +76,6 @@ class GattClientTest : public ::testing::Test { hal::FakeBluetoothGattInterface* fake_hal_gatt_iface_; std::shared_ptr<MockGattHandler> mock_handler_; std::unique_ptr<GattClientFactory> factory_; - - private: - DISALLOW_COPY_AND_ASSIGN(GattClientTest); }; TEST_F(GattClientTest, RegisterInstance) { diff --git a/system/service/test/gatt_server_unittest.cc b/system/service/test/gatt_server_unittest.cc index 467100c170..f0e6f98d33 100644 --- a/system/service/test/gatt_server_unittest.cc +++ b/system/service/test/gatt_server_unittest.cc @@ -32,6 +32,9 @@ class MockGattHandler : public hal::FakeBluetoothGattInterface::TestServerHandler { public: MockGattHandler() = default; + MockGattHandler(const MockGattHandler&) = delete; + MockGattHandler& operator=(const MockGattHandler&) = delete; + ~MockGattHandler() override = default; MOCK_METHOD2(RegisterServer, @@ -47,9 +50,6 @@ class MockGattHandler bt_status_t(int, int, int, int, std::vector<uint8_t>)); MOCK_METHOD4(SendResponse, bt_status_t(int, int, int, const btgatt_response_t&)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockGattHandler); }; class TestDelegate : public GattServer::Delegate { @@ -179,6 +179,9 @@ class TestDelegate : public GattServer::Delegate { class GattServerTest : public ::testing::Test { public: GattServerTest() = default; + GattServerTest(const GattServerTest&) = delete; + GattServerTest& operator=(const GattServerTest&) = delete; + ~GattServerTest() override = default; void SetUp() override { @@ -201,9 +204,6 @@ class GattServerTest : public ::testing::Test { hal::FakeBluetoothGattInterface* fake_hal_gatt_iface_; std::shared_ptr<MockGattHandler> mock_handler_; std::unique_ptr<GattServerFactory> factory_; - - private: - DISALLOW_COPY_AND_ASSIGN(GattServerTest); }; const int kDefaultServerId = 4; @@ -211,6 +211,10 @@ const int kDefaultServerId = 4; class GattServerPostRegisterTest : public GattServerTest { public: GattServerPostRegisterTest() = default; + GattServerPostRegisterTest(const GattServerPostRegisterTest&) = delete; + GattServerPostRegisterTest& operator=(const GattServerPostRegisterTest&) = + delete; + ~GattServerPostRegisterTest() override = default; void SetUp() override { @@ -295,9 +299,6 @@ class GattServerPostRegisterTest : public GattServerTest { uint16_t srvc_handle_; uint16_t char_handle_; uint16_t desc_handle_; - - private: - DISALLOW_COPY_AND_ASSIGN(GattServerPostRegisterTest); }; TEST_F(GattServerTest, RegisterServer) { diff --git a/system/service/test/ipc_linux_unittest.cc b/system/service/test/ipc_linux_unittest.cc index 176cd6a320..0c3ab31b7d 100644 --- a/system/service/test/ipc_linux_unittest.cc +++ b/system/service/test/ipc_linux_unittest.cc @@ -22,7 +22,6 @@ #include <base/at_exit.h> #include <base/command_line.h> #include <base/files/scoped_file.h> -#include <base/macros.h> #include <base/run_loop.h> #include <base/strings/stringprintf.h> #include <gtest/gtest.h> @@ -45,6 +44,9 @@ const char kTestSocketPath[] = "test_socket_path"; class IPCLinuxTest : public ::testing::Test { public: IPCLinuxTest() = default; + IPCLinuxTest(const IPCLinuxTest&) = delete; + IPCLinuxTest& operator=(const IPCLinuxTest&) = delete; + ~IPCLinuxTest() override = default; void SetUp() override { @@ -109,13 +111,14 @@ class IPCLinuxTest : public ::testing::Test { std::unique_ptr<bluetooth::Adapter> adapter_; std::unique_ptr<ipc::IPCManager> ipc_manager_; base::ScopedFD client_fd_; - - DISALLOW_COPY_AND_ASSIGN(IPCLinuxTest); }; class IPCLinuxTestDisabled : public IPCLinuxTest { public: IPCLinuxTestDisabled() = default; + IPCLinuxTestDisabled(const IPCLinuxTestDisabled&) = delete; + IPCLinuxTestDisabled& operator=(const IPCLinuxTestDisabled&) = delete; + ~IPCLinuxTestDisabled() override = default; void SetUpCommandLine() override { @@ -123,9 +126,6 @@ class IPCLinuxTestDisabled : public IPCLinuxTest { const base::CommandLine::CharType* argv[] = {"program"}; base::CommandLine::Init(ARRAY_SIZE(argv), argv); } - - private: - DISALLOW_COPY_AND_ASSIGN(IPCLinuxTestDisabled); }; class TestDelegate : public ipc::IPCManager::Delegate, @@ -133,6 +133,9 @@ class TestDelegate : public ipc::IPCManager::Delegate, public: TestDelegate() : started_count_(0), stopped_count_(0) {} + TestDelegate(const TestDelegate&) = delete; + TestDelegate& operator=(const TestDelegate&) = delete; + void OnIPCHandlerStarted(ipc::IPCManager::Type type) override { ASSERT_EQ(ipc::IPCManager::TYPE_LINUX, type); started_count_++; @@ -151,8 +154,6 @@ class TestDelegate : public ipc::IPCManager::Delegate, private: int started_count_; int stopped_count_; - - DISALLOW_COPY_AND_ASSIGN(TestDelegate); }; TEST_F(IPCLinuxTestDisabled, StartWithNoSocketPath) { diff --git a/system/service/test/low_energy_advertiser_unittest.cc b/system/service/test/low_energy_advertiser_unittest.cc index 3d6a7c23db..f46b80b2af 100644 --- a/system/service/test/low_energy_advertiser_unittest.cc +++ b/system/service/test/low_energy_advertiser_unittest.cc @@ -14,7 +14,6 @@ // limitations under the License. // -#include <base/macros.h> #include <gmock/gmock.h> #include <gtest/gtest.h> @@ -43,6 +42,9 @@ namespace { class MockAdvertiserHandler : public BleAdvertiserInterface { public: MockAdvertiserHandler() {} + MockAdvertiserHandler(const MockAdvertiserHandler&) = delete; + MockAdvertiserHandler& operator=(const MockAdvertiserHandler&) = delete; + ~MockAdvertiserHandler() override = default; MOCK_METHOD1(RegisterAdvertiser, void(IdStatusCallback)); @@ -78,14 +80,14 @@ class MockAdvertiserHandler : public BleAdvertiserInterface { int big_handle, int reason, TerminateBIGCallback cb)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockAdvertiserHandler); }; class LowEnergyAdvertiserTest : public ::testing::Test { public: LowEnergyAdvertiserTest() = default; + LowEnergyAdvertiserTest(const LowEnergyAdvertiserTest&) = delete; + LowEnergyAdvertiserTest& operator=(const LowEnergyAdvertiserTest&) = delete; + ~LowEnergyAdvertiserTest() override = default; void SetUp() override { @@ -106,15 +108,17 @@ class LowEnergyAdvertiserTest : public ::testing::Test { protected: std::shared_ptr<MockAdvertiserHandler> mock_handler_; std::unique_ptr<LowEnergyAdvertiserFactory> ble_advertiser_factory_; - - private: - DISALLOW_COPY_AND_ASSIGN(LowEnergyAdvertiserTest); }; // Used for tests that operate on a pre-registered advertiser. class LowEnergyAdvertiserPostRegisterTest : public LowEnergyAdvertiserTest { public: LowEnergyAdvertiserPostRegisterTest() : next_client_id_(0) {} + LowEnergyAdvertiserPostRegisterTest( + const LowEnergyAdvertiserPostRegisterTest&) = delete; + LowEnergyAdvertiserPostRegisterTest& operator=( + const LowEnergyAdvertiserPostRegisterTest&) = delete; + ~LowEnergyAdvertiserPostRegisterTest() override = default; void SetUp() override { @@ -208,8 +212,6 @@ class LowEnergyAdvertiserPostRegisterTest : public LowEnergyAdvertiserTest { private: int next_client_id_; - - DISALLOW_COPY_AND_ASSIGN(LowEnergyAdvertiserPostRegisterTest); }; TEST_F(LowEnergyAdvertiserTest, RegisterInstance) { diff --git a/system/service/test/low_energy_client_unittest.cc b/system/service/test/low_energy_client_unittest.cc index 389d758237..f2669ba085 100644 --- a/system/service/test/low_energy_client_unittest.cc +++ b/system/service/test/low_energy_client_unittest.cc @@ -16,7 +16,6 @@ #include "service/low_energy_client.h" -#include <base/macros.h> #include <gmock/gmock.h> #include <gtest/gtest.h> @@ -40,6 +39,9 @@ class MockGattHandler : public hal::FakeBluetoothGattInterface::TestClientHandler { public: MockGattHandler(){}; + MockGattHandler(const MockGattHandler&) = delete; + MockGattHandler& operator=(const MockGattHandler&) = delete; + ~MockGattHandler() override = default; MOCK_METHOD2(RegisterClient, @@ -47,15 +49,15 @@ class MockGattHandler MOCK_METHOD1(UnregisterClient, bt_status_t(int)); MOCK_METHOD4(Connect, bt_status_t(int, const RawAddress&, bool, int)); MOCK_METHOD3(Disconnect, bt_status_t(int, const RawAddress&, int)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockGattHandler); }; class TestDelegate : public LowEnergyClient::Delegate { public: TestDelegate() : connection_state_count_(0), last_mtu_(0) {} + TestDelegate(const TestDelegate&) = delete; + TestDelegate& operator=(const TestDelegate&) = delete; + ~TestDelegate() override = default; int connection_state_count() const { return connection_state_count_; } @@ -76,13 +78,14 @@ class TestDelegate : public LowEnergyClient::Delegate { int connection_state_count_; int last_mtu_; - - DISALLOW_COPY_AND_ASSIGN(TestDelegate); }; class LowEnergyClientTest : public ::testing::Test { public: LowEnergyClientTest() = default; + LowEnergyClientTest(const LowEnergyClientTest&) = delete; + LowEnergyClientTest& operator=(const LowEnergyClientTest&) = delete; + ~LowEnergyClientTest() override = default; void SetUp() override { @@ -107,15 +110,18 @@ class LowEnergyClientTest : public ::testing::Test { testing::MockAdapter mock_adapter_; std::shared_ptr<MockGattHandler> mock_handler_; std::unique_ptr<LowEnergyClientFactory> ble_factory_; - - private: - DISALLOW_COPY_AND_ASSIGN(LowEnergyClientTest); }; // Used for tests that operate on a pre-registered client. class LowEnergyClientPostRegisterTest : public LowEnergyClientTest { public: LowEnergyClientPostRegisterTest() : next_client_id_(0) {} + + LowEnergyClientPostRegisterTest(const LowEnergyClientPostRegisterTest&) = + delete; + LowEnergyClientPostRegisterTest& operator=( + const LowEnergyClientPostRegisterTest&) = delete; + ~LowEnergyClientPostRegisterTest() override = default; void SetUp() override { @@ -164,8 +170,6 @@ class LowEnergyClientPostRegisterTest : public LowEnergyClientTest { private: int next_client_id_; - - DISALLOW_COPY_AND_ASSIGN(LowEnergyClientPostRegisterTest); }; TEST_F(LowEnergyClientTest, RegisterInstance) { diff --git a/system/service/test/low_energy_scanner_unittest.cc b/system/service/test/low_energy_scanner_unittest.cc index 5cc5694fba..6abd74322f 100644 --- a/system/service/test/low_energy_scanner_unittest.cc +++ b/system/service/test/low_energy_scanner_unittest.cc @@ -16,7 +16,6 @@ #include "service/low_energy_scanner.h" -#include <base/macros.h> #include <gmock/gmock.h> #include <gtest/gtest.h> @@ -103,6 +102,9 @@ class TestDelegate : public LowEnergyScanner::Delegate { public: TestDelegate() : scan_result_count_(0) {} + TestDelegate(const TestDelegate&) = delete; + TestDelegate& operator=(const TestDelegate&) = delete; + ~TestDelegate() override = default; int scan_result_count() const { return scan_result_count_; } @@ -118,13 +120,14 @@ class TestDelegate : public LowEnergyScanner::Delegate { private: int scan_result_count_; ScanResult last_scan_result_; - - DISALLOW_COPY_AND_ASSIGN(TestDelegate); }; class LowEnergyScannerTest : public ::testing::Test { public: LowEnergyScannerTest() = default; + LowEnergyScannerTest(const LowEnergyScannerTest&) = delete; + LowEnergyScannerTest& operator=(const LowEnergyScannerTest&) = delete; + ~LowEnergyScannerTest() override = default; void SetUp() override { @@ -147,15 +150,18 @@ class LowEnergyScannerTest : public ::testing::Test { testing::MockAdapter mock_adapter_; std::shared_ptr<MockScannerHandler> mock_handler_; std::unique_ptr<LowEnergyScannerFactory> ble_factory_; - - private: - DISALLOW_COPY_AND_ASSIGN(LowEnergyScannerTest); }; // Used for tests that operate on a pre-registered scanner. class LowEnergyScannerPostRegisterTest : public LowEnergyScannerTest { public: LowEnergyScannerPostRegisterTest() : next_scanner_id_(0) {} + + LowEnergyScannerPostRegisterTest(const LowEnergyScannerPostRegisterTest&) = + delete; + LowEnergyScannerPostRegisterTest& operator=( + const LowEnergyScannerPostRegisterTest&) = delete; + ~LowEnergyScannerPostRegisterTest() override = default; void SetUp() override { @@ -203,8 +209,6 @@ class LowEnergyScannerPostRegisterTest : public LowEnergyScannerTest { private: int next_scanner_id_; - - DISALLOW_COPY_AND_ASSIGN(LowEnergyScannerPostRegisterTest); }; TEST_F(LowEnergyScannerTest, RegisterInstance) { diff --git a/system/service/test/mock_adapter.h b/system/service/test/mock_adapter.h index b652026858..4042f6a975 100644 --- a/system/service/test/mock_adapter.h +++ b/system/service/test/mock_adapter.h @@ -26,6 +26,9 @@ namespace testing { class MockAdapter : public Adapter { public: MockAdapter() = default; + MockAdapter(const MockAdapter&) = delete; + MockAdapter& operator=(const MockAdapter&) = delete; + ~MockAdapter() override = default; MOCK_METHOD1(AddObserver, void(Observer*)); @@ -60,9 +63,6 @@ class MockAdapter : public Adapter { MOCK_CONST_METHOD0(GetLeScannerFactory, LowEnergyScannerFactory*()); MOCK_CONST_METHOD0(GetGattClientFactory, GattClientFactory*()); MOCK_CONST_METHOD0(GetGattServerFactory, GattServerFactory*()); - - private: - DISALLOW_COPY_AND_ASSIGN(MockAdapter); }; } // namespace testing diff --git a/system/service/test/mock_daemon.h b/system/service/test/mock_daemon.h index 1c026221d2..410b962b52 100644 --- a/system/service/test/mock_daemon.h +++ b/system/service/test/mock_daemon.h @@ -27,15 +27,15 @@ namespace testing { class MockDaemon : public Daemon { public: MockDaemon() = default; + MockDaemon(const MockDaemon&) = delete; + MockDaemon& operator=(const MockDaemon&) = delete; + ~MockDaemon() override = default; MOCK_CONST_METHOD0(GetSettings, Settings*()); MOCK_CONST_METHOD0(GetMessageLoop, btbase::AbstractMessageLoop*()); MOCK_METHOD0(StartMainLoop, void()); MOCK_METHOD0(Init, bool()); - - private: - DISALLOW_COPY_AND_ASSIGN(MockDaemon); }; } // namespace testing diff --git a/system/service/test/settings_unittest.cc b/system/service/test/settings_unittest.cc index 60d372e375..31baaaaad8 100644 --- a/system/service/test/settings_unittest.cc +++ b/system/service/test/settings_unittest.cc @@ -16,7 +16,6 @@ #include <base/at_exit.h> #include <base/command_line.h> -#include <base/macros.h> #include <gtest/gtest.h> #include "array_utils.h" @@ -31,6 +30,8 @@ namespace { class SettingsTest : public ::testing::Test { public: SettingsTest() = default; + SettingsTest(const SettingsTest&) = delete; + SettingsTest& operator=(const SettingsTest&) = delete; void SetUp() override { base::CommandLine::Reset(); } @@ -39,9 +40,6 @@ class SettingsTest : public ::testing::Test { protected: base::AtExitManager exit_manager_; Settings settings_; - - private: - DISALLOW_COPY_AND_ASSIGN(SettingsTest); }; TEST_F(SettingsTest, EmptyCommandLine) { diff --git a/system/stack/Android.bp b/system/stack/Android.bp index d4e322a6df..8678e6204f 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -240,7 +240,6 @@ cc_test { "android.hardware.bluetooth.a2dp@1.0", "android.hardware.bluetooth.audio@2.0", "android.hardware.bluetooth.audio@2.1", - "android.hardware.bluetooth.audio@2.2", "android.hardware.bluetooth.audio-V1-ndk", "android.system.suspend.control-V1-ndk", "libaaudio", @@ -272,7 +271,6 @@ cc_test { "libbt-hci", "libbtdevice", "libg722codec", - "liblc3codec", "liblc3", "libosi", "libudrv-uipc", diff --git a/system/stack/acl/btm_ble_connection_establishment.cc b/system/stack/acl/btm_ble_connection_establishment.cc index 2fef1a5e38..d452a7cbb5 100644 --- a/system/stack/acl/btm_ble_connection_establishment.cc +++ b/system/stack/acl/btm_ble_connection_establishment.cc @@ -43,50 +43,6 @@ extern void btm_ble_advertiser_notify_terminated_legacy( extern bool btm_ble_init_pseudo_addr(tBTM_SEC_DEV_REC* p_dev_rec, const RawAddress& new_pseudo_addr); -void btm_send_hci_create_connection( - uint16_t scan_int, uint16_t scan_win, uint8_t init_filter_policy, - tBLE_ADDR_TYPE addr_type_peer, const RawAddress& bda_peer, - tBLE_ADDR_TYPE addr_type_own, uint16_t conn_int_min, uint16_t conn_int_max, - uint16_t conn_latency, uint16_t conn_timeout, uint16_t min_ce_len, - uint16_t max_ce_len, uint8_t initiating_phys) { - ASSERT_LOG(false, - "When gd_acl enabled this code path should not be exercised"); - - if (controller_get_interface()->supports_ble_extended_advertising()) { - EXT_CONN_PHY_CFG phy_cfg[3]; // maximum three phys - - int phy_cnt = - std::bitset<std::numeric_limits<uint8_t>::digits>(initiating_phys) - .count(); - - LOG_ASSERT(phy_cnt <= 3) << "More than three phys provided"; - // TODO(jpawlowski): tune parameters for different transports - for (int i = 0; i < phy_cnt; i++) { - phy_cfg[i].scan_int = scan_int; - phy_cfg[i].scan_win = scan_win; - phy_cfg[i].conn_int_min = conn_int_min; - phy_cfg[i].conn_int_max = conn_int_max; - phy_cfg[i].conn_latency = conn_latency; - phy_cfg[i].sup_timeout = conn_timeout; - phy_cfg[i].min_ce_len = min_ce_len; - phy_cfg[i].max_ce_len = max_ce_len; - } - - addr_type_peer &= ~BLE_ADDR_TYPE_ID_BIT; - btsnd_hcic_ble_ext_create_conn(init_filter_policy, addr_type_own, - addr_type_peer, bda_peer, initiating_phys, - phy_cfg); - } else { - btsnd_hcic_ble_create_ll_conn(scan_int, scan_win, init_filter_policy, - addr_type_peer, bda_peer, addr_type_own, - conn_int_min, conn_int_max, conn_latency, - conn_timeout, min_ce_len, max_ce_len); - } - - btm_cb.ble_ctr_cb.set_connection_state_connecting(); - btm_ble_set_topology_mask(BTM_BLE_STATE_INIT_BIT); -} - /** LE connection complete. */ void btm_ble_create_ll_conn_complete(tHCI_STATUS status) { if (status == HCI_SUCCESS) return; diff --git a/system/stack/avrc/avrc_pars_ct.cc b/system/stack/avrc/avrc_pars_ct.cc index 298f6eedf2..78962c773b 100644 --- a/system/stack/avrc/avrc_pars_ct.cc +++ b/system/stack/avrc/avrc_pars_ct.cc @@ -581,6 +581,10 @@ static tAVRC_STS avrc_ctrl_pars_vendor_rsp(tAVRC_MSG_VENDOR* p_msg, p_result->get_caps.capability_id, p_result->get_caps.count); if (p_result->get_caps.capability_id == AVRC_CAP_COMPANY_ID) { + if (p_result->get_caps.count > AVRC_CAP_MAX_NUM_COMP_ID) { + android_errorWriteLog(0x534e4554, "205837191"); + return AVRC_STS_INTERNAL_ERR; + } min_len += MIN(p_result->get_caps.count, AVRC_CAP_MAX_NUM_COMP_ID) * 3; if (len < min_len) goto length_error; for (int xx = 0; ((xx < p_result->get_caps.count) && @@ -590,6 +594,10 @@ static tAVRC_STS avrc_ctrl_pars_vendor_rsp(tAVRC_MSG_VENDOR* p_msg, } } else if (p_result->get_caps.capability_id == AVRC_CAP_EVENTS_SUPPORTED) { + if (p_result->get_caps.count > AVRC_CAP_MAX_NUM_COMP_ID) { + android_errorWriteLog(0x534e4554, "205837191"); + return AVRC_STS_INTERNAL_ERR; + } min_len += MIN(p_result->get_caps.count, AVRC_CAP_MAX_NUM_EVT_ID); if (len < min_len) goto length_error; for (int xx = 0; ((xx < p_result->get_caps.count) && diff --git a/system/stack/btm/btm_ble.cc b/system/stack/btm/btm_ble.cc index 94f862dc98..10977455b4 100644 --- a/system/stack/btm/btm_ble.cc +++ b/system/stack/btm/btm_ble.cc @@ -2073,32 +2073,6 @@ void btm_ble_reset_id(void) { })); } -/* This function set a random address to local controller. It also temporarily - * disable scans and adv before sending the command to the controller. */ -void btm_ble_set_random_address(const RawAddress& random_bda) { - tBTM_LE_RANDOM_CB* p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb; - tBTM_BLE_CB* p_ble_cb = &btm_cb.ble_ctr_cb; - const bool adv_mode = btm_cb.ble_ctr_cb.inq_var.adv_mode; - - if (adv_mode == BTM_BLE_ADV_ENABLE) - btsnd_hcic_ble_set_adv_enable(BTM_BLE_ADV_DISABLE); - if (p_ble_cb->is_ble_scan_active()) { - btm_ble_stop_scan(); - } - btm_ble_suspend_bg_conn(); - - p_cb->private_addr = random_bda; - btsnd_hcic_ble_set_random_addr(p_cb->private_addr); - LOG_DEBUG("Updating local random address:%s", PRIVATE_ADDRESS(random_bda)); - - if (adv_mode == BTM_BLE_ADV_ENABLE) - btsnd_hcic_ble_set_adv_enable(BTM_BLE_ADV_ENABLE); - if (p_ble_cb->is_ble_scan_active()) { - btm_ble_start_scan(); - } - btm_ble_resume_bg_conn(); -} - /******************************************************************************* * * Function btm_ble_get_acl_remote_addr diff --git a/system/stack/btm/btm_ble_addr.cc b/system/stack/btm/btm_ble_addr.cc index 44436b9f3e..34424dbf1f 100644 --- a/system/stack/btm/btm_ble_addr.cc +++ b/system/stack/btm/btm_ble_addr.cc @@ -38,8 +38,6 @@ extern tBTM_CB btm_cb; -void btm_ble_set_random_address(const RawAddress& random_bda); - /* This function generates Resolvable Private Address (RPA) from Identity * Resolving Key |irk| and |random|*/ static RawAddress generate_rpa_from_irk_and_rand(const Octet16& irk, @@ -195,6 +193,8 @@ tBTM_SEC_DEV_REC* btm_ble_resolve_random_addr(const RawAddress& random_bda) { /** Find the security record whose LE identity address is matching */ static tBTM_SEC_DEV_REC* btm_find_dev_by_identity_addr( const RawAddress& bd_addr, uint8_t addr_type) { + if (btm_cb.sec_dev_rec == nullptr) return nullptr; + list_node_t* end = list_end(btm_cb.sec_dev_rec); for (list_node_t* node = list_begin(btm_cb.sec_dev_rec); node != end; node = list_next(node)) { diff --git a/system/stack/btm/btm_ble_bgconn.cc b/system/stack/btm/btm_ble_bgconn.cc index 65c1b18673..f725351191 100644 --- a/system/stack/btm/btm_ble_bgconn.cc +++ b/system/stack/btm/btm_ble_bgconn.cc @@ -39,12 +39,6 @@ extern tBTM_CB btm_cb; -extern void btm_send_hci_create_connection( - uint16_t scan_int, uint16_t scan_win, uint8_t init_filter_policy, - uint8_t addr_type_peer, const RawAddress& bda_peer, uint8_t addr_type_own, - uint16_t conn_int_min, uint16_t conn_int_max, uint16_t conn_latency, - uint16_t conn_timeout, uint16_t min_ce_len, uint16_t max_ce_len, - uint8_t phy); extern void btm_ble_create_conn_cancel(); namespace { diff --git a/system/stack/btm/btm_ble_int.h b/system/stack/btm/btm_ble_int.h index 00c6aec5ab..dfb9f2277b 100644 --- a/system/stack/btm/btm_ble_int.h +++ b/system/stack/btm/btm_ble_int.h @@ -137,7 +137,6 @@ extern void btm_ble_adv_filter_init(void); extern bool btm_ble_topology_check(tBTM_BLE_STATE_MASK request); extern bool btm_ble_clear_topology_mask(tBTM_BLE_STATE_MASK request_state); extern bool btm_ble_set_topology_mask(tBTM_BLE_STATE_MASK request_state); -extern void btm_ble_set_random_address(const RawAddress& random_bda); extern void btm_ble_scanner_init(void); extern void btm_ble_scanner_cleanup(void); diff --git a/system/stack/btm/btm_inq.cc b/system/stack/btm/btm_inq.cc index f53c679907..b0c8be4dff 100644 --- a/system/stack/btm/btm_inq.cc +++ b/system/stack/btm/btm_inq.cc @@ -545,7 +545,8 @@ tBTM_STATUS BTM_StartInquiry(tBTM_INQ_RESULTS_CB* p_results_cb, btm_acl_update_inquiry_status(BTM_INQUIRY_STARTED); if (p_inq->inq_active & BTM_SSP_INQUIRY_ACTIVE) { - btm_process_inq_complete(BTM_NO_RESOURCES, BTM_GENERAL_INQUIRY); + btm_process_inq_complete(HCI_ERR_MAX_NUM_OF_CONNECTIONS, + BTM_GENERAL_INQUIRY); return BTM_CMD_STARTED; } @@ -1261,7 +1262,7 @@ void btm_sort_inq_result(void) { * Returns void * ******************************************************************************/ -void btm_process_inq_complete(uint8_t status, uint8_t mode) { +void btm_process_inq_complete(tHCI_STATUS status, uint8_t mode) { tBTM_CMPL_CB* p_inq_cb = btm_cb.btm_inq_vars.p_inq_cmpl_cb; tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars; @@ -1324,7 +1325,7 @@ void btm_process_inq_complete(uint8_t status, uint8_t mode) { * Returns void * ******************************************************************************/ -void btm_process_cancel_complete(uint8_t status, uint8_t mode) { +void btm_process_cancel_complete(tHCI_STATUS status, uint8_t mode) { btm_acl_update_inquiry_status(BTM_INQUIRY_CANCELLED); btm_process_inq_complete(status, mode); } @@ -1401,7 +1402,7 @@ tBTM_STATUS btm_initiate_rem_name(const RawAddress& remote_bda, uint8_t origin, * ******************************************************************************/ void btm_process_remote_name(const RawAddress* bda, const BD_NAME bdn, - uint16_t evt_len, uint8_t hci_status) { + uint16_t evt_len, tHCI_STATUS hci_status) { tBTM_REMOTE_DEV_NAME rem_name; tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars; tBTM_CMPL_CB* p_cb = p_inq->p_remname_cmpl_cb; diff --git a/system/stack/btm/btm_iso_impl.h b/system/stack/btm/btm_iso_impl.h index 623696ac31..e9cd6e8287 100644 --- a/system/stack/btm/btm_iso_impl.h +++ b/system/stack/btm/btm_iso_impl.h @@ -93,7 +93,7 @@ struct iso_impl { cig_create_cmpl_evt evt; LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; - LOG_ASSERT(len >= 3) << "Invalid packet length."; + LOG_ASSERT(len >= 3) << "Invalid packet length: " << +len; STREAM_TO_UINT8(evt.status, stream); STREAM_TO_UINT8(evt.cig_id, stream); @@ -104,7 +104,7 @@ struct iso_impl { if (evt.status == HCI_SUCCESS) { LOG_ASSERT(len >= (3) + (cis_cnt * sizeof(uint16_t))) - << "Invalid CIS count."; + << "Invalid CIS count: " << +cis_cnt; /* Remove entries for the reconfigured CIG */ if (evt_code == kIsoEventCigOnReconfigureCmpl) { @@ -138,7 +138,8 @@ struct iso_impl { void create_cig(uint8_t cig_id, struct iso_manager::cig_create_params cig_params) { - LOG_ASSERT(!IsCigKnown(cig_id)) << "Invalid cig - already exists."; + LOG_ASSERT(!IsCigKnown(cig_id)) + << "Invalid cig - already exists: " << +cig_id; btsnd_hcic_set_cig_params( cig_id, cig_params.sdu_itv_mtos, cig_params.sdu_itv_stom, @@ -151,7 +152,7 @@ struct iso_impl { void reconfigure_cig(uint8_t cig_id, struct iso_manager::cig_create_params cig_params) { - LOG_ASSERT(IsCigKnown(cig_id)) << "No such cig"; + LOG_ASSERT(IsCigKnown(cig_id)) << "No such cig: " << +cig_id; btsnd_hcic_set_cig_params( cig_id, cig_params.sdu_itv_mtos, cig_params.sdu_itv_stom, @@ -166,7 +167,7 @@ struct iso_impl { cig_remove_cmpl_evt evt; LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; - LOG_ASSERT(len == 2) << "Invalid packet length."; + LOG_ASSERT(len == 2) << "Invalid packet length: " << +len; STREAM_TO_UINT8(evt.status, stream); STREAM_TO_UINT8(evt.cig_id, stream); @@ -185,7 +186,7 @@ struct iso_impl { } void remove_cig(uint8_t cig_id) { - LOG_ASSERT(IsCigKnown(cig_id)) << "No such cig"; + LOG_ASSERT(IsCigKnown(cig_id)) << "No such cig: " << +cig_id; btsnd_hcic_remove_cig(cig_id, base::BindOnce(&iso_impl::on_remove_cig, base::Unretained(this))); @@ -196,7 +197,7 @@ struct iso_impl { uint16_t len) { uint8_t status; - LOG_ASSERT(len == 2) << "Invalid packet length: " << len; + LOG_ASSERT(len == 2) << "Invalid packet length: " << +len; STREAM_TO_UINT16(status, stream); @@ -205,7 +206,8 @@ struct iso_impl { if (status != HCI_SUCCESS) { auto cis = GetCisIfKnown(cis_param.cis_conn_handle); - LOG_ASSERT(cis != nullptr) << "No such cis"; + LOG_ASSERT(cis != nullptr) + << "No such cis: " << +cis_param.cis_conn_handle; evt.status = status; evt.cis_conn_hdl = cis_param.cis_conn_handle; @@ -219,7 +221,7 @@ struct iso_impl { void establish_cis(struct iso_manager::cis_establish_params conn_params) { for (auto& el : conn_params.conn_pairs) { auto cis = GetCisIfKnown(el.cis_conn_handle); - LOG_ASSERT(cis) << "No such cis"; + LOG_ASSERT(cis) << "No such cis: " << +el.cis_conn_handle; LOG_ASSERT(!(cis->state_flags & (kStateFlagIsConnected | kStateFlagIsConnecting))) << "Already connected or connecting"; @@ -233,7 +235,7 @@ struct iso_impl { void disconnect_cis(uint16_t cis_handle, uint8_t reason) { auto cis = GetCisIfKnown(cis_handle); - LOG_ASSERT(cis) << "No such cis"; + LOG_ASSERT(cis) << "No such cis: " << +cis_handle; LOG_ASSERT(cis->state_flags & kStateFlagIsConnected || cis->state_flags & kStateFlagIsConnecting) << "Not connected"; @@ -314,7 +316,7 @@ struct iso_impl { void remove_iso_data_path(uint16_t iso_handle, uint8_t data_path_dir) { iso_base* iso = GetIsoIfKnown(iso_handle); - LOG_ASSERT(iso != nullptr) << "No such iso connection"; + LOG_ASSERT(iso != nullptr) << "No such iso connection: " << loghex(iso_handle); LOG_ASSERT((iso->state_flags & kStateFlagHasDataPathSet) == kStateFlagHasDataPathSet) << "Data path not set"; @@ -371,7 +373,7 @@ struct iso_impl { void read_iso_link_quality(uint16_t iso_handle) { iso_base* iso = GetIsoIfKnown(iso_handle); if (iso == nullptr) { - LOG(ERROR) <<__func__ << "No such iso connection: " << +iso_handle; + LOG(ERROR) << __func__ << "No such iso connection: " << loghex(iso_handle); return; } @@ -414,14 +416,17 @@ struct iso_impl { uint16_t data_len) { iso_base* iso = GetIsoIfKnown(iso_handle); LOG_ASSERT(iso != nullptr) - << "No such iso connection handle: " << +iso_handle; + << "No such iso connection handle: " << loghex(iso_handle); if (!(iso->state_flags & kStateFlagIsBroadcast)) { - LOG_ASSERT(iso->state_flags & kStateFlagIsConnected) - << "CIS not established"; + if (!(iso->state_flags & kStateFlagIsConnected)) { + LOG(WARNING) << __func__ << "Cis handle: " << loghex(iso_handle) + << " not established"; + return; + } } LOG_ASSERT(iso->state_flags & kStateFlagHasDataPathSet) - << "Data path not set for handle: " << +iso_handle; + << "Data path not set for handle: " << loghex(iso_handle); /* Calculate sequence number for the ISO data packet. * It should be incremented by 1 every SDU Interval. @@ -449,14 +454,14 @@ struct iso_impl { void process_cis_est_pkt(uint8_t len, uint8_t* data) { cis_establish_cmpl_evt evt; - LOG_ASSERT(len == 28) << "Invalid packet length"; + LOG_ASSERT(len == 28) << "Invalid packet length: " << +len; LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; STREAM_TO_UINT8(evt.status, data); STREAM_TO_UINT16(evt.cis_conn_hdl, data); auto cis = GetCisIfKnown(evt.cis_conn_hdl); - LOG_ASSERT(cis != nullptr) << "No such cis"; + LOG_ASSERT(cis != nullptr) << "No such cis: " << +evt.cis_conn_hdl; cis->sync_info.first_sync_ts = bluetooth::common::time_get_os_boottime_us(); @@ -558,7 +563,7 @@ struct iso_impl { void process_create_big_cmpl_pkt(uint8_t len, uint8_t* data) { struct big_create_cmpl_evt evt; - LOG_ASSERT(len >= 18) << "Invalid packet length"; + LOG_ASSERT(len >= 18) << "Invalid packet length: " << +len; LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; STREAM_TO_UINT8(evt.status, data); @@ -576,9 +581,9 @@ struct iso_impl { uint8_t num_bis; STREAM_TO_UINT8(num_bis, data); - LOG_ASSERT(num_bis != 0) << "Invalid bis count"; + LOG_ASSERT(num_bis != 0) << "Bis count is 0"; LOG_ASSERT(len == (18 + num_bis * sizeof(uint16_t))) - << "Invalid packet length"; + << "Invalid packet length: " << len << ". Number of bis: " << +num_bis; uint32_t ts = bluetooth::common::time_get_os_boottime_us(); for (auto i = 0; i < num_bis; ++i) { @@ -604,7 +609,7 @@ struct iso_impl { void process_terminate_big_cmpl_pkt(uint8_t len, uint8_t* data) { struct big_terminate_cmpl_evt evt; - LOG_ASSERT(len == 2) << "Invalid packet length"; + LOG_ASSERT(len == 2) << "Invalid packet length: " << +len; LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; STREAM_TO_UINT8(evt.big_id, data); @@ -621,12 +626,13 @@ struct iso_impl { } } - LOG_ASSERT(is_known_handle) << "No such big"; + LOG_ASSERT(is_known_handle) << "No such big: " << +evt.big_id; big_callbacks_->OnBigEvent(kIsoEventBigOnTerminateCmpl, &evt); } void create_big(uint8_t big_id, struct big_create_params big_params) { - LOG_ASSERT(!IsBigKnown(big_id)) << "Invalid big - already exists"; + LOG_ASSERT(!IsBigKnown(big_id)) + << "Invalid big - already exists: " << +big_id; last_big_create_req_sdu_itv_ = big_params.sdu_itv; btsnd_hcic_create_big( @@ -637,7 +643,7 @@ struct iso_impl { } void terminate_big(uint8_t big_id, uint8_t reason) { - LOG_ASSERT(IsBigKnown(big_id)) << "No such big"; + LOG_ASSERT(IsBigKnown(big_id)) << "No such big: " << +big_id; btsnd_hcic_term_big(big_id, reason); } diff --git a/system/stack/btu/btu_hcif.cc b/system/stack/btu/btu_hcif.cc index 2d5abbfd92..7b6b876f7b 100644 --- a/system/stack/btu/btu_hcif.cc +++ b/system/stack/btu/btu_hcif.cc @@ -952,7 +952,7 @@ static void btu_hcif_inquiry_comp_evt(uint8_t* p) { STREAM_TO_UINT8(status, p); /* Tell inquiry processing that we are done */ - btm_process_inq_complete(status, BTM_BR_INQUIRY_MASK); + btm_process_inq_complete(to_hci_status_code(status), BTM_BR_INQUIRY_MASK); } /******************************************************************************* @@ -1091,10 +1091,9 @@ static void btu_hcif_rmt_name_request_comp_evt(const uint8_t* p, evt_len -= (1 + BD_ADDR_LEN); - btm_process_remote_name(&bd_addr, p, evt_len, status); + btm_process_remote_name(&bd_addr, p, evt_len, to_hci_status_code(status)); - btm_sec_rmt_name_request_complete(&bd_addr, p, - static_cast<tHCI_STATUS>(status)); + btm_sec_rmt_name_request_complete(&bd_addr, p, to_hci_status_code(status)); } constexpr uint8_t MIN_KEY_SIZE = 7; @@ -1423,7 +1422,8 @@ static void btu_hcif_hdl_command_status(uint16_t opcode, uint8_t status, case HCI_INQUIRY: if (status != HCI_SUCCESS) { // Tell inquiry processing that we are done - btm_process_inq_complete(status, BTM_BR_INQUIRY_MASK); + btm_process_inq_complete(to_hci_status_code(status), + BTM_BR_INQUIRY_MASK); } break; case HCI_SWITCH_ROLE: @@ -1460,9 +1460,10 @@ static void btu_hcif_hdl_command_status(uint16_t opcode, uint8_t status, case HCI_RMT_NAME_REQUEST: if (status != HCI_SUCCESS) { // Tell inquiry processing that we are done - btm_process_remote_name(nullptr, nullptr, 0, status); + btm_process_remote_name(nullptr, nullptr, 0, + to_hci_status_code(status)); btm_sec_rmt_name_request_complete(nullptr, nullptr, - static_cast<tHCI_STATUS>(status)); + to_hci_status_code(status)); } break; case HCI_READ_RMT_EXT_FEATURES: diff --git a/system/stack/eatt/eatt.h b/system/stack/eatt/eatt.h index d2071ab7a1..2eac63118d 100644 --- a/system/stack/eatt/eatt.h +++ b/system/stack/eatt/eatt.h @@ -99,6 +99,9 @@ class EattChannel { class EattExtension { public: EattExtension(); + EattExtension(const EattExtension&) = delete; + EattExtension& operator=(const EattExtension&) = delete; + virtual ~EattExtension(); static EattExtension* GetInstance() { @@ -277,8 +280,6 @@ class EattExtension { private: struct impl; std::unique_ptr<impl> pimpl_; - - DISALLOW_COPY_AND_ASSIGN(EattExtension); }; } // namespace eatt diff --git a/system/stack/hcic/hcicmds.cc b/system/stack/hcic/hcicmds.cc index fa5ea76e43..49f68001be 100644 --- a/system/stack/hcic/hcicmds.cc +++ b/system/stack/hcic/hcicmds.cc @@ -421,6 +421,8 @@ void bte_main_hci_send(BT_HDR* p_msg, uint16_t event); #define HCI_WRITE_IAC_LAP_LAP_OFF 1 /* Write Current IAC LAP */ +#define HCIC_PARAM_SIZE_CONFIGURE_DATA_PATH 3 + /******************************************************************************* * BLE Commands * Note: "local_controller_id" is for transport, not counted in HCI @@ -1880,11 +1882,11 @@ void btsnd_hcic_configure_data_path(uint8_t data_path_direction, BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); uint8_t* pp = (uint8_t*)(p + 1); uint8_t size = static_cast<uint8_t>(vendor_config.size()); - p->len = HCIC_PREAMBLE_SIZE + 3 + size; + p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_CONFIGURE_DATA_PATH + size; p->offset = 0; UINT16_TO_STREAM(pp, HCI_CONFIGURE_DATA_PATH); - UINT8_TO_STREAM(pp, p->len); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_CONFIGURE_DATA_PATH + size); UINT8_TO_STREAM(pp, data_path_direction); UINT8_TO_STREAM(pp, data_path_id); UINT8_TO_STREAM(pp, vendor_config.size()); @@ -1899,170 +1901,9 @@ bluetooth::legacy::hci::Interface interface_ = { // LINK_CONTROL .StartInquiry = btsnd_hcic_inquiry, // OCF 0x0401 .InquiryCancel = btsnd_hcic_inq_cancel, // OCF 0x0402 - .StartPeriodicInquiryMode = btsnd_hcic_per_inq_mode, // OCF 0x0403 - .ExitPeriodicInquiryMode = btsnd_hcic_exit_per_inq, // OCF 0x0404 - .CreateConnection = btsnd_hcic_create_conn, // OCF 0x0405 .Disconnect = btsnd_hcic_disconnect, // OCF 0x0406 - // UNUSED OCF 0x0407 btsnd_hcic_add_SCO_conn - .CreateConnectionCancel = btsnd_hcic_create_conn_cancel, // OCF 0x0408 - .AcceptConnectionRequest = btsnd_hcic_accept_conn, // OCF 0x0409 - .RejectConnectionRequest = btsnd_hcic_reject_conn, // OCF 0x040A - .LinkKeyRequestReply = btsnd_hcic_link_key_req_reply, // OCF 0x040B - .LinkKeyRequestNegativeReply = - btsnd_hcic_link_key_neg_reply, // OCF 0x040C, - .PinCodeRequestReply = btsnd_hcic_pin_code_req_reply, // OCF 0x040D, - .PinCodeRequestNegativeReply = - btsnd_hcic_pin_code_neg_reply, // OCF 0x040E, .ChangeConnectionPacketType = btsnd_hcic_change_conn_type, // OCF 0x040F, - // UNUSED OCF 0x0410 - .AuthenticationRequested = btsnd_hcic_auth_request, // OCF 0x0411, - // UNUSED OCF 0x0412 - .SetConnectionEncryption = btsnd_hcic_set_conn_encrypt, // OCF 0x0413, - // UNUSED OCF 0x0414 - .ChangeConnectionLinkKey = nullptr, // OCF 0x0415, - // UNUSED OCF 0x0416 - .CentralLinkKey = nullptr, // OCF 0x0417, - // UNUSED OCF 0x0418 - .RemoteNameRequest = btsnd_hcic_rmt_name_req, // OCF 0x0419, - .RemoteNameRequestCancel = btsnd_hcic_rmt_name_req_cancel, // OCF 0x041A, - .ReadRemoteSupportedFeatures = btsnd_hcic_rmt_features_req, // OCF 0x041B, - .ReadRemoteExtendedFeatures = btsnd_hcic_rmt_ext_features, // OCF 0x041C, - .ReadRemoteVersionInformation = btsnd_hcic_rmt_ver_req, // OCF 0x041D, - // UNUSED OCF 0x041E - .ReadClockOffset = btsnd_hcic_read_rmt_clk_offset, // OCF 0x041F, - .ReadLmpHandle = btsnd_hcic_read_lmp_handle, // OCF 0x0420, - // UNUSED OCF 0x0420 - 0x0427 - .SetupSynchronousConnection = btsnd_hcic_setup_esco_conn, // OCF 0x0428, - .AcceptSynchronousConnection = btsnd_hcic_accept_esco_conn, // OCF 0x0429, - .RejectSynchronousConnection = btsnd_hcic_reject_esco_conn, // OCF 0x042A, - .IoCapabilityRequestReply = btsnd_hcic_io_cap_req_reply, // OCF 0x042B, - .UserConfirmationRequestReply = btsnd_hcic_user_conf_reply, // OCF 0x042C, - .UserConfirmationRequestNegativeReply = - btsnd_hcic_user_conf_reply, // OCF 0x042D, - .UserPasskeyRequestReply = btsnd_hcic_user_passkey_reply, // OCF 0x042E, - .UserPasskeyRequestNegativeReply = - btsnd_hcic_user_passkey_neg_reply, // OCF 0x042F, - .RemoteOobDataRequestReply = btsnd_hcic_rem_oob_reply, // OCF 0x0430, - // UNUSED OCF 0x0431 - 0x0432 - .RemoteOobDataRequestNegativeReply = - btsnd_hcic_rem_oob_neg_reply, // OCF 0x0433, - .IoCapabilityRequestNegativeReply = - btsnd_hcic_io_cap_req_neg_reply, // OCF 0x0434, - // UNUSED OCF 0x0435 - 0x043C - .EnhancedSetupSynchronousConnection = - btsnd_hcic_enhanced_set_up_synchronous_connection, // OCF 0x043D, - .EnhancedAcceptSynchronousConnection = - btsnd_hcic_enhanced_accept_synchronous_connection, // OCF 0x043E, - // UNUSED OCF 0x043F - 0x0444 - .RemoteOobExtendedDataRequestReply = nullptr, // OCF 0x0445, - - // LINK_POLICY - .HoldMode = btsnd_hcic_hold_mode, // OCF 0x0801, - // UNUSED OCF 0x0802 - .SniffMode = btsnd_hcic_sniff_mode, // OCF 0x0803, - .ExitSniffMode = btsnd_hcic_exit_sniff_mode, // OCF 0x0804, - // UNUSED OCF 0x0805 - 0x0806 - .QosSetup = btsnd_hcic_qos_setup, // OCF 0x0807, - // UNUSED OCF 0x0808 - .RoleDiscovery = nullptr, // OCF 0x0809, - // UNUSED OCF 0x080A .StartRoleSwitch = btsnd_hcic_switch_role, // OCF 0x080B, - .ReadLinkPolicySettings = nullptr, // OCF 0x080C, - .WriteLinkPolicySettings = btsnd_hcic_write_policy_set, // OCF 0x080D, - .ReadDefaultLinkPolicySettings = nullptr, // OCF 0x080E, - .WriteDefaultLinkPolicySettings = - btsnd_hcic_write_def_policy_set, // OCF 0x080F, - .FlowSpecification = nullptr, // OCF 0x0810, - .SniffSubrating = btsnd_hcic_sniff_sub_rate, // OCF 0x0811, - - // CONTROLLER_AND_BASEBAND - .SetEventMask = nullptr, // OCF 0x0C01, - // UNUSED OCF 0x0C02 - .Reset = nullptr, // OCF 0x0C03, - // UNUSED OCF 0x0C04 - .SetEventFilter = btsnd_hcic_set_event_filter, // OCF 0x0C05, - // UNUSED OCF 0x0C06 = 0x0C07 - .Flush = nullptr, // OCF 0x0C08, - .ReadPinType = nullptr, // OCF 0x0C09, - .WritePinType = btsnd_hcic_write_pin_type, // OCF 0x0C0A, - .CreateNewUnitKey = nullptr, // OCF 0x0C0B, - // UNUSED OCF 0x0C0C - .ReadStoredLinkKey = nullptr, // OCF 0x0C0D, - // UNUSED OCF 0x0C0E - 0x0C10 - .WriteStoredLinkKey = nullptr, // OCF 0x0C11, - .DeleteStoredLinkKey = btsnd_hcic_delete_stored_key, // OCF 0x0C12, - .WriteLocalName = btsnd_hcic_change_name, // OCF 0x0C13, - .ReadLocalName = btsnd_hcic_read_name, // OCF 0x0C14, - .ReadConnectionAcceptTimeout = nullptr, // OCF 0x0C15, - .WriteConnectionAcceptTimeout = btsnd_hcic_write_page_tout, // OCF 0x0C16, - .ReadPageTimeout = nullptr, // OCF 0x0C17, - .WritePageTimeout = nullptr, // OCF 0x0C18, - .ReadScanEnable = nullptr, // OCF 0x0C19, - .WriteScanEnable = btsnd_hcic_write_scan_enable, // OCF 0x0C1A, - .ReadPageScanActivity = nullptr, // OCF 0x0C1B, - .WritePageScanActivity = btsnd_hcic_write_pagescan_cfg, // OCF 0x0C1C, - .ReadInquiryScanActivity = nullptr, // OCF 0x0C1D, - .WriteInquiryScanActivity = btsnd_hcic_write_inqscan_cfg, // OCF 0x0C1E, - .ReadAuthenticationEnable = nullptr, // OCF 0x0C1F, - // UNUSED OCF 0x0C20 - 0x0C22 - .ReadClassOfDevice = nullptr, // OCF 0x0C23, - .WriteClassOfDevice = btsnd_hcic_write_dev_class, // OCF 0x0C24, - .ReadVoiceSetting = nullptr, // OCF 0x0C25, - .WriteVoiceSetting = btsnd_hcic_write_voice_settings, // OCF 0x0C26, - .ReadAutomaticFlushTimeout = - btsnd_hcic_read_automatic_flush_timeout, // OCF 0x0C27, - .WriteAutomaticFlushTimeout = - btsnd_hcic_write_auto_flush_tout, // OCF 0x0C28, - .ReadNumBroadcastRetransmits = nullptr, // OCF 0x0C29, - .WriteNumBroadcastRetransmits = nullptr, // OCF 0x0C2A, - .ReadHoldModeActivity = nullptr, // OCF 0x0C2B, - .WriteHoldModeActivity = nullptr, // OCF 0x0C2C, - .ReadTransmitPowerLevel = btsnd_hcic_read_tx_power, // OCF 0x0C2D, - .ReadSynchronousFlowControlEnable = nullptr, // OCF 0x0C2E, - .WriteSynchronousFlowControlEnable = nullptr, // OCF 0x0C2F, - // UNUSED OCF 0x0C30 - .SetControllerToHostFlowControl = nullptr, // OCF 0x0C31, - // UNUSED OCF 0x0C32 - .HostBufferSize = nullptr, // OCF 0x0C33, - // UNUSED OCF 0x0C34 - .HostNumCompletedPackets = nullptr, // OCF 0x0C35, - .ReadLinkSupervisionTimeout = - btsnd_hcic_write_link_super_tout, // OCF 0x0C36, - .WriteLinkSupervisionTimeout = nullptr, // OCF 0x0C37, - .ReadNumberOfSupportedIac = nullptr, // OCF 0x0C38, - .ReadCurrentIacLap = nullptr, // OCF 0x0C39, - .WriteCurrentIacLap = btsnd_hcic_write_cur_iac_lap, // OCF 0x0C3A, - .SetAfhHostChannelClassification = nullptr, // OCF 0x0C3F, - .ReadInquiryScanType = nullptr, // OCF 0x0C42, - .WriteInquiryScanType = btsnd_hcic_write_inqscan_type, // OCF 0x0C43, - .ReadInquiryMode = nullptr, // OCF 0x0C44, - .WriteInquiryMode = btsnd_hcic_write_inquiry_mode, // OCF 0x0C45, - .ReadPageScanType = nullptr, // OCF 0x0C46, - .WritePageScanType = btsnd_hcic_write_pagescan_type, // OCF 0x0C47, - .ReadAfhChannelAssessmentMode = nullptr, // OCF 0x0C48, - .WriteAfhChannelAssessmentMode = nullptr, // OCF 0x0C49, - .ReadExtendedInquiryResponse = nullptr, // OCF 0x0C51, - .WriteExtendedInquiryResponse = - btsnd_hcic_write_ext_inquiry_response, // OCF 0x0C52, - .RefreshEncryptionKey = nullptr, // OCF 0x0C53, - .ReadSimplePairingMode = nullptr, // OCF 0x0C55, - .WriteSimplePairingMode = nullptr, // OCF 0x0C56, - .ReadLocalOobData = btsnd_hcic_read_local_oob_data, // OCF 0x0C57, - .ReadInquiryResponseTransmitPowerLevel = nullptr, // OCF 0x0C58, - .WriteInquiryTransmitPowerLevel = nullptr, // OCF 0x0C59, - .EnhancedFlush = btsnd_hcic_enhanced_flush, // OCF 0x0C5F, - .SendKeypressNotification = btsnd_hcic_send_keypress_notif, // OCF 0x0C60, - - // STATUS_PARAMETERS - .ReadFailedContactCounter = - btsnd_hcic_read_failed_contact_counter, // OCF 0x1401, - .ResetFailedContactCounter = nullptr, // OCF 0x1402, - .ReadLinkQuality = btsnd_hcic_get_link_quality, // OCF 0x1403, - // UNUSED OCF 0x1404 - .ReadRssi = btsnd_hcic_read_rssi, // OCF 0x1405, - .ReadAfhChannelMap = nullptr, // OCF 0x1406, - .ReadClock = nullptr, // OCF 0x1407, - .ReadEncryptionKeySize = nullptr, // OCF 0x1408, }; const bluetooth::legacy::hci::Interface& diff --git a/system/stack/include/bt_dev_class.h b/system/stack/include/bt_dev_class.h index a141c26863..e0a6305995 100644 --- a/system/stack/include/bt_dev_class.h +++ b/system/stack/include/bt_dev_class.h @@ -29,6 +29,99 @@ typedef uint8_t DEV_CLASS[DEV_CLASS_LEN]; /* Device class */ inline constexpr DEV_CLASS kDevClassEmpty = {}; #endif // __cplusplus +/* 0x00 is used as unclassified for all minor device classes */ +#define BTM_COD_MINOR_UNCLASSIFIED 0x00 +#define BTM_COD_MINOR_WEARABLE_HEADSET 0x04 +#define BTM_COD_MINOR_CONFM_HANDSFREE 0x08 +#define BTM_COD_MINOR_CAR_AUDIO 0x20 +#define BTM_COD_MINOR_SET_TOP_BOX 0x24 + +/* minor device class field for Peripheral Major Class */ +/* Bits 6-7 independently specify mouse, keyboard, or combo mouse/keyboard */ +#define BTM_COD_MINOR_KEYBOARD 0x40 +#define BTM_COD_MINOR_POINTING 0x80 +/* Bits 2-5 OR'd with selection from bits 6-7 */ +/* #define BTM_COD_MINOR_UNCLASSIFIED 0x00 */ +#define BTM_COD_MINOR_JOYSTICK 0x04 +#define BTM_COD_MINOR_GAMEPAD 0x08 +#define BTM_COD_MINOR_REMOTE_CONTROL 0x0C +#define BTM_COD_MINOR_DIGITIZING_TABLET 0x14 +#define BTM_COD_MINOR_CARD_READER 0x18 /* e.g. SIM card reader */ +#define BTM_COD_MINOR_DIGITAL_PAN 0x1C + +/* minor device class field for Imaging Major Class */ +/* Bits 5-7 independently specify display, camera, scanner, or printer */ +#define BTM_COD_MINOR_DISPLAY 0x10 +/* Bits 2-3 Reserved */ +/* #define BTM_COD_MINOR_UNCLASSIFIED 0x00 */ + +/* minor device class field for Wearable Major Class */ +/* Bits 2-7 meaningful */ +#define BTM_COD_MINOR_WRIST_WATCH 0x04 +#define BTM_COD_MINOR_GLASSES 0x14 + +/* minor device class field for Health Major Class */ +/* Bits 2-7 meaningful */ +#define BTM_COD_MINOR_BLOOD_MONITOR 0x04 +#define BTM_COD_MINOR_THERMOMETER 0x08 +#define BTM_COD_MINOR_WEIGHING_SCALE 0x0C +#define BTM_COD_MINOR_GLUCOSE_METER 0x10 +#define BTM_COD_MINOR_PULSE_OXIMETER 0x14 +#define BTM_COD_MINOR_HEART_PULSE_MONITOR 0x18 +#define BTM_COD_MINOR_STEP_COUNTER 0x20 + +/*************************** + * major device class field + ***************************/ +#define BTM_COD_MAJOR_COMPUTER 0x01 +#define BTM_COD_MAJOR_PHONE 0x02 +#define BTM_COD_MAJOR_AUDIO 0x04 +#define BTM_COD_MAJOR_PERIPHERAL 0x05 +#define BTM_COD_MAJOR_IMAGING 0x06 +#define BTM_COD_MAJOR_WEARABLE 0x07 +#define BTM_COD_MAJOR_HEALTH 0x09 +#define BTM_COD_MAJOR_UNCLASSIFIED 0x1F + +/*************************** + * service class fields + ***************************/ +#define BTM_COD_SERVICE_LMTD_DISCOVER 0x0020 +#define BTM_COD_SERVICE_LE_AUDIO 0x0040 +#define BTM_COD_SERVICE_POSITIONING 0x0100 +#define BTM_COD_SERVICE_NETWORKING 0x0200 +#define BTM_COD_SERVICE_RENDERING 0x0400 +#define BTM_COD_SERVICE_CAPTURING 0x0800 +#define BTM_COD_SERVICE_OBJ_TRANSFER 0x1000 +#define BTM_COD_SERVICE_AUDIO 0x2000 +#define BTM_COD_SERVICE_TELEPHONY 0x4000 +#define BTM_COD_SERVICE_INFORMATION 0x8000 + +/* class of device field macros */ +#define BTM_COD_MINOR_CLASS(u8, pd) \ + { (u8) = (pd)[2] & 0xFC; } +#define BTM_COD_MAJOR_CLASS(u8, pd) \ + { (u8) = (pd)[1] & 0x1F; } +#define BTM_COD_SERVICE_CLASS(u16, pd) \ + { \ + (u16) = (pd)[0]; \ + (u16) <<= 8; \ + (u16) += (pd)[1] & 0xE0; \ + } + +/* to set the fields (assumes that format type is always 0) */ +#define FIELDS_TO_COD(pd, mn, mj, sv) \ + { \ + (pd)[2] = mn; \ + (pd)[1] = (mj) + ((sv)&BTM_COD_SERVICE_CLASS_LO_B); \ + (pd)[0] = (sv) >> 8; \ + } + +/* the COD masks */ +#define BTM_COD_MINOR_CLASS_MASK 0xFC +#define BTM_COD_MAJOR_CLASS_MASK 0x1F +#define BTM_COD_SERVICE_CLASS_LO_B 0x00E0 +#define BTM_COD_SERVICE_CLASS_MASK 0xFFE0 + #define DEVCLASS_TO_STREAM(p, a) \ { \ int ijk; \ diff --git a/system/stack/include/btm_api_types.h b/system/stack/include/btm_api_types.h index 9999eafc10..981347ff4e 100644 --- a/system/stack/include/btm_api_types.h +++ b/system/stack/include/btm_api_types.h @@ -75,99 +75,6 @@ typedef void(tBTM_VSC_CMPL_CB)(tBTM_VSC_CMPL* p1); * minor device class field ****************************/ -/* 0x00 is used as unclassified for all minor device classes */ -#define BTM_COD_MINOR_UNCLASSIFIED 0x00 -#define BTM_COD_MINOR_WEARABLE_HEADSET 0x04 -#define BTM_COD_MINOR_CONFM_HANDSFREE 0x08 -#define BTM_COD_MINOR_CAR_AUDIO 0x20 -#define BTM_COD_MINOR_SET_TOP_BOX 0x24 - -/* minor device class field for Peripheral Major Class */ -/* Bits 6-7 independently specify mouse, keyboard, or combo mouse/keyboard */ -#define BTM_COD_MINOR_KEYBOARD 0x40 -#define BTM_COD_MINOR_POINTING 0x80 -/* Bits 2-5 OR'd with selection from bits 6-7 */ -/* #define BTM_COD_MINOR_UNCLASSIFIED 0x00 */ -#define BTM_COD_MINOR_JOYSTICK 0x04 -#define BTM_COD_MINOR_GAMEPAD 0x08 -#define BTM_COD_MINOR_REMOTE_CONTROL 0x0C -#define BTM_COD_MINOR_DIGITIZING_TABLET 0x14 -#define BTM_COD_MINOR_CARD_READER 0x18 /* e.g. SIM card reader */ -#define BTM_COD_MINOR_DIGITAL_PAN 0x1C - -/* minor device class field for Imaging Major Class */ -/* Bits 5-7 independently specify display, camera, scanner, or printer */ -#define BTM_COD_MINOR_DISPLAY 0x10 -/* Bits 2-3 Reserved */ -/* #define BTM_COD_MINOR_UNCLASSIFIED 0x00 */ - -/* minor device class field for Wearable Major Class */ -/* Bits 2-7 meaningful */ -#define BTM_COD_MINOR_WRIST_WATCH 0x04 -#define BTM_COD_MINOR_GLASSES 0x14 - -/* minor device class field for Health Major Class */ -/* Bits 2-7 meaningful */ -#define BTM_COD_MINOR_BLOOD_MONITOR 0x04 -#define BTM_COD_MINOR_THERMOMETER 0x08 -#define BTM_COD_MINOR_WEIGHING_SCALE 0x0C -#define BTM_COD_MINOR_GLUCOSE_METER 0x10 -#define BTM_COD_MINOR_PULSE_OXIMETER 0x14 -#define BTM_COD_MINOR_HEART_PULSE_MONITOR 0x18 -#define BTM_COD_MINOR_STEP_COUNTER 0x20 - -/*************************** - * major device class field - ***************************/ -#define BTM_COD_MAJOR_COMPUTER 0x01 -#define BTM_COD_MAJOR_PHONE 0x02 -#define BTM_COD_MAJOR_AUDIO 0x04 -#define BTM_COD_MAJOR_PERIPHERAL 0x05 -#define BTM_COD_MAJOR_IMAGING 0x06 -#define BTM_COD_MAJOR_WEARABLE 0x07 -#define BTM_COD_MAJOR_HEALTH 0x09 -#define BTM_COD_MAJOR_UNCLASSIFIED 0x1F - -/*************************** - * service class fields - ***************************/ -#define BTM_COD_SERVICE_LMTD_DISCOVER 0x0020 -#define BTM_COD_SERVICE_LE_AUDIO 0x0040 -#define BTM_COD_SERVICE_POSITIONING 0x0100 -#define BTM_COD_SERVICE_NETWORKING 0x0200 -#define BTM_COD_SERVICE_RENDERING 0x0400 -#define BTM_COD_SERVICE_CAPTURING 0x0800 -#define BTM_COD_SERVICE_OBJ_TRANSFER 0x1000 -#define BTM_COD_SERVICE_AUDIO 0x2000 -#define BTM_COD_SERVICE_TELEPHONY 0x4000 -#define BTM_COD_SERVICE_INFORMATION 0x8000 - -/* class of device field macros */ -#define BTM_COD_MINOR_CLASS(u8, pd) \ - { (u8) = (pd)[2] & 0xFC; } -#define BTM_COD_MAJOR_CLASS(u8, pd) \ - { (u8) = (pd)[1] & 0x1F; } -#define BTM_COD_SERVICE_CLASS(u16, pd) \ - { \ - (u16) = (pd)[0]; \ - (u16) <<= 8; \ - (u16) += (pd)[1] & 0xE0; \ - } - -/* to set the fields (assumes that format type is always 0) */ -#define FIELDS_TO_COD(pd, mn, mj, sv) \ - { \ - (pd)[2] = mn; \ - (pd)[1] = (mj) + ((sv)&BTM_COD_SERVICE_CLASS_LO_B); \ - (pd)[0] = (sv) >> 8; \ - } - -/* the COD masks */ -#define BTM_COD_MINOR_CLASS_MASK 0xFC -#define BTM_COD_MAJOR_CLASS_MASK 0x1F -#define BTM_COD_SERVICE_CLASS_LO_B 0x00E0 -#define BTM_COD_SERVICE_CLASS_MASK 0xFFE0 - /* BTM service definitions * Used for storing EIR data to bit mask */ diff --git a/system/stack/include/hcimsgs.h b/system/stack/include/hcimsgs.h index 2202d89efc..95ef118272 100644 --- a/system/stack/include/hcimsgs.h +++ b/system/stack/include/hcimsgs.h @@ -65,167 +65,9 @@ struct Interface { void (*StartInquiry)(const LAP inq_lap, uint8_t duration, uint8_t response_cnt); void (*InquiryCancel)(); - void (*StartPeriodicInquiryMode)(uint16_t max_period, uint16_t min_period, - const LAP inq_lap, uint8_t duration, - uint8_t response_cnt); - void (*ExitPeriodicInquiryMode)(); - void (*CreateConnection)(const RawAddress& dest, uint16_t packet_types, - uint8_t page_scan_rep_mode, uint8_t page_scan_mode, - uint16_t clock_offset, uint8_t allow_switch); void (*Disconnect)(uint16_t handle, uint8_t reason); - // UNUSED 0x0407 btsnd_hcic_add_SCO_conn - void (*CreateConnectionCancel)(const RawAddress& dest); - void (*AcceptConnectionRequest)(const RawAddress& dest, uint8_t role); - void (*RejectConnectionRequest)(const RawAddress& dest, uint8_t reason); - void (*LinkKeyRequestReply)(const RawAddress& bd_addr, - const LinkKey& link_key); - void (*LinkKeyRequestNegativeReply)(const RawAddress& bd_addr); - void (*PinCodeRequestReply)(const RawAddress& bd_addr, uint8_t pin_code_len, - PIN_CODE pin_code); - void (*PinCodeRequestNegativeReply)(const RawAddress& bd_addr); void (*ChangeConnectionPacketType)(uint16_t handle, uint16_t packet_types); - void (*AuthenticationRequested)(uint16_t handle); - void (*SetConnectionEncryption)(uint16_t handle, bool enable); - void (*ChangeConnectionLinkKey)(); // 0x0415, - // UNUSED 0x0416 - void (*CentralLinkKey)(); // 0x0417, - void (*RemoteNameRequest)(const RawAddress& bd_addr, - uint8_t page_scan_rep_mode, uint8_t page_scan_mode, - uint16_t clock_offset); - void (*RemoteNameRequestCancel)(const RawAddress& bd_addr); - void (*ReadRemoteSupportedFeatures)(uint16_t handle); - void (*ReadRemoteExtendedFeatures)(uint16_t handle, uint8_t page_num); - void (*ReadRemoteVersionInformation)(uint16_t handle); - void (*ReadClockOffset)(uint16_t handle); - void (*ReadLmpHandle)(uint16_t handle); - void (*SetupSynchronousConnection)(uint16_t handle, - uint32_t transmit_bandwidth, - uint32_t receive_bandwidth, - uint16_t max_latency, uint16_t voice, - uint8_t retrans_effort, - uint16_t packet_types); - void (*AcceptSynchronousConnection)( - const RawAddress& bd_addr, uint32_t transmit_bandwidth, - uint32_t receive_bandwidth, uint16_t max_latency, uint16_t content_fmt, - uint8_t retrans_effort, uint16_t packet_types); - void (*RejectSynchronousConnection)(const RawAddress& bd_addr, - uint8_t reason); - void (*IoCapabilityRequestReply)(const RawAddress& bd_addr, - uint8_t capability, uint8_t oob_present, - uint8_t auth_req); - void (*UserConfirmationRequestReply)(const RawAddress& bd_addr, bool is_yes); - void (*UserConfirmationRequestNegativeReply)(const RawAddress& bd_addr, - bool is_yes); - void (*UserPasskeyRequestReply)(const RawAddress& bd_addr, uint32_t value); - void (*UserPasskeyRequestNegativeReply)(const RawAddress& bd_addr); - void (*RemoteOobDataRequestReply)(const RawAddress& bd_addr, const Octet16& c, - const Octet16& r); - void (*RemoteOobDataRequestNegativeReply)(const RawAddress& bd_addr); - void (*IoCapabilityRequestNegativeReply)(const RawAddress& bd_addr, - uint8_t err_code); - void (*EnhancedSetupSynchronousConnection)(uint16_t conn_handle, - enh_esco_params_t* p_params); - void (*EnhancedAcceptSynchronousConnection)(const RawAddress& bd_addr, - enh_esco_params_t* p_params); - void (*RemoteOobExtendedDataRequestReply)(); - - // LINK_POLICY 0x08xx - void (*HoldMode)(uint16_t handle, uint16_t max_hold_period, - uint16_t min_hold_period); - void (*SniffMode)(uint16_t handle, uint16_t max_sniff_period, - uint16_t min_sniff_period, uint16_t sniff_attempt, - uint16_t sniff_timeout); - void (*ExitSniffMode)(uint16_t handle); - void (*QosSetup)(uint16_t handle, uint8_t flags, uint8_t service_type, - uint32_t token_rate, uint32_t peak, uint32_t latency, - uint32_t delay_var); - // UNUSED 0x0808 - void (*RoleDiscovery)(); void (*StartRoleSwitch)(const RawAddress& bd_addr, uint8_t role); - void (*ReadLinkPolicySettings)(); - void (*WriteLinkPolicySettings)(uint16_t handle, uint16_t settings); - void (*ReadDefaultLinkPolicySettings)(); - void (*WriteDefaultLinkPolicySettings)(uint16_t settings); - void (*FlowSpecification)(); - void (*SniffSubrating)(uint16_t handle, uint16_t max_lat, - uint16_t min_remote_lat, uint16_t min_local_lat); - - // CONTROLLER_AND_BASEBAND 0x0Cxx - void (*SetEventMask)(); - void (*Reset)(); - void (*SetEventFilter)(uint8_t filt_type, uint8_t filt_cond_type, - uint8_t* filt_cond, uint8_t filt_cond_len); - void (*Flush)(); - void (*ReadPinType)(); - void (*WritePinType)(uint8_t type); - void (*CreateNewUnitKey)(); - void (*ReadStoredLinkKey)(); - void (*WriteStoredLinkKey)(); - void (*DeleteStoredLinkKey)(const RawAddress& bd_addr, bool delete_all_flag); - void (*WriteLocalName)(BD_NAME name); - void (*ReadLocalName)(); - void (*ReadConnectionAcceptTimeout)(); - void (*WriteConnectionAcceptTimeout)(uint16_t timeout); - void (*ReadPageTimeout)(); - void (*WritePageTimeout)(); - void (*ReadScanEnable)(); - void (*WriteScanEnable)(uint8_t flag); - void (*ReadPageScanActivity)(); - void (*WritePageScanActivity)(uint16_t interval, uint16_t window); - void (*ReadInquiryScanActivity)(); - void (*WriteInquiryScanActivity)(uint16_t interval, uint16_t window); - void (*ReadAuthenticationEnable)(); - void (*WriteAuthenticationEnable)(uint8_t flag); - void (*ReadClassOfDevice)(); - void (*WriteClassOfDevice)(DEV_CLASS dev_class); - void (*ReadVoiceSetting)(); - void (*WriteVoiceSetting)(uint16_t flags); - void (*ReadAutomaticFlushTimeout)(uint16_t handle); - void (*WriteAutomaticFlushTimeout)(uint16_t handle, uint16_t tout); - void (*ReadNumBroadcastRetransmits)(); - void (*WriteNumBroadcastRetransmits)(); - void (*ReadHoldModeActivity)(); - void (*WriteHoldModeActivity)(); - void (*ReadTransmitPowerLevel)(uint16_t handle, uint8_t type); - void (*ReadSynchronousFlowControlEnable)(); - void (*WriteSynchronousFlowControlEnable)(); - void (*SetControllerToHostFlowControl)(); - void (*HostBufferSize)(); - void (*HostNumCompletedPackets)(); - void (*ReadLinkSupervisionTimeout)(uint16_t handle, uint16_t timeout); - void (*WriteLinkSupervisionTimeout)(); - void (*ReadNumberOfSupportedIac)(); - void (*ReadCurrentIacLap)(); - void (*WriteCurrentIacLap)(uint8_t num_cur_iac, LAP* const iac_lap); - void (*SetAfhHostChannelClassification)(); - void (*ReadInquiryScanType)(); - void (*WriteInquiryScanType)(uint8_t type); - void (*ReadInquiryMode)(); // 0x0C44, - void (*WriteInquiryMode)(uint8_t mode); - void (*ReadPageScanType)(); // 0x0C46, - void (*WritePageScanType)(uint8_t type); - void (*ReadAfhChannelAssessmentMode)(); - void (*WriteAfhChannelAssessmentMode)(); - void (*ReadExtendedInquiryResponse)(); - void (*WriteExtendedInquiryResponse)(void* buffer, uint8_t fec_req); - void (*RefreshEncryptionKey)(); - void (*ReadSimplePairingMode)(); - void (*WriteSimplePairingMode)(); - void (*ReadLocalOobData)(); - void (*ReadInquiryResponseTransmitPowerLevel)(); - void (*WriteInquiryTransmitPowerLevel)(); - void (*EnhancedFlush)(uint16_t handle, uint8_t packet_type); - void (*SendKeypressNotification)(const RawAddress& bd_addr, uint8_t notif); - - // STATUS_PARAMETER 0x14xxS - void (*ReadFailedContactCounter)(uint16_t handle); - void (*ResetFailedContactCounter)(); - void (*ReadLinkQuality)(uint16_t handle); - // UNUSED 0x1404 - void (*ReadRssi)(uint16_t handle); - void (*ReadAfhChannelMap)(); - void (*ReadClock)(); - void (*ReadEncryptionKeySize)(); }; const Interface& GetInterface(); diff --git a/system/stack/include/inq_hci_link_interface.h b/system/stack/include/inq_hci_link_interface.h index 6ceaae6be2..7d88994520 100644 --- a/system/stack/include/inq_hci_link_interface.h +++ b/system/stack/include/inq_hci_link_interface.h @@ -24,13 +24,13 @@ #include "types/raw_address.h" extern void btm_process_remote_name(const RawAddress* bda, const BD_NAME name, - uint16_t evt_len, uint8_t hci_status); + uint16_t evt_len, tHCI_STATUS hci_status); extern void btm_process_inq_results(const uint8_t* p, uint8_t hci_evt_len, uint8_t inq_res_mode); -extern void btm_process_inq_complete(uint8_t status, uint8_t mode); -extern void btm_process_cancel_complete(uint8_t status, uint8_t mode); +extern void btm_process_inq_complete(tHCI_STATUS status, uint8_t mode); +extern void btm_process_cancel_complete(tHCI_STATUS status, uint8_t mode); extern void btm_acl_process_sca_cmpl_pkt(uint8_t len, uint8_t* data); extern tINQ_DB_ENT* btm_inq_db_new(const RawAddress& p_bda); diff --git a/system/stack/l2cap/l2c_api.cc b/system/stack/l2cap/l2c_api.cc index b0d7d330a9..41adef29d3 100644 --- a/system/stack/l2cap/l2c_api.cc +++ b/system/stack/l2cap/l2c_api.cc @@ -32,11 +32,11 @@ #include <cstdint> #include <string> -#include "btm_sec.h" #include "device/include/controller.h" // TODO Remove #include "main/shim/shim.h" #include "osi/include/allocator.h" #include "osi/include/log.h" +#include "stack/btm/btm_sec.h" #include "stack/include/bt_hdr.h" #include "stack/include/l2c_api.h" #include "stack/l2cap/l2c_int.h" diff --git a/system/stack/l2cap/l2c_ble.cc b/system/stack/l2cap/l2c_ble.cc index 113723efc3..3e5eb7a516 100644..100755 --- a/system/stack/l2cap/l2c_ble.cc +++ b/system/stack/l2cap/l2c_ble.cc @@ -28,11 +28,8 @@ #include <base/strings/stringprintf.h> #include "bt_target.h" -#include "bta_hearing_aid_api.h" +#include "bta/include/bta_hearing_aid_api.h" #include "device/include/controller.h" -#include "l2c_api.h" -#include "l2c_int.h" -#include "l2cdefs.h" #include "main/shim/l2c_api.h" #include "main/shim/shim.h" #include "osi/include/allocator.h" @@ -41,6 +38,9 @@ #include "stack/btm/btm_dev.h" #include "stack/btm/btm_sec.h" #include "stack/include/acl_api.h" +#include "stack/include/l2c_api.h" +#include "stack/include/l2cdefs.h" +#include "stack/l2cap/l2c_int.h" #include "stack_config.h" #include "types/raw_address.h" @@ -671,7 +671,7 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) { con_info.l2cap_result = L2CAP_LE_RESULT_INVALID_PARAMETERS; l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CREDIT_BASED_CONNECT_RSP_NEG, &con_info); - break; + return; } /* At least some of the channels has been created and parameters are @@ -698,8 +698,27 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) { for (int i = 0; i < p_lcb->pending_ecoc_conn_cnt; i++) { uint16_t cid = p_lcb->pending_ecoc_connection_cids[i]; + STREAM_TO_UINT16(rcid, p); + /* if duplicated remote cid then disconnect original channel + * and current channel by sending event to upper layer */ + temp_p_ccb = l2cu_find_ccb_by_remote_cid(p_lcb, rcid); + if (temp_p_ccb != nullptr) { + L2CAP_TRACE_ERROR( + "Already Allocated Destination cid. " + "rcid = %d " + "send peer_disc_req", rcid); + + l2cu_send_peer_disc_req(temp_p_ccb); + + temp_p_ccb = l2cu_find_ccb_by_cid(p_lcb, cid); + con_info.l2cap_result = L2CAP_LE_RESULT_UNACCEPTABLE_PARAMETERS; + l2c_csm_execute(temp_p_ccb, L2CEVT_L2CAP_CREDIT_BASED_CONNECT_RSP_NEG, + &con_info); + continue; + } + temp_p_ccb = l2cu_find_ccb_by_cid(p_lcb, cid); - STREAM_TO_UINT16(temp_p_ccb->remote_cid, p); + temp_p_ccb->remote_cid = rcid; L2CAP_TRACE_DEBUG( "local cid = %d " @@ -779,7 +798,7 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) { return; } - if (p_ccb->peer_conn_cfg.mps > mps) { + if (p_ccb->peer_conn_cfg.mps > mps && num_of_channels > 1) { L2CAP_TRACE_WARNING( "L2CAP - rcvd config req mps reduction new mps < mps (%d < %d)", mtu, p_ccb->peer_conn_cfg.mtu); @@ -812,6 +831,11 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) { case L2CAP_CMD_CREDIT_BASED_RECONFIG_RES: { uint16_t result; + if (p + sizeof(uint16_t) > p_pkt_end) { + android_errorWriteLog(0x534e4554, "212694559"); + LOG(ERROR) << "invalid read"; + return; + } STREAM_TO_UINT16(result, p); L2CAP_TRACE_DEBUG( @@ -1022,7 +1046,7 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) { l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DISCONNECT_REQ, NULL); } } else - l2cu_send_peer_disc_rsp(p_lcb, id, lcid, rcid); + l2cu_send_peer_cmd_reject(p_lcb, L2CAP_CMD_REJ_INVALID_CID, id, 0, 0); break; diff --git a/system/stack/l2cap/l2c_csm.cc b/system/stack/l2cap/l2c_csm.cc index cd1cb3adf3..229c5042a0 100644..100755 --- a/system/stack/l2cap/l2c_csm.cc +++ b/system/stack/l2cap/l2c_csm.cc @@ -30,14 +30,14 @@ #include "bt_target.h" #include "common/time_util.h" -#include "l2c_int.h" -#include "l2cdefs.h" #include "main/shim/metrics_api.h" #include "osi/include/allocator.h" #include "osi/include/log.h" #include "stack/btm/btm_sec.h" #include "stack/include/acl_api.h" #include "stack/include/bt_hdr.h" +#include "stack/include/l2cdefs.h" +#include "stack/l2cap/l2c_int.h" /******************************************************************************/ /* L O C A L F U N C T I O N P R O T O T Y P E S */ @@ -823,12 +823,22 @@ static void l2c_csm_w4_l2ca_connect_rsp(tL2C_CCB* p_ccb, tL2CEVT event, for (int i = 0; i < p_ccb->p_lcb->pending_ecoc_conn_cnt; i++) { uint16_t cid = p_ccb->p_lcb->pending_ecoc_connection_cids[i]; + if (cid == 0) { + LOG_WARN("pending_ecoc_connection_cids[%d] is %d", i, cid); + continue; + } + tL2C_CCB* temp_p_ccb = l2cu_find_ccb_by_cid(p_ccb->p_lcb, cid); - auto it = std::find(p_ci->lcids.begin(), p_ci->lcids.end(), cid); - if (it != p_ci->lcids.end()) { - temp_p_ccb->chnl_state = CST_OPEN; - } else { - l2cu_release_ccb(temp_p_ccb); + if (temp_p_ccb) { + auto it = std::find(p_ci->lcids.begin(), p_ci->lcids.end(), cid); + if (it != p_ci->lcids.end()) { + temp_p_ccb->chnl_state = CST_OPEN; + } else { + l2cu_release_ccb(temp_p_ccb); + } + } + else { + LOG_WARN("temp_p_ccb is NULL, pending_ecoc_connection_cids[%d] is %d", i, cid); } } p_ccb->p_lcb->pending_ecoc_conn_cnt = 0; @@ -871,21 +881,22 @@ static void l2c_csm_w4_l2ca_connect_rsp(tL2C_CCB* p_ccb, tL2CEVT event, case L2CEVT_L2CA_CREDIT_BASED_CONNECT_RSP_NEG: p_ci = (tL2C_CONN_INFO*)p_data; - if (p_ccb->p_lcb && p_ccb->p_lcb->transport == BT_TRANSPORT_LE) { - l2cu_send_peer_credit_based_conn_res(p_ccb, p_ci->lcids, - p_ci->l2cap_result); - } alarm_cancel(p_ccb->l2c_ccb_timer); - for (int i = 0; i < p_ccb->p_lcb->pending_ecoc_conn_cnt; i++) { - uint16_t cid = p_ccb->p_lcb->pending_ecoc_connection_cids[i]; - tL2C_CCB* temp_p_ccb = l2cu_find_ccb_by_cid(p_ccb->p_lcb, cid); - l2cu_release_ccb(temp_p_ccb); - } - - p_ccb->p_lcb->pending_ecoc_conn_cnt = 0; - memset(p_ccb->p_lcb->pending_ecoc_connection_cids, 0, - L2CAP_CREDIT_BASED_MAX_CIDS); + if (p_ccb->p_lcb != nullptr) { + if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) { + l2cu_send_peer_credit_based_conn_res(p_ccb, p_ci->lcids, + p_ci->l2cap_result); + } + for (int i = 0; i < p_ccb->p_lcb->pending_ecoc_conn_cnt; i++) { + uint16_t cid = p_ccb->p_lcb->pending_ecoc_connection_cids[i]; + tL2C_CCB* temp_p_ccb = l2cu_find_ccb_by_cid(p_ccb->p_lcb, cid); + l2cu_release_ccb(temp_p_ccb); + } + p_ccb->p_lcb->pending_ecoc_conn_cnt = 0; + memset(p_ccb->p_lcb->pending_ecoc_connection_cids, 0, + L2CAP_CREDIT_BASED_MAX_CIDS); + } break; case L2CEVT_L2CA_CONNECT_RSP_NEG: p_ci = (tL2C_CONN_INFO*)p_data; diff --git a/system/stack/l2cap/l2c_fcr.cc b/system/stack/l2cap/l2c_fcr.cc index 6c17e502d3..1688e9b79a 100644 --- a/system/stack/l2cap/l2c_fcr.cc +++ b/system/stack/l2cap/l2c_fcr.cc @@ -29,13 +29,13 @@ #include <string.h> #include "common/time_util.h" -#include "l2c_api.h" -#include "l2c_int.h" -#include "l2cdefs.h" #include "osi/include/allocator.h" #include "osi/include/log.h" #include "stack/include/bt_hdr.h" #include "stack/include/bt_types.h" +#include "stack/include/l2c_api.h" +#include "stack/include/l2cdefs.h" +#include "stack/l2cap/l2c_int.h" /* Flag passed to retransmit_i_frames() when all packets should be retransmitted */ diff --git a/system/stack/l2cap/l2c_main.cc b/system/stack/l2cap/l2c_main.cc index b9bd0c148d..98b00cdfdf 100644 --- a/system/stack/l2cap/l2c_main.cc +++ b/system/stack/l2cap/l2c_main.cc @@ -27,15 +27,15 @@ #include <string.h> #include "bt_target.h" -#include "hcimsgs.h" -#include "l2c_api.h" -#include "l2c_int.h" -#include "l2cdefs.h" +#include "hcimsgs.h" // HCID_GET_ #include "main/shim/shim.h" #include "osi/include/allocator.h" #include "osi/include/log.h" #include "osi/include/osi.h" #include "stack/include/bt_hdr.h" +#include "stack/include/l2c_api.h" +#include "stack/include/l2cdefs.h" +#include "stack/l2cap/l2c_int.h" /******************************************************************************/ /* L O C A L F U N C T I O N P R O T O T Y P E S */ diff --git a/system/stack/l2cap/l2c_utils.cc b/system/stack/l2cap/l2c_utils.cc index ebb7a6d018..647e3ae9ea 100644..100755 --- a/system/stack/l2cap/l2c_utils.cc +++ b/system/stack/l2cap/l2c_utils.cc @@ -23,13 +23,11 @@ ******************************************************************************/ #define LOG_TAG "l2c_utils" +#include <base/logging.h> #include <stdio.h> #include <string.h> -#include "btm_api.h" #include "device/include/controller.h" -#include "l2c_int.h" -#include "l2cdefs.h" #include "main/shim/l2c_api.h" #include "main/shim/shim.h" #include "osi/include/allocator.h" @@ -37,11 +35,12 @@ #include "stack/btm/btm_sec.h" #include "stack/include/acl_api.h" #include "stack/include/bt_hdr.h" +#include "stack/include/btm_api.h" #include "stack/include/hci_error_code.h" +#include "stack/include/l2cdefs.h" +#include "stack/l2cap/l2c_int.h" #include "types/raw_address.h" -#include <base/logging.h> - tL2C_CCB* l2cu_get_next_channel_in_rr(tL2C_LCB* p_lcb); // TODO Move /******************************************************************************* @@ -2948,7 +2947,7 @@ void l2cu_reject_ble_connection(tL2C_CCB* p_ccb, uint8_t rem_id, uint16_t result) { if (p_ccb->ecoc) l2cu_reject_credit_based_conn_req( - p_ccb->p_lcb, rem_id, p_ccb->p_lcb->pending_ecoc_reconfig_cnt, result); + p_ccb->p_lcb, rem_id, p_ccb->p_lcb->pending_ecoc_conn_cnt, result); else l2cu_reject_ble_coc_connection(p_ccb->p_lcb, rem_id, result); } diff --git a/system/stack/test/ble_advertiser_test.cc b/system/stack/test/ble_advertiser_test.cc index b4a8b851b0..35855168f8 100644 --- a/system/stack/test/ble_advertiser_test.cc +++ b/system/stack/test/ble_advertiser_test.cc @@ -89,6 +89,9 @@ constexpr uint8_t COMPLETE = 0x03; // Complete extended advertising data class AdvertiserHciMock : public BleAdvertiserHciInterface { public: AdvertiserHciMock() = default; + AdvertiserHciMock(const AdvertiserHciMock&) = delete; + AdvertiserHciMock& operator=(const AdvertiserHciMock&) = delete; + ~AdvertiserHciMock() override = default; MOCK_METHOD1(ReadInstanceCount, @@ -133,9 +136,6 @@ class AdvertiserHciMock : public BleAdvertiserHciInterface { }; bool QuirkAdvertiserZeroHandle() override { return false; } - - private: - DISALLOW_COPY_AND_ASSIGN(AdvertiserHciMock); }; } // namespace diff --git a/system/stack/test/btm_iso_test.cc b/system/stack/test/btm_iso_test.cc index 94e77fceba..f4984296f7 100644 --- a/system/stack/test/btm_iso_test.cc +++ b/system/stack/test/btm_iso_test.cc @@ -69,6 +69,9 @@ namespace { class MockCigCallbacks : public bluetooth::hci::iso_manager::CigCallbacks { public: MockCigCallbacks() = default; + MockCigCallbacks(const MockCigCallbacks&) = delete; + MockCigCallbacks& operator=(const MockCigCallbacks&) = delete; + ~MockCigCallbacks() override = default; MOCK_METHOD((void), OnSetupIsoDataPath, @@ -86,14 +89,14 @@ class MockCigCallbacks : public bluetooth::hci::iso_manager::CigCallbacks { MOCK_METHOD((void), OnCisEvent, (uint8_t event, void* data), (override)); MOCK_METHOD((void), OnCigEvent, (uint8_t event, void* data), (override)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockCigCallbacks); }; class MockBigCallbacks : public bluetooth::hci::iso_manager::BigCallbacks { public: MockBigCallbacks() = default; + MockBigCallbacks(const MockBigCallbacks&) = delete; + MockBigCallbacks& operator=(const MockBigCallbacks&) = delete; + ~MockBigCallbacks() override = default; MOCK_METHOD((void), OnSetupIsoDataPath, @@ -104,9 +107,6 @@ class MockBigCallbacks : public bluetooth::hci::iso_manager::BigCallbacks { (override)); MOCK_METHOD((void), OnBigEvent, (uint8_t event, void* data), (override)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockBigCallbacks); }; } // namespace @@ -1288,7 +1288,8 @@ TEST_F(IsoManagerDeathTest, CreateBigInvalidResponsePacket) { }); ASSERT_EXIT(IsoManager::GetInstance()->CreateBig(0x01, kDefaultBigParams), - ::testing::KilledBySignal(SIGABRT), "Invalid bis count"); + ::testing::KilledBySignal(SIGABRT), + "num_bis != 0. Bis count is 0"); } TEST_F(IsoManagerDeathTest, CreateBigInvalidResponsePacket2) { @@ -1804,6 +1805,17 @@ TEST_F(IsoManagerTest, RemoveIsoDataPathInvalidStatus) { iso_handle, kDefaultIsoDataPathParams.data_path_dir); } +TEST_F(IsoManagerTest, SendIsoDataWithNoCigConnected) { + std::vector<uint8_t> data_vec(108, 0); + IsoManager::GetInstance()->CreateCig( + volatile_test_cig_create_cmpl_evt_.cig_id, kDefaultCigParams); + + auto handle = volatile_test_cig_create_cmpl_evt_.conn_handles[0]; + IsoManager::GetInstance()->SendIsoData(handle, data_vec.data(), + data_vec.size()); + EXPECT_CALL(bte_interface_, HciSend).Times(0); +} + TEST_F(IsoManagerTest, SendIsoDataCigValid) { IsoManager::GetInstance()->CreateCig( volatile_test_cig_create_cmpl_evt_.cig_id, kDefaultCigParams); @@ -2136,17 +2148,6 @@ TEST_F(IsoManagerDeathTest, SendIsoDataWithNoCigBigHandle) { ::testing::KilledBySignal(SIGABRT), "No such iso"); } -TEST_F(IsoManagerDeathTest, SendIsoDataWithNoCigConnected) { - std::vector<uint8_t> data_vec(108, 0); - IsoManager::GetInstance()->CreateCig( - volatile_test_cig_create_cmpl_evt_.cig_id, kDefaultCigParams); - - auto handle = volatile_test_cig_create_cmpl_evt_.conn_handles[0]; - ASSERT_EXIT(IsoManager::GetInstance()->SendIsoData(handle, data_vec.data(), - data_vec.size()), - ::testing::KilledBySignal(SIGABRT), "CIS not established"); -} - TEST_F(IsoManagerTest, HandleDisconnectNoSuchHandle) { // Don't expect any callbacks when connection handle is not for ISO. EXPECT_CALL(*cig_callbacks_, OnCigEvent).Times(0); diff --git a/system/stack/test/common/mock_eatt.h b/system/stack/test/common/mock_eatt.h index 8b5d9d58ca..a7b6c5f867 100644 --- a/system/stack/test/common/mock_eatt.h +++ b/system/stack/test/common/mock_eatt.h @@ -27,6 +27,9 @@ using bluetooth::eatt::EattExtension; class MockEattExtension : public EattExtension { public: MockEattExtension() = default; + MockEattExtension(const MockEattExtension&) = delete; + MockEattExtension& operator=(const MockEattExtension&) = delete; + ~MockEattExtension() override = default; static MockEattExtension* GetInstance(); @@ -65,7 +68,4 @@ class MockEattExtension : public EattExtension { MOCK_METHOD((void), Start, ()); MOCK_METHOD((void), Stop, ()); - - private: - DISALLOW_COPY_AND_ASSIGN(MockEattExtension); }; diff --git a/system/stack/test/fuzzers/Android.bp b/system/stack/test/fuzzers/Android.bp index 1dd4f61d64..ca3c6a3afc 100644 --- a/system/stack/test/fuzzers/Android.bp +++ b/system/stack/test/fuzzers/Android.bp @@ -34,7 +34,6 @@ cc_defaults { "libbt-hci", "libbtdevice", "libg722codec", - "liblc3codec", "liblc3", "libosi", "libudrv-uipc", @@ -52,7 +51,6 @@ cc_defaults { "android.hardware.bluetooth.a2dp@1.0", "android.hardware.bluetooth.audio@2.0", "android.hardware.bluetooth.audio@2.1", - "android.hardware.bluetooth.audio@2.2", "android.hardware.bluetooth.audio-V1-ndk", "android.system.suspend.control-V1-ndk", "libaaudio", diff --git a/system/test/Android.bp b/system/test/Android.bp index fa07d7ec9e..7754163ae7 100644 --- a/system/test/Android.bp +++ b/system/test/Android.bp @@ -425,6 +425,13 @@ filegroup { } filegroup { + name: "TestCommonStackConfig", + srcs: [ + "common/stack_config.cc", + ], +} + +filegroup { name: "TestMockBluetoothInterface", srcs: [ "mock/mock_bluetooth_interface.cc", diff --git a/system/test/common/stack_config.cc b/system/test/common/stack_config.cc new file mode 100644 index 0000000000..db34351d73 --- /dev/null +++ b/system/test/common/stack_config.cc @@ -0,0 +1,51 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "internal_include/stack_config.h" + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include <cstdarg> +#include <cstring> + +const std::string kSmpOptions("mock smp options"); +bool get_trace_config_enabled(void) { return false; } +bool get_pts_avrcp_test(void) { return false; } +bool get_pts_secure_only_mode(void) { return false; } +bool get_pts_conn_updates_disabled(void) { return false; } +bool get_pts_crosskey_sdp_disable(void) { return false; } +const std::string* get_pts_smp_options(void) { return &kSmpOptions; } +int get_pts_smp_failure_case(void) { return 123; } +struct config_t; +config_t* get_all(void) { return nullptr; } +struct packet_fragmenter_t; +const packet_fragmenter_t* packet_fragmenter_get_interface() { return nullptr; } + +stack_config_t mock_stack_config{ + .get_trace_config_enabled = get_trace_config_enabled, + .get_pts_avrcp_test = get_pts_avrcp_test, + .get_pts_secure_only_mode = get_pts_secure_only_mode, + .get_pts_conn_updates_disabled = get_pts_conn_updates_disabled, + .get_pts_crosskey_sdp_disable = get_pts_crosskey_sdp_disable, + .get_pts_smp_options = get_pts_smp_options, + .get_pts_smp_failure_case = get_pts_smp_failure_case, + .get_all = get_all, +}; + +const stack_config_t* stack_config_get_interface(void) { + return &mock_stack_config; +} diff --git a/system/test/headless/Android.bp b/system/test/headless/Android.bp index b05e31c3c4..b0f6c343e2 100644 --- a/system/test/headless/Android.bp +++ b/system/test/headless/Android.bp @@ -49,7 +49,6 @@ cc_test { "libbtif", "libflatbuffers-cpp", "libg722codec", - "liblc3codec", "liblc3", "libosi", "libprotobuf-cpp-lite", @@ -61,7 +60,6 @@ cc_test { "android.hardware.bluetooth.a2dp@1.0", "android.hardware.bluetooth.audio@2.0", "android.hardware.bluetooth.audio@2.1", - "android.hardware.bluetooth.audio@2.2", "android.hardware.bluetooth.audio-V1-ndk", "android.hardware.bluetooth@1.0", "android.hardware.bluetooth@1.1", diff --git a/system/test/headless/headless.cc b/system/test/headless/headless.cc index d9b12fd2f7..498ae1a067 100644 --- a/system/test/headless/headless.cc +++ b/system/test/headless/headless.cc @@ -137,8 +137,7 @@ void link_quality_report(uint64_t timestamp, int report_id, int rssi, int snr, } /** Switch buffer size callback */ -void switch_buffer_size(RawAddress* remote_addr, - bool is_low_latency_buffer_size) { +void switch_buffer_size(bool is_low_latency_buffer_size) { LOG_INFO("%s", __func__); } diff --git a/system/test/mock/mock_bluetooth_interface.cc b/system/test/mock/mock_bluetooth_interface.cc index 8f1423e77a..4312828ff5 100644 --- a/system/test/mock/mock_bluetooth_interface.cc +++ b/system/test/mock/mock_bluetooth_interface.cc @@ -149,6 +149,8 @@ static bool allow_low_latency_audio(bool allowed, const RawAddress& address) { return true; } +static int clear_event_filter(void) { return 0; } + EXPORT_SYMBOL bt_interface_t bluetoothInterface = { sizeof(bluetoothInterface), init, @@ -188,7 +190,8 @@ EXPORT_SYMBOL bt_interface_t bluetoothInterface = { get_metric_id, set_dynamic_audio_buffer_size, generate_local_oob_data, - allow_low_latency_audio}; + allow_low_latency_audio, + clear_event_filter}; // callback reporting helpers diff --git a/system/test/mock/mock_bta_dm_act.h b/system/test/mock/mock_bta_dm_act.h index 2c99aa172d..5a566dcb7d 100644 --- a/system/test/mock/mock_bta_dm_act.h +++ b/system/test/mock/mock_bta_dm_act.h @@ -255,6 +255,15 @@ struct bta_dm_ble_observe { }; extern struct bta_dm_ble_observe bta_dm_ble_observe; +// Name: bta_dm_clear_event_filter +// Params: None +// Return: void +struct bta_dm_clear_event_filter { + std::function<void()> body{[]() {}}; + void operator()() { body(); }; +}; +extern struct bta_dm_clear_event_filter bta_dm_clear_event_filter; + // Name: bta_dm_ble_passkey_reply // Params: const RawAddress& bd_addr, bool accept, uint32_t passkey // Return: void diff --git a/system/test/mock/mock_bta_leaudio.cc b/system/test/mock/mock_bta_leaudio.cc index 1af8dbf369..ecb0114721 100644 --- a/system/test/mock/mock_bta_leaudio.cc +++ b/system/test/mock/mock_bta_leaudio.cc @@ -52,7 +52,10 @@ void LeAudioClient::AddFromStorage(const RawAddress& address, bool auto_connect) { mock_function_count_map[__func__]++; } -void LeAudioClient::Cleanup() { mock_function_count_map[__func__]++; } +void LeAudioClient::Cleanup(base::Callback<void()> cleanupCb) { + std::move(cleanupCb).Run(); + mock_function_count_map[__func__]++; +} LeAudioClient* LeAudioClient::Get(void) { mock_function_count_map[__func__]++; @@ -64,7 +67,15 @@ bool LeAudioClient::IsLeAudioClientRunning(void) { } void LeAudioClient::Initialize( bluetooth::le_audio::LeAudioClientCallbacks* callbacks_, - base::Closure initCb, base::Callback<bool()> hal_2_1_verifier) { + base::Closure initCb, base::Callback<bool()> hal_2_1_verifier, + const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>& + offloading_preference) { + mock_function_count_map[__func__]++; +} +void LeAudioClient::DebugDump(int fd) { mock_function_count_map[__func__]++; } +void LeAudioClient::InitializeAudioSetConfigurationProvider() { + mock_function_count_map[__func__]++; +} +void LeAudioClient::CleanupAudioSetConfigurationProvider() { mock_function_count_map[__func__]++; } -void LeAudioClient::DebugDump(int fd) { mock_function_count_map[__func__]++; }
\ No newline at end of file diff --git a/system/test/mock/mock_device_controller.cc b/system/test/mock/mock_device_controller.cc index bb89e7d0f9..32c7710f74 100644 --- a/system/test/mock/mock_device_controller.cc +++ b/system/test/mock/mock_device_controller.cc @@ -367,6 +367,8 @@ uint8_t get_le_all_initiating_phys() { return phy; } +tBTM_STATUS clear_event_filter() { return BTM_SUCCESS; } + const controller_t interface = { get_is_ready, @@ -451,7 +453,8 @@ const controller_t interface = { get_ble_resolving_list_max_size, set_ble_resolving_list_max_size, get_local_supported_codecs, - get_le_all_initiating_phys}; + get_le_all_initiating_phys, + clear_event_filter}; } // namespace device_controller } // namespace mock diff --git a/system/test/mock/mock_le_audio_hal_verifier.cc b/system/test/mock/mock_le_audio_hal_verifier.cc index 9c378edf24..8d729236c6 100644 --- a/system/test/mock/mock_le_audio_hal_verifier.cc +++ b/system/test/mock/mock_le_audio_hal_verifier.cc @@ -29,3 +29,8 @@ bool LeAudioHalVerifier::SupportsLeAudioHardwareOffload() { mock_function_count_map[__func__]++; return true; } + +bool LeAudioHalVerifier::SupportsLeAudioBroadcast() { + mock_function_count_map[__func__]++; + return true; +} diff --git a/system/test/mock/mock_main_shim_btm_api.cc b/system/test/mock/mock_main_shim_btm_api.cc index f0223d2b60..a2a13194c4 100644 --- a/system/test/mock/mock_main_shim_btm_api.cc +++ b/system/test/mock/mock_main_shim_btm_api.cc @@ -432,3 +432,8 @@ void btm_api_process_inquiry_result_with_rssi(RawAddress raw_address, int8_t rssi) { mock_function_count_map[__func__]++; } + +tBTM_STATUS bluetooth::shim::BTM_ClearEventFilter() { + mock_function_count_map[__func__]++; + return BTM_SUCCESS; +} diff --git a/system/test/mock/mock_main_shim_metrics_api.cc b/system/test/mock/mock_main_shim_metrics_api.cc index 1b638395b0..25b32283fc 100644 --- a/system/test/mock/mock_main_shim_metrics_api.cc +++ b/system/test/mock/mock_main_shim_metrics_api.cc @@ -174,5 +174,9 @@ void bluetooth::shim::LogMetricManufacturerInfo( raw_address, source_type, source_name, manufacturer, model, hardware_version, software_version); } +bool bluetooth::shim::CountCounterMetrics(int32_t key, int64_t count) { + mock_function_count_map[__func__]++; + return false; +} // END mockcify generation diff --git a/system/test/mock/mock_stack_acl_btm_ble_connection_establishment.cc b/system/test/mock/mock_stack_acl_btm_ble_connection_establishment.cc index 061920d710..d9ded82226 100644 --- a/system/test/mock/mock_stack_acl_btm_ble_connection_establishment.cc +++ b/system/test/mock/mock_stack_acl_btm_ble_connection_establishment.cc @@ -50,7 +50,6 @@ namespace mock { namespace stack_acl_btm_ble_connection_establishment { // Function state capture and return values, if needed -struct btm_send_hci_create_connection btm_send_hci_create_connection; struct btm_ble_create_ll_conn_complete btm_ble_create_ll_conn_complete; struct maybe_resolve_address maybe_resolve_address; struct btm_ble_conn_complete btm_ble_conn_complete; @@ -61,20 +60,6 @@ struct btm_ble_create_conn_cancel_complete btm_ble_create_conn_cancel_complete; } // namespace mock } // namespace test -// Mocked functions, if any -void btm_send_hci_create_connection( - uint16_t scan_int, uint16_t scan_win, uint8_t init_filter_policy, - uint8_t addr_type_peer, const RawAddress& bda_peer, uint8_t addr_type_own, - uint16_t conn_int_min, uint16_t conn_int_max, uint16_t conn_latency, - uint16_t conn_timeout, uint16_t min_ce_len, uint16_t max_ce_len, - uint8_t initiating_phys) { - mock_function_count_map[__func__]++; - test::mock::stack_acl_btm_ble_connection_establishment:: - btm_send_hci_create_connection( - scan_int, scan_win, init_filter_policy, addr_type_peer, bda_peer, - addr_type_own, conn_int_min, conn_int_max, conn_latency, conn_timeout, - min_ce_len, max_ce_len, initiating_phys); -} void btm_ble_create_ll_conn_complete(tHCI_STATUS status) { mock_function_count_map[__func__]++; test::mock::stack_acl_btm_ble_connection_establishment:: diff --git a/system/test/mock/mock_stack_acl_btm_ble_connection_establishment.h b/system/test/mock/mock_stack_acl_btm_ble_connection_establishment.h index c546d030e6..d988d946aa 100644 --- a/system/test/mock/mock_stack_acl_btm_ble_connection_establishment.h +++ b/system/test/mock/mock_stack_acl_btm_ble_connection_establishment.h @@ -48,38 +48,6 @@ namespace mock { namespace stack_acl_btm_ble_connection_establishment { // Shared state between mocked functions and tests -// Name: btm_send_hci_create_connection -// Params: uint16_t scan_int, uint16_t scan_win, uint8_t init_filter_policy, -// uint8_t addr_type_peer, const RawAddress& bda_peer, uint8_t addr_type_own, -// uint16_t conn_int_min, uint16_t conn_int_max, uint16_t conn_latency, uint16_t -// conn_timeout, uint16_t min_ce_len, uint16_t max_ce_len, uint8_t -// initiating_phys Returns: void -struct btm_send_hci_create_connection { - std::function<void( - uint16_t scan_int, uint16_t scan_win, uint8_t init_filter_policy, - uint8_t addr_type_peer, const RawAddress& bda_peer, uint8_t addr_type_own, - uint16_t conn_int_min, uint16_t conn_int_max, uint16_t conn_latency, - uint16_t conn_timeout, uint16_t min_ce_len, uint16_t max_ce_len, - uint8_t initiating_phys)> - body{[](uint16_t scan_int, uint16_t scan_win, uint8_t init_filter_policy, - uint8_t addr_type_peer, const RawAddress& bda_peer, - uint8_t addr_type_own, uint16_t conn_int_min, - uint16_t conn_int_max, uint16_t conn_latency, - uint16_t conn_timeout, uint16_t min_ce_len, uint16_t max_ce_len, - uint8_t initiating_phys) {}}; - void operator()(uint16_t scan_int, uint16_t scan_win, - uint8_t init_filter_policy, uint8_t addr_type_peer, - const RawAddress& bda_peer, uint8_t addr_type_own, - uint16_t conn_int_min, uint16_t conn_int_max, - uint16_t conn_latency, uint16_t conn_timeout, - uint16_t min_ce_len, uint16_t max_ce_len, - uint8_t initiating_phys) { - body(scan_int, scan_win, init_filter_policy, addr_type_peer, bda_peer, - addr_type_own, conn_int_min, conn_int_max, conn_latency, conn_timeout, - min_ce_len, max_ce_len, initiating_phys); - }; -}; -extern struct btm_send_hci_create_connection btm_send_hci_create_connection; // Name: btm_ble_create_ll_conn_complete // Params: tHCI_STATUS status // Returns: void diff --git a/system/test/mock/mock_stack_btm_ble.cc b/system/test/mock/mock_stack_btm_ble.cc index da844aa876..5ebd1a5f57 100644 --- a/system/test/mock/mock_stack_btm_ble.cc +++ b/system/test/mock/mock_stack_btm_ble.cc @@ -230,9 +230,6 @@ void btm_ble_rand_enc_complete(uint8_t* p, uint16_t op_code, tBTM_RAND_ENC_CB* p_enc_cplt_cback) { mock_function_count_map[__func__]++; } -void btm_ble_set_random_address(const RawAddress& random_bda) { - mock_function_count_map[__func__]++; -} void btm_ble_test_command_complete(uint8_t* p) { mock_function_count_map[__func__]++; } diff --git a/system/test/mock/mock_stack_btm_inq.cc b/system/test/mock/mock_stack_btm_inq.cc index f938adbe7c..1d1c8e25ee 100644 --- a/system/test/mock/mock_stack_btm_inq.cc +++ b/system/test/mock/mock_stack_btm_inq.cc @@ -166,10 +166,10 @@ void btm_inq_rmt_name_failed_cancelled(void) { mock_function_count_map[__func__]++; } void btm_inq_stop_on_ssp(void) { mock_function_count_map[__func__]++; } -void btm_process_cancel_complete(uint8_t status, uint8_t mode) { +void btm_process_cancel_complete(tHCI_STATUS status, uint8_t mode) { mock_function_count_map[__func__]++; } -void btm_process_inq_complete(uint8_t status, uint8_t mode) { +void btm_process_inq_complete(tHCI_STATUS status, uint8_t mode) { mock_function_count_map[__func__]++; } void btm_process_inq_results(const uint8_t* p, uint8_t hci_evt_len, @@ -177,7 +177,7 @@ void btm_process_inq_results(const uint8_t* p, uint8_t hci_evt_len, mock_function_count_map[__func__]++; } void btm_process_remote_name(const RawAddress* bda, const BD_NAME bdn, - uint16_t evt_len, uint8_t hci_status) { + uint16_t evt_len, tHCI_STATUS hci_status) { mock_function_count_map[__func__]++; } void btm_set_eir_uuid(const uint8_t* p_eir, tBTM_INQ_RESULTS* p_results) { diff --git a/system/test/rootcanal/Android.bp b/system/test/rootcanal/Android.bp index 2887239f41..5d6700f273 100644 --- a/system/test/rootcanal/Android.bp +++ b/system/test/rootcanal/Android.bp @@ -61,7 +61,6 @@ cc_binary { "android.hardware.bluetooth-async", "android.hardware.bluetooth-hci", "libbt-rootcanal", - "libbt-rootcanal-types", "libscriptedbeaconpayload-protos-lite", ], include_dirs: [ @@ -111,7 +110,6 @@ cc_library_shared { "android.hardware.bluetooth-async", "android.hardware.bluetooth-hci", "libbt-rootcanal", - "libbt-rootcanal-types", "libscriptedbeaconpayload-protos-lite", ], include_dirs: [ diff --git a/system/test/stub/osi.cc b/system/test/stub/osi.cc index e07adcba52..f5b5602ca3 100644 --- a/system/test/stub/osi.cc +++ b/system/test/stub/osi.cc @@ -380,15 +380,21 @@ alarm_t* alarm_new_periodic(const char* name) { mock_function_count_map[__func__]++; return nullptr; } +struct fake_osi_alarm_set_on_mloop fake_osi_alarm_set_on_mloop_; bool alarm_is_scheduled(const alarm_t* alarm) { mock_function_count_map[__func__]++; - return false; + return (fake_osi_alarm_set_on_mloop_.cb != nullptr); } uint64_t alarm_get_remaining_ms(const alarm_t* alarm) { mock_function_count_map[__func__]++; return 0; } -void alarm_cancel(alarm_t* alarm) { mock_function_count_map[__func__]++; } +void alarm_cancel(alarm_t* alarm) { + mock_function_count_map[__func__]++; + fake_osi_alarm_set_on_mloop_.interval_ms = 0; + fake_osi_alarm_set_on_mloop_.cb = nullptr; + fake_osi_alarm_set_on_mloop_.data = nullptr; +} void alarm_cleanup(void) { mock_function_count_map[__func__]++; } void alarm_debug_dump(int fd) { mock_function_count_map[__func__]++; } void alarm_free(alarm_t* alarm) { mock_function_count_map[__func__]++; } @@ -397,7 +403,6 @@ void alarm_set(alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb, mock_function_count_map[__func__]++; } -struct fake_osi_alarm_set_on_mloop fake_osi_alarm_set_on_mloop_; void alarm_set_on_mloop(alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb, void* data) { mock_function_count_map[__func__]++; diff --git a/system/test/suite/adapter/bluetooth_test.h b/system/test/suite/adapter/bluetooth_test.h index 44f52c80da..6b50be9f95 100644 --- a/system/test/suite/adapter/bluetooth_test.h +++ b/system/test/suite/adapter/bluetooth_test.h @@ -41,6 +41,9 @@ class BluetoothTest : public ::testing::Test, public bluetooth::hal::BluetoothInterface::Observer { protected: BluetoothTest() = default; + BluetoothTest(const BluetoothTest&) = delete; + BluetoothTest& operator=(const BluetoothTest&) = delete; + virtual ~BluetoothTest() = default; // Getter for the bt_interface @@ -115,8 +118,6 @@ class BluetoothTest : public ::testing::Test, bt_discovery_state_t discovery_state_; bt_acl_state_t acl_state_; bt_bond_state_t bond_state_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothTest); }; } // bttest diff --git a/system/test/suite/gatt/gatt_test.h b/system/test/suite/gatt/gatt_test.h index 1fcea738bd..da0d6d218c 100644 --- a/system/test/suite/gatt/gatt_test.h +++ b/system/test/suite/gatt/gatt_test.h @@ -31,6 +31,9 @@ class GattTest : public BluetoothTest, public bluetooth::hal::BluetoothGattInterface::ServerObserver { protected: GattTest() = default; + GattTest(const GattTest&) = delete; + GattTest& operator=(const GattTest&) = delete; + virtual ~GattTest() = default; // Gets the gatt_scanner_interface @@ -125,8 +128,6 @@ class GattTest : public BluetoothTest, // The status of the last callback. Is BT_STATUS_SUCCESS if no issues. int status_; - - DISALLOW_COPY_AND_ASSIGN(GattTest); }; } // bttest diff --git a/system/tools/bdtool/adapter.c b/system/tools/bdtool/adapter.c index bfbbfeb904..3b964a0f78 100644 --- a/system/tools/bdtool/adapter.c +++ b/system/tools/bdtool/adapter.c @@ -257,7 +257,7 @@ static void parse_properties(int num_properties, bt_property_t* property) { case BT_PROPERTY_SERVICE_RECORD: case BT_PROPERTY_ADAPTER_SCAN_MODE: case BT_PROPERTY_ADAPTER_BONDED_DEVICES: - case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT: + case BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT: case BT_PROPERTY_REMOTE_VERSION_INFO: case BT_PROPERTY_LOCAL_LE_FEATURES: case BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP: diff --git a/system/vendor_libs/test_vendor_lib/Android.bp b/system/vendor_libs/test_vendor_lib/Android.bp index 177a37f990..1c69551e1e 100644 --- a/system/vendor_libs/test_vendor_lib/Android.bp +++ b/system/vendor_libs/test_vendor_lib/Android.bp @@ -84,7 +84,6 @@ cc_library_static { ], static_libs: [ "libjsoncpp", - "libbt-rootcanal-types", "libscriptedbeaconpayload-protos-lite", ], } @@ -127,7 +126,6 @@ cc_test_host { "liblog", ], static_libs: [ - "libbt-rootcanal-types", "libbt-rootcanal", ], cflags: [ @@ -174,7 +172,6 @@ cc_binary_host { ], static_libs: [ "libjsoncpp", - "libbt-rootcanal-types", "libprotobuf-cpp-lite", "libscriptedbeaconpayload-protos-lite", "libbt-rootcanal", diff --git a/system/vendor_libs/test_vendor_lib/include/inquiry.h b/system/vendor_libs/test_vendor_lib/include/inquiry.h deleted file mode 100644 index f989af4bea..0000000000 --- a/system/vendor_libs/test_vendor_lib/include/inquiry.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -namespace test_vendor_lib { - -class Inquiry { - public: - enum class InquiryState : uint8_t { - STANDBY = 0x00, - INQUIRY = 0x01, - }; - enum class InquiryType : uint8_t { - STANDARD = 0x00, - RSSI = 0x01, - EXTENDED = 0x02, - }; -}; -} // namespace test_vendor_lib diff --git a/system/vendor_libs/test_vendor_lib/include/le_advertisement.h b/system/vendor_libs/test_vendor_lib/include/le_advertisement.h deleted file mode 100644 index a5c139630e..0000000000 --- a/system/vendor_libs/test_vendor_lib/include/le_advertisement.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include <cstdint> - -namespace test_vendor_lib { - -class LeAdvertisement { - public: - enum class AdvertisementType : uint8_t { - ADV_IND = 0, // Connectable and scannable - ADV_DIRECT_IND = 1, // Connectable directed - ADV_SCAN_IND = 2, // Scannable undirected - ADV_NONCONN_IND = 3, // Non connectable undirected - SCAN_RESPONSE = 4, - }; - enum class AddressType : uint8_t { - PUBLIC = 0, - RANDOM = 1, - PUBLIC_IDENTITY = 2, - RANDOM_IDENTITY = 3, - }; -}; - -} // namespace test_vendor_lib diff --git a/system/vendor_libs/test_vendor_lib/include/sco.h b/system/vendor_libs/test_vendor_lib/include/sco.h deleted file mode 100644 index b3691cf10f..0000000000 --- a/system/vendor_libs/test_vendor_lib/include/sco.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include <cstdint> - -namespace test_vendor_lib { -namespace sco { - -// SCO data packets are specified in the Bluetooth Core Specification Version -// 4.2, Volume 2, Part E, Section 5.4.3 -enum class PacketStatusFlagsType : uint8_t { - CORRECTLY_RECEIVED = 0, - POSSIBLY_INCOMPLETE = 1, - NO_DATA = 2, - PARTIALLY_LOST = 3 -}; -} // namespace sco -} // namespace test_vendor_lib diff --git a/system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc b/system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc index ce68d3f7da..8d4f08ff8a 100644 --- a/system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc +++ b/system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc @@ -19,6 +19,7 @@ #include <memory> #include <random> +#include "crypto_toolbox/crypto_toolbox.h" #include "os/log.h" #include "packet/raw_builder.h" @@ -231,6 +232,7 @@ DualModeController::DualModeController(const std::string& properties_filename, u SET_SUPPORTED(LE_ADD_DEVICE_TO_CONNECT_LIST, LeAddDeviceToConnectList); SET_SUPPORTED(LE_REMOVE_DEVICE_FROM_CONNECT_LIST, LeRemoveDeviceFromConnectList); + SET_SUPPORTED(LE_ENCRYPT, LeEncrypt); SET_SUPPORTED(LE_RAND, LeRand); SET_SUPPORTED(LE_READ_SUPPORTED_STATES, LeReadSupportedStates); SET_HANDLER(LE_GET_VENDOR_CAPABILITIES, LeVendorCap); @@ -2289,6 +2291,18 @@ void DualModeController::LeReadRemoteFeatures(CommandView command) { status, kNumCommandPackets)); } +void DualModeController::LeEncrypt(CommandView command) { + auto command_view = gd_hci::LeEncryptView::Create( + gd_hci::LeSecurityCommandView::Create(command)); + ASSERT(command_view.IsValid()); + + auto encrypted_data = bluetooth::crypto_toolbox::aes_128( + command_view.GetKey(), + command_view.GetPlaintextData()); + + send_event_(bluetooth::hci::LeEncryptCompleteBuilder::Create( + kNumCommandPackets, ErrorCode::SUCCESS, encrypted_data)); +} static std::random_device rd{}; static std::mt19937_64 s_mt{rd()}; @@ -2416,7 +2430,8 @@ void DualModeController::LeSetExtendedAdvertisingParameters( command_view.GetPrimaryAdvertisingIntervalMax(), command_view.GetAdvertisingEventLegacyProperties(), command_view.GetOwnAddressType(), command_view.GetPeerAddressType(), - command_view.GetPeerAddress(), command_view.GetAdvertisingFilterPolicy()); + command_view.GetPeerAddress(), command_view.GetAdvertisingFilterPolicy(), + command_view.GetAdvertisingTxPower()); send_event_( bluetooth::hci::LeSetExtendedAdvertisingParametersCompleteBuilder::Create( diff --git a/system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h b/system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h index 1e88f51b8b..785bc041cc 100644 --- a/system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h +++ b/system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h @@ -471,6 +471,9 @@ class DualModeController : public Device { // 7.8.21 void LeReadRemoteFeatures(CommandView args); + // 7.8.22 + void LeEncrypt(CommandView args); + // 7.8.23 void LeRand(CommandView args); diff --git a/system/vendor_libs/test_vendor_lib/model/controller/le_advertiser.cc b/system/vendor_libs/test_vendor_lib/model/controller/le_advertiser.cc index 27a63fe5e8..661d7b76e3 100644 --- a/system/vendor_libs/test_vendor_lib/model/controller/le_advertiser.cc +++ b/system/vendor_libs/test_vendor_lib/model/controller/le_advertiser.cc @@ -17,6 +17,7 @@ #include "le_advertiser.h" using namespace bluetooth::hci; +using namespace std::literals; namespace test_vendor_lib { void LeAdvertiser::Initialize(AddressWithType address, @@ -33,21 +34,28 @@ void LeAdvertiser::Initialize(AddressWithType address, advertisement_ = advertisement; scan_response_ = scan_response; interval_ = interval; + tx_power_ = kTxPowerUnavailable; } void LeAdvertiser::InitializeExtended( - AddressType address_type, AddressWithType peer_address, + unsigned advertising_handle, + AddressType address_type, + AddressWithType peer_address, LeScanningFilterPolicy filter_policy, model::packets::AdvertisementType type, - std::chrono::steady_clock::duration interval) { + std::chrono::steady_clock::duration interval, + uint8_t tx_power) { + + advertising_handle_ = advertising_handle; address_ = AddressWithType(address_.GetAddress(), address_type); peer_address_ = peer_address; filter_policy_ = filter_policy; type_ = type; interval_ = interval; - LOG_INFO("%s -> %s type = %hhx interval = %d ms", address_.ToString().c_str(), - peer_address.ToString().c_str(), type_, - static_cast<int>(interval_.count())); + tx_power_ = tx_power; + LOG_INFO("%s -> %s type = %hhx interval = %d ms tx_power = 0x%hhx", + address_.ToString().c_str(), peer_address.ToString().c_str(), type_, + static_cast<int>(interval_.count()), tx_power); } void LeAdvertiser::Clear() { @@ -57,7 +65,7 @@ void LeAdvertiser::Clear() { type_ = model::packets::AdvertisementType::ADV_IND; advertisement_.clear(); scan_response_.clear(); - interval_ = std::chrono::milliseconds(0); + interval_ = 0ms; enabled_ = false; } @@ -77,30 +85,55 @@ void LeAdvertiser::SetScanResponse(const std::vector<uint8_t>& data) { } void LeAdvertiser::Enable() { + EnableExtended(0ms); + extended_ = false; +} + +void LeAdvertiser::EnableExtended(std::chrono::milliseconds duration_ms) { enabled_ = true; - last_le_advertisement_ = std::chrono::steady_clock::now() - interval_; + extended_ = true; num_events_ = 0; - LOG_INFO("%s -> %s type = %hhx ad length %zu, scan length %zu", - address_.ToString().c_str(), peer_address_.ToString().c_str(), type_, - advertisement_.size(), scan_response_.size()); -} -void LeAdvertiser::EnableExtended( - std::chrono::steady_clock::duration duration) { - Enable(); - if (duration != std::chrono::milliseconds(0)) { - ending_time_ = std::chrono::steady_clock::now() + duration; + using Duration = std::chrono::steady_clock::duration; + using TimePoint = std::chrono::steady_clock::time_point; + + Duration adv_direct_ind_timeout = 1280ms; // 1.28s + Duration adv_direct_ind_interval_low = 10000us; // 10ms + Duration adv_direct_ind_interval_high = 3750us; // 3.75ms + Duration duration = duration_ms; + TimePoint now = std::chrono::steady_clock::now(); + + switch (type_) { + // [Vol 6] Part B. 4.4.2.4.3 High duty cycle connectable directed advertising + case model::packets::AdvertisementType::ADV_DIRECT_IND: + duration = duration == 0ms ? + adv_direct_ind_timeout : + std::min(duration, adv_direct_ind_timeout); + interval_ = adv_direct_ind_interval_high; + break; + + // [Vol 6] Part B. 4.4.2.4.2 Low duty cycle connectable directed advertising + case model::packets::AdvertisementType::SCAN_RESPONSE: + interval_ = adv_direct_ind_interval_low; + break; + + // Duration set to parameter, + // interval set by Initialize(). + default: + break; } - extended_ = true; + + last_le_advertisement_ = now - interval_; + ending_time_ = now + duration; + limited_ = duration != 0ms; + LOG_INFO("%s -> %s type = %hhx ad length %zu, scan length %zu", address_.ToString().c_str(), peer_address_.ToString().c_str(), type_, advertisement_.size(), scan_response_.size()); } void LeAdvertiser::Disable() { enabled_ = false; } - bool LeAdvertiser::IsEnabled() const { return enabled_; } - bool LeAdvertiser::IsExtended() const { return extended_; } bool LeAdvertiser::IsConnectable() const { @@ -110,30 +143,67 @@ bool LeAdvertiser::IsConnectable() const { uint8_t LeAdvertiser::GetNumAdvertisingEvents() const { return num_events_; } -std::unique_ptr<model::packets::LeAdvertisementBuilder> -LeAdvertiser::GetAdvertisement(std::chrono::steady_clock::time_point now) { +std::unique_ptr<bluetooth::hci::EventBuilder> +LeAdvertiser::GetEvent(std::chrono::steady_clock::time_point now) { + // Advertiser disabled. if (!enabled_) { return nullptr; } - if (now - last_le_advertisement_ < interval_) { - return nullptr; + // [Vol 4] Part E 7.8.9 LE Set Advertising Enable command + // [Vol 4] Part E 7.8.56 LE Set Extended Advertising Enable command + if (type_ == model::packets::AdvertisementType::ADV_DIRECT_IND && + now >= ending_time_ && limited_) { + LOG_INFO("Directed Advertising Timeout"); + enabled_ = false; + return bluetooth::hci::LeConnectionCompleteBuilder::Create( + ErrorCode::ADVERTISING_TIMEOUT, 0, + bluetooth::hci::Role::CENTRAL, + bluetooth::hci::AddressType::PUBLIC_DEVICE_ADDRESS, + bluetooth::hci::Address(), 0, 0, 0, + bluetooth::hci::ClockAccuracy::PPM_500); } - if (last_le_advertisement_ < ending_time_ && ending_time_ < now) { + // [Vol 4] Part E 7.8.56 LE Set Extended Advertising Enable command + if (extended_ && now >= ending_time_ && limited_) { + LOG_INFO("Extended Advertising Timeout"); enabled_ = false; + return bluetooth::hci::LeAdvertisingSetTerminatedBuilder::Create( + ErrorCode::SUCCESS, advertising_handle_, 0, num_events_); + } + + return nullptr; +} + +std::unique_ptr<model::packets::LinkLayerPacketBuilder> +LeAdvertiser::GetAdvertisement(std::chrono::steady_clock::time_point now) { + if (!enabled_) { + return nullptr; + } + + if (now - last_le_advertisement_ < interval_) { return nullptr; } last_le_advertisement_ = now; num_events_ += (num_events_ < 255 ? 1 : 0); - return model::packets::LeAdvertisementBuilder::Create( - address_.GetAddress(), peer_address_.GetAddress(), - static_cast<model::packets::AddressType>(address_.GetAddressType()), - type_, advertisement_); + if (tx_power_ == kTxPowerUnavailable) { + return model::packets::LeAdvertisementBuilder::Create( + address_.GetAddress(), peer_address_.GetAddress(), + static_cast<model::packets::AddressType>(address_.GetAddressType()), + type_, advertisement_); + } else { + uint8_t tx_power_jittered = 2 + tx_power_ - (num_events_ & 0x03); + return model::packets::RssiWrapperBuilder::Create( + address_.GetAddress(), peer_address_.GetAddress(), tx_power_jittered, + model::packets::LeAdvertisementBuilder::Create( + address_.GetAddress(), peer_address_.GetAddress(), + static_cast<model::packets::AddressType>(address_.GetAddressType()), + type_, advertisement_)); + } } -std::unique_ptr<model::packets::LeScanResponseBuilder> +std::unique_ptr<model::packets::LinkLayerPacketBuilder> LeAdvertiser::GetScanResponse(bluetooth::hci::Address scanned, bluetooth::hci::Address scanner) { if (scanned != address_.GetAddress() || !enabled_) { @@ -153,10 +223,20 @@ LeAdvertiser::GetScanResponse(bluetooth::hci::Address scanned, case bluetooth::hci::LeScanningFilterPolicy::ACCEPT_ALL: break; } - return model::packets::LeScanResponseBuilder::Create( - address_.GetAddress(), peer_address_.GetAddress(), - static_cast<model::packets::AddressType>(address_.GetAddressType()), - model::packets::AdvertisementType::SCAN_RESPONSE, scan_response_); + if (tx_power_ == kTxPowerUnavailable) { + return model::packets::LeScanResponseBuilder::Create( + address_.GetAddress(), peer_address_.GetAddress(), + static_cast<model::packets::AddressType>(address_.GetAddressType()), + type_, advertisement_); + } else { + uint8_t tx_power_jittered = 2 + tx_power_ - (num_events_ & 0x03); + return model::packets::RssiWrapperBuilder::Create( + address_.GetAddress(), peer_address_.GetAddress(), tx_power_jittered, + model::packets::LeScanResponseBuilder::Create( + address_.GetAddress(), peer_address_.GetAddress(), + static_cast<model::packets::AddressType>(address_.GetAddressType()), + type_, advertisement_)); + } } } // namespace test_vendor_lib diff --git a/system/vendor_libs/test_vendor_lib/model/controller/le_advertiser.h b/system/vendor_libs/test_vendor_lib/model/controller/le_advertiser.h index a9d14ab82a..37f7488b7c 100644 --- a/system/vendor_libs/test_vendor_lib/model/controller/le_advertiser.h +++ b/system/vendor_libs/test_vendor_lib/model/controller/le_advertiser.h @@ -40,11 +40,13 @@ class LeAdvertiser { const std::vector<uint8_t>& scan_response, std::chrono::steady_clock::duration interval); - void InitializeExtended(bluetooth::hci::AddressType address_type, + void InitializeExtended(unsigned advertising_handle, + bluetooth::hci::AddressType address_type, bluetooth::hci::AddressWithType peer_address, bluetooth::hci::LeScanningFilterPolicy filter_policy, model::packets::AdvertisementType type, - std::chrono::steady_clock::duration interval); + std::chrono::steady_clock::duration interval, + uint8_t tx_power); void SetAddress(bluetooth::hci::Address address); @@ -52,32 +54,32 @@ class LeAdvertiser { void SetScanResponse(const std::vector<uint8_t>& data); - std::unique_ptr<model::packets::LeAdvertisementBuilder> GetAdvertisement( + // Generate LE Connection Complete or LE Extended Advertising Set Terminated + // events at the end of the advertising period. The advertiser is + // automatically disabled. + std::unique_ptr<bluetooth::hci::EventBuilder> GetEvent( std::chrono::steady_clock::time_point); - std::unique_ptr<model::packets::LeScanResponseBuilder> GetScanResponse( + std::unique_ptr<model::packets::LinkLayerPacketBuilder> GetAdvertisement( + std::chrono::steady_clock::time_point); + + std::unique_ptr<model::packets::LinkLayerPacketBuilder> GetScanResponse( bluetooth::hci::Address scanned_address, bluetooth::hci::Address scanner_address); void Clear(); - void Disable(); - void Enable(); - - void EnableExtended(std::chrono::steady_clock::duration duration); + void EnableExtended(std::chrono::milliseconds duration); bool IsEnabled() const; - bool IsExtended() const; - bool IsConnectable() const; uint8_t GetNumAdvertisingEvents() const; - bluetooth::hci::AddressWithType GetAddress() const; - private: +private: bluetooth::hci::AddressWithType address_{}; bluetooth::hci::AddressWithType peer_address_{}; // For directed advertisements @@ -87,10 +89,14 @@ class LeAdvertiser { std::vector<uint8_t> scan_response_; std::chrono::steady_clock::duration interval_{}; std::chrono::steady_clock::time_point ending_time_{}; + std::chrono::steady_clock::time_point last_le_advertisement_{}; + static constexpr uint8_t kTxPowerUnavailable = 0x7f; + uint8_t tx_power_{kTxPowerUnavailable}; uint8_t num_events_{0}; bool extended_{false}; bool enabled_{false}; - std::chrono::steady_clock::time_point last_le_advertisement_; + bool limited_{false}; // Set if the advertising set has a timeout. + unsigned advertising_handle_{0}; }; } // namespace test_vendor_lib diff --git a/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc b/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc index 2374ca02dc..e79982fa0c 100644 --- a/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc +++ b/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc @@ -19,7 +19,6 @@ #include <hci/hci_packets.h> #include "crypto_toolbox/crypto_toolbox.h" -#include "include/le_advertisement.h" #include "os/log.h" #include "packet/raw_builder.h" @@ -32,6 +31,7 @@ using bluetooth::hci::EventCode; using namespace model::packets; using model::packets::PacketType; +using namespace std::literals; namespace test_vendor_lib { @@ -51,6 +51,17 @@ static uint8_t GetRssi() { return -(rssi); } +void LinkLayerController::SendLeLinkLayerPacketWithRssi( + Address source, Address dest, uint8_t rssi, + std::unique_ptr<model::packets::LinkLayerPacketBuilder> packet) { + std::shared_ptr<model::packets::RssiWrapperBuilder> shared_packet = + model::packets::RssiWrapperBuilder::Create(source, dest, rssi, + std::move(packet)); + ScheduleTask(kNoDelayMs, [this, shared_packet]() { + send_to_remote_(shared_packet, Phy::Type::LOW_ENERGY); + }); +} + void LinkLayerController::SendLeLinkLayerPacket( std::unique_ptr<model::packets::LinkLayerPacketBuilder> packet) { std::shared_ptr<model::packets::LinkLayerPacketBuilder> shared_packet = @@ -218,6 +229,20 @@ ErrorCode LinkLayerController::SendScoToRemote( void LinkLayerController::IncomingPacket( model::packets::LinkLayerPacketView incoming) { ASSERT(incoming.IsValid()); + if (incoming.GetType() == PacketType::RSSI_WRAPPER) { + auto rssi_wrapper = model::packets::RssiWrapperView::Create(incoming); + ASSERT(rssi_wrapper.IsValid()); + auto wrapped = + model::packets::LinkLayerPacketView::Create(rssi_wrapper.GetPayload()); + IncomingPacketWithRssi(wrapped, rssi_wrapper.GetRssi()); + } else { + IncomingPacketWithRssi(incoming, GetRssi()); + } +} + +void LinkLayerController::IncomingPacketWithRssi( + model::packets::LinkLayerPacketView incoming, uint8_t rssi) { + ASSERT(incoming.IsValid()); auto destination_address = incoming.GetDestinationAddress(); // Match broadcasts @@ -278,7 +303,7 @@ void LinkLayerController::IncomingPacket( break; case model::packets::PacketType::INQUIRY: if (inquiry_scans_enabled_) { - IncomingInquiryPacket(incoming); + IncomingInquiryPacket(incoming, rssi); } break; case model::packets::PacketType::INQUIRY_RESPONSE: @@ -307,7 +332,7 @@ void LinkLayerController::IncomingPacket( break; case model::packets::PacketType::LE_ADVERTISEMENT: if (le_scan_enable_ != bluetooth::hci::OpCode::NONE || le_connect_) { - IncomingLeAdvertisementPacket(incoming); + IncomingLeAdvertisementPacket(incoming, rssi); } break; case model::packets::PacketType::LE_CONNECT: @@ -341,7 +366,7 @@ void LinkLayerController::IncomingPacket( case model::packets::PacketType::LE_SCAN_RESPONSE: if (le_scan_enable_ != bluetooth::hci::OpCode::NONE && le_scan_type_ == 1) { - IncomingLeScanResponsePacket(incoming); + IncomingLeScanResponsePacket(incoming, rssi); } break; case model::packets::PacketType::PAGE: @@ -403,6 +428,9 @@ void LinkLayerController::IncomingPacket( case (model::packets::PacketType::READ_CLOCK_OFFSET_RESPONSE): IncomingReadClockOffsetResponse(incoming); break; + case (model::packets::PacketType::RSSI_WRAPPER): + LOG_ERROR("Dropping double-wrapped RSSI packet"); + break; case model::packets::PacketType::SCO_CONNECTION_REQUEST: IncomingScoConnectionRequest(incoming); break; @@ -722,7 +750,7 @@ void LinkLayerController::IncomingEncryptConnectionResponse( } void LinkLayerController::IncomingInquiryPacket( - model::packets::LinkLayerPacketView incoming) { + model::packets::LinkLayerPacketView incoming, uint8_t rssi) { auto inquiry = model::packets::InquiryView::Create(incoming); ASSERT(inquiry.IsValid()); @@ -741,7 +769,7 @@ void LinkLayerController::IncomingInquiryPacket( properties_.GetAddress(), peer, properties_.GetPageScanRepetitionMode(), properties_.GetClassOfDevice(), properties_.GetClockOffset(), - GetRssi())); + rssi)); } break; case (model::packets::InquiryType::EXTENDED): { SendLinkLayerPacket( @@ -749,7 +777,7 @@ void LinkLayerController::IncomingInquiryPacket( properties_.GetAddress(), peer, properties_.GetPageScanRepetitionMode(), properties_.GetClassOfDevice(), properties_.GetClockOffset(), - GetRssi(), properties_.GetExtendedInquiryData())); + rssi, properties_.GetExtendedInquiryData())); } break; default: @@ -1251,7 +1279,7 @@ static Address generate_rpa( } void LinkLayerController::IncomingLeAdvertisementPacket( - model::packets::LinkLayerPacketView incoming) { + model::packets::LinkLayerPacketView incoming, uint8_t rssi) { // TODO: Handle multiple advertisements per packet. Address address = incoming.GetSourceAddress(); @@ -1273,7 +1301,7 @@ void LinkLayerController::IncomingLeAdvertisementPacket( raw_builder_ptr->AddAddress(address); raw_builder_ptr->AddOctets1(ad.size()); raw_builder_ptr->AddOctets(ad); - raw_builder_ptr->AddOctets1(GetRssi()); + raw_builder_ptr->AddOctets1(rssi); if (properties_.IsUnmasked(EventCode::LE_META_EVENT)) { send_event_(bluetooth::hci::EventBuilder::Create( bluetooth::hci::EventCode::LE_META_EVENT, @@ -1313,7 +1341,7 @@ void LinkLayerController::IncomingLeAdvertisementPacket( raw_builder_ptr->AddOctets1(0); // Secondary_PHY raw_builder_ptr->AddOctets1(0xFF); // Advertising_SID - not provided raw_builder_ptr->AddOctets1(0x7F); // Tx_Power - Not available - raw_builder_ptr->AddOctets1(GetRssi()); + raw_builder_ptr->AddOctets1(rssi); raw_builder_ptr->AddOctets2(0); // Periodic_Advertising_Interval - None raw_builder_ptr->AddOctets1(0); // Direct_Address_Type - PUBLIC raw_builder_ptr->AddAddress(Address::kEmpty); // Direct_Address @@ -1801,13 +1829,12 @@ void LinkLayerController::IncomingLeScanPacket( } void LinkLayerController::IncomingLeScanResponsePacket( - model::packets::LinkLayerPacketView incoming) { + model::packets::LinkLayerPacketView incoming, uint8_t rssi) { auto scan_response = model::packets::LeScanResponseView::Create(incoming); ASSERT(scan_response.IsValid()); vector<uint8_t> ad = scan_response.GetData(); auto adv_type = scan_response.GetAdvertisementType(); - auto address_type = - static_cast<LeAdvertisement::AddressType>(scan_response.GetAddressType()); + auto address_type = scan_response.GetAddressType(); if (le_scan_enable_ == bluetooth::hci::OpCode::LE_SET_SCAN_ENABLE) { if (adv_type != model::packets::AdvertisementType::SCAN_RESPONSE) { return; @@ -1818,7 +1845,7 @@ void LinkLayerController::IncomingLeScanResponsePacket( report.address_type_ = static_cast<bluetooth::hci::AddressType>(address_type); report.advertising_data_ = scan_response.GetData(); - report.rssi_ = GetRssi(); + report.rssi_ = rssi; if (properties_.IsUnmasked(EventCode::LE_META_EVENT) && properties_.GetLeEventSupported( @@ -1844,7 +1871,7 @@ void LinkLayerController::IncomingLeScanResponsePacket( report.advertising_sid_ = 0xFF; report.tx_power_ = 0x7F; report.advertising_data_ = ad; - report.rssi_ = GetRssi(); + report.rssi_ = rssi; send_event_( bluetooth::hci::LeExtendedAdvertisingReportBuilder::Create({report})); } @@ -2060,11 +2087,16 @@ void LinkLayerController::Close() { void LinkLayerController::LeAdvertising() { steady_clock::time_point now = steady_clock::now(); for (auto& advertiser : advertisers_) { - auto ad = advertiser.GetAdvertisement(now); - if (ad == nullptr) { - continue; + + auto event = advertiser.GetEvent(now); + if (event != nullptr) { + send_event_(std::move(event)); + } + + auto advertisement = advertiser.GetAdvertisement(now); + if (advertisement != nullptr) { + SendLeLinkLayerPacket(std::move(advertisement)); } - SendLeLinkLayerPacket(std::move(ad)); } } @@ -2979,7 +3011,7 @@ ErrorCode LinkLayerController::SetLeExtendedAdvertisingParameters( bluetooth::hci::LegacyAdvertisingProperties type, bluetooth::hci::OwnAddressType own_address_type, bluetooth::hci::PeerAddressType peer_address_type, Address peer, - bluetooth::hci::AdvertisingFilterPolicy filter_policy) { + bluetooth::hci::AdvertisingFilterPolicy filter_policy, uint8_t tx_power) { model::packets::AdvertisementType ad_type; switch (type) { case bluetooth::hci::LegacyAdvertisingProperties::ADV_IND: @@ -2995,9 +3027,11 @@ ErrorCode LinkLayerController::SetLeExtendedAdvertisingParameters( peer = Address::kEmpty; break; case bluetooth::hci::LegacyAdvertisingProperties::ADV_DIRECT_IND_HIGH: - case bluetooth::hci::LegacyAdvertisingProperties::ADV_DIRECT_IND_LOW: ad_type = model::packets::AdvertisementType::ADV_DIRECT_IND; break; + case bluetooth::hci::LegacyAdvertisingProperties::ADV_DIRECT_IND_LOW: + ad_type = model::packets::AdvertisementType::SCAN_RESPONSE; + break; } auto interval_ms = static_cast<int>((interval_max + interval_min) * 0.625 / 2); @@ -3054,10 +3088,13 @@ ErrorCode LinkLayerController::SetLeExtendedAdvertisingParameters( break; } - advertisers_[set].InitializeExtended(own_address_address_type, peer_address, - scanning_filter_policy, ad_type, - std::chrono::milliseconds(interval_ms)); - + advertisers_[set].InitializeExtended(set, + own_address_address_type, + peer_address, + scanning_filter_policy, + ad_type, + std::chrono::milliseconds(interval_ms), + tx_power); return ErrorCode::SUCCESS; } @@ -3518,6 +3555,7 @@ uint8_t LinkLayerController::LeReadNumberOfSupportedAdvertisingSets() { ErrorCode LinkLayerController::SetLeExtendedAdvertisingEnable( bluetooth::hci::Enable enable, const std::vector<bluetooth::hci::EnabledSet>& enabled_sets) { + for (const auto& set : enabled_sets) { if (set.advertising_handle_ > advertisers_.size()) { return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; @@ -3526,8 +3564,7 @@ ErrorCode LinkLayerController::SetLeExtendedAdvertisingEnable( for (const auto& set : enabled_sets) { auto handle = set.advertising_handle_; if (enable == bluetooth::hci::Enable::ENABLED) { - advertisers_[handle].EnableExtended( - std::chrono::milliseconds(10 * set.duration_)); + advertisers_[handle].EnableExtended(10ms * set.duration_); } else { advertisers_[handle].Disable(); } diff --git a/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h b/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h index 097e9722ad..7a9a10f2df 100644 --- a/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h +++ b/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h @@ -18,7 +18,6 @@ #include "hci/address.h" #include "hci/hci_packets.h" -#include "include/inquiry.h" #include "include/phy.h" #include "model/controller/acl_connection_handler.h" #include "model/controller/le_advertiser.h" @@ -97,6 +96,9 @@ class LinkLayerController { private: void SendDisconnectionCompleteEvent(uint16_t handle, uint8_t reason); + void IncomingPacketWithRssi(model::packets::LinkLayerPacketView incoming, + uint8_t rssi); + public: void IncomingPacket(model::packets::LinkLayerPacketView incoming); @@ -156,7 +158,7 @@ class LinkLayerController { bluetooth::hci::LegacyAdvertisingProperties type, bluetooth::hci::OwnAddressType own_address_type, bluetooth::hci::PeerAddressType peer_address_type, Address peer, - bluetooth::hci::AdvertisingFilterPolicy filter_policy); + bluetooth::hci::AdvertisingFilterPolicy filter_policy, uint8_t tx_power); ErrorCode LeRemoveAdvertisingSet(uint8_t set); ErrorCode LeClearAdvertisingSets(); void LeConnectionUpdateComplete(uint16_t handle, uint16_t interval_min, @@ -376,6 +378,9 @@ class LinkLayerController { void HandleIso(bluetooth::hci::IsoView iso); protected: + void SendLeLinkLayerPacketWithRssi( + Address source, Address dest, uint8_t rssi, + std::unique_ptr<model::packets::LinkLayerPacketBuilder> packet); void SendLeLinkLayerPacket( std::unique_ptr<model::packets::LinkLayerPacketBuilder> packet); void SendLinkLayerPacket( @@ -386,7 +391,8 @@ class LinkLayerController { void IncomingEncryptConnection(model::packets::LinkLayerPacketView packet); void IncomingEncryptConnectionResponse( model::packets::LinkLayerPacketView packet); - void IncomingInquiryPacket(model::packets::LinkLayerPacketView packet); + void IncomingInquiryPacket(model::packets::LinkLayerPacketView packet, + uint8_t rssi); void IncomingInquiryResponsePacket( model::packets::LinkLayerPacketView packet); void IncomingIoCapabilityRequestPacket( @@ -402,8 +408,8 @@ class LinkLayerController { model::packets::LinkLayerPacketView packet); void IncomingKeypressNotificationPacket( model::packets::LinkLayerPacketView packet); - void IncomingLeAdvertisementPacket( - model::packets::LinkLayerPacketView packet); + void IncomingLeAdvertisementPacket(model::packets::LinkLayerPacketView packet, + uint8_t rssi); void IncomingLeConnectPacket(model::packets::LinkLayerPacketView packet); void IncomingLeConnectCompletePacket( model::packets::LinkLayerPacketView packet); @@ -418,7 +424,8 @@ class LinkLayerController { void IncomingLeReadRemoteFeaturesResponse( model::packets::LinkLayerPacketView packet); void IncomingLeScanPacket(model::packets::LinkLayerPacketView packet); - void IncomingLeScanResponsePacket(model::packets::LinkLayerPacketView packet); + void IncomingLeScanResponsePacket(model::packets::LinkLayerPacketView packet, + uint8_t rssi); void IncomingPagePacket(model::packets::LinkLayerPacketView packet); void IncomingPageRejectPacket(model::packets::LinkLayerPacketView packet); void IncomingPageResponsePacket(model::packets::LinkLayerPacketView packet); diff --git a/system/vendor_libs/test_vendor_lib/model/devices/loopback.cc b/system/vendor_libs/test_vendor_lib/model/devices/loopback.cc index c13f95d13d..de1a358771 100644 --- a/system/vendor_libs/test_vendor_lib/model/devices/loopback.cc +++ b/system/vendor_libs/test_vendor_lib/model/devices/loopback.cc @@ -16,7 +16,6 @@ #include "loopback.h" -#include "le_advertisement.h" #include "model/setup/device_boutique.h" #include "os/log.h" diff --git a/system/vendor_libs/test_vendor_lib/model/devices/server_port_factory.cc b/system/vendor_libs/test_vendor_lib/model/devices/server_port_factory.cc deleted file mode 100644 index b0b2165022..0000000000 --- a/system/vendor_libs/test_vendor_lib/model/devices/server_port_factory.cc +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2015 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 "server_port_factory.h" - -#include "os/log.h" -#include "osi/include/osi.h" - -#include <netinet/in.h> -#include <sys/socket.h> - -using std::vector; - -namespace test_vendor_lib { -namespace net { - -ServerPortFactory::ServerPortFactory(int port, std::function<void(int fd)>& callback) { - port_ = port; - callback_ = callback; -} - -int ServerPortFactory::SetUp(int port) { - struct sockaddr_in listen_address; - socklen_t sockaddr_in_size = sizeof(struct sockaddr_in); - memset(&listen_address, 0, sockaddr_in_size); - - OSI_NO_INTR(listen_fd_ = socket(AF_INET, SOCK_STREAM, 0)); - if (listen_fd_ < 0) { - LOG_INFO("Error creating socket for test channel."); - return -1; - } - - LOG_INFO("port: %d", port); - listen_address.sin_family = AF_INET; - listen_address.sin_port = htons(port); - listen_address.sin_addr.s_addr = htonl(INADDR_ANY); - - if (bind(listen_fd_, reinterpret_cast<sockaddr*>(&listen_address), sockaddr_in_size) < 0) { - LOG_INFO("Error binding test channel listener socket to address."); - close(listen_fd_); - return -1; - } - - if (listen(listen_fd_, 1) < 0) { - LOG_INFO("Error listening for test channel."); - close(listen_fd_); - return -1; - } - return listen_fd_; -} - -void ServerPortFactory::CleanUp() { - if (listen_fd_ == -1) { - return; - } - if (close(listen_fd_)) { - LOG_ERROR("Error closing listen_fd_."); - } - listen_fd_ = -1; -} - -int ServerPortFactory::Accept(int listen_fd_) { - int accept_fd = -1; - struct sockaddr_in test_channel_address; - socklen_t sockaddr_in_size = sizeof(struct sockaddr_in); - memset(&test_channel_address, 0, sockaddr_in_size); - - OSI_NO_INTR(accept_fd = accept(listen_fd_, reinterpret_cast<sockaddr*>(&test_channel_address), &sockaddr_in_size)); - if (accept_fd < 0) { - LOG_INFO("Error accepting test channel connection errno=%d (%s).", errno, strerror(errno)); - - if (errno != EAGAIN && errno != EWOULDBLOCK) { - LOG_ERROR("Closing listen_fd_ (won't try again)."); - close(listen_fd_); - return -1; - } - } - - LOG_INFO("accept_fd = %d.", accept_fd); - - return accept_fd; -} - -void ServerPortFactory::OnCommandReady(int fd, std::function<void(void)> unwatch) { - uint8_t command_name_size = 0; - read(fd, &command_name_size, 1); - vector<uint8_t> command_name_raw; - command_name_raw.resize(command_name_size); - read(fd, &command_name_raw[0], command_name_size); - std::string command_name(command_name_raw.begin(), command_name_raw.end()); - - if (command_name == "CLOSE_TEST_CHANNEL" || command_name == "") { - LOG_INFO("Test channel closed"); - unwatch(); - close(fd); - return; - } - - uint8_t num_args = 0; - read(fd, &num_args, 1); - vector<std::string> args; - for (uint8_t i = 0; i < num_args; ++i) { - uint8_t arg_size = 0; - read(fd, &arg_size, 1); - vector<uint8_t> arg; - arg.resize(arg_size); - read(fd, &arg[0], arg_size); - args.push_back(std::string(arg.begin(), arg.end())); - } - - command_handler_(command_name, args); -} - -void ServerPortFactory::SendResponse(int fd, const std::string& response) const { - size_t size = response.size(); - // Cap to 64K - if (size > 0xffff) { - size = 0xffff; - } - char size_buf[4] = {static_cast<uint8_t>(size & 0xff), static_cast<uint8_t>((size >> 8) & 0xff), - static_cast<uint8_t>((size >> 16) & 0xff), static_cast<uint8_t>((size >> 24) & 0xff)}; - int written = write(fd, size_buf, 4); - ASSERT_LOG(written == 4, "What happened? written = %d errno = %d", written, errno); - written = write(fd, response.c_str(), size); - ASSERT_LOG(written == static_cast<int>(size), "What happened? written = %d errno = %d", written, errno); -} - -void ServerPortFactory::RegisterCommandHandler( - const std::function<void(const std::string&, const std::vector<std::string>&)>& callback) { - command_handler_ = callback; -} - -} // namespace net -} // namespace test_vendor_lib diff --git a/system/vendor_libs/test_vendor_lib/model/devices/server_port_factory.h b/system/vendor_libs/test_vendor_lib/model/devices/server_port_factory.h deleted file mode 100644 index 5f19c49180..0000000000 --- a/system/vendor_libs/test_vendor_lib/model/devices/server_port_factory.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include <functional> -#include <memory> -#include <string> -#include <vector> - -namespace test_vendor_lib { -namespace net { - -// Starts a server and calls the registered lambda for each connection. -class ServerPortFactory { - public: - // Opens a server port and sets the listen file descriptor. - ServerPortFactory(int port, std::function<void(int fd)>& on_connection); - - // Closes the port (if succesfully opened in SetUp). - ~ServerPortFactory() {} - - // Waits for a connection request and returns the file descriptor to watch. - // Returns -1 on an error. - void Accept(int listen_fd); - - private: - std::function<void(int fd)> on_connection_; - - int port; - int listen_fd_ = -1; - - ServerPortFactory(const ServerPortFactory&) = delete; - ServerPortFactory& operator=(const ServerPortFactory&) = delete; -}; - -} // namespace net -} // namespace test_vendor_lib diff --git a/system/vendor_libs/test_vendor_lib/model/devices/sniffer.cc b/system/vendor_libs/test_vendor_lib/model/devices/sniffer.cc index efdca87487..edeb22d152 100644 --- a/system/vendor_libs/test_vendor_lib/model/devices/sniffer.cc +++ b/system/vendor_libs/test_vendor_lib/model/devices/sniffer.cc @@ -47,10 +47,28 @@ void Sniffer::IncomingPacket(model::packets::LinkLayerPacketView packet) { if (!match_source && !match_dest) { return; } - LOG_INFO("%s %s -> %s (Type %s)", - (match_source ? (match_dest ? "<->" : "<--") : "-->"), - source.ToString().c_str(), dest.ToString().c_str(), - model::packets::PacketTypeText(packet.GetType()).c_str()); + model::packets::PacketType packet_type = packet.GetType(); + + if (packet_type == model::packets::PacketType::RSSI_WRAPPER) { + auto wrapper_view = model::packets::RssiWrapperView::Create(packet); + ASSERT(wrapper_view.IsValid()); + auto wrapped_view = + model::packets::LinkLayerPacketView::Create(wrapper_view.GetPayload()); + ASSERT(wrapped_view.IsValid()); + LOG_INFO( + "%s %s -> %s (Type %s wrapping %s)", + (match_source ? (match_dest ? "<->" : "<--") : "-->"), + source.ToString().c_str(), dest.ToString().c_str(), + model::packets::PacketTypeText(packet_type).c_str(), + (packet_type == model::packets::PacketType::RSSI_WRAPPER + ? model::packets::PacketTypeText(wrapped_view.GetType()).c_str() + : "")); + } else { + LOG_INFO("%s %s -> %s (Type %s)", + (match_source ? (match_dest ? "<->" : "<--") : "-->"), + source.ToString().c_str(), dest.ToString().c_str(), + model::packets::PacketTypeText(packet_type).c_str()); + } } } // namespace test_vendor_lib diff --git a/system/vendor_libs/test_vendor_lib/net/posix/posix_async_socket.cc b/system/vendor_libs/test_vendor_lib/net/posix/posix_async_socket.cc index c5e8af3a94..1d57d10f34 100644 --- a/system/vendor_libs/test_vendor_lib/net/posix/posix_async_socket.cc +++ b/system/vendor_libs/test_vendor_lib/net/posix/posix_async_socket.cc @@ -41,7 +41,7 @@ PosixAsyncSocket::PosixAsyncSocket(int fd, AsyncManager* am) fcntl(fd, F_SETFL, flags | O_NONBLOCK); flags = fcntl(fd, F_GETFD); - fcntl(fd, F_SETFD, flags | O_CLOEXEC); + fcntl(fd, F_SETFD, flags | FD_CLOEXEC); #ifdef SO_NOSIGPIPE // Disable SIGPIPE generation on Darwin. diff --git a/system/vendor_libs/test_vendor_lib/packets/link_layer_packets.pdl b/system/vendor_libs/test_vendor_lib/packets/link_layer_packets.pdl index 0d0e1e1772..c1336e7a2d 100644 --- a/system/vendor_libs/test_vendor_lib/packets/link_layer_packets.pdl +++ b/system/vendor_libs/test_vendor_lib/packets/link_layer_packets.pdl @@ -56,6 +56,7 @@ enum PacketType : 8 { SCO_CONNECTION_REQUEST = 0x30, SCO_CONNECTION_RESPONSE = 0x31, SCO_DISCONNECT = 0x32, + RSSI_WRAPPER = 0x33, } packet LinkLayerPacket { @@ -141,11 +142,11 @@ enum AddressType : 8 { } enum AdvertisementType : 8 { - ADV_IND = 0, // Connectable and scannable - ADV_DIRECT_IND = 1, // Connectable directed - ADV_SCAN_IND = 2, // Scannable undirected - ADV_NONCONN_IND = 3, // Non connectable undirected - SCAN_RESPONSE = 4, + ADV_IND = 0, // Connectable and scannable + ADV_DIRECT_IND = 1, // Connectable directed, high duty cycle + ADV_SCAN_IND = 2, // Scannable undirected + ADV_NONCONN_IND = 3, // Non connectable undirected + SCAN_RESPONSE = 4, // Aliased with connectable directed, low duty cycle } packet LeAdvertisement : LinkLayerPacket (type = LE_ADVERTISEMENT) { @@ -406,3 +407,8 @@ packet ScoConnectionResponse : LinkLayerPacket (type = SCO_CONNECTION_RESPONSE) packet ScoDisconnect : LinkLayerPacket (type = SCO_DISCONNECT) { reason : 8, } + +packet RssiWrapper : LinkLayerPacket (type = RSSI_WRAPPER) { + rssi : 8, + _payload_, +} diff --git a/system/vendor_libs/test_vendor_lib/test/iterator_test.cc b/system/vendor_libs/test_vendor_lib/test/iterator_test.cc deleted file mode 100644 index 0e7b67cf3a..0000000000 --- a/system/vendor_libs/test_vendor_lib/test/iterator_test.cc +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright 2017 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 "hci_packet.h" -#include "l2cap_test_packets.h" - -#include <gtest/gtest.h> -#include <memory> - -using std::unique_ptr; -using std::vector; -namespace test_vendor_lib { - -class TestPacket : public HciPacket { - public: - static std::shared_ptr<TestPacket> make_new_packet(vector<uint8_t> v) { - return std::shared_ptr<TestPacket>(new TestPacket(v)); - } - size_t get_length() { - return test_vector_.size(); - } - uint8_t& get_at_index(size_t index) { - return test_vector_[index]; - } - - private: - TestPacket(vector<uint8_t> v) { - test_vector_ = v; - } - vector<uint8_t> test_vector_; -}; - -class IteratorTest : public ::testing::Test { - public: - IteratorTest() = default; - ~IteratorTest() override = default; - - void SetUp() override { - packet = TestPacket::make_new_packet(complete_l2cap_packet); - } - - void TearDown() override { - packet.reset(); - } - - std::shared_ptr<TestPacket> packet; -}; - -TEST_F(IteratorTest, extractTest) { - Iterator general_case = packet->get_begin(); - - ASSERT_EQ(0x95, general_case.extract<uint8_t>()); - ASSERT_EQ(0x471f, general_case.extract<uint16_t>()); - ASSERT_EQ(0x951f0200u, general_case.extract<uint32_t>()); - ASSERT_EQ(0x33000101000000cbu, general_case.extract<uint64_t>()); -} - -TEST_F(IteratorTest, extractBoundsDeathTest) { - Iterator bounds_test = packet->get_end(); - - ASSERT_DEATH(bounds_test.extract<uint8_t>(), ""); - ASSERT_DEATH(bounds_test.extract<uint16_t>(), ""); - ASSERT_DEATH(bounds_test.extract<uint32_t>(), ""); - ASSERT_DEATH(bounds_test.extract<uint64_t>(), ""); -} - -TEST_F(IteratorTest, dereferenceDeathTest) { - Iterator dereference_test = packet->get_end(); - - ASSERT_EQ(0x45, *(dereference_test - static_cast<size_t>(1))); - ASSERT_DEATH(*dereference_test, ""); -} -TEST_F(IteratorTest, plusEqTest) { - Iterator plus_eq = packet->get_begin(); - for (size_t i = 0; i < complete_l2cap_packet.size(); i += 2) { - ASSERT_EQ(complete_l2cap_packet[i], *plus_eq) - << "+= test: Dereferenced iterator does not equal expected at index " << i; - plus_eq += 2; - } -} - -TEST_F(IteratorTest, preIncrementTest) { - Iterator plus_plus = packet->get_begin(); - for (size_t i = 0; i < complete_l2cap_packet.size() - 1; i++) { - ASSERT_EQ(complete_l2cap_packet[i + 1], *(++plus_plus)) - << "Pre-increment test: Dereferenced iterator does not equal expected " - << "at index " << i; - } -} - -TEST_F(IteratorTest, postIncrementTest) { - Iterator plus_plus = packet->get_begin(); - for (size_t i = 0; i < complete_l2cap_packet.size(); i++) { - ASSERT_EQ(complete_l2cap_packet[i], *(plus_plus++)) - << "Post-increment test: Dereferenced iterator does not equal expected " - << "at index " << i; - } -} - -TEST_F(IteratorTest, additionTest) { - Iterator plus = packet->get_begin(); - for (size_t i = 0; i < complete_l2cap_packet.size(); i++) { - ASSERT_EQ(complete_l2cap_packet[i], *plus) - << "+ test: Dereferenced iterator does not equal expected at index " << i; - plus = plus + static_cast<size_t>(1); - } -} - -TEST_F(IteratorTest, minusEqTest) { - Iterator minus_eq = packet->get_end(); - minus_eq -= 1; - for (size_t i = complete_l2cap_packet.size() - 1; i > 0; i -= 2) { - ASSERT_EQ(complete_l2cap_packet[i], *minus_eq) - << "-= test: Dereferenced iterator does not equal expected at index " << i; - minus_eq -= 2; - } -} - -TEST_F(IteratorTest, preDecrementTest) { - Iterator minus_minus = packet->get_end(); - for (size_t i = complete_l2cap_packet.size(); i > 0; i--) { - ASSERT_EQ(complete_l2cap_packet[i - 1], *(--minus_minus)) - << "Pre-decrement test: Dereferenced iterator does not equal expected " - << "at index " << i; - } -} - -TEST_F(IteratorTest, postDecrementTest) { - Iterator minus_minus = packet->get_end(); - minus_minus--; - for (size_t i = complete_l2cap_packet.size() - 1; i > 0; i--) { - ASSERT_EQ(complete_l2cap_packet[i], *(minus_minus--)) - << "Post-decrement test: Dereferenced iterator does not equal expected " - << "at index " << i; - } -} - -TEST_F(IteratorTest, subtractionTest) { - Iterator minus = packet->get_end(); - minus = minus - static_cast<size_t>(1); - for (size_t i = complete_l2cap_packet.size() - 1; i > 0; i--) { - ASSERT_EQ(complete_l2cap_packet[i], *minus) - << "- test: Dereferenced iterator does not equal expected at index " << i; - minus = minus - static_cast<size_t>(1); - } -} - -TEST_F(IteratorTest, plusEqBoundsTest) { - Iterator plus_eq = packet->get_end(); - plus_eq--; - for (size_t i = 0; i < 100; i++) { - plus_eq += i; - ASSERT_EQ(packet->get_end(), plus_eq) << "+= test: Iterator exceeded the upper bound set by get_length()"; - } -} - -TEST_F(IteratorTest, preIncrementBoundsTest) { - Iterator plus_plus = packet->get_end(); - plus_plus--; - for (size_t i = 0; i < 100; i++) { - ASSERT_EQ(packet->get_end(), ++plus_plus) << "Pre-increment test: Iterator exceeded the upper bound set " - "by get_length()"; - } -} - -TEST_F(IteratorTest, postIncrementBoundsTest) { - Iterator plus_plus = packet->get_end(); - plus_plus--; - for (size_t i = 0; i < 100; i++) { - ASSERT_EQ(packet->get_end(), plus_plus++) << "Post-increment test: Iterator exceeded the upper bound set " - "by get_length()"; - } -} - -TEST_F(IteratorTest, additionBoundsTest) { - Iterator plus = packet->get_end(); - plus--; - for (size_t i = 0; i < 100; i++) { - plus = plus + static_cast<size_t>(i); - ASSERT_EQ(packet->get_end(), plus) << "+ test: Iterator exceeded the upper bound set by get_length()"; - } -} - -TEST_F(IteratorTest, minusEqBoundsTest) { - Iterator minus_eq = packet->get_begin(); - for (size_t i = 0; i < 100; i++) { - minus_eq -= i; - ASSERT_EQ(complete_l2cap_packet[0], *minus_eq) << "-= test: Iterator is less than the lower bound set by " - "packet->get_begin()"; - } -} - -TEST_F(IteratorTest, preDecrementBoundsTest) { - Iterator minus_minus = packet->get_begin(); - for (size_t i = 0; i < 100; i++) { - ASSERT_EQ(complete_l2cap_packet[0], *(--minus_minus)) - << "Pre-decrement test: Iterator is less than the lower bound set by " - "packet->get_begin()"; - } -} - -TEST_F(IteratorTest, postDecrementBoundsTest) { - Iterator minus_minus = packet->get_begin(); - for (size_t i = 0; i < 100; i++) { - ASSERT_EQ(complete_l2cap_packet[0], *(minus_minus--)) - << "Post-decrement test: Iterator is less than the lower bound set by " - "packet->get_begin()"; - } -} - -TEST_F(IteratorTest, subtractionBoundsTest) { - Iterator minus = packet->get_begin(); - for (size_t i = 0; i < 100; i++) { - minus = minus - static_cast<size_t>(i); - ASSERT_EQ(complete_l2cap_packet[0], *minus) << "- test: Iterator is less than the lower bound set " - "by packet->get_begin()"; - } -} -}; // namespace test_vendor_lib diff --git a/system/vendor_libs/test_vendor_lib/test/l2cap_sdu_test.cc b/system/vendor_libs/test_vendor_lib/test/l2cap_sdu_test.cc deleted file mode 100644 index 7aa0ec6bd3..0000000000 --- a/system/vendor_libs/test_vendor_lib/test/l2cap_sdu_test.cc +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2017 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 "l2cap_sdu.h" - -#include <gtest/gtest.h> -#include <memory> - -#include "l2cap_test_packets.h" - -using std::vector; - -namespace test_vendor_lib { - -std::shared_ptr<L2capSdu> packet_1 = L2capSdu::L2capSduConstructor(l2cap_test_packet_1); -std::shared_ptr<L2capSdu> packet_2 = L2capSdu::L2capSduConstructor(l2cap_test_packet_2); -std::shared_ptr<L2capSdu> packet_3 = L2capSdu::L2capSduConstructor(l2cap_test_packet_3); -std::shared_ptr<L2capSdu> packet_4 = L2capSdu::L2capSduConstructor(l2cap_test_packet_4); -std::shared_ptr<L2capSdu> packet_5 = L2capSdu::L2capSduConstructor(l2cap_test_packet_5); -std::shared_ptr<L2capSdu> packet_6 = L2capSdu::L2capSduConstructor(l2cap_test_packet_6); -std::shared_ptr<L2capSdu> packet_7 = L2capSdu::L2capSduConstructor(l2cap_test_packet_7); -std::shared_ptr<L2capSdu> packet_8 = L2capSdu::L2capSduConstructor(l2cap_test_packet_8); -std::shared_ptr<L2capSdu> packet_9 = L2capSdu::L2capSduConstructor(l2cap_test_packet_9); - -class L2capSduTest : public ::testing::Test { - public: - L2capSduTest(){}; - - ~L2capSduTest() override = default; - -}; // L2capSduTest - -TEST_F(L2capSduTest, getFcsTest) { - EXPECT_EQ(0x72aa, packet_1->get_fcs()); - EXPECT_EQ(0x5b57, packet_2->get_fcs()); - EXPECT_EQ(0xe644, packet_3->get_fcs()); - EXPECT_EQ(0x21b0, packet_4->get_fcs()); - EXPECT_EQ(0xae96, packet_5->get_fcs()); - EXPECT_EQ(0x9254, packet_6->get_fcs()); - EXPECT_EQ(0xf6fa, packet_7->get_fcs()); - EXPECT_EQ(0x1da4, packet_8->get_fcs()); - EXPECT_EQ(0x781a, packet_9->get_fcs()); -} - -TEST_F(L2capSduTest, getPayloadLengthTest) { - EXPECT_EQ(l2cap_test_packet_1.size() - 4, packet_1->get_payload_length()); - EXPECT_EQ(l2cap_test_packet_2.size() - 4, packet_2->get_payload_length()); - EXPECT_EQ(l2cap_test_packet_3.size() - 4, packet_3->get_payload_length()); - EXPECT_EQ(l2cap_test_packet_4.size() - 4, packet_4->get_payload_length()); - EXPECT_EQ(l2cap_test_packet_5.size() - 4, packet_5->get_payload_length()); - EXPECT_EQ(l2cap_test_packet_6.size() - 4, packet_6->get_payload_length()); - EXPECT_EQ(l2cap_test_packet_7.size() - 4, packet_7->get_payload_length()); - EXPECT_EQ(l2cap_test_packet_8.size() - 4, packet_8->get_payload_length()); - EXPECT_EQ(l2cap_test_packet_9.size() - 4, packet_9->get_payload_length()); -} - -TEST_F(L2capSduTest, calculateFcsTest) { - EXPECT_EQ(0x72aa, packet_1->calculate_fcs()); - EXPECT_EQ(0x5b57, packet_2->calculate_fcs()); - EXPECT_EQ(0xe644, packet_3->calculate_fcs()); - EXPECT_EQ(0x21b0, packet_4->calculate_fcs()); - EXPECT_EQ(0xae96, packet_5->calculate_fcs()); - EXPECT_EQ(0x9254, packet_6->calculate_fcs()); - EXPECT_EQ(0xf6fa, packet_7->calculate_fcs()); - EXPECT_EQ(0x1da4, packet_8->calculate_fcs()); - EXPECT_EQ(0x781a, packet_9->calculate_fcs()); -} - -TEST_F(L2capSduTest, getControlsTest) { - EXPECT_EQ(0x4102, packet_1->get_controls()); - EXPECT_EQ(0xc104, packet_2->get_controls()); - EXPECT_EQ(0xc106, packet_3->get_controls()); - EXPECT_EQ(0xc108, packet_4->get_controls()); - EXPECT_EQ(0xc10a, packet_5->get_controls()); - EXPECT_EQ(0xc10c, packet_6->get_controls()); - EXPECT_EQ(0xc10e, packet_7->get_controls()); - EXPECT_EQ(0xc110, packet_8->get_controls()); - EXPECT_EQ(0x8112, packet_9->get_controls()); -} - -TEST_F(L2capSduTest, getTotalLengthTest) { - EXPECT_EQ(0x1f95, packet_1->get_total_l2cap_length()); -} - -TEST_F(L2capSduTest, getVectorSizeTest) { - EXPECT_EQ(l2cap_test_packet_1.size(), packet_1->get_vector_size()); - EXPECT_EQ(l2cap_test_packet_2.size(), packet_2->get_vector_size()); - EXPECT_EQ(l2cap_test_packet_3.size(), packet_3->get_vector_size()); - EXPECT_EQ(l2cap_test_packet_4.size(), packet_4->get_vector_size()); - EXPECT_EQ(l2cap_test_packet_5.size(), packet_5->get_vector_size()); - EXPECT_EQ(l2cap_test_packet_6.size(), packet_6->get_vector_size()); - EXPECT_EQ(l2cap_test_packet_7.size(), packet_7->get_vector_size()); - EXPECT_EQ(l2cap_test_packet_8.size(), packet_8->get_vector_size()); - EXPECT_EQ(l2cap_test_packet_9.size(), packet_9->get_vector_size()); -} - -TEST_F(L2capSduTest, getCidTest) { - EXPECT_EQ(0x0047, packet_1->get_channel_id()); - EXPECT_EQ(0x0047, packet_2->get_channel_id()); - EXPECT_EQ(0x0047, packet_3->get_channel_id()); - EXPECT_EQ(0x0047, packet_4->get_channel_id()); - EXPECT_EQ(0x0047, packet_5->get_channel_id()); - EXPECT_EQ(0x0047, packet_6->get_channel_id()); - EXPECT_EQ(0x0047, packet_7->get_channel_id()); - EXPECT_EQ(0x0047, packet_8->get_channel_id()); - EXPECT_EQ(0x0047, packet_9->get_channel_id()); -} - -} // namespace test_vendor_lib diff --git a/system/vendor_libs/test_vendor_lib/test/l2cap_test.cc b/system/vendor_libs/test_vendor_lib/test/l2cap_test.cc deleted file mode 100644 index b218287943..0000000000 --- a/system/vendor_libs/test_vendor_lib/test/l2cap_test.cc +++ /dev/null @@ -1,517 +0,0 @@ -/****************************************************************************** - * - * Copyright 2017 Google, Inc. - * - * 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 "hci_packet.h" -#include "l2cap_packet.h" -#include "l2cap_test_packets.h" - -#include <gtest/gtest.h> -#include <memory> - -using std::shared_ptr; -using std::vector; - -namespace test_vendor_lib { - -class TestPacket : public HciPacket { - public: - TestPacket(const std::vector<uint8_t>& packet) { - complete_packet_ = packet; - } - TestPacket() = default; - - private: - std::vector<uint8_t> complete_packet_; - size_t get_length() { - return complete_packet_.size(); - } - uint8_t& get_at_index(size_t index) { - return complete_packet_[index]; - } -}; - -class L2capTest : public ::testing::Test { - public: - std::shared_ptr<L2capSdu> update_fcs(vector<uint8_t> sdu) { - sdu.resize(sdu.size() - 2); - - return L2capSdu::L2capSduBuilder(sdu); - } - - void compare_packets(shared_ptr<HciPacket> expected, shared_ptr<HciPacket> received) { - Iterator expected_begin = expected->get_begin(); - Iterator expected_end = expected->get_end(); - - Iterator received_begin = received->get_begin(); - Iterator received_end = received->get_end(); - - ASSERT_EQ(expected_end - expected_begin, received_end - received_begin); - - while (expected_begin < expected_end) { - ASSERT_EQ(*expected_begin, *received_begin); - expected_begin++; - received_begin++; - } - } -}; - -TEST_F(L2capTest, assembleGoodPackets) { - vector<std::shared_ptr<L2capSdu> > test_packet; - - // Test 1: Pass correct packets. - test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[0])); - test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[1])); - test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[2])); - - shared_ptr<L2capPacket> test_1 = L2capPacket::assemble(test_packet); - ASSERT_NE(test_1, nullptr); - - shared_ptr<TestPacket> expected(new TestPacket(good_l2cap_packet)); - - compare_packets(expected, test_1); - - test_packet.clear(); - - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_1)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_2)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_3)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_4)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_5)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_6)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_7)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_8)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_9)); - - test_1 = L2capPacket::assemble(test_packet); - ASSERT_NE(test_1, nullptr); - - expected.reset(new TestPacket(complete_l2cap_packet)); - compare_packets(expected, test_1); - - test_packet.clear(); -} - -TEST_F(L2capTest, assembleOutofOrderPackets) { - vector<std::shared_ptr<L2capSdu> > test_packet; - - // Test 2: Pass out of order packets. - test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[1])); - test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[0])); - test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[2])); - - shared_ptr<L2capPacket> test_2 = L2capPacket::assemble(test_packet); - EXPECT_EQ(test_2, nullptr); - - test_packet.clear(); - - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_1)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_3)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_2)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_6)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_5)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_4)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_8)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_7)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_9)); - - test_2 = L2capPacket::assemble(test_packet); - EXPECT_EQ(test_2, nullptr); - - test_packet.clear(); -} - -TEST_F(L2capTest, assembleBadControlBytes) { - vector<std::shared_ptr<L2capSdu> > test_packet; - - // Test 3: Pass packets missing the finished control bytes. - test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[0])); - test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[1])); - - shared_ptr<L2capPacket> test_3 = L2capPacket::assemble(test_packet); - EXPECT_EQ(test_3, nullptr); - - test_packet.clear(); - - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_1)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_2)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_3)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_4)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_5)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_6)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_7)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_8)); - - test_3 = L2capPacket::assemble(test_packet); - EXPECT_EQ(test_3, nullptr); - - test_packet.clear(); -} - -TEST_F(L2capTest, assembleBadFCS) { - vector<std::shared_ptr<L2capSdu> > test_packet; - - // Test 4: Pass packets with incorrect frame check sequences. - test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[0])); - good_sdu[1][good_sdu[1].size() - 1]++; - test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[1])); - good_sdu[1][good_sdu[1].size() - 1]--; - test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[2])); - - shared_ptr<L2capPacket> test_4 = L2capPacket::assemble(test_packet); - EXPECT_EQ(test_4, nullptr); - - test_packet.clear(); - - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_1)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_2)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_3)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_4)); - l2cap_test_packet_5[l2cap_test_packet_5.size() - 1]++; - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_5)); - l2cap_test_packet_5[l2cap_test_packet_5.size() - 1]--; - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_6)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_7)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_8)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_9)); - - test_4 = L2capPacket::assemble(test_packet); - EXPECT_EQ(test_4, nullptr); - - test_packet.clear(); -} - -TEST_F(L2capTest, assembleEmptyPayload) { - vector<std::shared_ptr<L2capSdu> > test_packet; - - // Test 5: Pass a packet with an empty payload. - test_packet.push_back(L2capSdu::L2capSduConstructor(empty_sdu_payload[0])); - test_packet.push_back(L2capSdu::L2capSduConstructor(empty_sdu_payload[1])); - - shared_ptr<L2capPacket> test_5 = L2capPacket::assemble(test_packet); - ASSERT_NE(test_5, nullptr); - - shared_ptr<TestPacket> expected(new TestPacket(empty_l2cap_payload)); - compare_packets(expected, test_5); - - test_packet.clear(); -} - -TEST_F(L2capTest, assembleAllStartingControlError) { - vector<std::shared_ptr<L2capSdu> > test_packet; - - // Test 6: Pass a SDU with all the control bytes set to as the starting bytes. - test_packet.push_back(L2capSdu::L2capSduConstructor(all_first_packet[0])); - test_packet.push_back(L2capSdu::L2capSduConstructor(all_first_packet[1])); - test_packet.push_back(L2capSdu::L2capSduConstructor(all_first_packet[2])); - - shared_ptr<L2capPacket> test_6 = L2capPacket::assemble(test_packet); - EXPECT_EQ(test_6, nullptr); - - test_packet.clear(); -} - -TEST_F(L2capTest, assembleBadCID) { - vector<std::shared_ptr<L2capSdu> > test_packet; - - // Test 7: Pass SDUs with mixed channel ids. - test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[0])); - good_sdu[1][2]++; - test_packet.push_back(update_fcs(good_sdu[1])); - good_sdu[1][2]--; - test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[2])); - - shared_ptr<L2capPacket> test_7 = L2capPacket::assemble(test_packet); - EXPECT_EQ(test_7, nullptr); - - test_packet.clear(); - - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_1)); - l2cap_test_packet_2[2]++; - test_packet.push_back((update_fcs(l2cap_test_packet_2))); - l2cap_test_packet_2[2]--; - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_3)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_4)); - l2cap_test_packet_5[2]++; - test_packet.push_back((update_fcs(l2cap_test_packet_5))); - l2cap_test_packet_5[2]--; - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_6)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_7)); - l2cap_test_packet_8[2]--; - test_packet.push_back((update_fcs(l2cap_test_packet_8))); - l2cap_test_packet_8[2]++; - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_9)); - - test_7 = L2capPacket::assemble(test_packet); - EXPECT_EQ(test_7, nullptr); - - test_packet.clear(); -} - -TEST_F(L2capTest, assembleUnsegmentedSDU) { - vector<std::shared_ptr<L2capSdu> > test_packet; - - // Test 8: Pass a complete l2cap packet. - test_packet.push_back(L2capSdu::L2capSduConstructor(one_sdu[0])); - - shared_ptr<L2capPacket> test_8 = L2capPacket::assemble(test_packet); - EXPECT_NE(test_8, nullptr); - - test_packet.clear(); -} - -TEST_F(L2capTest, assembleBadTxSeq) { - vector<std::shared_ptr<L2capSdu> > test_packet; - - // Test 9: Pass SDUs with incorrect TxSeq. - good_sdu[0][4] += 4; - test_packet.push_back((update_fcs(good_sdu[0]))); - good_sdu[0][4] -= 4; - test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[1])); - test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[2])); - - shared_ptr<L2capPacket> test_9 = L2capPacket::assemble(test_packet); - EXPECT_EQ(test_9, nullptr); - - test_packet.clear(); -} - -TEST_F(L2capTest, assembleBadTotalSDULength) { - vector<std::shared_ptr<L2capSdu> > test_packet; - - // Test 10: Pass SDUs with an incorrect total SDU length - good_sdu[0][7]++; - test_packet.push_back((update_fcs(good_sdu[0]))); - good_sdu[0][7]--; - test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[1])); - test_packet.push_back(L2capSdu::L2capSduConstructor(good_sdu[2])); - - shared_ptr<L2capPacket> test_10 = L2capPacket::assemble(test_packet); - EXPECT_EQ(test_10, nullptr); - - test_packet.clear(); - - l2cap_test_packet_1[6]++; - test_packet.push_back((update_fcs(l2cap_test_packet_1))); - l2cap_test_packet_1[6]--; - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_2)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_3)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_4)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_5)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_6)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_7)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_8)); - test_packet.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_9)); - - test_10 = L2capPacket::assemble(test_packet); - - EXPECT_EQ(test_10, nullptr); - - test_packet.clear(); -} - -// Begin Fragment Test1 -TEST_F(L2capTest, fragmentSmallSegmentTest) { - std::vector<std::shared_ptr<L2capSdu> > sdu; - std::shared_ptr<L2capPacket> l2cap_expected; - std::shared_ptr<L2capPacket> l2cap_received; - - sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[0])); - sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[1])); - sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[2])); - - l2cap_expected = L2capPacket::assemble(sdu); - - sdu.clear(); - - // Test1: Small segments - sdu = l2cap_expected->fragment(16, 0x02, 0x41); - - l2cap_received = L2capPacket::assemble(sdu); - ASSERT_NE(l2cap_received, nullptr) << "packet reassembly failed after fragment" << std::endl - << "Test1: Small Segment request" << std::endl - << "sdu used: good_sdu" << std::endl - << "function call: fragment(16, 0x02, 0x41)" << std::endl; - - compare_packets(l2cap_expected, l2cap_received); - - sdu.clear(); - l2cap_expected.reset(); - l2cap_received.reset(); -} // End Fragment Test1 - -// Begin Fragment Test2 -TEST_F(L2capTest, fragmentLargeSegmentTest) { - std::vector<std::shared_ptr<L2capSdu> > sdu; - std::shared_ptr<L2capPacket> l2cap_expected; - std::shared_ptr<L2capPacket> l2cap_received; - - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_1)); - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_2)); - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_3)); - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_4)); - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_5)); - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_6)); - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_7)); - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_8)); - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_9)); - - l2cap_expected = L2capPacket::assemble(sdu); - - sdu.clear(); - - // Test2: Large Segments - sdu = l2cap_expected->fragment(1024, 0x02, 0x41); - - l2cap_received = L2capPacket::assemble(sdu); - ASSERT_NE(l2cap_received, nullptr) << "packet reassembly failed after fragment" << std::endl - << "Test2: Large Segment request" << std::endl - << "sdu used: l2cap_test_packet[1-9]" << std::endl - << "function call: fragment(1024, 0x02, 0x41)" << std::endl; - - compare_packets(l2cap_expected, l2cap_received); - - sdu.clear(); - l2cap_expected.reset(); - l2cap_received.reset(); -} // End Fragment Test2 - -// Begin Fragment Test3 -TEST_F(L2capTest, fragmentTxSeqTest) { - std::vector<std::shared_ptr<L2capSdu> > sdu; - std::shared_ptr<L2capPacket> l2cap_expected; - std::shared_ptr<L2capPacket> l2cap_received; - - sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[0])); - sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[1])); - sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[2])); - - l2cap_expected = L2capPacket::assemble(sdu); - - sdu.clear(); - - // Test3: Non-zero starting TxSeq - sdu = l2cap_expected->fragment(24, 0x08, 0x41); - - l2cap_received = L2capPacket::assemble(sdu); - ASSERT_NE(l2cap_received, nullptr) << "packet reassembly failed after fragment" << std::endl - << "Test3: Non-zero starting TxSeq" << std::endl - << "sdu used: good_sdu" << std::endl - << "function call: fragment(24, 0x08, 0x41)" << std::endl; - - compare_packets(l2cap_expected, l2cap_received); - - sdu.clear(); - l2cap_expected.reset(); - l2cap_received.reset(); -} // End Fragment Test3 - -// Begin Fragment Test4 -TEST_F(L2capTest, fragmentPayloadTest) { - std::vector<std::shared_ptr<L2capSdu> > sdu; - std::shared_ptr<L2capPacket> l2cap_expected; - std::shared_ptr<L2capPacket> l2cap_received; - - sdu.push_back(L2capSdu::L2capSduConstructor(empty_sdu_payload[0])); - sdu.push_back(L2capSdu::L2capSduConstructor(empty_sdu_payload[1])); - - l2cap_expected = L2capPacket::assemble(sdu); - - sdu.clear(); - - // Test4: Packet with no payload - sdu = l2cap_expected->fragment(16, 0x02, 0x41); - - l2cap_received = L2capPacket::assemble(sdu); - ASSERT_NE(l2cap_received, nullptr) << "packet reassembly failed after fragment" << std::endl - << "Test4: Packet with no payload" << std::endl - << "sdu used: empty_sdu_payload" << std::endl - << "function call: fragment(16, 0x02, 0x41)" << std::endl; - - compare_packets(l2cap_expected, l2cap_received); - - sdu.clear(); - l2cap_expected.reset(); - l2cap_received.reset(); -} // End Fragment Test4 - -// Begin Fragment Test5 -TEST_F(L2capTest, fragmentSegmentSizeTest) { - std::vector<std::shared_ptr<L2capSdu> > sdu; - std::shared_ptr<L2capPacket> l2cap_expected; - std::shared_ptr<L2capPacket> l2cap_received; - - sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[0])); - sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[1])); - sdu.push_back(L2capSdu::L2capSduConstructor(good_sdu[2])); - - l2cap_expected = L2capPacket::assemble(sdu); - - sdu.clear(); - - // Test5: Larger segment size than packet size - sdu = l2cap_expected->fragment(256, 0x02, 0x41); - - l2cap_received = L2capPacket::assemble(sdu); - ASSERT_NE(l2cap_received, nullptr) << "packet reassembly failed after fragment" << std::endl - << "Test5: Segment size > Payload" << std::endl - << "sdu used: good_sdu" << std::endl - << "function call: fragment(256, 0x02, 0x41)" << std::endl; - - compare_packets(l2cap_expected, l2cap_received); - - sdu.clear(); - l2cap_expected.reset(); - l2cap_received.reset(); -} // End Fragment Test5 - -// Begin Fragment Test6 -TEST_F(L2capTest, fragmentSegmentSizeTest2) { - std::vector<std::shared_ptr<L2capSdu> > sdu; - std::shared_ptr<L2capPacket> l2cap_expected; - std::shared_ptr<L2capPacket> l2cap_received; - - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_1)); - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_2)); - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_3)); - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_4)); - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_5)); - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_6)); - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_7)); - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_8)); - sdu.push_back(L2capSdu::L2capSduConstructor(l2cap_test_packet_9)); - - l2cap_expected = L2capPacket::assemble(sdu); - sdu.clear(); - - // Test6: Small segment size on large packet. - sdu = l2cap_expected->fragment(512, 0x02, 0x41); - - l2cap_received = L2capPacket::assemble(sdu); - ASSERT_NE(l2cap_received, nullptr) << "packet reassembly failed after fragment" << std::endl - << "Test6: Small Segment request on large packet" << std::endl - << "sdu used: l2cap_test_packet_[1-9]" << std::endl - << "function call: fragment(64, 0x02, 0x41)" << std::endl; - - compare_packets(l2cap_expected, l2cap_received); - - sdu.clear(); - l2cap_expected.reset(); - l2cap_received.reset(); -} // End Fragment Test6 - -} // namespace test_vendor_lib diff --git a/system/vendor_libs/test_vendor_lib/test/link_layer_socket_device_test.cc b/system/vendor_libs/test_vendor_lib/test/link_layer_socket_device_test.cc deleted file mode 100644 index 5b4ee49dc2..0000000000 --- a/system/vendor_libs/test_vendor_lib/test/link_layer_socket_device_test.cc +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "model/devices/link_layer_socket_device.h" - -#include <gtest/gtest.h> -#include <cstdint> -#include <cstring> -#include <vector> - -#include <netdb.h> -#include <netinet/in.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <unistd.h> - -#include "model/setup/async_manager.h" -#include "packets/link_layer/command_view.h" - -std::vector<uint8_t> count = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, -}; - -using test_vendor_lib::packets::CommandBuilder; -using test_vendor_lib::packets::CommandView; -using test_vendor_lib::packets::LinkLayerPacketBuilder; -using test_vendor_lib::packets::LinkLayerPacketView; -using test_vendor_lib::packets::PacketView; -using test_vendor_lib::packets::View; - -static const size_t kMaxConnections = 300; - -namespace test_vendor_lib { - -class LinkLayerSocketDeviceTest : public ::testing::Test { - public: - static const uint16_t kPort = 6123; - - protected: - class MockPhyLayer : public PhyLayer { - public: - MockPhyLayer(const std::function<void(std::shared_ptr<LinkLayerPacketBuilder>)>& on_receive) - : PhyLayer(Phy::Type::LOW_ENERGY, 0, [](LinkLayerPacketView) {}), on_receive_(on_receive) {} - void Send(const std::shared_ptr<LinkLayerPacketBuilder> packet) override { - on_receive_(packet); - } - void Receive(LinkLayerPacketView) override {} - void TimerTick() override {} - - private: - std::function<void(std::shared_ptr<LinkLayerPacketBuilder>)> on_receive_; - }; - - int StartServer() { - struct sockaddr_in serv_addr; - int fd = socket(AF_INET, SOCK_STREAM, 0); - EXPECT_FALSE(fd < 0); - - memset(&serv_addr, 0, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = INADDR_ANY; - serv_addr.sin_port = htons(kPort); - int reuse_flag = 1; - EXPECT_FALSE(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_flag, sizeof(reuse_flag)) < 0); - EXPECT_FALSE(bind(fd, (sockaddr*)&serv_addr, sizeof(serv_addr)) < 0); - - listen(fd, 1); - return fd; - } - - int AcceptConnection(int fd) { - return accept(fd, NULL, NULL); - } - - void ValidatePacket(size_t index, bool at_server, std::shared_ptr<LinkLayerPacketBuilder> received) { - /* Convert the Builder into a View */ - std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>(); - std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr); - received->Serialize(it); - LinkLayerPacketView received_view = LinkLayerPacketView::Create(packet_ptr); - - /* Validate received packet */ - ASSERT_EQ(received_view.GetSourceAddress(), source_); - ASSERT_EQ(received_view.GetDestinationAddress(), dest_); - ASSERT_EQ(Link::PacketType::COMMAND, received_view.GetType()); - CommandView command_view = CommandView::GetCommand(received_view); - if (at_server) { - ASSERT_EQ(client_opcodes_[index], command_view.GetOpcode()); - } else { - ASSERT_EQ(server_opcodes_[index], command_view.GetOpcode()); - } - auto args_itr = command_view.GetData(); - ASSERT_EQ(args_itr.NumBytesRemaining(), count.size()); - for (size_t i = 0; i < count.size(); i++) { - ASSERT_EQ(*args_itr++, count[i]); - } - if (at_server) { - validated_client_packets_[index]++; - } else { - validated_server_packets_[index]++; - } - } - - void SetUp() override { - servers_.reserve(kMaxConnections); - clients_.reserve(kMaxConnections); - socket_fd_ = StartServer(); - - async_manager_.WatchFdForNonBlockingReads(socket_fd_, [this](int fd) { - int connection_fd = AcceptConnection(fd); - ASSERT_GE(connection_fd, 0); - size_t index = servers_.size(); - servers_.emplace_back(connection_fd, Phy::Type::LOW_ENERGY); - ASSERT_EQ(servers_.size() - 1, index) << "Race condition"; - std::shared_ptr<MockPhyLayer> mock_phy = std::make_shared<MockPhyLayer>( - [this, index](std::shared_ptr<LinkLayerPacketBuilder> received) { ValidatePacket(index, true, received); }); - servers_[index].RegisterPhyLayer(mock_phy); - }); - } - - void TearDown() override { - async_manager_.StopWatchingFileDescriptor(socket_fd_); - close(socket_fd_); - } - - int ConnectClient() { - int socket_cli_fd = socket(AF_INET, SOCK_STREAM, 0); - EXPECT_FALSE(socket_cli_fd < 0); - - struct hostent* server; - server = gethostbyname("localhost"); - EXPECT_FALSE(server == NULL); - - struct sockaddr_in serv_addr; - memset((void*)&serv_addr, 0, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = INADDR_ANY; - serv_addr.sin_port = htons(kPort); - - int result = connect(socket_cli_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); - EXPECT_FALSE(result < 0); - - EXPECT_GE(socket_cli_fd, 0); - - return socket_cli_fd; - } - - void ValidateConnection(size_t pair_id) { - ASSERT_GT(clients_.size(), pair_id); - ASSERT_GT(servers_.size(), pair_id); - } - - size_t CreateConnection() { - int fd = ConnectClient(); - size_t index = clients_.size(); - clients_.emplace_back(fd, Phy::Type::LOW_ENERGY); - std::shared_ptr<MockPhyLayer> mock_phy = std::make_shared<MockPhyLayer>( - [this, index](std::shared_ptr<LinkLayerPacketBuilder> received) { ValidatePacket(index, false, received); }); - clients_[index].RegisterPhyLayer(mock_phy); - for (size_t timeout = 10; timeout > 0 && clients_.size() > servers_.size(); timeout--) { - sleep(0); // Wait for server to be created - } - ValidateConnection(index); - return index; - } - - LinkLayerPacketView NextPacket() { - std::shared_ptr<std::vector<uint8_t>> count_shared = std::make_shared<std::vector<uint8_t>>(count); - LinkLayerPacketView view = LinkLayerPacketView::Create(count_shared); - return view; - } - - void SendFromClient(size_t pair_id) { - ASSERT_GT(clients_.size(), pair_id); - LinkLayerPacketView view = NextPacket(); - client_opcodes_[pair_id] = CommandView::GetCommand(view).GetOpcode(); - clients_[pair_id].IncomingPacket(view); - } - - void SendFromServer(size_t pair_id) { - ASSERT_GT(servers_.size(), pair_id); - LinkLayerPacketView view = NextPacket(); - server_opcodes_[pair_id] = CommandView::GetCommand(view).GetOpcode(); - servers_[pair_id].IncomingPacket(view); - } - - void ReadFromClient(size_t pair_id) { - ASSERT_GT(clients_.size(), pair_id); - size_t validated_packets = validated_server_packets_[pair_id]; - for (size_t tries = 0; tries < 10 && validated_server_packets_[pair_id] == validated_packets; tries++) { - clients_[pair_id].TimerTick(); - } - ASSERT_EQ(validated_server_packets_[pair_id], validated_packets + 1); - } - - void ReadFromServer(size_t pair_id) { - ASSERT_GT(servers_.size(), pair_id); - size_t validated_packets = validated_client_packets_[pair_id]; - for (size_t tries = 0; tries < 10 && validated_client_packets_[pair_id] == validated_packets; tries++) { - servers_[pair_id].TimerTick(); - } - ASSERT_EQ(validated_client_packets_[pair_id], validated_packets + 1); - } - - private: - uint16_t packet_id_{1}; - AsyncManager async_manager_; - int socket_fd_; - std::vector<LinkLayerSocketDevice> servers_; - std::vector<LinkLayerSocketDevice> clients_; - uint16_t server_opcodes_[kMaxConnections]{0}; - uint16_t client_opcodes_[kMaxConnections]{0}; - size_t validated_server_packets_[kMaxConnections]{0}; - size_t validated_client_packets_[kMaxConnections]{0}; - Address source_{{1, 2, 3, 4, 5, 6}}; - Address dest_{{6, 5, 4, 3, 2, 1}}; -}; - -TEST_F(LinkLayerSocketDeviceTest, TestClientFirst) { - size_t pair_id = CreateConnection(); - ASSERT_EQ(pair_id, 0u); - ValidateConnection(pair_id); - - SendFromClient(pair_id); - ReadFromServer(pair_id); -} - -TEST_F(LinkLayerSocketDeviceTest, TestServerFirst) { - size_t pair_id = CreateConnection(); - ASSERT_EQ(pair_id, 0u); - - SendFromServer(pair_id); - ReadFromClient(pair_id); -} - -TEST_F(LinkLayerSocketDeviceTest, TestMultiplePackets) { - static const int num_packets = 30; - size_t pair_id = CreateConnection(); - ASSERT_EQ(pair_id, 0u); - for (int i = 0; i < num_packets; i++) { - SendFromClient(pair_id); - SendFromServer(pair_id); - ReadFromServer(pair_id); - ReadFromClient(pair_id); - } -} - -TEST_F(LinkLayerSocketDeviceTest, TestMultipleConnectionsFromServer) { - static size_t last_pair_id = -1; - size_t pair_id; - for (size_t i = 0; i < kMaxConnections; i++) { - pair_id = CreateConnection(); - ASSERT_EQ(pair_id, last_pair_id + 1); - last_pair_id = pair_id; - SendFromServer(pair_id); - ReadFromClient(pair_id); - } -} - -TEST_F(LinkLayerSocketDeviceTest, TestMultipleConnectionsFromClient) { - for (size_t i = 0; i < kMaxConnections; i++) { - size_t pair_id = CreateConnection(); - ASSERT_EQ(pair_id, i); - SendFromClient(pair_id); - ReadFromServer(pair_id); - } -} - -TEST_F(LinkLayerSocketDeviceTest, TestMultipleConnections) { - for (size_t i = 0; i < kMaxConnections; i++) { - size_t pair_id = CreateConnection(); - ASSERT_EQ(pair_id, i); - SendFromClient(pair_id); - SendFromServer(pair_id); - ReadFromClient(pair_id); - ReadFromServer(pair_id); - } -} - -} // namespace test_vendor_lib diff --git a/system/vendor_libs/test_vendor_lib/test/packet_stream_unittest.cc b/system/vendor_libs/test_vendor_lib/test/packet_stream_unittest.cc deleted file mode 100644 index ab2d767da9..0000000000 --- a/system/vendor_libs/test_vendor_lib/test/packet_stream_unittest.cc +++ /dev/null @@ -1,116 +0,0 @@ -// -// Copyright 2015 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 "packet_stream.h" -#include "command_packet.h" -#include "event_packet.h" -#include "packet.h" - -#include <gtest/gtest.h> -#include <cstdint> -#include <memory> -#include <vector> -using std::vector; - -#include "hci/include/hci_hal.h" - -#include <sys/socket.h> - -namespace { -const char small_payload[] = "foo bar baz"; -const char large_payload[] = - "Aristotle's principles will then be no more principles to him, than those " - "of Epicurus and the Stoics: let this diversity of opinions be propounded " - "to, and laid before him; he will himself choose, if he be able; if not, " - "he will remain in doubt."; -} // namespace - -namespace test_vendor_lib { - -class PacketStreamTest : public ::testing::Test { - public: - PacketStreamTest() { - socketpair(AF_LOCAL, SOCK_STREAM, 0, socketpair_fds_); - CheckSocketpairInit(); - } - - ~PacketStreamTest() override { - close(socketpair_fds_[0]); - close(socketpair_fds_[1]); - } - - void CheckedReceiveCommand(const char* payload, uint16_t opcode) { - uint8_t payload_size = strlen(payload); - vector<uint8_t> packet; - - packet.push_back(DATA_TYPE_COMMAND); - packet.push_back(opcode); - packet.push_back(opcode >> 8); - packet.push_back(payload_size); - - // Set the packet's payload. - for (int i = 0; i < payload_size; ++i) packet.push_back(payload[i]); - - // Send the packet to |packet_stream_|. - write(socketpair_fds_[1], &packet[1], packet.size()); - - // Read the command packet. - std::unique_ptr<CommandPacket> command = packet_stream_.ReceiveCommand(socketpair_fds_[0]); - - const vector<uint8_t> received_payload = command->GetPayload(); - - // Validate the packet by checking that it's the appropriate size and then - // checking each byte. - EXPECT_EQ(packet.size(), command->GetPacketSize()); - EXPECT_EQ(DATA_TYPE_COMMAND, command->GetType()); - EXPECT_EQ(opcode, command->GetOpcode()); - EXPECT_EQ(static_cast<size_t>(payload_size + 1), command->GetPayloadSize()); - EXPECT_EQ(payload_size, received_payload[0]); - for (int i = 0; i < payload_size; ++i) EXPECT_EQ(packet[4 + i], received_payload[i + 1]); - } - - protected: - PacketStream packet_stream_; - - int socketpair_fds_[2]; - - private: - // Workaround because ASSERT cannot be used directly in a constructor - void CheckSocketpairInit() { - ASSERT_TRUE(socketpair_fds_[0] > 0); - ASSERT_TRUE(socketpair_fds_[1] > 0); - } -}; - -TEST_F(PacketStreamTest, ReceivePacketType) { - serial_data_type_t command_type = DATA_TYPE_COMMAND; - write(socketpair_fds_[1], &command_type, 1); - EXPECT_EQ(command_type, packet_stream_.ReceivePacketType(socketpair_fds_[0])); -} - -TEST_F(PacketStreamTest, ReceiveEmptyCommand) { - CheckedReceiveCommand("", HCI_RESET); -} - -TEST_F(PacketStreamTest, ReceiveSmallCommand) { - CheckedReceiveCommand(small_payload, HCI_RESET); -} - -TEST_F(PacketStreamTest, ReceiveLargeCommand) { - CheckedReceiveCommand(large_payload, HCI_RESET); -} - -} // namespace test_vendor_lib diff --git a/system/vendor_libs/test_vendor_lib/types/Android.bp b/system/vendor_libs/test_vendor_lib/types/Android.bp deleted file mode 100644 index e68af2acf5..0000000000 --- a/system/vendor_libs/test_vendor_lib/types/Android.bp +++ /dev/null @@ -1,45 +0,0 @@ -// Bluetooth types -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "system_bt_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["system_bt_license"], -} - -cc_library_headers { - name: "libbt-rootcanal-types-header", - export_include_dirs: ["./"], - vendor_available: true, - host_supported: true, -} - -cc_library_static { - name: "libbt-rootcanal-types", - vendor_available: true, - defaults: ["fluoride_types_defaults"], - cflags: [ - /* we export all classes, so change default visibility, instead of having EXPORT_SYMBOL on each class*/ - "-fvisibility=default", - ], - host_supported: true, - srcs: [ - "bluetooth/uuid.cc", - ], - header_libs: ["libbt-rootcanal-types-header"], - export_header_lib_headers: ["libbt-rootcanal-types-header"], -} - -cc_test { - name: "rootcanal-test_types", - test_suites: ["device-tests"], - defaults: ["fluoride_defaults"], - host_supported: true, - srcs: [ - "test/bluetooth/uuid_unittest.cc", - ], - static_libs: [ - "libbt-rootcanal-types", - ], -} diff --git a/system/vendor_libs/test_vendor_lib/types/BUILD.gn b/system/vendor_libs/test_vendor_lib/types/BUILD.gn deleted file mode 100644 index 8629d3be76..0000000000 --- a/system/vendor_libs/test_vendor_lib/types/BUILD.gn +++ /dev/null @@ -1,65 +0,0 @@ -# -# Copyright 2017 Google, Inc. -# -# 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. -# - -static_library("types") { - cflags = [ - "-fvisibility=default", - ] - - sources = [ - "bluetooth/uuid.cc", - "le_address.cc", - "address.cc", - ] - - include_dirs = [ - "//bt/system", - ] - - configs += [ - "//bt/system:target_defaults", - ] -} - -if (use.test) { - executable("types_unittests") { - sources = [ - "test/address_unittest.cc", - "test/bluetooth/uuid_unittest.cc", - ] - - include_dirs = [ - "//bt/system", - ] - - libs = [ - "dl", - "pthread", - "resolv", - "rt", - "z", - ] - - deps = [ - "//bt/system/types", - ] - - configs += [ - "//bt/system:external_gmock_main", - "//bt/system:target_defaults", - ] - } -} diff --git a/system/vendor_libs/test_vendor_lib/types/bluetooth/uuid.cc b/system/vendor_libs/test_vendor_lib/types/bluetooth/uuid.cc deleted file mode 100644 index cc1420642e..0000000000 --- a/system/vendor_libs/test_vendor_lib/types/bluetooth/uuid.cc +++ /dev/null @@ -1,182 +0,0 @@ -/****************************************************************************** - * - * Copyright (C) 2017 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 "uuid.h" - -#include <algorithm> -#include <cstring> -#include <random> - -namespace bluetooth { - -static_assert(sizeof(Uuid) == 16, "Uuid must be 16 bytes long!"); - -using UUID128Bit = Uuid::UUID128Bit; - -const Uuid Uuid::kEmpty = Uuid::From128BitBE(UUID128Bit{{0x00}}); - -namespace { -constexpr Uuid kBase = Uuid::From128BitBE( - UUID128Bit{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}}); -} // namespace - -size_t Uuid::GetShortestRepresentationSize() const { - if (memcmp(uu.data() + kNumBytes32, kBase.uu.data() + kNumBytes32, kNumBytes128 - kNumBytes32) != 0) { - return kNumBytes128; - } - - if (uu[0] == 0 && uu[1] == 0) return kNumBytes16; - - return kNumBytes32; -} - -bool Uuid::Is16Bit() const { - return GetShortestRepresentationSize() == kNumBytes16; -} - -uint16_t Uuid::As16Bit() const { - return (((uint16_t)uu[2]) << 8) + uu[3]; -} - -uint32_t Uuid::As32Bit() const { - return (((uint32_t)uu[0]) << 24) + (((uint32_t)uu[1]) << 16) + (((uint32_t)uu[2]) << 8) + uu[3]; -} - -Uuid Uuid::FromString(const std::string& uuid, bool* is_valid) { - if (is_valid) *is_valid = false; - Uuid ret = kBase; - - if (uuid.empty()) return ret; - - uint8_t* p = ret.uu.data(); - if (uuid.size() == kString128BitLen) { - if (uuid[8] != '-' || uuid[13] != '-' || uuid[18] != '-' || uuid[23] != '-') { - return ret; - } - - int c; - int rc = sscanf(uuid.c_str(), - "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx" - "-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%n", - &p[0], &p[1], &p[2], &p[3], &p[4], &p[5], &p[6], &p[7], &p[8], &p[9], &p[10], &p[11], &p[12], - &p[13], &p[14], &p[15], &c); - if (rc != 16) return ret; - if (c != kString128BitLen) return ret; - - if (is_valid) *is_valid = true; - } else if (uuid.size() == 8) { - int c; - int rc = sscanf(uuid.c_str(), "%02hhx%02hhx%02hhx%02hhx%n", &p[0], &p[1], &p[2], &p[3], &c); - if (rc != 4) return ret; - if (c != 8) return ret; - - if (is_valid) *is_valid = true; - } else if (uuid.size() == 4) { - int c; - int rc = sscanf(uuid.c_str(), "%02hhx%02hhx%n", &p[2], &p[3], &c); - if (rc != 2) return ret; - if (c != 4) return ret; - - if (is_valid) *is_valid = true; - } - - return ret; -} - -Uuid Uuid::From16Bit(uint16_t uuid16) { - Uuid u = kBase; - - u.uu[2] = (uint8_t)((0xFF00 & uuid16) >> 8); - u.uu[3] = (uint8_t)(0x00FF & uuid16); - return u; -} - -Uuid Uuid::From32Bit(uint32_t uuid32) { - Uuid u = kBase; - - u.uu[0] = (uint8_t)((0xFF000000 & uuid32) >> 24); - u.uu[1] = (uint8_t)((0x00FF0000 & uuid32) >> 16); - u.uu[2] = (uint8_t)((0x0000FF00 & uuid32) >> 8); - u.uu[3] = (uint8_t)(0x000000FF & uuid32); - return u; -} - -Uuid Uuid::From128BitBE(const uint8_t* uuid) { - UUID128Bit tmp; - memcpy(tmp.data(), uuid, kNumBytes128); - return From128BitBE(tmp); -} - -Uuid Uuid::From128BitLE(const UUID128Bit& uuid) { - Uuid u; - std::reverse_copy(uuid.data(), uuid.data() + kNumBytes128, u.uu.begin()); - return u; -} - -Uuid Uuid::From128BitLE(const uint8_t* uuid) { - UUID128Bit tmp; - memcpy(tmp.data(), uuid, kNumBytes128); - return From128BitLE(tmp); -} - -const UUID128Bit Uuid::To128BitLE() const { - UUID128Bit le; - std::reverse_copy(uu.data(), uu.data() + kNumBytes128, le.begin()); - return le; -} - -const UUID128Bit& Uuid::To128BitBE() const { - return uu; -} - -Uuid Uuid::GetRandom() { - Uuid uuid; - std::independent_bits_engine<std::default_random_engine, 8, unsigned int> - engine; - std::generate(std::begin(uuid.uu), std::end(uuid.uu), std::ref(engine)); - return uuid; -} - -bool Uuid::IsEmpty() const { - return *this == kEmpty; -} - -bool Uuid::operator<(const Uuid& rhs) const { - return std::lexicographical_compare(uu.begin(), uu.end(), rhs.uu.begin(), rhs.uu.end()); -} - -bool Uuid::operator==(const Uuid& rhs) const { - return uu == rhs.uu; -} - -bool Uuid::operator!=(const Uuid& rhs) const { - return uu != rhs.uu; -} - -std::string Uuid::ToString() const { - char buffer[37]; - - snprintf( - buffer, sizeof(buffer), - "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7], uu[8], uu[9], - uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]); - - return buffer; -} -} // namespace bluetooth diff --git a/system/vendor_libs/test_vendor_lib/types/bluetooth/uuid.h b/system/vendor_libs/test_vendor_lib/types/bluetooth/uuid.h deleted file mode 100644 index cea2cf48d8..0000000000 --- a/system/vendor_libs/test_vendor_lib/types/bluetooth/uuid.h +++ /dev/null @@ -1,140 +0,0 @@ -/****************************************************************************** - * - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - -#pragma once - -#include <stdint.h> -#include <array> -#include <ostream> -#include <string> - -namespace bluetooth { - -// This class is representing Bluetooth UUIDs across whole stack. -// Here are some general endianness rules: -// 1. UUID is internally kept as as Big Endian. -// 2. Bytes representing UUID coming from upper layers, Java or Binder, are Big -// Endian. -// 3. Bytes representing UUID coming from lower layer, HCI packets, are Little -// Endian. -// 4. UUID in storage is always string. -class Uuid final { - public: - static constexpr size_t kNumBytes128 = 16; - static constexpr size_t kNumBytes32 = 4; - static constexpr size_t kNumBytes16 = 2; - - static constexpr size_t kString128BitLen = 36; - - static const Uuid kEmpty; // 00000000-0000-0000-0000-000000000000 - - using UUID128Bit = std::array<uint8_t, kNumBytes128>; - - Uuid() = default; - - // Creates and returns a random 128-bit UUID. - static Uuid GetRandom(); - - // Returns the shortest possible representation of this UUID in bytes. Either - // kNumBytes16, kNumBytes32, or kNumBytes128 - size_t GetShortestRepresentationSize() const; - - // Returns true if this UUID can be represented as 16 bit. - bool Is16Bit() const; - - // Returns 16 bit Little Endian representation of this UUID. Use - // GetShortestRepresentationSize() or Is16Bit() before using this method. - uint16_t As16Bit() const; - - // Returns 32 bit Little Endian representation of this UUID. Use - // GetShortestRepresentationSize() before using this method. - uint32_t As32Bit() const; - - // Converts string representing 128, 32, or 16 bit UUID in - // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, xxxxxxxx, or xxxx format to UUID. If - // set, optional is_valid parameter will be set to true if conversion is - // successfull, false otherwise. - static Uuid FromString(const std::string& uuid, bool* is_valid = nullptr); - - // Converts 16bit Little Endian representation of UUID to UUID - static Uuid From16Bit(uint16_t uuid16bit); - - // Converts 32bit Little Endian representation of UUID to UUID - static Uuid From32Bit(uint32_t uuid32bit); - - // Converts 128 bit Big Endian array representing UUID to UUID. - static constexpr Uuid From128BitBE(const UUID128Bit& uuid) { - Uuid u(uuid); - return u; - } - - // Converts 128 bit Big Endian array representing UUID to UUID. |uuid| points - // to beginning of array. - static Uuid From128BitBE(const uint8_t* uuid); - - // Converts 128 bit Little Endian array representing UUID to UUID. - static Uuid From128BitLE(const UUID128Bit& uuid); - - // Converts 128 bit Little Endian array representing UUID to UUID. |uuid| - // points to beginning of array. - static Uuid From128BitLE(const uint8_t* uuid); - - // Returns 128 bit Little Endian representation of this UUID - const UUID128Bit To128BitLE() const; - - // Returns 128 bit Big Endian representation of this UUID - const UUID128Bit& To128BitBE() const; - - // Returns string representing this UUID in - // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format, lowercase. - std::string ToString() const; - - // Returns true if this UUID is equal to kEmpty - bool IsEmpty() const; - - bool operator<(const Uuid& rhs) const; - bool operator==(const Uuid& rhs) const; - bool operator!=(const Uuid& rhs) const; - - private: - constexpr Uuid(const UUID128Bit& val) : uu{val} {}; - - // Network-byte-ordered ID (Big Endian). - UUID128Bit uu; -}; -} // namespace bluetooth - -inline std::ostream& operator<<(std::ostream& os, const bluetooth::Uuid& a) { - os << a.ToString(); - return os; -} - -// Custom std::hash specialization so that bluetooth::UUID can be used as a key -// in std::unordered_map. -namespace std { - -template <> -struct hash<bluetooth::Uuid> { - std::size_t operator()(const bluetooth::Uuid& key) const { - const auto& uuid_bytes = key.To128BitBE(); - std::hash<std::string> hash_fn; - return hash_fn(std::string(reinterpret_cast<const char*>(uuid_bytes.data()), uuid_bytes.size())); - } -}; - -} // namespace std diff --git a/system/vendor_libs/test_vendor_lib/types/test/bluetooth/uuid_unittest.cc b/system/vendor_libs/test_vendor_lib/types/test/bluetooth/uuid_unittest.cc deleted file mode 100644 index be2ef102f1..0000000000 --- a/system/vendor_libs/test_vendor_lib/types/test/bluetooth/uuid_unittest.cc +++ /dev/null @@ -1,155 +0,0 @@ -/****************************************************************************** - * - * Copyright (C) 2017 Google, Inc. - * - * 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 <bluetooth/uuid.h> -#include <gtest/gtest.h> - -using bluetooth::Uuid; - -static const Uuid ONES = Uuid::From128BitBE( - Uuid::UUID128Bit{{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}}); - -static const Uuid SEQUENTIAL = Uuid::From128BitBE( - Uuid::UUID128Bit{{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89}}); - -constexpr Uuid kBase = Uuid::From128BitBE( - Uuid::UUID128Bit{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}}); - -TEST(UuidTest, IsEmpty) { - EXPECT_TRUE(Uuid::kEmpty.IsEmpty()); - EXPECT_FALSE(kBase.IsEmpty()); -} - -TEST(UuidTest, GetShortestRepresentationSize) { - EXPECT_TRUE(Uuid::kNumBytes16 == kBase.GetShortestRepresentationSize()); - EXPECT_TRUE(Uuid::kNumBytes32 == Uuid::From32Bit(0x01234567).GetShortestRepresentationSize()); - EXPECT_TRUE(Uuid::kNumBytes128 == Uuid::kEmpty.GetShortestRepresentationSize()); -} - -TEST(UuidTest, As16Bit) { - // Even though this is is not 16bit UUID, we should be able to get proper bits - EXPECT_EQ((uint16_t)0x1111, ONES.As16Bit()); - EXPECT_EQ((uint16_t)0x4567, SEQUENTIAL.As16Bit()); - EXPECT_EQ((uint16_t)0x0000, kBase.As16Bit()); -} - -TEST(UuidTest, As32Bit) { - // Even though this is is not 32bit UUID, we should be able to get proper bits - EXPECT_EQ((uint32_t)0x11111111, ONES.As32Bit()); - EXPECT_EQ((uint32_t)0x01234567, SEQUENTIAL.As32Bit()); - EXPECT_EQ((uint32_t)0x00000000, kBase.As32Bit()); - EXPECT_EQ((uint32_t)0x12345678, Uuid::From32Bit(0x12345678).As32Bit()); -} - -TEST(UuidTest, Is16Bit) { - EXPECT_FALSE(ONES.Is16Bit()); - EXPECT_FALSE(SEQUENTIAL.Is16Bit()); - EXPECT_TRUE(kBase.Is16Bit()); - EXPECT_TRUE(Uuid::FromString("1ae8").Is16Bit()); -} - -TEST(UuidTest, From16Bit) { - EXPECT_EQ(Uuid::From16Bit(0x0000), kBase); - - const uint8_t u2[] = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}; - Uuid uuid = Uuid::From16Bit(0x0001); - EXPECT_TRUE(memcmp(&uuid, u2, sizeof(u2)) == 0); - - const uint8_t u3[] = {0x00, 0x00, 0x55, 0x3e, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}; - uuid = Uuid::From16Bit(0x553e); - EXPECT_TRUE(memcmp(&uuid, u3, sizeof(u3)) == 0); - - const uint8_t u4[] = {0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}; - uuid = Uuid::From16Bit(0xffff); - EXPECT_TRUE(memcmp(&uuid, u4, sizeof(u4)) == 0); -} - -TEST(UuidTest, From32Bit) { - EXPECT_EQ(Uuid::From32Bit(0x00000000), kBase); - - const uint8_t u2[] = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}; - Uuid uuid = Uuid::From32Bit(0x00000001); - EXPECT_TRUE(memcmp(&uuid, u2, sizeof(u2)) == 0); - - const uint8_t u3[] = {0x33, 0x44, 0x55, 0x3e, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}; - uuid = Uuid::From32Bit(0x3344553e); - EXPECT_TRUE(memcmp(&uuid, u3, sizeof(u3)) == 0); - - const uint8_t u4[] = {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}; - uuid = Uuid::From32Bit(0xffffffff); - EXPECT_TRUE(memcmp(&uuid, u4, sizeof(u4)) == 0); -} - -TEST(UuidTest, ToString) { - const std::string UUID_BASE_STR = "00000000-0000-1000-8000-00805f9b34fb"; - const std::string UUID_EMP_STR = "00000000-0000-0000-0000-000000000000"; - const std::string UUID_ONES_STR = "11111111-1111-1111-1111-111111111111"; - const std::string UUID_SEQ_STR = "01234567-89ab-cdef-abcd-ef0123456789"; - - EXPECT_EQ(UUID_BASE_STR, kBase.ToString()); - EXPECT_EQ(UUID_EMP_STR, Uuid::kEmpty.ToString()); - EXPECT_EQ(UUID_ONES_STR, ONES.ToString()); - EXPECT_EQ(UUID_SEQ_STR, SEQUENTIAL.ToString()); - - Uuid uuid = Uuid::From32Bit(0x12345678); - EXPECT_EQ("12345678-0000-1000-8000-00805f9b34fb", uuid.ToString()); -} - -TEST(BtifStorageTest, test_string_to_uuid) { - const uint8_t u1[] = {0xe3, 0x9c, 0x62, 0x85, 0x86, 0x7f, 0x4b, 0x1d, 0x9d, 0xb0, 0x35, 0xfb, 0xd9, 0xae, 0xbf, 0x22}; - bool is_valid = false; - Uuid uuid = Uuid::FromString("e39c6285-867f-4b1d-9db0-35fbd9aebf22", &is_valid); - EXPECT_TRUE(is_valid); - EXPECT_TRUE(memcmp(&uuid, u1, sizeof(u1)) == 0); - - const uint8_t u2[] = {0x00, 0x00, 0x1a, 0xe8, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}; - is_valid = false; - uuid = Uuid::FromString("1Ae8", &is_valid); - EXPECT_TRUE(is_valid); - EXPECT_TRUE(memcmp(&uuid, u2, sizeof(u2)) == 0); - - const uint8_t u3[] = {0x12, 0x34, 0x11, 0x28, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}; - is_valid = false; - uuid = Uuid::FromString("12341128", &is_valid); - EXPECT_TRUE(is_valid); - EXPECT_TRUE(memcmp(&uuid, u3, sizeof(u3)) == 0); -} - -TEST(BtifStorageTest, test_string_to_uuid_invalid) { - bool is_valid = false; - Uuid uuid = Uuid::FromString("This is not a UUID", &is_valid); - EXPECT_FALSE(is_valid); - - uuid = Uuid::FromString("11212", &is_valid); - EXPECT_FALSE(is_valid); - - uuid = Uuid::FromString("1121 ", &is_valid); - EXPECT_FALSE(is_valid); - - uuid = Uuid::FromString("AGFE", &is_valid); - EXPECT_FALSE(is_valid); - - uuid = Uuid::FromString("ABFG", &is_valid); - EXPECT_FALSE(is_valid); - - uuid = Uuid::FromString("e39c6285867f14b1d9db035fbd9aebf22", &is_valid); - EXPECT_FALSE(is_valid); - - uuid = Uuid::FromString("12234567-89ab-cdef-abcd-ef01234567ZZ", &is_valid); - EXPECT_FALSE(is_valid); -} |