公司odm一款移动设备需要过CTA认证,发现通话录音不会弹出权限提示框并且生成0kb录音文件,故该测试项不通过。
通过log初步分析是获取输入设备属性返回-19导致初始化失败,从而无法录音:
03-29 16:05:32.005 454 6208 E AudioPolicyIntefaceImpl: inputType = 1
03-29 16:05:32.005 469 2397 E AudioRecord: openRecord_l status = -19
inputTyoe = 1表示
typedef enum {
API_INPUT_INVALID = -1,
API_INPUT_LEGACY = 0,// e.g. audio recording from a microphone
API_INPUT_MIX_CAPTURE,// used for “remote submix”, capture of the media to play it remotely
API_INPUT_MIX_EXT_POLICY_REROUTE,// used for platform audio rerouting, where mixes are
// handled by external and dynamically installed
// policies which reroute audio mixes
API_INPUT_TELEPHONY_RX, // used for capture from telephony RX path
} input_type_t;
进一步分析,注意加粗部分:
CTA异常:
03-29 16:05:31.843 418 4715 D audio_hw_primary: enable_audio_route: apply mixer and update path: voicemmode1-call
03-29 16:05:31.843 418 4715 D audio_route: Apply path: voicemmode1-call
03-29 16:05:31.848 418 4715 D audio_hw_primary: select_devices: done
03-29 16:05:31.972 418 4715 D voice : voice_set_sidetone: enable, out_snd_device: 16 (SND_DEVICE_OUT_VOICE_HANDSET, 有输出没输入)
03-29 16:05:31.972 418 4715 D audio_route: Apply path: sidetone-handset (免提)
03-29 16:05:31.977 418 4715 D msm8916_platform: platform_set_voice_volume Setting voice volume: 20
03-29 16:05:31.977 418 4715 D msm8916_platform: usecase_id = 34
03-29 16:05:31.977 418 4715 D msm8916_platform: usecase_id:voicemmode1-call
03-29 16:05:32.005 454 6208 E AudioPolicyIntefaceImpl: AudioPolicyService::getInputForAttr - E, attr->source = 1 (AUDIO_SOURCE_MIC)
03-29 16:05:32.005 454 6208 D AudioPolicyManagerCustom: voice_conc:BLOCK VoIP requst incall mode for inputSource: 1
03-29 16:05:32.005 454 6208 E AudioPolicyIntefaceImpl: inputType = 1 (API_INPUT_MIX_CAPTURE)
03-29 16:05:32.005 469 2397 E AudioRecord: openRecord_l status = -19 (#define ENODEV 19)
03-29 16:05:32.005 469 2397 E AudioRecord: Could not get audio input for session 113, record source 1, sample rate 8000, format 0x1, channel mask 0x10, flags 0
正常通话录音:
04-01 15:03:22.755 438 5896 D audio_hw_primary: enable_audio_route: apply mixer and update path: incall-rec-uplink-and-downlink
04-01 15:03:22.755 438 5896 D audio_route: Apply path: incall-rec-uplink-and-downlink
04-01 15:03:22.761 438 5896 D audio_hw_primary: select_devices: done
04-01 15:03:22.753 438 5896 D voice : voice_get_incall_rec_snd_device: in_snd_device(94: voice-dmic-ef) incall_record_device(67: handset-mic) (有输入有输出)
04-01 15:03:22.755 438 5896 D audio_hw_primary: enable_audio_route: apply mixer and update path: incall-rec-uplink-and-downlink
04-01 15:03:22.755 438 5896 D audio_route: Apply path: incall-rec-uplink-and-downlink
04-01 15:03:21.205 511 5384 E AudioPolicyIntefaceImpl: AudioPolicyService::getInputForAttr - E, attr->source = 4 (AUDIO_SOURCE_VOICE_CALL)
04-01 15:03:21.205 511 5384 D AudioPolicyManagerCustom: voice_conc:Creating input during incall mode for inputSource: 4
04-01 15:03:21.214 511 5384 E AudioPolicyIntefaceImpl: inputType = 3 (API_INPUT_TELEPHONY_RX)
04-01 15:03:21.214 511 5384 E AudioPolicyIntefaceImpl: skip check android.permission.CAPTURE_AUDIO_OUTPUT for CTA request!
04-01 15:03:21.214 523 4058 E AudioRecord: openRecord_l status = 0
我怀疑只要把inputsource从1改为4就好了,不过实验室不肯改。
通过一系列的加log,复测发现一句重要的系统log!!!
skip check android.permission.CAPTURE_AUDIO_OUTPUT for CTA request!
在HAL层发现对应代码:
status_t AudioPolicyManagerCustom::getInputForAttr(const audio_attributes_t *attr,
audio_io_handle_t *input,
audio_session_t session,
uid_t uid,
const audio_config_base_t *config,
audio_input_flags_t flags,
audio_port_handle_t *selectedDeviceId,
input_type_t *inputType,
audio_port_handle_t *portId)
{
audio_source_t inputSource;
inputSource = attr->source;
#ifdef VOICE_CONCURRENCY
char propValue[PROPERTY_VALUE_MAX];
bool prop_rec_enabled=false, prop_voip_enabled = false;
if(property_get("vendor.voice.record.conc.disabled", propValue, NULL)) {
prop_rec_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
}
if(property_get("vendor.voice.voip.conc.disabled", propValue, NULL)) {
prop_voip_enabled = atoi(propValue) || !strncmp("true", propValue, 4);
}
if (prop_rec_enabled && mvoice_call_state) {
//check if voice call is active / running in background
//some of VoIP apps(like SIP2SIP call) supports resume of VoIP call when call in progress
//Need to block input request
if((AUDIO_MODE_IN_CALL == mEngine->getPhoneState()) ||
((AUDIO_MODE_IN_CALL == mPrevPhoneState) &&
(AUDIO_MODE_IN_COMMUNICATION == mEngine->getPhoneState())))
{
switch(inputSource) {
case AUDIO_SOURCE_VOICE_UPLINK:
case AUDIO_SOURCE_VOICE_DOWNLINK:
case AUDIO_SOURCE_VOICE_CALL:
ALOGD("voice_conc:Creating input during incall mode for inputSource: %d",
inputSource);
break;
case AUDIO_SOURCE_VOICE_COMMUNICATION:
if(prop_voip_enabled) {
ALOGD("voice_conc:BLOCK VoIP requst incall mode for inputSource: %d",
inputSource);
return NO_INIT;
}
break;
default:
ALOGD("voice_conc:BLOCK VoIP requst incall mode for inputSource: %d",
inputSource);
return NO_INIT;
}
}
}//check for VoIP flag
else if(prop_voip_enabled && mvoice_call_state) {
//check if voice call is active / running in background
//some of VoIP apps(like SIP2SIP call) supports resume of VoIP call when call in progress
//Need to block input request
if((AUDIO_MODE_IN_CALL == mEngine->getPhoneState()) ||
((AUDIO_MODE_IN_CALL == mPrevPhoneState) &&
(AUDIO_MODE_IN_COMMUNICATION == mEngine->getPhoneState())))
{
if(inputSource == AUDIO_SOURCE_VOICE_COMMUNICATION) {
ALOGD("BLOCKING VoIP request during incall mode for inputSource: %d ",inputSource);
return NO_INIT;
}
}
}
#endif
return AudioPolicyManager::getInputForAttr(attr,
input,
session,
uid,
config,
flags,
selectedDeviceId,
inputType,
portId);
}
原来是属性vendor.voice.record.conc.disabled搞的鬼,可见高通代码很严谨,不允许MIC通话录音,应该是安全层面考虑。不过我grep其他平台,该属性竟然都是false,只有8909为true!
/hardware/qcom/audio/configs/msm8909/msm8909.mk
还有通话录音这个功能原生代码是没有的,需要各odm自己添加该功能。
CTA没有用正常的通话录音导致测试失败。
HAL层代码多看看,混口饭吃还能多吃一口,不过真的很费时。