Loading android/app/jni/com_android_bluetooth_a2dp.cpp +93 −22 Original line number Diff line number Diff line Loading @@ -33,6 +33,15 @@ static jmethodID method_onCodecConfigChanged; static struct { jclass clazz; jmethodID constructor; jmethodID getCodecType; jmethodID getCodecPriority; jmethodID getSampleRate; jmethodID getBitsPerSample; jmethodID getChannelMode; jmethodID getCodecSpecific1; jmethodID getCodecSpecific2; jmethodID getCodecSpecific3; jmethodID getCodecSpecific4; } android_bluetooth_BluetoothCodecConfig; static const btav_source_interface_t* sBluetoothA2dpInterface = NULL; Loading Loading @@ -142,6 +151,24 @@ static void classInitNative(JNIEnv* env, jclass clazz) { env->FindClass("android/bluetooth/BluetoothCodecConfig"); android_bluetooth_BluetoothCodecConfig.constructor = env->GetMethodID(jniBluetoothCodecConfigClass, "<init>", "(IIIIIJJJJ)V"); android_bluetooth_BluetoothCodecConfig.getCodecType = env->GetMethodID(jniBluetoothCodecConfigClass, "getCodecType", "()I"); android_bluetooth_BluetoothCodecConfig.getCodecPriority = env->GetMethodID(jniBluetoothCodecConfigClass, "getCodecPriority", "()I"); android_bluetooth_BluetoothCodecConfig.getSampleRate = env->GetMethodID(jniBluetoothCodecConfigClass, "getSampleRate", "()I"); android_bluetooth_BluetoothCodecConfig.getBitsPerSample = env->GetMethodID(jniBluetoothCodecConfigClass, "getBitsPerSample", "()I"); android_bluetooth_BluetoothCodecConfig.getChannelMode = env->GetMethodID(jniBluetoothCodecConfigClass, "getChannelMode", "()I"); android_bluetooth_BluetoothCodecConfig.getCodecSpecific1 = env->GetMethodID( jniBluetoothCodecConfigClass, "getCodecSpecific1", "()J"); android_bluetooth_BluetoothCodecConfig.getCodecSpecific2 = env->GetMethodID( jniBluetoothCodecConfigClass, "getCodecSpecific2", "()J"); android_bluetooth_BluetoothCodecConfig.getCodecSpecific3 = env->GetMethodID( jniBluetoothCodecConfigClass, "getCodecSpecific3", "()J"); android_bluetooth_BluetoothCodecConfig.getCodecSpecific4 = env->GetMethodID( jniBluetoothCodecConfigClass, "getCodecSpecific4", "()J"); method_onConnectionStateChanged = env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V"); Loading @@ -157,7 +184,59 @@ static void classInitNative(JNIEnv* env, jclass clazz) { ALOGI("%s: succeeds", __func__); } static void initNative(JNIEnv* env, jobject object) { static std::vector<btav_a2dp_codec_config_t> prepareCodecPreferences( JNIEnv* env, jobject object, jobjectArray codecConfigArray) { std::vector<btav_a2dp_codec_config_t> codec_preferences; int numConfigs = env->GetArrayLength(codecConfigArray); for (int i = 0; i < numConfigs; i++) { jobject jcodecConfig = env->GetObjectArrayElement(codecConfigArray, i); if (jcodecConfig == nullptr) continue; if (!env->IsInstanceOf(jcodecConfig, android_bluetooth_BluetoothCodecConfig.clazz)) { ALOGE("Invalid BluetoothCodecConfig instance"); continue; } jint codecType = env->CallIntMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecType); jint codecPriority = env->CallIntMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecPriority); jint sampleRate = env->CallIntMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getSampleRate); jint bitsPerSample = env->CallIntMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getBitsPerSample); jint channelMode = env->CallIntMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getChannelMode); jlong codecSpecific1 = env->CallLongMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific1); jlong codecSpecific2 = env->CallLongMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific2); jlong codecSpecific3 = env->CallLongMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific3); jlong codecSpecific4 = env->CallLongMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific4); btav_a2dp_codec_config_t codec_config = { .codec_type = static_cast<btav_a2dp_codec_index_t>(codecType), .codec_priority = static_cast<btav_a2dp_codec_priority_t>(codecPriority), .sample_rate = static_cast<btav_a2dp_codec_sample_rate_t>(sampleRate), .bits_per_sample = static_cast<btav_a2dp_codec_bits_per_sample_t>(bitsPerSample), .channel_mode = static_cast<btav_a2dp_codec_channel_mode_t>(channelMode), .codec_specific_1 = codecSpecific1, .codec_specific_2 = codecSpecific2, .codec_specific_3 = codecSpecific3, .codec_specific_4 = codecSpecific4}; codec_preferences.push_back(codec_config); } return codec_preferences; } static void initNative(JNIEnv* env, jobject object, jobjectArray codecConfigArray) { const bt_interface_t* btInf = getBluetoothInterface(); if (btInf == NULL) { ALOGE("Bluetooth module is not loaded"); Loading Loading @@ -196,7 +275,11 @@ static void initNative(JNIEnv* env, jobject object) { return; } bt_status_t status = sBluetoothA2dpInterface->init(&sBluetoothA2dpCallbacks); std::vector<btav_a2dp_codec_config_t> codec_priorities = prepareCodecPreferences(env, object, codecConfigArray); bt_status_t status = sBluetoothA2dpInterface->init(&sBluetoothA2dpCallbacks, codec_priorities); if (status != BT_STATUS_SUCCESS) { ALOGE("Failed to initialize Bluetooth A2DP, status: %d", status); sBluetoothA2dpInterface = NULL; Loading Loading @@ -262,26 +345,12 @@ static jboolean disconnectA2dpNative(JNIEnv* env, jobject object, return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; } static jboolean setCodecConfigPreferenceNative( JNIEnv* env, jobject object, jint codecType, jint codecPriority, jint sampleRate, jint bitsPerSample, jint channelMode, jlong codecSpecific1, jlong codecSpecific2, jlong codecSpecific3, jlong codecSpecific4) { static jboolean setCodecConfigPreferenceNative(JNIEnv* env, jobject object, jobjectArray codecConfigArray) { if (!sBluetoothA2dpInterface) return JNI_FALSE; btav_a2dp_codec_config_t codec_config = { .codec_type = static_cast<btav_a2dp_codec_index_t>(codecType), .codec_priority = static_cast<btav_a2dp_codec_priority_t>(codecPriority), .sample_rate = static_cast<btav_a2dp_codec_sample_rate_t>(sampleRate), .bits_per_sample = static_cast<btav_a2dp_codec_bits_per_sample_t>(bitsPerSample), .channel_mode = static_cast<btav_a2dp_codec_channel_mode_t>(channelMode), .codec_specific_1 = codecSpecific1, .codec_specific_2 = codecSpecific2, .codec_specific_3 = codecSpecific3, .codec_specific_4 = codecSpecific4}; std::vector<btav_a2dp_codec_config_t> codec_preferences; codec_preferences.push_back(codec_config); std::vector<btav_a2dp_codec_config_t> codec_preferences = prepareCodecPreferences(env, object, codecConfigArray); bt_status_t status = sBluetoothA2dpInterface->config_codec(codec_preferences); if (status != BT_STATUS_SUCCESS) { Loading @@ -292,11 +361,13 @@ static jboolean setCodecConfigPreferenceNative( static JNINativeMethod sMethods[] = { {"classInitNative", "()V", (void*)classInitNative}, {"initNative", "()V", (void*)initNative}, {"initNative", "([Landroid/bluetooth/BluetoothCodecConfig;)V", (void*)initNative}, {"cleanupNative", "()V", (void*)cleanupNative}, {"connectA2dpNative", "([B)Z", (void*)connectA2dpNative}, {"disconnectA2dpNative", "([B)Z", (void*)disconnectA2dpNative}, {"setCodecConfigPreferenceNative", "(IIIIIJJJJ)Z", {"setCodecConfigPreferenceNative", "([Landroid/bluetooth/BluetoothCodecConfig;)Z", (void*)setCodecConfigPreferenceNative}, }; Loading android/app/res/values/config.xml +12 −0 Original line number Diff line number Diff line Loading @@ -74,4 +74,16 @@ <!-- Enabling the phone policy --> <bool name="enable_phone_policy">true</bool> <!-- Configuring priorities of A2DP source codecs. Larger value means higher priority. Value -1 means the codec is disabled. Value 0 is reserved and should not be used here. Enabled codecs should have priorities in the interval [1, 999999], and each priority value should be unique. --> <integer name="a2dp_source_codec_priority_sbc">1001</integer> <integer name="a2dp_source_codec_priority_aac">2001</integer> <integer name="a2dp_source_codec_priority_aptx">3001</integer> <integer name="a2dp_source_codec_priority_aptx_hd">4001</integer> <integer name="a2dp_source_codec_priority_ldac">5001</integer> </resources> android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java +107 −11 Original line number Diff line number Diff line Loading @@ -37,6 +37,8 @@ import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothUuid; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.content.res.Resources.NotFoundException; import android.media.AudioManager; import android.os.Handler; import android.os.Message; Loading @@ -45,6 +47,7 @@ import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.util.Log; import com.android.bluetooth.R; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.ProfileService; Loading @@ -58,6 +61,7 @@ import java.util.Set; final class A2dpStateMachine extends StateMachine { private static final boolean DBG = false; private static final String TAG = "A2dpStateMachine"; static final int CONNECT = 1; static final int DISCONNECT = 2; Loading @@ -74,6 +78,7 @@ final class A2dpStateMachine extends StateMachine { private final AudioManager mAudioManager; private IntentBroadcastHandler mIntentBroadcastHandler; private final WakeLock mWakeLock; private BluetoothCodecConfig[] mCodecConfigPriorities; private static final int MSG_CONNECTION_STATE_CHANGED = 0; Loading Loading @@ -105,6 +110,11 @@ final class A2dpStateMachine extends StateMachine { private BluetoothDevice mPlayingA2dpDevice = null; private BluetoothCodecStatus mCodecStatus = null; private int mA2dpSourceCodecPrioritySbc = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; private int mA2dpSourceCodecPriorityAac = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; private int mA2dpSourceCodecPriorityAptx = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; private int mA2dpSourceCodecPriorityAptxHd = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; private int mA2dpSourceCodecPriorityLdac = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; static { classInitNative(); Loading @@ -115,8 +125,9 @@ final class A2dpStateMachine extends StateMachine { mService = svc; mContext = context; mAdapter = BluetoothAdapter.getDefaultAdapter(); mCodecConfigPriorities = assignCodecConfigPriorities(context.getResources()); initNative(); initNative(mCodecConfigPriorities); mDisconnected = new Disconnected(); mPending = new Pending(); Loading @@ -137,12 +148,101 @@ final class A2dpStateMachine extends StateMachine { } static A2dpStateMachine make(A2dpService svc, Context context) { Log.d("A2dpStateMachine", "make"); Log.d(TAG, "make"); A2dpStateMachine a2dpSm = new A2dpStateMachine(svc, context); a2dpSm.start(); return a2dpSm; } // Assign the A2DP Source codec config priorities private BluetoothCodecConfig[] assignCodecConfigPriorities(Resources resources) { if (resources == null) { return null; } int value; try { value = resources.getInteger(R.integer.a2dp_source_codec_priority_sbc); } catch (NotFoundException e) { value = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; } if ((value >= BluetoothCodecConfig.CODEC_PRIORITY_DISABLED) && (value < BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST)) { mA2dpSourceCodecPrioritySbc = value; } try { value = resources.getInteger(R.integer.a2dp_source_codec_priority_aac); } catch (NotFoundException e) { value = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; } if ((value >= BluetoothCodecConfig.CODEC_PRIORITY_DISABLED) && (value < BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST)) { mA2dpSourceCodecPriorityAac = value; } try { value = resources.getInteger(R.integer.a2dp_source_codec_priority_aptx); } catch (NotFoundException e) { value = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; } if ((value >= BluetoothCodecConfig.CODEC_PRIORITY_DISABLED) && (value < BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST)) { mA2dpSourceCodecPriorityAptx = value; } try { value = resources.getInteger(R.integer.a2dp_source_codec_priority_aptx_hd); } catch (NotFoundException e) { value = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; } if ((value >= BluetoothCodecConfig.CODEC_PRIORITY_DISABLED) && (value < BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST)) { mA2dpSourceCodecPriorityAptxHd = value; } try { value = resources.getInteger(R.integer.a2dp_source_codec_priority_ldac); } catch (NotFoundException e) { value = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; } if ((value >= BluetoothCodecConfig.CODEC_PRIORITY_DISABLED) && (value < BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST)) { mA2dpSourceCodecPriorityLdac = value; } BluetoothCodecConfig codecConfig; BluetoothCodecConfig[] codecConfigArray = new BluetoothCodecConfig[BluetoothCodecConfig.SOURCE_CODEC_TYPE_MAX]; codecConfig = new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, mA2dpSourceCodecPrioritySbc, 0 /* sampleRate */, 0 /* bitsPerSample */, 0 /* channelMode */, 0 /* codecSpecific1 */, 0 /* codecSpecific2 */, 0 /* codecSpecific3 */, 0 /* codecSpecific4 */); codecConfigArray[0] = codecConfig; codecConfig = new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, mA2dpSourceCodecPriorityAac, 0 /* sampleRate */, 0 /* bitsPerSample */, 0 /* channelMode */, 0 /* codecSpecific1 */, 0 /* codecSpecific2 */, 0 /* codecSpecific3 */, 0 /* codecSpecific4 */); codecConfigArray[1] = codecConfig; codecConfig = new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX, mA2dpSourceCodecPriorityAptx, 0 /* sampleRate */, 0 /* bitsPerSample */, 0 /* channelMode */, 0 /* codecSpecific1 */, 0 /* codecSpecific2 */, 0 /* codecSpecific3 */, 0 /* codecSpecific4 */); codecConfigArray[2] = codecConfig; codecConfig = new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD, mA2dpSourceCodecPriorityAptxHd, 0 /* sampleRate */, 0 /* bitsPerSample */, 0 /* channelMode */, 0 /* codecSpecific1 */, 0 /* codecSpecific2 */, 0 /* codecSpecific3 */, 0 /* codecSpecific4 */); codecConfigArray[3] = codecConfig; codecConfig = new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC, mA2dpSourceCodecPriorityLdac, 0 /* sampleRate */, 0 /* bitsPerSample */, 0 /* channelMode */, 0 /* codecSpecific1 */, 0 /* codecSpecific2 */, 0 /* codecSpecific3 */, 0 /* codecSpecific4 */); codecConfigArray[4] = codecConfig; return codecConfigArray; } public void doQuit() { if ((mTargetDevice != null) && (getConnectionState(mTargetDevice) == BluetoothProfile.STATE_CONNECTING)) { Loading Loading @@ -698,11 +798,9 @@ final class A2dpStateMachine extends StateMachine { } void setCodecConfigPreference(BluetoothCodecConfig codecConfig) { setCodecConfigPreferenceNative(codecConfig.getCodecType(), codecConfig.getCodecPriority(), codecConfig.getSampleRate(), codecConfig.getBitsPerSample(), codecConfig.getChannelMode(), codecConfig.getCodecSpecific1(), codecConfig.getCodecSpecific2(), codecConfig.getCodecSpecific3(), codecConfig.getCodecSpecific4()); BluetoothCodecConfig[] codecConfigArray = new BluetoothCodecConfig[1]; codecConfigArray[0] = codecConfig; setCodecConfigPreferenceNative(codecConfigArray); } boolean okToConnect(BluetoothDevice device) { Loading Loading @@ -854,11 +952,9 @@ final class A2dpStateMachine extends StateMachine { final static int AUDIO_STATE_STARTED = 2; private native static void classInitNative(); private native void initNative(); private native void initNative(BluetoothCodecConfig[] codecConfigPriorites); private native void cleanupNative(); private native boolean connectA2dpNative(byte[] address); private native boolean disconnectA2dpNative(byte[] address); private native boolean setCodecConfigPreferenceNative(int codecType, int codecPriority, int sampleRate, int bitsPerSample, int channelMode, long codecSpecific1, long codecSpecific2, long codecSpecific3, long codecSpecific4); private native boolean setCodecConfigPreferenceNative(BluetoothCodecConfig[] codecConfigArray); } Loading
android/app/jni/com_android_bluetooth_a2dp.cpp +93 −22 Original line number Diff line number Diff line Loading @@ -33,6 +33,15 @@ static jmethodID method_onCodecConfigChanged; static struct { jclass clazz; jmethodID constructor; jmethodID getCodecType; jmethodID getCodecPriority; jmethodID getSampleRate; jmethodID getBitsPerSample; jmethodID getChannelMode; jmethodID getCodecSpecific1; jmethodID getCodecSpecific2; jmethodID getCodecSpecific3; jmethodID getCodecSpecific4; } android_bluetooth_BluetoothCodecConfig; static const btav_source_interface_t* sBluetoothA2dpInterface = NULL; Loading Loading @@ -142,6 +151,24 @@ static void classInitNative(JNIEnv* env, jclass clazz) { env->FindClass("android/bluetooth/BluetoothCodecConfig"); android_bluetooth_BluetoothCodecConfig.constructor = env->GetMethodID(jniBluetoothCodecConfigClass, "<init>", "(IIIIIJJJJ)V"); android_bluetooth_BluetoothCodecConfig.getCodecType = env->GetMethodID(jniBluetoothCodecConfigClass, "getCodecType", "()I"); android_bluetooth_BluetoothCodecConfig.getCodecPriority = env->GetMethodID(jniBluetoothCodecConfigClass, "getCodecPriority", "()I"); android_bluetooth_BluetoothCodecConfig.getSampleRate = env->GetMethodID(jniBluetoothCodecConfigClass, "getSampleRate", "()I"); android_bluetooth_BluetoothCodecConfig.getBitsPerSample = env->GetMethodID(jniBluetoothCodecConfigClass, "getBitsPerSample", "()I"); android_bluetooth_BluetoothCodecConfig.getChannelMode = env->GetMethodID(jniBluetoothCodecConfigClass, "getChannelMode", "()I"); android_bluetooth_BluetoothCodecConfig.getCodecSpecific1 = env->GetMethodID( jniBluetoothCodecConfigClass, "getCodecSpecific1", "()J"); android_bluetooth_BluetoothCodecConfig.getCodecSpecific2 = env->GetMethodID( jniBluetoothCodecConfigClass, "getCodecSpecific2", "()J"); android_bluetooth_BluetoothCodecConfig.getCodecSpecific3 = env->GetMethodID( jniBluetoothCodecConfigClass, "getCodecSpecific3", "()J"); android_bluetooth_BluetoothCodecConfig.getCodecSpecific4 = env->GetMethodID( jniBluetoothCodecConfigClass, "getCodecSpecific4", "()J"); method_onConnectionStateChanged = env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V"); Loading @@ -157,7 +184,59 @@ static void classInitNative(JNIEnv* env, jclass clazz) { ALOGI("%s: succeeds", __func__); } static void initNative(JNIEnv* env, jobject object) { static std::vector<btav_a2dp_codec_config_t> prepareCodecPreferences( JNIEnv* env, jobject object, jobjectArray codecConfigArray) { std::vector<btav_a2dp_codec_config_t> codec_preferences; int numConfigs = env->GetArrayLength(codecConfigArray); for (int i = 0; i < numConfigs; i++) { jobject jcodecConfig = env->GetObjectArrayElement(codecConfigArray, i); if (jcodecConfig == nullptr) continue; if (!env->IsInstanceOf(jcodecConfig, android_bluetooth_BluetoothCodecConfig.clazz)) { ALOGE("Invalid BluetoothCodecConfig instance"); continue; } jint codecType = env->CallIntMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecType); jint codecPriority = env->CallIntMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecPriority); jint sampleRate = env->CallIntMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getSampleRate); jint bitsPerSample = env->CallIntMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getBitsPerSample); jint channelMode = env->CallIntMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getChannelMode); jlong codecSpecific1 = env->CallLongMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific1); jlong codecSpecific2 = env->CallLongMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific2); jlong codecSpecific3 = env->CallLongMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific3); jlong codecSpecific4 = env->CallLongMethod( jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific4); btav_a2dp_codec_config_t codec_config = { .codec_type = static_cast<btav_a2dp_codec_index_t>(codecType), .codec_priority = static_cast<btav_a2dp_codec_priority_t>(codecPriority), .sample_rate = static_cast<btav_a2dp_codec_sample_rate_t>(sampleRate), .bits_per_sample = static_cast<btav_a2dp_codec_bits_per_sample_t>(bitsPerSample), .channel_mode = static_cast<btav_a2dp_codec_channel_mode_t>(channelMode), .codec_specific_1 = codecSpecific1, .codec_specific_2 = codecSpecific2, .codec_specific_3 = codecSpecific3, .codec_specific_4 = codecSpecific4}; codec_preferences.push_back(codec_config); } return codec_preferences; } static void initNative(JNIEnv* env, jobject object, jobjectArray codecConfigArray) { const bt_interface_t* btInf = getBluetoothInterface(); if (btInf == NULL) { ALOGE("Bluetooth module is not loaded"); Loading Loading @@ -196,7 +275,11 @@ static void initNative(JNIEnv* env, jobject object) { return; } bt_status_t status = sBluetoothA2dpInterface->init(&sBluetoothA2dpCallbacks); std::vector<btav_a2dp_codec_config_t> codec_priorities = prepareCodecPreferences(env, object, codecConfigArray); bt_status_t status = sBluetoothA2dpInterface->init(&sBluetoothA2dpCallbacks, codec_priorities); if (status != BT_STATUS_SUCCESS) { ALOGE("Failed to initialize Bluetooth A2DP, status: %d", status); sBluetoothA2dpInterface = NULL; Loading Loading @@ -262,26 +345,12 @@ static jboolean disconnectA2dpNative(JNIEnv* env, jobject object, return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; } static jboolean setCodecConfigPreferenceNative( JNIEnv* env, jobject object, jint codecType, jint codecPriority, jint sampleRate, jint bitsPerSample, jint channelMode, jlong codecSpecific1, jlong codecSpecific2, jlong codecSpecific3, jlong codecSpecific4) { static jboolean setCodecConfigPreferenceNative(JNIEnv* env, jobject object, jobjectArray codecConfigArray) { if (!sBluetoothA2dpInterface) return JNI_FALSE; btav_a2dp_codec_config_t codec_config = { .codec_type = static_cast<btav_a2dp_codec_index_t>(codecType), .codec_priority = static_cast<btav_a2dp_codec_priority_t>(codecPriority), .sample_rate = static_cast<btav_a2dp_codec_sample_rate_t>(sampleRate), .bits_per_sample = static_cast<btav_a2dp_codec_bits_per_sample_t>(bitsPerSample), .channel_mode = static_cast<btav_a2dp_codec_channel_mode_t>(channelMode), .codec_specific_1 = codecSpecific1, .codec_specific_2 = codecSpecific2, .codec_specific_3 = codecSpecific3, .codec_specific_4 = codecSpecific4}; std::vector<btav_a2dp_codec_config_t> codec_preferences; codec_preferences.push_back(codec_config); std::vector<btav_a2dp_codec_config_t> codec_preferences = prepareCodecPreferences(env, object, codecConfigArray); bt_status_t status = sBluetoothA2dpInterface->config_codec(codec_preferences); if (status != BT_STATUS_SUCCESS) { Loading @@ -292,11 +361,13 @@ static jboolean setCodecConfigPreferenceNative( static JNINativeMethod sMethods[] = { {"classInitNative", "()V", (void*)classInitNative}, {"initNative", "()V", (void*)initNative}, {"initNative", "([Landroid/bluetooth/BluetoothCodecConfig;)V", (void*)initNative}, {"cleanupNative", "()V", (void*)cleanupNative}, {"connectA2dpNative", "([B)Z", (void*)connectA2dpNative}, {"disconnectA2dpNative", "([B)Z", (void*)disconnectA2dpNative}, {"setCodecConfigPreferenceNative", "(IIIIIJJJJ)Z", {"setCodecConfigPreferenceNative", "([Landroid/bluetooth/BluetoothCodecConfig;)Z", (void*)setCodecConfigPreferenceNative}, }; Loading
android/app/res/values/config.xml +12 −0 Original line number Diff line number Diff line Loading @@ -74,4 +74,16 @@ <!-- Enabling the phone policy --> <bool name="enable_phone_policy">true</bool> <!-- Configuring priorities of A2DP source codecs. Larger value means higher priority. Value -1 means the codec is disabled. Value 0 is reserved and should not be used here. Enabled codecs should have priorities in the interval [1, 999999], and each priority value should be unique. --> <integer name="a2dp_source_codec_priority_sbc">1001</integer> <integer name="a2dp_source_codec_priority_aac">2001</integer> <integer name="a2dp_source_codec_priority_aptx">3001</integer> <integer name="a2dp_source_codec_priority_aptx_hd">4001</integer> <integer name="a2dp_source_codec_priority_ldac">5001</integer> </resources>
android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java +107 −11 Original line number Diff line number Diff line Loading @@ -37,6 +37,8 @@ import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothUuid; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.content.res.Resources.NotFoundException; import android.media.AudioManager; import android.os.Handler; import android.os.Message; Loading @@ -45,6 +47,7 @@ import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.util.Log; import com.android.bluetooth.R; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.ProfileService; Loading @@ -58,6 +61,7 @@ import java.util.Set; final class A2dpStateMachine extends StateMachine { private static final boolean DBG = false; private static final String TAG = "A2dpStateMachine"; static final int CONNECT = 1; static final int DISCONNECT = 2; Loading @@ -74,6 +78,7 @@ final class A2dpStateMachine extends StateMachine { private final AudioManager mAudioManager; private IntentBroadcastHandler mIntentBroadcastHandler; private final WakeLock mWakeLock; private BluetoothCodecConfig[] mCodecConfigPriorities; private static final int MSG_CONNECTION_STATE_CHANGED = 0; Loading Loading @@ -105,6 +110,11 @@ final class A2dpStateMachine extends StateMachine { private BluetoothDevice mPlayingA2dpDevice = null; private BluetoothCodecStatus mCodecStatus = null; private int mA2dpSourceCodecPrioritySbc = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; private int mA2dpSourceCodecPriorityAac = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; private int mA2dpSourceCodecPriorityAptx = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; private int mA2dpSourceCodecPriorityAptxHd = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; private int mA2dpSourceCodecPriorityLdac = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; static { classInitNative(); Loading @@ -115,8 +125,9 @@ final class A2dpStateMachine extends StateMachine { mService = svc; mContext = context; mAdapter = BluetoothAdapter.getDefaultAdapter(); mCodecConfigPriorities = assignCodecConfigPriorities(context.getResources()); initNative(); initNative(mCodecConfigPriorities); mDisconnected = new Disconnected(); mPending = new Pending(); Loading @@ -137,12 +148,101 @@ final class A2dpStateMachine extends StateMachine { } static A2dpStateMachine make(A2dpService svc, Context context) { Log.d("A2dpStateMachine", "make"); Log.d(TAG, "make"); A2dpStateMachine a2dpSm = new A2dpStateMachine(svc, context); a2dpSm.start(); return a2dpSm; } // Assign the A2DP Source codec config priorities private BluetoothCodecConfig[] assignCodecConfigPriorities(Resources resources) { if (resources == null) { return null; } int value; try { value = resources.getInteger(R.integer.a2dp_source_codec_priority_sbc); } catch (NotFoundException e) { value = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; } if ((value >= BluetoothCodecConfig.CODEC_PRIORITY_DISABLED) && (value < BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST)) { mA2dpSourceCodecPrioritySbc = value; } try { value = resources.getInteger(R.integer.a2dp_source_codec_priority_aac); } catch (NotFoundException e) { value = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; } if ((value >= BluetoothCodecConfig.CODEC_PRIORITY_DISABLED) && (value < BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST)) { mA2dpSourceCodecPriorityAac = value; } try { value = resources.getInteger(R.integer.a2dp_source_codec_priority_aptx); } catch (NotFoundException e) { value = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; } if ((value >= BluetoothCodecConfig.CODEC_PRIORITY_DISABLED) && (value < BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST)) { mA2dpSourceCodecPriorityAptx = value; } try { value = resources.getInteger(R.integer.a2dp_source_codec_priority_aptx_hd); } catch (NotFoundException e) { value = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; } if ((value >= BluetoothCodecConfig.CODEC_PRIORITY_DISABLED) && (value < BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST)) { mA2dpSourceCodecPriorityAptxHd = value; } try { value = resources.getInteger(R.integer.a2dp_source_codec_priority_ldac); } catch (NotFoundException e) { value = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; } if ((value >= BluetoothCodecConfig.CODEC_PRIORITY_DISABLED) && (value < BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST)) { mA2dpSourceCodecPriorityLdac = value; } BluetoothCodecConfig codecConfig; BluetoothCodecConfig[] codecConfigArray = new BluetoothCodecConfig[BluetoothCodecConfig.SOURCE_CODEC_TYPE_MAX]; codecConfig = new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC, mA2dpSourceCodecPrioritySbc, 0 /* sampleRate */, 0 /* bitsPerSample */, 0 /* channelMode */, 0 /* codecSpecific1 */, 0 /* codecSpecific2 */, 0 /* codecSpecific3 */, 0 /* codecSpecific4 */); codecConfigArray[0] = codecConfig; codecConfig = new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC, mA2dpSourceCodecPriorityAac, 0 /* sampleRate */, 0 /* bitsPerSample */, 0 /* channelMode */, 0 /* codecSpecific1 */, 0 /* codecSpecific2 */, 0 /* codecSpecific3 */, 0 /* codecSpecific4 */); codecConfigArray[1] = codecConfig; codecConfig = new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX, mA2dpSourceCodecPriorityAptx, 0 /* sampleRate */, 0 /* bitsPerSample */, 0 /* channelMode */, 0 /* codecSpecific1 */, 0 /* codecSpecific2 */, 0 /* codecSpecific3 */, 0 /* codecSpecific4 */); codecConfigArray[2] = codecConfig; codecConfig = new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD, mA2dpSourceCodecPriorityAptxHd, 0 /* sampleRate */, 0 /* bitsPerSample */, 0 /* channelMode */, 0 /* codecSpecific1 */, 0 /* codecSpecific2 */, 0 /* codecSpecific3 */, 0 /* codecSpecific4 */); codecConfigArray[3] = codecConfig; codecConfig = new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC, mA2dpSourceCodecPriorityLdac, 0 /* sampleRate */, 0 /* bitsPerSample */, 0 /* channelMode */, 0 /* codecSpecific1 */, 0 /* codecSpecific2 */, 0 /* codecSpecific3 */, 0 /* codecSpecific4 */); codecConfigArray[4] = codecConfig; return codecConfigArray; } public void doQuit() { if ((mTargetDevice != null) && (getConnectionState(mTargetDevice) == BluetoothProfile.STATE_CONNECTING)) { Loading Loading @@ -698,11 +798,9 @@ final class A2dpStateMachine extends StateMachine { } void setCodecConfigPreference(BluetoothCodecConfig codecConfig) { setCodecConfigPreferenceNative(codecConfig.getCodecType(), codecConfig.getCodecPriority(), codecConfig.getSampleRate(), codecConfig.getBitsPerSample(), codecConfig.getChannelMode(), codecConfig.getCodecSpecific1(), codecConfig.getCodecSpecific2(), codecConfig.getCodecSpecific3(), codecConfig.getCodecSpecific4()); BluetoothCodecConfig[] codecConfigArray = new BluetoothCodecConfig[1]; codecConfigArray[0] = codecConfig; setCodecConfigPreferenceNative(codecConfigArray); } boolean okToConnect(BluetoothDevice device) { Loading Loading @@ -854,11 +952,9 @@ final class A2dpStateMachine extends StateMachine { final static int AUDIO_STATE_STARTED = 2; private native static void classInitNative(); private native void initNative(); private native void initNative(BluetoothCodecConfig[] codecConfigPriorites); private native void cleanupNative(); private native boolean connectA2dpNative(byte[] address); private native boolean disconnectA2dpNative(byte[] address); private native boolean setCodecConfigPreferenceNative(int codecType, int codecPriority, int sampleRate, int bitsPerSample, int channelMode, long codecSpecific1, long codecSpecific2, long codecSpecific3, long codecSpecific4); private native boolean setCodecConfigPreferenceNative(BluetoothCodecConfig[] codecConfigArray); }