android开机铃声通过耳机输出

Posted yujixuan@blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android开机铃声通过耳机输出相关的知识,希望对你有一定的参考价值。

功能描述

在系统开机时,强制开机铃声只通过耳机通道播放;

不管是否有插入耳机,最终开机铃声都通过耳机通道输出;开机后保持原有的音频策略设置;

android开机铃声添加过程

android的开机铃声添加方案,一般是放在 开机动画bootanimation的过程中实现的;

Android bootanimation所在的位置是:(qcom android N)

frameworks/base/cmds/bootanimation/

code/frameworks/base/cmds/bootanimation$ tree ./
./
├── Android.mk
├── audioplay.cpp
├── audioplay.h
├── BootAnimation.cpp
├── BootAnimation.h
├── bootanimation_main.cpp
├── bootanim.rc
└── FORMAT.md

开机铃声的添加可以通过两种方式:

通过 audioplay.cpp

通过[[OpenSLES]]; 待详细分析…

通过MediaPlayer 类

在BootAnimation类定义中,添加 bootMusic接口;

void BootAnimation::bootMusic()
{
    int index;
    const char *fileName = "/system/media/boot.wav"; //选择一个有权限访问的位置 存放开机铃声
    MediaPlayer* mp = new MediaPlayer();             //创建MediaPlayer
    MediaPlayer* mp = new MediaPlayer();
    audio_devices_t device = Audiosystem::getDevicesForStream(AUDIO_STREAM_ENFORCED_AUDIBLE);
    if (mp->setDataSource(NULL, fileName, NULL) == NO_ERROR)
    {
        mp->setAudioStreamType(AUDIO_STREAM_ENFORCED_AUDIBLE/*AudioSystem: :ENFORCED_AUDIBLE*/);
        mp->prepare();
    }
    LOGE ("bootMusic\\n");
    AudioSystem::initStreamVolume(AUDIO_STREAM_ENFORCED_AUDIBLE, 0,7);
    AudioSystem::setStreamVolumeIndex(AUDIO_STREAM_ENFORCED_AUDIBLE, 7, device);
    AudioSystem::getStreamVolumeIndex(AUDIO_STREAM_ENFORCED_AUDIBLE/*AudioSystem::ENFORCED_AUDIBLE*/, &index, device);
    LOGE ("index %d",index);
    if (index != 0)
    {
        LOGD("playing %s", fileName);
        mp->setVolume(0.4f, 0.4f);
        mp->seekTo(0);
        mp->start();
    }
}

AudioSystem 类型的选择

/* Audio stream types */
typedef enum {
    /* These values must kept in sync with
     * frameworks/base/media/java/android/media/AudioSystem.java
     */
    AUDIO_STREAM_DEFAULT          = -1,
    AUDIO_STREAM_MIN              = 0,
    AUDIO_STREAM_VOICE_CALL       = 0,
    AUDIO_STREAM_SYSTEM           = 1,
    AUDIO_STREAM_RING             = 2,
    AUDIO_STREAM_MUSIC            = 3,
    AUDIO_STREAM_ALARM            = 4,
    AUDIO_STREAM_NOTIFICATION     = 5,
    AUDIO_STREAM_BLUETOOTH_SCO    = 6,
    AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user
                                        * and must be routed to speaker
                                        */
    AUDIO_STREAM_DTMF             = 8,
    AUDIO_STREAM_TTS              = 9,  /* Transmitted Through Speaker.
                                         * Plays over speaker only, silent on other devices.
                                         */
    AUDIO_STREAM_ACCESSIBILITY    = 10, /* For accessibility talk back prompts */
    AUDIO_STREAM_REROUTING        = 11, /* For dynamic policy output mixes */
    AUDIO_STREAM_PATCH            = 12, /* For internal audio flinger tracks. Fixed volume */
    AUDIO_STREAM_PUBLIC_CNT       = AUDIO_STREAM_TTS + 1,
    AUDIO_STREAM_FOR_POLICY_CNT   = AUDIO_STREAM_PATCH, /* number of streams considered by
                                           audio policy for volume and routing */
    AUDIO_STREAM_CNT              = AUDIO_STREAM_PATCH + 1,
} audio_stream_type_t;

通常场景下,开机铃声选择AUDIO_STREAM_ENFORCED_AUDIBLE 类型;

在开机动画播放前 调用

bool BootAnimation::threadLoop()
{
    bool r;
    // We have no bootanimation file, so we use the stock android logo
    // animation.
    bootMusic();
//    	sleep(5);   
    if (mZipFileName.isEmpty()) {
        r = android();
    } else {
        r = movie();
    }
    //......
}

在调试过程中,在播放开机动画之前,可以设置一段延时用于调试,因为 BootAnimation最终是被编译成可执行文件被访问,为了提高效率,在debug阶段,

我们可以直接编译 BootAnimation, 将得到的可执行文件bootanimation push到设备中,直接执行,设置延时的目的是防止开机动画直接结束;

audio output device的选择

添加完开机铃声的播放,考虑下如何选择音频输出设备的选择;

在执行bootanimation时,可以获取到如下log:

默认选择的是 speaker输出,即使android 设备上插着耳机;

针对这个需求,可将audio_stream_type 选择为AUDIO_STREAM_MUSIC;通过执行bootanimation 去测试,当耳机插入时,声音会通过耳机输出;

但是存在的问题是,当未插入耳机是,声音还是会冲speaker输出,另外在执行播放开机铃声的时候,系统还未检测到耳机的存在,即使在开机后执行bootanimation 能够通过耳机播放铃声,开机过程中依旧是不行的;

在默认的音频策略中,耳机的优先级本就高于speaker, 想到一个思路就是在,播放开机铃声之前,强制设置耳机存在的状态; 完成开机后,还需要再设置回去;

暂时未测试该方案,使用了另外一个方案;

强制绑定输出设备

思路是在hal中,不管之前的策略如何设置,只要判断到未完成开机(根据"service.bootanim.exit" 的property 值来判断),就将输出设备 设置为HEADPHONES;

修改点如下:

diff --git a/hardware/qcom/audio/hal/audio_hw.c b/hardware/qcom/audio/hal/audio_hw.c
old mode 100644
newmode 100755
index d0d1e6031d..f91a5c7979
--- a/hardware/qcom/audio/hal/audio_hw.c
+++ b/hardware/qcom/audio/hal/audio_hw.c
@@ -825,7 +825,15 @@ intselect_devices(struct audio_device *adev, audio_usecase_t uc_id)
 in_snd_device == usecase->in_snd_device) {
 return0;
 }
-
+ charpropValue[16];
+ if(property_get("service.bootanim.exit", propValue, "0")) {
+ if(atoi(propValue) == 0){
+ out_snd_device = SND_DEVICE_OUT_HEADPHONES;
+ ALOGD("%s: out_snd_device force select headphone\\n", __func__);
+ }
+ else+ ALOGV("bootanimation exit,normal select device\\n ");
+ }
 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
 out_snd_device, platform_get_snd_device_name(out_snd_device),
 in_snd_device, platform_get_snd_device_name(in_snd_device));

开机完成后,“service.bootanim.exit” 将被置1, 即有新的音频输出时,使用默认的选择策略;

以上是关于android开机铃声通过耳机输出的主要内容,如果未能解决你的问题,请参考以下文章

Android平台上裁剪m4a

怎么设置手机铃声自动放歌

如何通过我的活动在 Android 中设置铃声?

通过 Android 手机中的耳机插孔发送数据

如何在我的活动中设置Android铃声?

当铃声静音时,如何防止我的应用程序(使用 AVPlayer)静音?