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

Commit fd556cc7 authored by Pavlin Radoslavov's avatar Pavlin Radoslavov Committed by Gerrit Code Review
Browse files

Merge "Update the A2DP Codec Config API"

parents d550d3bc 7eb3349c
Loading
Loading
Loading
Loading
+69 −8
Original line number Diff line number Diff line
@@ -30,6 +30,11 @@ static jmethodID method_onConnectionStateChanged;
static jmethodID method_onAudioStateChanged;
static jmethodID method_onCodecConfigChanged;

static struct {
  jclass clazz;
  jmethodID constructor;
} android_bluetooth_BluetoothCodecConfig;

static const btav_source_interface_t* sBluetoothA2dpInterface = NULL;
static jobject mCallbacksObj = NULL;

@@ -73,19 +78,58 @@ static void bta2dp_audio_state_callback(btav_audio_state_t state,

static void bta2dp_audio_config_callback(
    btav_a2dp_codec_config_t codec_config,
    std::vector<btav_a2dp_codec_config_t> codec_capabilities) {
    std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities,
    std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities) {
  ALOGI("%s", __func__);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

  sCallbackEnv->CallVoidMethod(
      mCallbacksObj, method_onCodecConfigChanged, (jint)codec_config.codec_type,
      (jint)codec_config.codec_priority, (jint)codec_config.sample_rate,
      (jint)codec_config.bits_per_sample, (jint)codec_config.channel_mode,
      (jlong)codec_config.codec_specific_1,
  jobject codecConfigObj = sCallbackEnv->NewObject(
      android_bluetooth_BluetoothCodecConfig.clazz,
      android_bluetooth_BluetoothCodecConfig.constructor,
      (jint)codec_config.codec_type, (jint)codec_config.codec_priority,
      (jint)codec_config.sample_rate, (jint)codec_config.bits_per_sample,
      (jint)codec_config.channel_mode, (jlong)codec_config.codec_specific_1,
      (jlong)codec_config.codec_specific_2,
      (jlong)codec_config.codec_specific_3,
      (jlong)codec_config.codec_specific_4);

  jsize i = 0;
  jobjectArray local_capabilities_array = sCallbackEnv->NewObjectArray(
      (jsize)codecs_local_capabilities.size(),
      android_bluetooth_BluetoothCodecConfig.clazz, NULL);
  for (auto const& cap : codecs_local_capabilities) {
    jobject capObj = sCallbackEnv->NewObject(
        android_bluetooth_BluetoothCodecConfig.clazz,
        android_bluetooth_BluetoothCodecConfig.constructor,
        (jint)cap.codec_type, (jint)cap.codec_priority, (jint)cap.sample_rate,
        (jint)cap.bits_per_sample, (jint)cap.channel_mode,
        (jlong)cap.codec_specific_1, (jlong)cap.codec_specific_2,
        (jlong)cap.codec_specific_3, (jlong)cap.codec_specific_4);
    sCallbackEnv->SetObjectArrayElement(local_capabilities_array, i++, capObj);
    sCallbackEnv->DeleteLocalRef(capObj);
  }

  i = 0;
  jobjectArray selectable_capabilities_array = sCallbackEnv->NewObjectArray(
      (jsize)codecs_selectable_capabilities.size(),
      android_bluetooth_BluetoothCodecConfig.clazz, NULL);
  for (auto const& cap : codecs_selectable_capabilities) {
    jobject capObj = sCallbackEnv->NewObject(
        android_bluetooth_BluetoothCodecConfig.clazz,
        android_bluetooth_BluetoothCodecConfig.constructor,
        (jint)cap.codec_type, (jint)cap.codec_priority, (jint)cap.sample_rate,
        (jint)cap.bits_per_sample, (jint)cap.channel_mode,
        (jlong)cap.codec_specific_1, (jlong)cap.codec_specific_2,
        (jlong)cap.codec_specific_3, (jlong)cap.codec_specific_4);
    sCallbackEnv->SetObjectArrayElement(selectable_capabilities_array, i++,
                                        capObj);
    sCallbackEnv->DeleteLocalRef(capObj);
  }

  sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCodecConfigChanged,
                               codecConfigObj, local_capabilities_array,
                               selectable_capabilities_array);
}

static btav_source_callbacks_t sBluetoothA2dpCallbacks = {
@@ -94,14 +138,21 @@ static btav_source_callbacks_t sBluetoothA2dpCallbacks = {
};

static void classInitNative(JNIEnv* env, jclass clazz) {
  jclass jniBluetoothCodecConfigClass =
      env->FindClass("android/bluetooth/BluetoothCodecConfig");
  android_bluetooth_BluetoothCodecConfig.constructor =
      env->GetMethodID(jniBluetoothCodecConfigClass, "<init>", "(IIIIIJJJJ)V");

  method_onConnectionStateChanged =
      env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V");

  method_onAudioStateChanged =
      env->GetMethodID(clazz, "onAudioStateChanged", "(I[B)V");

  method_onCodecConfigChanged =
      env->GetMethodID(clazz, "onCodecConfigChanged", "(IIIIIJJJJ)V");
  method_onCodecConfigChanged = env->GetMethodID(
      clazz, "onCodecConfigChanged",
      "(Landroid/bluetooth/BluetoothCodecConfig;[Landroid/bluetooth/"
      "BluetoothCodecConfig;[Landroid/bluetooth/BluetoothCodecConfig;)V");

  ALOGI("%s: succeeds", __func__);
}
@@ -130,6 +181,13 @@ static void initNative(JNIEnv* env, jobject object) {
    return;
  }

  android_bluetooth_BluetoothCodecConfig.clazz = (jclass)env->NewGlobalRef(
      env->FindClass("android/bluetooth/BluetoothCodecConfig"));
  if (android_bluetooth_BluetoothCodecConfig.clazz == nullptr) {
    ALOGE("Failed to allocate Global Ref for BluetoothCodecConfig class");
    return;
  }

  sBluetoothA2dpInterface =
      (btav_source_interface_t*)btInf->get_profile_interface(
          BT_PROFILE_ADVANCED_AUDIO_ID);
@@ -158,6 +216,9 @@ static void cleanupNative(JNIEnv* env, jobject object) {
    sBluetoothA2dpInterface = NULL;
  }

  env->DeleteGlobalRef(android_bluetooth_BluetoothCodecConfig.clazz);
  android_bluetooth_BluetoothCodecConfig.clazz = nullptr;

  if (mCallbacksObj != NULL) {
    env->DeleteGlobalRef(mCallbacksObj);
    mCallbacksObj = NULL;
+6 −5
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.bluetooth.a2dp;

import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothCodecStatus;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
@@ -224,10 +225,10 @@ public class A2dpService extends ProfileService {
        return mStateMachine.isPlaying(device);
    }

    public BluetoothCodecConfig getCodecConfig() {
    public BluetoothCodecStatus getCodecStatus() {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (DBG) Log.d(TAG, "getCodecConfig()");
        return mStateMachine.getCodecConfig();
        if (DBG) Log.d(TAG, "getCodecStatus()");
        return mStateMachine.getCodecStatus();
    }

    public void setCodecConfigPreference(BluetoothCodecConfig codecConfig) {
@@ -328,10 +329,10 @@ public class A2dpService extends ProfileService {
            return service.isA2dpPlaying(device);
        }

        public BluetoothCodecConfig getCodecConfig() {
        public BluetoothCodecStatus getCodecStatus() {
            A2dpService service = getService();
            if (service == null) return null;
            return service.getCodecConfig();
            return service.getCodecStatus();
        }

        public void setCodecConfigPreference(BluetoothCodecConfig codecConfig) {
+21 −15
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ package com.android.bluetooth.a2dp;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothCodecStatus;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
@@ -103,7 +104,7 @@ final class A2dpStateMachine extends StateMachine {
    private BluetoothDevice mIncomingDevice = null;
    private BluetoothDevice mPlayingA2dpDevice = null;

    private BluetoothCodecConfig mCodecConfig = null;
    private BluetoothCodecStatus mCodecStatus = null;

    static {
        classInitNative();
@@ -654,30 +655,35 @@ final class A2dpStateMachine extends StateMachine {
        return false;
    }

    BluetoothCodecConfig getCodecConfig() {
    BluetoothCodecStatus getCodecStatus() {
        synchronized (this) {
            return mCodecConfig;
            return mCodecStatus;
        }
    }

    private void onCodecConfigChanged(int codecType, int codecPriority, int sampleRate,
            int bitsPerSample, int channelMode, long codecSpecific1, long codecSpecific2,
            long codecSpecific3, long codecSpecific4) {
        BluetoothCodecConfig prevCodecConfig;
        BluetoothCodecConfig newCodecConfig = new BluetoothCodecConfig(codecType, codecPriority,
                sampleRate, bitsPerSample, channelMode, codecSpecific1, codecSpecific2,
                codecSpecific3, codecSpecific4);
    private void onCodecConfigChanged(BluetoothCodecConfig newCodecConfig,
            BluetoothCodecConfig[] codecsLocalCapabilities,
            BluetoothCodecConfig[] codecsSelectableCapabilities) {
        BluetoothCodecConfig prevCodecConfig = null;
        synchronized (this) {
            prevCodecConfig = mCodecConfig;
            mCodecConfig = newCodecConfig;
            if (mCodecStatus != null) {
                prevCodecConfig = mCodecStatus.getCodecConfig();
            }
            mCodecStatus = new BluetoothCodecStatus(
                    newCodecConfig, codecsLocalCapabilities, codecsSelectableCapabilities);
        }

        Intent intent = new Intent(BluetoothA2dp.ACTION_CODEC_CONFIG_CHANGED);
        intent.putExtra(BluetoothCodecConfig.EXTRA_CODEC_CONFIG, newCodecConfig);
        intent.putExtra(BluetoothCodecConfig.EXTRA_PREVIOUS_CODEC_CONFIG, prevCodecConfig);
        intent.putExtra(BluetoothCodecStatus.EXTRA_CODEC_STATUS, mCodecStatus);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);

        log("A2DP Codec Config: " + prevCodecConfig + "->" + newCodecConfig);
        for (BluetoothCodecConfig codecConfig : codecsLocalCapabilities) {
            log("A2DP Codec Local Capability: " + codecConfig);
        }
        for (BluetoothCodecConfig codecConfig : codecsSelectableCapabilities) {
            log("A2DP Codec Selectable Capability: " + codecConfig);
        }

        // Inform the Audio Service about the codec configuration change,
        // so the Audio Service can reset accordingly the audio feeding