参考链接:Android7.1 音频声音控制策略
参考文中给了两种方法,第一种没有成功,第二种成功了。第一种可能是参数给错了,例子给的是Speaker和耳机,我需要的是Speaker和USB音频。
第一种:
文件路径:hardware\qcom\audio\hal\Audio_hw.c
int start_output_stream(struct stream_out *out)
{
...
// Jon Add Begin
out->devices = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
// End
...
uc_info->devices = out->devices;
...
//完成声卡和路由的切换和打开
select_devices(adev, out->usecase);
...
}
git比较如下:
ubt@ubt-ThinkPad-E470:~/proj/firefly-rk3399$ git diff hardware/qcom/audio/hal
diff --git a/hardware/qcom/audio/hal/audio_hw.c b/hardware/qcom/audio/hal/audio_hw.c
index 0a5bccb..bc0683d 100644
--- a/hardware/qcom/audio/hal/audio_hw.c
+++ b/hardware/qcom/audio/hal/audio_hw.c
@@ -1645,6 +1645,9 @@ int start_output_stream(struct stream_out *out)
goto error_config;
}
+ // dlc-add 20210223
+ //out->devices = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
+
uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
uc_info->id = out->usecase;
uc_info->type = PCM_PLAYBACK;
其中 SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES 在platform.h 音频设备定义,下面仅列举一部分:
/* Sound devices specific to the platform
* The DEVICE_OUT_* and DEVICE_IN_* should be mapped to these sound
* devices to enable corresponding mixer paths
*/
enum {
SND_DEVICE_NONE = 0,
/* Playback devices */
SND_DEVICE_MIN,
SND_DEVICE_OUT_BEGIN = SND_DEVICE_MIN,
SND_DEVICE_OUT_HANDSET = SND_DEVICE_OUT_BEGIN,
SND_DEVICE_OUT_SPEAKER,
SND_DEVICE_OUT_HEADPHONES,
SND_DEVICE_OUT_HEADPHONES_DSD,
SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES,
SND_DEVICE_OUT_SPEAKER_AND_LINE,
SND_DEVICE_OUT_VOICE_HANDSET,
SND_DEVICE_OUT_VOICE_SPEAKER,
SND_DEVICE_OUT_VOICE_HEADPHONES,
SND_DEVICE_OUT_VOICE_LINE,
SND_DEVICE_OUT_HDMI,
SND_DEVICE_OUT_DISPLAY_PORT,
SND_DEVICE_OUT_BT_SCO,
SND_DEVICE_OUT_BT_A2DP,
SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP,
SND_DEVICE_OUT_AFE_PROXY,
SND_DEVICE_OUT_USB_HEADSET,
SND_DEVICE_OUT_USB_HEADPHONES,
SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET,
SND_DEVICE_OUT_SPEAKER_PROTECTED,
SND_DEVICE_OUT_VOICE_SPEAKER_PROTECTED,
SND_DEVICE_OUT_END,
/* Capture devices */
SND_DEVICE_IN_BEGIN = SND_DEVICE_OUT_END,
SND_DEVICE_IN_HANDSET_MIC = SND_DEVICE_IN_BEGIN, // 58
SND_DEVICE_IN_SPEAKER_MIC,
SND_DEVICE_IN_HEADSET_MIC,
SND_DEVICE_IN_VOICE_SPEAKER_MIC,
SND_DEVICE_IN_VOICE_HEADSET_MIC,
SND_DEVICE_IN_BT_SCO_MIC,
SND_DEVICE_IN_CAMCORDER_MIC,
SND_DEVICE_IN_END,
SND_DEVICE_MAX = SND_DEVICE_IN_END,
};
根据需求配置,如果需要Speaker和USB,则应使用 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET ,这个我没有测试,大家有时间可以试试。
第二种方式:
在Framework中修改,路径如下:frameworks\av\services\audiopolicy\managerdefault\AudioPolicyManager.cpp
audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,
bool fromCache)
{
...
/*Begin Add Jon*/
if(strategy == STRATEGY_MEDIA)
return AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_WIRED_HEADSET;
/*End*/
return mEngine->getDeviceForStrategy(strategy);
}
git文件比较如下:
ubt@ubt-ThinkPad-E470:~/proj/firefly-rk3399$ git diff frameworks/av/services/audiopolicy/managerdefault
diff --git a/frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 1a8a84a..2951461 100644
--- a/frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -4657,6 +4657,19 @@ audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strate
strategy, mDeviceForStrategy[strategy]);
return mDeviceForStrategy[strategy];
}
+
+ // dlc-add 20210223
+ /*Begin Add Jon*/
+ ALOGD(" getDeviceForStrategy() strategy type:%d", strategy );
+
+ if( (strategy == STRATEGY_MEDIA) ||
+ (strategy == STRATEGY_SONIFICATION) ||
+ (strategy == STRATEGY_SONIFICATION_RESPECTFUL) )
+ return AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_USB_DEVICE;
+
+
+ /*End*/
+
return mEngine->getDeviceForStrategy(strategy);
}
其中添加的判断语句意思为:判断声音为媒体、闹钟和铃声。直接返回 SPEAKER和USB_DEVICE。
其中 strategy类型如下:
enum routing_strategy {
STRATEGY_MEDIA,
STRATEGY_PHONE,
STRATEGY_SONIFICATION,
STRATEGY_SONIFICATION_RESPECTFUL,
STRATEGY_DTMF,
STRATEGY_ENFORCED_AUDIBLE,
STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
STRATEGY_ACCESSIBILITY,
STRATEGY_REROUTING,
NUM_STRATEGIES
};
根据需要自行修改。
返回的类型枚举如下:
enum {
AUDIO_DEVICE_NONE = 0x0,
/* reserved bits */
AUDIO_DEVICE_BIT_IN = 0x80000000,
AUDIO_DEVICE_BIT_DEFAULT = 0x40000000,
/* output devices */
AUDIO_DEVICE_OUT_EARPIECE = 0x1, // 听筒
AUDIO_DEVICE_OUT_SPEAKER = 0x2, // 扬声器
AUDIO_DEVICE_OUT_WIRED_HEADSET = 0x4, // 线控耳机,可以通过耳机控制远端播放、暂停、音量调节等功能的耳机
AUDIO_DEVICE_OUT_WIRED_HEADPHONE = 0x8, // 普通耳机,只能听,不能操控播放
AUDIO_DEVICE_OUT_BLUETOOTH_SCO = 0x10, // 单声道蓝牙耳机,十进制32
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20, // 车载免提蓝牙设备,十进制64
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40, // 立体声蓝牙耳机
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP = 0x80, // 十进制128
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100, // 十进制256
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200, // 十进制512
AUDIO_DEVICE_OUT_AUX_DIGITAL = 0x400, // 十进制1024
AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800, // 十进制2048
AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000, // 十进制4096
AUDIO_DEVICE_OUT_USB_ACCESSORY = 0x2000,
AUDIO_DEVICE_OUT_USB_DEVICE = 0x4000,
AUDIO_DEVICE_OUT_REMOTE_SUBMIX = 0x8000,
AUDIO_DEVICE_OUT_DEFAULT = AUDIO_DEVICE_BIT_DEFAULT,
AUDIO_DEVICE_OUT_ALL = (AUDIO_DEVICE_OUT_EARPIECE |
AUDIO_DEVICE_OUT_SPEAKER |
AUDIO_DEVICE_OUT_WIRED_HEADSET |
AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
AUDIO_DEVICE_OUT_AUX_DIGITAL |
AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
AUDIO_DEVICE_OUT_USB_ACCESSORY |
AUDIO_DEVICE_OUT_USB_DEVICE |
AUDIO_DEVICE_OUT_REMOTE_SUBMIX |
AUDIO_DEVICE_OUT_DEFAULT),
AUDIO_DEVICE_OUT_ALL_A2DP = (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
AUDIO_DEVICE_OUT_ALL_SCO = (AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
AUDIO_DEVICE_OUT_ALL_USB = (AUDIO_DEVICE_OUT_USB_ACCESSORY |
AUDIO_DEVICE_OUT_USB_DEVICE),
/* input devices */
AUDIO_DEVICE_IN_COMMUNICATION = AUDIO_DEVICE_BIT_IN | 0x1,
AUDIO_DEVICE_IN_AMBIENT = AUDIO_DEVICE_BIT_IN | 0x2,
AUDIO_DEVICE_IN_BUILTIN_MIC = AUDIO_DEVICE_BIT_IN | 0x4, //手机自带MIC
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = AUDIO_DEVICE_BIT_IN | 0x8,
AUDIO_DEVICE_IN_WIRED_HEADSET = AUDIO_DEVICE_BIT_IN | 0x10, //耳机
AUDIO_DEVICE_IN_AUX_DIGITAL = AUDIO_DEVICE_BIT_IN | 0x20,
AUDIO_DEVICE_IN_VOICE_CALL = AUDIO_DEVICE_BIT_IN | 0x40,
AUDIO_DEVICE_IN_BACK_MIC = AUDIO_DEVICE_BIT_IN | 0x80,
AUDIO_DEVICE_IN_REMOTE_SUBMIX = AUDIO_DEVICE_BIT_IN | 0x100,
AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET = AUDIO_DEVICE_BIT_IN | 0x200,
AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET = AUDIO_DEVICE_BIT_IN | 0x400,
AUDIO_DEVICE_IN_USB_ACCESSORY = AUDIO_DEVICE_BIT_IN | 0x800,
AUDIO_DEVICE_IN_USB_DEVICE = AUDIO_DEVICE_BIT_IN | 0x1000,
AUDIO_DEVICE_IN_DEFAULT = AUDIO_DEVICE_BIT_IN | AUDIO_DEVICE_BIT_DEFAULT,
AUDIO_DEVICE_IN_ALL = (AUDIO_DEVICE_IN_COMMUNICATION |
AUDIO_DEVICE_IN_AMBIENT |
AUDIO_DEVICE_IN_BUILTIN_MIC |
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET |
AUDIO_DEVICE_IN_WIRED_HEADSET |
AUDIO_DEVICE_IN_AUX_DIGITAL |
AUDIO_DEVICE_IN_VOICE_CALL |
AUDIO_DEVICE_IN_BACK_MIC |
AUDIO_DEVICE_IN_REMOTE_SUBMIX |
AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET |
AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET |
AUDIO_DEVICE_IN_USB_ACCESSORY |
AUDIO_DEVICE_IN_USB_DEVICE |
AUDIO_DEVICE_IN_DEFAULT),
AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
};
我需要的是Speaker和USB转音频同时输出声音,因此直接返回这两个return AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_USB_DEVICE;如果有其他需要,根据定义自选,简单暴力。
这样设置后,可能会有一些意想不到的效果,配置以后一定要多测试。
2021.02.26 更新:
采用第二种方式 更新后,在同时使用USB音频和Speaker播放时,会出现卡顿的情况。
因为在原系统上,接入USB音频后,媒体音量会通过USB音频输出,通知音量会随机选择通过SUB音频或通过Speaker输出。因此修改了相应的功能,在插入USB音频时,不管是媒体声音,还是通知声音,都从USB音频播放。USB音频拔出后,均从Speaker输出。修改如下:
audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,
4640 bool fromCache)
4641 {
4642 // dlc add
4643 routing_strategy tmp_strategy;
4644
4645 if( (strategy == STRATEGY_MEDIA) ||
4646 (strategy == STRATEGY_SONIFICATION) ||
4647 (strategy == STRATEGY_SONIFICATION_RESPECTFUL) )
4648 {
4649 tmp_strategy = STRATEGY_MEDIA;
4650 }
4651
4652 // Routing
4653 // see if we have an explicit route
4654 // scan the whole RouteMap, for each entry, convert the stream type to a strategy
4655 // (getStrategy(stream)).
4656 // if the strategy from the stream type in the RouteMap is the same as the argument above,
4657 // and activity count is non-zero
4658 // the device = the device from the descriptor in the RouteMap, and exit.
4659 for (size_t routeIndex = 0; routeIndex < mOutputRoutes.size(); routeIndex++) {
4660 sp<SessionRoute> route = mOutputRoutes.valueAt(routeIndex);
4661 routing_strategy routeStrategy = getStrategy(route->mStreamType);
4662 //if ((routeStrategy == strategy) && route->isActive()) {
4663 if ((routeStrategy == tmp_strategy) && route->isActive()) {
4664 return route->mDeviceDescriptor->type();
4665 }
4666 }
4667
4668 if (fromCache) {
4669 ALOGVV("getDeviceForStrategy() from cache strategy %d, device %x",
4670 strategy, mDeviceForStrategy[strategy]);
4671 //return mDeviceForStrategy[strategy];
4672 return mDeviceForStrategy[tmp_strategy];
4673 }
4674
4675 // dlc-add 20210223
4676 /*Begin Add Jon
4677 ALOGD(" getDeviceForStrategy() strategy type:%d", strategy );
4678
4679 if( (strategy == STRATEGY_MEDIA) ||
4680 (strategy == STRATEGY_SONIFICATION) ||
4681 (strategy == STRATEGY_SONIFICATION_RESPECTFUL) )
4682 return AUDIO_DEVICE_OUT_USB_DEVICE;
4683
4684
4685 End */
4685 End */
4686
4687 //return mEngine->getDeviceForStrategy(strategy);
4688 return mEngine->getDeviceForStrategy(tmp_strategy);
4689 }
git比较如下:
@@ -4647,7 +4659,8 @@ audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strate
audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,
bool fromCache)
{
+ // dlc add
+ routing_strategy tmp_strategy;
+
+ if( (strategy == STRATEGY_MEDIA) ||
+ (strategy == STRATEGY_SONIFICATION) ||
+ (strategy == STRATEGY_SONIFICATION_RESPECTFUL) )
+ {
+ tmp_strategy = STRATEGY_MEDIA;
+ }
+
// Routing
// see if we have an explicit route
// scan the whole RouteMap, for each entry, convert the stream type to a strategy
for (size_t routeIndex = 0; routeIndex < mOutputRoutes.size(); routeIndex++) {
sp<SessionRoute> route = mOutputRoutes.valueAt(routeIndex);
routing_strategy routeStrategy = getStrategy(route->mStreamType);
- if ((routeStrategy == strategy) && route->isActive()) {
+ //if ((routeStrategy == strategy) && route->isActive()) {
+ if ((routeStrategy == tmp_strategy) && route->isActive()) {
return route->mDeviceDescriptor->type();
}
}
if (fromCache) {
ALOGVV("getDeviceForStrategy() from cache strategy %d, device %x",
strategy, mDeviceForStrategy[strategy]);
- return mDeviceForStrategy[strategy];
+ //return mDeviceForStrategy[strategy];
+ return mDeviceForStrategy[tmp_strategy];
}
- return mEngine->getDeviceForStrategy(strategy);
+
+ // dlc-add 20210223
+ /*Begin Add Jon
+ ALOGD(" getDeviceForStrategy() strategy type:%d", strategy );
+
+ if( (strategy == STRATEGY_MEDIA) ||
+ (strategy == STRATEGY_SONIFICATION) ||
+ (strategy == STRATEGY_SONIFICATION_RESPECTFUL) )
+ return AUDIO_DEVICE_OUT_USB_DEVICE;
+
+
+ End */
+
+ //return mEngine->getDeviceForStrategy(strategy);
+ return mEngine->getDeviceForStrategy(tmp_strategy);