功能描述
在系统开机时,强制开机铃声只通过耳机通道播放;
不管是否有插入耳机,最终开机铃声都通过耳机通道输出;开机后保持原有的音频策略设置;
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* 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);
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, &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 类型的选择
typedef enum {
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,
AUDIO_STREAM_DTMF = 8,
AUDIO_STREAM_TTS = 9,
AUDIO_STREAM_ACCESSIBILITY = 10,
AUDIO_STREAM_REROUTING = 11,
AUDIO_STREAM_PATCH = 12,
AUDIO_STREAM_PUBLIC_CNT = AUDIO_STREAM_TTS + 1,
AUDIO_STREAM_FOR_POLICY_CNT = AUDIO_STREAM_PATCH,
AUDIO_STREAM_CNT = AUDIO_STREAM_PATCH + 1,
} audio_stream_type_t;
通常场景下,开机铃声选择AUDIO_STREAM_ENFORCED_AUDIBLE 类型;
在开机动画播放前 调用
bool BootAnimation::threadLoop()
{
bool r;
bootMusic();
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, 即有新的音频输出时,使用默认的选择策略;
|