android R 控制設(shè)備媒體輸出通道

1.定制需求,合入第三方藍(lán)牙模塊,發(fā)送媒體數(shù)據(jù)傳輸?shù)降谌皆O(shè)備上;
(遇到問(wèn)題:第三方藍(lán)牙模塊發(fā)送數(shù)據(jù)過(guò)到第三方設(shè)備,但是本機(jī)的媒體應(yīng)用還走了當(dāng)前設(shè)備的喇叭,需要切換到耳機(jī)模式)

2.走AudioManager 模塊只能配置當(dāng)前進(jìn)程的媒體輸出方式;

        if(mAudioManager==null) {
            mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        }
        mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
//        mAudioManager.setMode(AudioManager.MODE_INVALID);
//        mAudioManager.stopBluetoothSco();        //停止藍(lán)牙耳機(jī)
//        mAudioManager.setBluetoothScoOn(false);  //設(shè)藍(lán)牙ScoOn關(guān)閉,藍(lán)牙耳機(jī)則會(huì)停止
//        mAudioManager.setSpeakerphoneOn(false);  //設(shè)置外放話筒關(guān)閉

3.通過(guò)AudioSystem設(shè)置時(shí)好像也沒(méi)有效果,當(dāng)設(shè)備走設(shè)備系統(tǒng)藍(lán)牙的時(shí)候才有效;

/*
try {
            @SuppressLint("PrivateApi") Class audioSystemClass = Class.forName("android.media.AudioSystem");
            Method setForceUse = audioSystemClass.getMethod("setForceUse", int.class, int.class);
            setForceUse.invoke(null, FOR_MEDIA, FORCE_SPEAKER);
            setForceUse.invoke(null, FOR_COMMUNICATION, FORCE_SPEAKER);

           // setForceUse.invoke(null, FOR_MEDIA, FORCE_NONE);
            //setForceUse.invoke(null, FOR_COMMUNICATION, FORCE_NONE);
        } catch (Exception e) {
            e.printStackTrace();
        }
*/

通過(guò)日志定位

audio_platform: mode(0),devices(0x2):platform device:OUT_DULSPK(0x4)

4.為了簡(jiǎn)易處理,直接添加一個(gè)屬性配置,來(lái)控制hal層的獲取的通道
\hardware\aw\audio\hal\platform.c

int get_platform_device(audio_mode_t mode, audio_devices_t devices,
                        const struct platform *platform)
{
    struct platform_info *info = platform->info;
    int pdev = OUT_NONE;

    /* 1. get platform device */
    if (devices & AUDIO_DEVICE_BIT_IN) {
        audio_devices_t indev = devices & (~AUDIO_DEVICE_BIT_IN);
        /* record device */
        if (indev & AUDIO_DEVICE_IN_BUILTIN_MIC) {
            pdev = (platform->uc & UC_DMIC) ? IN_DMIC : IN_AMIC;
        } else if (indev & AUDIO_DEVICE_IN_WIRED_HEADSET) {
            pdev = IN_HPMIC;
        } else if (indev & AUDIO_DEVICE_IN_ALL_SCO) {
            pdev = IN_BTSCO;
        } else {
            pdev = IN_AMIC;
        }
    } else {
        /* playback device */
        int headphone = AUDIO_DEVICE_OUT_WIRED_HEADSET |
                        AUDIO_DEVICE_OUT_WIRED_HEADPHONE;

        if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
            pdev = OUT_EAR;
        } else if (devices & AUDIO_DEVICE_OUT_SPEAKER &&
                   devices & headphone) {
            pdev = (platform->uc & UC_DUAL_SPK) ? OUT_DULSPK_HP : OUT_SPK_HP;
        } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
            pdev = (platform->uc & UC_DUAL_SPK) ? OUT_DULSPK : OUT_SPK;
        } else if (devices & headphone) {
            pdev = OUT_HP;
        } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
            pdev = OUT_BTSCO;
        } else if (devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
            pdev = OUT_HDMI;
        } else {
            pdev = OUT_SPK;
        }
    }
    /* phone record and playback */
    if (AUDIO_MODE_IN_CALL == mode) {
        if (devices & AUDIO_DEVICE_BIT_IN) {
            pdev = (platform->uc & UC_DPHONE)? IN_DPH_REC : IN_APH_REC;
        } else {
            pdev = (platform->uc & UC_DPHONE)? OUT_DPH_PLAY : OUT_APH_PLAY;
        }
    }
    /* TODO: force use platform device */
    /* add attribute start */
    char str[50] = "null";
    char djgd_speaker[10];
    char djgd_fm_speaker[10];
    property_get("persist.sys.djgd_speaker", djgd_speaker, "");
    property_get("persist.sys.djgd_fm_speaker", djgd_fm_speaker, "");
    ALOGV("persist.sys.djgd_speaker :%s(%d)",djgd_speaker, strstr(djgd_speaker, "1"));
    ALOGV("persist.sys.djgd_fm_speaker :%s(%d)",djgd_fm_speaker, strstr(djgd_fm_speaker, "1"));
    if (strstr(djgd_speaker, "1") !=NULL || strstr(djgd_fm_speaker, "1") !=NULL)
    {
        pdev = OUT_HP;
    }
    /* add attribute end*/
    ALOGV("mode(%#x),devices(%#x):platform device:%s(%#x)",
          mode, devices, pdev2str(str, pdev), pdev);

    return pdev;
}

5.經(jīng)測(cè)試發(fā)現(xiàn),只修改上面的位置還會(huì)有些問(wèn)題,就是當(dāng)有媒體還在播放時(shí)會(huì)有占用通道沒(méi)有沒(méi)被釋放,導(dǎo)致媒體通道沒(méi)有切花過(guò)來(lái);

Index: \hardware\aw\audio\hal\audio_hw.c
===================================================================
  */
 
 #define LOG_TAG "audio_hw_primary"
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0

+static int m_platform_device = 4;
+
 static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
                          size_t bytes)
 {
@@ -999,6 +1001,24 @@
     int platform_device = 0;
     ALOGV("out_write");
 
+    platform_device = get_platform_device(adev->mode, adev->out_devices,
+                                          adev->platform);
+    ALOGV("platform_device :%d,m_platform_device %d",platform_device,m_platform_device);
+    if (platform_device != m_platform_device )
+    {
+        m_platform_device=platform_device;
+        ALOGV("m_platform_device :%d",m_platform_device);
+        /*pthread_mutex_lock(&out->lock);
+        out->standby = 0;
+        pthread_mutex_lock(&adev->lock);
+        ret = start_output_stream(out);
+        pthread_mutex_unlock(&adev->lock);*/
+        out_standby(&out->stream.common);
+        usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
+               out_get_sample_rate(&out->stream.common));
+        pthread_mutex_unlock(&out->lock);
+        return bytes;
+    }
     pthread_mutex_lock(&out->lock);
     if (out->standby) {
         out->standby = 0;
@@ -1021,6 +1041,7 @@
     platform_plugins_process_read_write(adev->platform, ON_OUT_WRITE,
                                         out->config, (void*)buffer,
                                         out_frames * frame_size);
+
     /* audio dump data write */
     debug_dump_data(buf, out_frames * frame_size, &out->dd_write_out);
     if(out->equalizer != NULL)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容