Loading android/app/jni/com_android_bluetooth_hfp.cpp +27 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <mutex> #include <shared_mutex> #include "btif/include/btif_hf.h" #include "com_android_bluetooth.h" #include "hardware/bluetooth_headset_callbacks.h" #include "hardware/bluetooth_headset_interface.h" Loading Loading @@ -954,6 +955,31 @@ static jboolean setActiveDeviceNative(JNIEnv* env, jobject /* object */, return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; } static jboolean enableSwbNative(JNIEnv* env, jobject /* object */, jint swbCodec, jboolean enable, jbyteArray address) { std::shared_lock<std::shared_timed_mutex> lock(interface_mutex); if (!sBluetoothHfpInterface) { ALOGW("%s: sBluetoothHfpInterface is null", __func__); return JNI_FALSE; } jbyte* addr = env->GetByteArrayElements(address, NULL); if (!addr) { ALOGE("%s: failed to get device address", __func__); jniThrowIOException(env, EINVAL); return JNI_FALSE; } bt_status_t ret = sBluetoothHfpInterface->EnableSwb( (bluetooth::headset::bthf_swb_codec_t)swbCodec, (bool)enable, (RawAddress*)addr); if (ret != BT_STATUS_SUCCESS) { ALOGE("%s: Failed to %s", __func__, (enable ? "enable" : "disable")); return JNI_FALSE; } ALOGV("%s: Successfully %s", __func__, (enable ? "enabled" : "disabled")); return JNI_TRUE; } int register_com_android_bluetooth_hfp(JNIEnv* env) { const JNINativeMethod methods[] = { {"initializeNative", "(IZ)V", (void*)initializeNative}, Loading Loading @@ -987,6 +1013,7 @@ int register_com_android_bluetooth_hfp(JNIEnv* env) { {"setScoAllowedNative", "(Z)Z", (void*)setScoAllowedNative}, {"sendBsirNative", "(Z[B)Z", (void*)sendBsirNative}, {"setActiveDeviceNative", "([B)Z", (void*)setActiveDeviceNative}, {"enableSwbNative", "(IZ[B)Z", (void*)enableSwbNative}, }; const int result = REGISTER_NATIVE_METHODS( env, "com/android/bluetooth/hfp/HeadsetNativeInterface", methods); Loading android/app/src/com/android/bluetooth/hfp/HeadsetNativeInterface.java +15 −0 Original line number Diff line number Diff line Loading @@ -512,6 +512,19 @@ public class HeadsetNativeInterface { return setActiveDeviceNative(getByteAddress(device)); } /** * Enable Super Wide Band * * @param swbCodec SWB Codec * @param enable True to enable, False to disable * @param device current active SCO device * @return True on success, False on failure */ @VisibleForTesting public boolean enableSwb(int swbCodec, boolean enable, BluetoothDevice device) { return enableSwbNative(swbCodec, enable, getByteAddress(device)); } /* Native methods */ private native boolean atResponseCodeNative(int responseCode, int errorCode, byte[] address); Loading Loading @@ -558,4 +571,6 @@ public class HeadsetNativeInterface { private native boolean sendBsirNative(boolean value, byte[] address); private native boolean setActiveDeviceNative(byte[] address); private native boolean enableSwbNative(int swbCodec, boolean enable, byte[] address); } android/app/src/com/android/bluetooth/hfp/HeadsetService.java +49 −1 Original line number Diff line number Diff line Loading @@ -155,12 +155,14 @@ public class HeadsetService extends ProfileService { private boolean mStarted; private static HeadsetService sHeadsetService; @VisibleForTesting boolean mIsAptXSwbEnabled = false; @VisibleForTesting boolean mIsAptXSwbPmEnabled = false; private final ServiceFactory mFactory = new ServiceFactory(); public HeadsetService(Context ctx) { super(ctx); } public static boolean isEnabled() { return BluetoothProperties.isProfileHfpAgEnabled().orElse(false); } Loading Loading @@ -191,11 +193,26 @@ public class HeadsetService extends ProfileService { // Step 3: Initialize system interface mSystemInterface = HeadsetObjectsFactory.getInstance().makeSystemInterface(this); // Step 4: Initialize native interface if (Flags.hfpCodecAptxVoice()) { mIsAptXSwbEnabled = SystemProperties.getBoolean("bluetooth.hfp.codec_aptx_voice.enabled", false); Log.i(TAG, "mIsAptXSwbEnabled: " + mIsAptXSwbEnabled); mIsAptXSwbPmEnabled = SystemProperties.getBoolean( "bluetooth.hfp.swb.aptx.power_management.enabled", false); Log.i(TAG, "mIsAptXSwbPmEnabled: " + mIsAptXSwbPmEnabled); } setHeadsetService(this); mMaxHeadsetConnections = mAdapterService.getMaxConnectedAudioDevices(); mNativeInterface = HeadsetObjectsFactory.getInstance().getNativeInterface(); // Add 1 to allow a pending device to be connecting or disconnecting mNativeInterface.init(mMaxHeadsetConnections + 1, isInbandRingingEnabled()); if (Flags.hfpCodecAptxVoice()) { enableSwbCodec( HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, mIsAptXSwbEnabled, mActiveDevice); } // Step 5: Check if state machine table is empty, crash if not if (mStateMachines.size() > 0) { throw new IllegalStateException( Loading Loading @@ -1208,6 +1225,9 @@ public class HeadsetService extends ProfileService { } stateMachine.sendMessage(HeadsetStateMachine.CONNECT_AUDIO, device); } if (Flags.hfpCodecAptxVoice()) { enableSwbCodec(HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, true, device); } return true; } Loading Loading @@ -1242,6 +1262,9 @@ public class HeadsetService extends ProfileService { } stateMachine.sendMessage(HeadsetStateMachine.DISCONNECT_AUDIO, device); } if (Flags.hfpCodecAptxVoice()) { enableSwbCodec(HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, false, device); } return true; } Loading Loading @@ -1806,6 +1829,9 @@ public class HeadsetService extends ProfileService { if (!mSystemInterface.getVoiceRecognitionWakeLock().isHeld()) { mSystemInterface.getVoiceRecognitionWakeLock().acquire(sStartVrTimeoutMs); } if (Flags.hfpCodecAptxVoice()) { enableSwbCodec(HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, true, fromDevice); } return true; } } Loading Loading @@ -1844,6 +1870,9 @@ public class HeadsetService extends ProfileService { Log.w(TAG, "stopVoiceRecognitionByHeadset: failed request from " + fromDevice); return false; } if (Flags.hfpCodecAptxVoice()) { enableSwbCodec(HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, false, fromDevice); } return true; } } Loading Loading @@ -2381,6 +2410,25 @@ public class HeadsetService extends ProfileService { } } /** Enable SWB Codec. */ void enableSwbCodec(int swbCodec, boolean enable, BluetoothDevice device) { logD("enableSwbCodec: swbCodec: " + swbCodec + " enable: " + enable + " device: " + device); boolean result = mNativeInterface.enableSwb(swbCodec, enable, device); logD("enableSwbCodec result: " + result); } /** Check whether AptX SWB Codec is enabled. */ boolean isAptXSwbEnabled() { logD("mIsAptXSwbEnabled: " + mIsAptXSwbEnabled); return mIsAptXSwbEnabled; } /** Check whether AptX SWB Codec Power Management is enabled. */ boolean isAptXSwbPmEnabled() { logD("isAptXSwbPmEnabled: " + mIsAptXSwbPmEnabled); return mIsAptXSwbPmEnabled; } private static void logD(String message) { if (DBG) { Log.d(TAG, message); Loading android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java +58 −9 Original line number Diff line number Diff line Loading @@ -36,7 +36,6 @@ import android.os.Build; import android.os.Looper; import android.os.Message; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.telephony.PhoneNumberUtils; import android.telephony.PhoneStateListener; Loading Loading @@ -168,10 +167,6 @@ public class HeadsetStateMachine extends StateMachine { private BluetoothSinkAudioPolicy mHsClientAudioPolicy; static final boolean IS_APTX_SUPPORT_ENABLED = Flags.hfpCodecAptxVoice() && SystemProperties.getBoolean("bluetooth.hfp.codec_aptx_voice.enabled", false); // Keys are AT commands, and values are the company IDs. private static final Map<String, Integer> VENDOR_SPECIFIC_AT_COMMAND_COMPANY_ID; Loading Loading @@ -494,6 +489,39 @@ public class HeadsetStateMachine extends StateMachine { */ abstract int getAudioStateInt(); protected void setAptxVoice(HeadsetCallState callState) { if (!Flags.hfpCodecAptxVoice()) { return; } if (!mHeadsetService.isAptXSwbEnabled()) { return; } if (!mHeadsetService.isAptXSwbPmEnabled()) { return; } if (mHeadsetService.isVirtualCallStarted()) { stateLogD("CALL_STATE_CHANGED: enable AptX SWB for all voip calls "); mHeadsetService.enableSwbCodec( HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, true, mDevice); } else if ((callState.mCallState == HeadsetHalConstants.CALL_STATE_DIALING) || (callState.mCallState == HeadsetHalConstants.CALL_STATE_INCOMING) || ((callState.mCallState == HeadsetHalConstants.CALL_STATE_IDLE) && (callState.mNumActive > 0))) { if (!mSystemInterface.isHighDefCallInProgress()) { stateLogD("CALL_STATE_CHANGED: disable AptX SWB for non-HD call "); mHeadsetService.enableSwbCodec( HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, false, mDevice); mHasSwbAptXEnabled = false; } else { stateLogD("CALL_STATE_CHANGED: enable AptX SWB for HD call "); mHeadsetService.enableSwbCodec( HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, true, mDevice); mHasSwbAptXEnabled = true; } } else { stateLogD("CALL_STATE_CHANGED: AptX SWB state unchanged"); } } } class Disconnected extends HeadsetStateBase { Loading Loading @@ -696,7 +724,8 @@ public class HeadsetStateMachine extends StateMachine { break; } case CALL_STATE_CHANGED: stateLogD("ignoring CALL_STATE_CHANGED event"); HeadsetCallState callState = (HeadsetCallState) message.obj; setAptxVoice(callState); break; case DEVICE_STATE_CHANGED: stateLogD("ignoring DEVICE_STATE_CHANGED event"); Loading Loading @@ -958,14 +987,15 @@ public class HeadsetStateMachine extends StateMachine { } break; } case CALL_STATE_CHANGED: { case CALL_STATE_CHANGED: HeadsetCallState callState = (HeadsetCallState) message.obj; setAptxVoice(callState); if (!mNativeInterface.phoneStateChange(mDevice, callState)) { stateLogW("processCallState: failed to update call state " + callState); break; } break; } case DEVICE_STATE_CHANGED: if (mDeviceSilenced) { stateLogW("DEVICE_STATE_CHANGED: " + mDevice Loading Loading @@ -1200,6 +1230,22 @@ public class HeadsetStateMachine extends StateMachine { if (isAtLeastU()) { mSystemInterface.getAudioManager().setLeAudioSuspended(true); } if (Flags.hfpCodecAptxVoice() && mHeadsetService.isAptXSwbEnabled() && mHeadsetService.isAptXSwbPmEnabled()) { if (!mHeadsetService.isVirtualCallStarted() && mSystemInterface.isHighDefCallInProgress()) { stateLogD("CONNECT_AUDIO: enable AptX SWB for HD call "); mHeadsetService.enableSwbCodec( HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, true, mDevice); } else { stateLogD("CONNECT_AUDIO: disable AptX SWB for non-HD or Voip calls"); mHeadsetService.enableSwbCodec( HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, false, mDevice); } } if (!mNativeInterface.connectAudio(mDevice)) { mSystemInterface.getAudioManager().setA2dpSuspended(false); if (isAtLeastU()) { Loading Loading @@ -1703,7 +1749,7 @@ public class HeadsetStateMachine extends StateMachine { + (" hasSwbEnabled=" + mHasSwbLc3Enabled) + (" hasAptXSwbEnabled=" + mHasSwbAptXEnabled)); am.setParameters("bt_lc3_swb=" + (mHasSwbLc3Enabled ? "on" : "off")); if (IS_APTX_SUPPORT_ENABLED) { if (Flags.hfpCodecAptxVoice() && mHeadsetService.isAptXSwbEnabled()) { /* AptX bt_swb: 0 -> on, 65535 -> off */ am.setParameters("bt_swb=" + (mHasSwbAptXEnabled ? "0" : "65535")); } Loading Loading @@ -1851,6 +1897,9 @@ public class HeadsetStateMachine extends StateMachine { switch (wbsConfig) { case HeadsetHalConstants.BTHF_WBS_YES: mHasWbsEnabled = true; if (Flags.hfpCodecAptxVoice() && mHeadsetService.isAptXSwbEnabled()) { mHasSwbAptXEnabled = false; } break; case HeadsetHalConstants.BTHF_WBS_NO: case HeadsetHalConstants.BTHF_WBS_NONE: Loading android/app/src/com/android/bluetooth/hfp/HeadsetSystemInterface.java +12 −0 Original line number Diff line number Diff line Loading @@ -240,6 +240,18 @@ public class HeadsetSystemInterface { return false; } /** Check for HD codec for voice call */ @VisibleForTesting public boolean isHighDefCallInProgress() { BluetoothInCallService bluetoothInCallService = getBluetoothInCallServiceInstance(); if (bluetoothInCallService != null) { return bluetoothInCallService.isHighDefCallInProgress(); } else { Log.e(TAG, "Handsfree phone proxy null"); } return false; } /** * Get the the alphabetic name of current registered operator. * Loading Loading
android/app/jni/com_android_bluetooth_hfp.cpp +27 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <mutex> #include <shared_mutex> #include "btif/include/btif_hf.h" #include "com_android_bluetooth.h" #include "hardware/bluetooth_headset_callbacks.h" #include "hardware/bluetooth_headset_interface.h" Loading Loading @@ -954,6 +955,31 @@ static jboolean setActiveDeviceNative(JNIEnv* env, jobject /* object */, return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; } static jboolean enableSwbNative(JNIEnv* env, jobject /* object */, jint swbCodec, jboolean enable, jbyteArray address) { std::shared_lock<std::shared_timed_mutex> lock(interface_mutex); if (!sBluetoothHfpInterface) { ALOGW("%s: sBluetoothHfpInterface is null", __func__); return JNI_FALSE; } jbyte* addr = env->GetByteArrayElements(address, NULL); if (!addr) { ALOGE("%s: failed to get device address", __func__); jniThrowIOException(env, EINVAL); return JNI_FALSE; } bt_status_t ret = sBluetoothHfpInterface->EnableSwb( (bluetooth::headset::bthf_swb_codec_t)swbCodec, (bool)enable, (RawAddress*)addr); if (ret != BT_STATUS_SUCCESS) { ALOGE("%s: Failed to %s", __func__, (enable ? "enable" : "disable")); return JNI_FALSE; } ALOGV("%s: Successfully %s", __func__, (enable ? "enabled" : "disabled")); return JNI_TRUE; } int register_com_android_bluetooth_hfp(JNIEnv* env) { const JNINativeMethod methods[] = { {"initializeNative", "(IZ)V", (void*)initializeNative}, Loading Loading @@ -987,6 +1013,7 @@ int register_com_android_bluetooth_hfp(JNIEnv* env) { {"setScoAllowedNative", "(Z)Z", (void*)setScoAllowedNative}, {"sendBsirNative", "(Z[B)Z", (void*)sendBsirNative}, {"setActiveDeviceNative", "([B)Z", (void*)setActiveDeviceNative}, {"enableSwbNative", "(IZ[B)Z", (void*)enableSwbNative}, }; const int result = REGISTER_NATIVE_METHODS( env, "com/android/bluetooth/hfp/HeadsetNativeInterface", methods); Loading
android/app/src/com/android/bluetooth/hfp/HeadsetNativeInterface.java +15 −0 Original line number Diff line number Diff line Loading @@ -512,6 +512,19 @@ public class HeadsetNativeInterface { return setActiveDeviceNative(getByteAddress(device)); } /** * Enable Super Wide Band * * @param swbCodec SWB Codec * @param enable True to enable, False to disable * @param device current active SCO device * @return True on success, False on failure */ @VisibleForTesting public boolean enableSwb(int swbCodec, boolean enable, BluetoothDevice device) { return enableSwbNative(swbCodec, enable, getByteAddress(device)); } /* Native methods */ private native boolean atResponseCodeNative(int responseCode, int errorCode, byte[] address); Loading Loading @@ -558,4 +571,6 @@ public class HeadsetNativeInterface { private native boolean sendBsirNative(boolean value, byte[] address); private native boolean setActiveDeviceNative(byte[] address); private native boolean enableSwbNative(int swbCodec, boolean enable, byte[] address); }
android/app/src/com/android/bluetooth/hfp/HeadsetService.java +49 −1 Original line number Diff line number Diff line Loading @@ -155,12 +155,14 @@ public class HeadsetService extends ProfileService { private boolean mStarted; private static HeadsetService sHeadsetService; @VisibleForTesting boolean mIsAptXSwbEnabled = false; @VisibleForTesting boolean mIsAptXSwbPmEnabled = false; private final ServiceFactory mFactory = new ServiceFactory(); public HeadsetService(Context ctx) { super(ctx); } public static boolean isEnabled() { return BluetoothProperties.isProfileHfpAgEnabled().orElse(false); } Loading Loading @@ -191,11 +193,26 @@ public class HeadsetService extends ProfileService { // Step 3: Initialize system interface mSystemInterface = HeadsetObjectsFactory.getInstance().makeSystemInterface(this); // Step 4: Initialize native interface if (Flags.hfpCodecAptxVoice()) { mIsAptXSwbEnabled = SystemProperties.getBoolean("bluetooth.hfp.codec_aptx_voice.enabled", false); Log.i(TAG, "mIsAptXSwbEnabled: " + mIsAptXSwbEnabled); mIsAptXSwbPmEnabled = SystemProperties.getBoolean( "bluetooth.hfp.swb.aptx.power_management.enabled", false); Log.i(TAG, "mIsAptXSwbPmEnabled: " + mIsAptXSwbPmEnabled); } setHeadsetService(this); mMaxHeadsetConnections = mAdapterService.getMaxConnectedAudioDevices(); mNativeInterface = HeadsetObjectsFactory.getInstance().getNativeInterface(); // Add 1 to allow a pending device to be connecting or disconnecting mNativeInterface.init(mMaxHeadsetConnections + 1, isInbandRingingEnabled()); if (Flags.hfpCodecAptxVoice()) { enableSwbCodec( HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, mIsAptXSwbEnabled, mActiveDevice); } // Step 5: Check if state machine table is empty, crash if not if (mStateMachines.size() > 0) { throw new IllegalStateException( Loading Loading @@ -1208,6 +1225,9 @@ public class HeadsetService extends ProfileService { } stateMachine.sendMessage(HeadsetStateMachine.CONNECT_AUDIO, device); } if (Flags.hfpCodecAptxVoice()) { enableSwbCodec(HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, true, device); } return true; } Loading Loading @@ -1242,6 +1262,9 @@ public class HeadsetService extends ProfileService { } stateMachine.sendMessage(HeadsetStateMachine.DISCONNECT_AUDIO, device); } if (Flags.hfpCodecAptxVoice()) { enableSwbCodec(HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, false, device); } return true; } Loading Loading @@ -1806,6 +1829,9 @@ public class HeadsetService extends ProfileService { if (!mSystemInterface.getVoiceRecognitionWakeLock().isHeld()) { mSystemInterface.getVoiceRecognitionWakeLock().acquire(sStartVrTimeoutMs); } if (Flags.hfpCodecAptxVoice()) { enableSwbCodec(HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, true, fromDevice); } return true; } } Loading Loading @@ -1844,6 +1870,9 @@ public class HeadsetService extends ProfileService { Log.w(TAG, "stopVoiceRecognitionByHeadset: failed request from " + fromDevice); return false; } if (Flags.hfpCodecAptxVoice()) { enableSwbCodec(HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, false, fromDevice); } return true; } } Loading Loading @@ -2381,6 +2410,25 @@ public class HeadsetService extends ProfileService { } } /** Enable SWB Codec. */ void enableSwbCodec(int swbCodec, boolean enable, BluetoothDevice device) { logD("enableSwbCodec: swbCodec: " + swbCodec + " enable: " + enable + " device: " + device); boolean result = mNativeInterface.enableSwb(swbCodec, enable, device); logD("enableSwbCodec result: " + result); } /** Check whether AptX SWB Codec is enabled. */ boolean isAptXSwbEnabled() { logD("mIsAptXSwbEnabled: " + mIsAptXSwbEnabled); return mIsAptXSwbEnabled; } /** Check whether AptX SWB Codec Power Management is enabled. */ boolean isAptXSwbPmEnabled() { logD("isAptXSwbPmEnabled: " + mIsAptXSwbPmEnabled); return mIsAptXSwbPmEnabled; } private static void logD(String message) { if (DBG) { Log.d(TAG, message); Loading
android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java +58 −9 Original line number Diff line number Diff line Loading @@ -36,7 +36,6 @@ import android.os.Build; import android.os.Looper; import android.os.Message; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.telephony.PhoneNumberUtils; import android.telephony.PhoneStateListener; Loading Loading @@ -168,10 +167,6 @@ public class HeadsetStateMachine extends StateMachine { private BluetoothSinkAudioPolicy mHsClientAudioPolicy; static final boolean IS_APTX_SUPPORT_ENABLED = Flags.hfpCodecAptxVoice() && SystemProperties.getBoolean("bluetooth.hfp.codec_aptx_voice.enabled", false); // Keys are AT commands, and values are the company IDs. private static final Map<String, Integer> VENDOR_SPECIFIC_AT_COMMAND_COMPANY_ID; Loading Loading @@ -494,6 +489,39 @@ public class HeadsetStateMachine extends StateMachine { */ abstract int getAudioStateInt(); protected void setAptxVoice(HeadsetCallState callState) { if (!Flags.hfpCodecAptxVoice()) { return; } if (!mHeadsetService.isAptXSwbEnabled()) { return; } if (!mHeadsetService.isAptXSwbPmEnabled()) { return; } if (mHeadsetService.isVirtualCallStarted()) { stateLogD("CALL_STATE_CHANGED: enable AptX SWB for all voip calls "); mHeadsetService.enableSwbCodec( HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, true, mDevice); } else if ((callState.mCallState == HeadsetHalConstants.CALL_STATE_DIALING) || (callState.mCallState == HeadsetHalConstants.CALL_STATE_INCOMING) || ((callState.mCallState == HeadsetHalConstants.CALL_STATE_IDLE) && (callState.mNumActive > 0))) { if (!mSystemInterface.isHighDefCallInProgress()) { stateLogD("CALL_STATE_CHANGED: disable AptX SWB for non-HD call "); mHeadsetService.enableSwbCodec( HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, false, mDevice); mHasSwbAptXEnabled = false; } else { stateLogD("CALL_STATE_CHANGED: enable AptX SWB for HD call "); mHeadsetService.enableSwbCodec( HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, true, mDevice); mHasSwbAptXEnabled = true; } } else { stateLogD("CALL_STATE_CHANGED: AptX SWB state unchanged"); } } } class Disconnected extends HeadsetStateBase { Loading Loading @@ -696,7 +724,8 @@ public class HeadsetStateMachine extends StateMachine { break; } case CALL_STATE_CHANGED: stateLogD("ignoring CALL_STATE_CHANGED event"); HeadsetCallState callState = (HeadsetCallState) message.obj; setAptxVoice(callState); break; case DEVICE_STATE_CHANGED: stateLogD("ignoring DEVICE_STATE_CHANGED event"); Loading Loading @@ -958,14 +987,15 @@ public class HeadsetStateMachine extends StateMachine { } break; } case CALL_STATE_CHANGED: { case CALL_STATE_CHANGED: HeadsetCallState callState = (HeadsetCallState) message.obj; setAptxVoice(callState); if (!mNativeInterface.phoneStateChange(mDevice, callState)) { stateLogW("processCallState: failed to update call state " + callState); break; } break; } case DEVICE_STATE_CHANGED: if (mDeviceSilenced) { stateLogW("DEVICE_STATE_CHANGED: " + mDevice Loading Loading @@ -1200,6 +1230,22 @@ public class HeadsetStateMachine extends StateMachine { if (isAtLeastU()) { mSystemInterface.getAudioManager().setLeAudioSuspended(true); } if (Flags.hfpCodecAptxVoice() && mHeadsetService.isAptXSwbEnabled() && mHeadsetService.isAptXSwbPmEnabled()) { if (!mHeadsetService.isVirtualCallStarted() && mSystemInterface.isHighDefCallInProgress()) { stateLogD("CONNECT_AUDIO: enable AptX SWB for HD call "); mHeadsetService.enableSwbCodec( HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, true, mDevice); } else { stateLogD("CONNECT_AUDIO: disable AptX SWB for non-HD or Voip calls"); mHeadsetService.enableSwbCodec( HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, false, mDevice); } } if (!mNativeInterface.connectAudio(mDevice)) { mSystemInterface.getAudioManager().setA2dpSuspended(false); if (isAtLeastU()) { Loading Loading @@ -1703,7 +1749,7 @@ public class HeadsetStateMachine extends StateMachine { + (" hasSwbEnabled=" + mHasSwbLc3Enabled) + (" hasAptXSwbEnabled=" + mHasSwbAptXEnabled)); am.setParameters("bt_lc3_swb=" + (mHasSwbLc3Enabled ? "on" : "off")); if (IS_APTX_SUPPORT_ENABLED) { if (Flags.hfpCodecAptxVoice() && mHeadsetService.isAptXSwbEnabled()) { /* AptX bt_swb: 0 -> on, 65535 -> off */ am.setParameters("bt_swb=" + (mHasSwbAptXEnabled ? "0" : "65535")); } Loading Loading @@ -1851,6 +1897,9 @@ public class HeadsetStateMachine extends StateMachine { switch (wbsConfig) { case HeadsetHalConstants.BTHF_WBS_YES: mHasWbsEnabled = true; if (Flags.hfpCodecAptxVoice() && mHeadsetService.isAptXSwbEnabled()) { mHasSwbAptXEnabled = false; } break; case HeadsetHalConstants.BTHF_WBS_NO: case HeadsetHalConstants.BTHF_WBS_NONE: Loading
android/app/src/com/android/bluetooth/hfp/HeadsetSystemInterface.java +12 −0 Original line number Diff line number Diff line Loading @@ -240,6 +240,18 @@ public class HeadsetSystemInterface { return false; } /** Check for HD codec for voice call */ @VisibleForTesting public boolean isHighDefCallInProgress() { BluetoothInCallService bluetoothInCallService = getBluetoothInCallServiceInstance(); if (bluetoothInCallService != null) { return bluetoothInCallService.isHighDefCallInProgress(); } else { Log.e(TAG, "Handsfree phone proxy null"); } return false; } /** * Get the the alphabetic name of current registered operator. * Loading