Android 8.1开启Bluetooth A2DP sink

**

Android 8.1开启Bluetooth A2DP sink功能

**

Android O源码已经支持A2DP sink,只需要开启就可以了

一个是BTA_AV_SINK_INCLUDED设为TRUE,BTA_AV_SINK_INCLUDED在\system\bt\include的bt_target.h
另外一个是bluetooth app这边的profile_supported_a2dp_sink需设为true开启这个profile

但是实际上光开启这两个值A2DP sink是不能工作的,我用的是RK3399,不知道其他平台是不是OK的

调试发现这个btif_av_init只会执行一次,也就是加了source之后sink是加不进来了,因为这个if判断执行过一次就不会再成立了,这个设计的初衷不知道是不是source和sink只能有一个,因为我这边发现打开sink后,source是有问题的,看起来是不能使用了,目前是暂时把这个判断拿掉了,因为我们source端没什么要求应该是用不上,但是sink端是一定需要的

/*******************************************************************************
 *
 * Function         btif_av_init
 *
 * Description      Initializes btif AV if not already done
 *
 * Returns          bt_status_t
 *
 ******************************************************************************/

bt_status_t btif_av_init(int service_id) {
  if (btif_av_cb.sm_handle == NULL) {
    alarm_free(av_open_on_rc_timer);
    av_open_on_rc_timer = alarm_new("btif_av.av_open_on_rc_timer");
    switch (service_id) {
      case BTA_A2DP_SOURCE_SERVICE_ID:
        if (!btif_a2dp_source_startup())
          return BT_STATUS_FAIL;  // Already running
        break;
      case BTA_A2DP_SINK_SERVICE_ID:
        if (!btif_a2dp_sink_startup())
          return BT_STATUS_FAIL;  // Already running
        break;
      default:
        break;
    }
    btif_enable_service(service_id);

    /* Also initialize the AV state machine */
    btif_av_cb.sm_handle = btif_sm_init(
        (const btif_sm_handler_t*)btif_av_state_handlers, BTIF_AV_STATE_IDLE);
  }

  return BT_STATUS_SUCCESS;
}

修改完这个后A2DP sink profile是有了,另外的手机也可以连上,数据也有传到我们的板子上,就是没有声音,调试发现就是播放没有执行
播放函数在pachages\appsBluetooth\src\com\android\bluetooth\a2dpsink\A2dpSinkStreamHandler.java

@Override
    public void handleMessage(Message message) {
        if (DBG) {
            Log.d(TAG, " process message: " + message.what);
            Log.d(TAG, " audioFocus =  " + mAudioFocus);
        }
        switch (message.what) {
            case SRC_STR_START:
                // Audio stream has started, stop it if we don't have focus.
                mStreamAvailable = true;
                +++++
                /*if (mAudioFocus == AudioManager.AUDIOFOCUS_NONE) {
                    requestAudioFocus();
                }*/
                +++++
                if (mAudioFocus == AudioManager.AUDIOFOCUS_NONE) {
                    sendAvrcpPause();
                } else {
                    startAvrcpUpdates();
                }
                break;

            case SRC_STR_STOP:
                // Audio stream has stopped, maintain focus but stop avrcp updates.
                mStreamAvailable = false;
                stopAvrcpUpdates();
                break;

            case SNK_PLAY:
                // Local play command, gain focus and start avrcp updates.
                if (mAudioFocus == AudioManager.AUDIOFOCUS_NONE) {
                    requestAudioFocus();
                }
                startAvrcpUpdates();
                break;

            case SNK_PAUSE:
                // Local pause command, maintain focus but stop avrcp updates.
                stopAvrcpUpdates();
                break;

            case SRC_PLAY:
                // Remote play command, if we have audio focus update avrcp, otherwise send pause.
                if (mAudioFocus == AudioManager.AUDIOFOCUS_NONE) {
                    sendAvrcpPause();
                } else {
                    startAvrcpUpdates();
                }
                break;

            case SRC_PAUSE:
                // Remote pause command, stop avrcp updates.
                stopAvrcpUpdates();
                break;

            case DISCONNECT:
                // Remote device has disconnected, restore everything to default state.
                sendAvrcpPause();
                stopAvrcpUpdates();
                abandonAudioFocus();
                mSentPause = false;
                break;

            case AUDIO_FOCUS_CHANGE:
                // message.obj is the newly granted audio focus.
                switch ((int) message.obj) {
                    case AudioManager.AUDIOFOCUS_GAIN:
                        // Begin playing audio, if we paused the remote, send a play now.
                        startAvrcpUpdates();
                        startFluorideStreaming();
                        if (mSentPause) {
                            sendAvrcpPlay();
                            mSentPause = false;
                        }
                        break;

                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                        // Make the volume duck.
                        int duckPercent = mContext.getResources().getInteger(
                                R.integer.a2dp_sink_duck_percent);
                        if (duckPercent < 0 || duckPercent > 100) {
                            Log.e(TAG, "Invalid duck percent using default.");
                            duckPercent = DEFAULT_DUCK_PERCENT;
                        }
                        float duckRatio = (duckPercent / 100.0f);
                        if (DBG) {
                            Log.d(TAG, "Setting reduce gain on transient loss gain=" + duckRatio);
                        }
                        setFluorideAudioTrackGain(duckRatio);
                        break;

                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                        // Temporary loss of focus, if we are actively streaming pause the remote
                        // and make sure we resume playback when we regain focus.
                        if (mStreamAvailable) {
                            sendAvrcpPause();
                            mSentPause = true;
                        }
                        stopFluorideStreaming();
                        break;

                    case AudioManager.AUDIOFOCUS_LOSS:
                        // Permanent loss of focus probably due to another audio app, abandon focus
                        // and stop playback.
                        mAudioFocus = AudioManager.AUDIOFOCUS_NONE;
                        abandonAudioFocus();
                        sendAvrcpPause();
                        break;
                }
                break;

            default:
                Log.w(TAG, "Received unexpected event: " + message.what);
        }
    }

开始播放后mAudioFocus 为0,就不会进到startAvrcpUpdates();,现在是在前面去requestAudioFocus();,这样在手机上播放的声音就都要RK3399的板子上了。

目前没有发现什么问题,有问题一起讨论哈!

你可能感兴趣的:(android)