Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 49cc3887 authored by Pavlin Radoslavov's avatar Pavlin Radoslavov Committed by android-build-merger
Browse files

Merge "Add a mechanism to configure the default A2DP codec priorities" am: a060da25

am: 1fdca5ea

Change-Id: Icbcefe85e3f0e28ad9b4015547204c836f307e10
parents 345299ee 1fdca5ea
Loading
Loading
Loading
Loading
+93 −22
Original line number Diff line number Diff line
@@ -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;
@@ -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");
@@ -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");
@@ -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;
@@ -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) {
@@ -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},
};

+12 −0
Original line number Diff line number Diff line
@@ -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>
+107 −11
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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;
@@ -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;

@@ -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();
@@ -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();
@@ -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)) {
@@ -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) {
@@ -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);
}