volume设置,跳过binder部分(binder请独立理解)
没有采用深度优先的方法,容易绕来绕去,就不知道再看什么了。
采用不断透调的方法讲解,一步一步从上层直逼底层,从整体上了解音量设置过程。
透调中有点难度的调用最后讲解。
android_media_AudioSystem.cpp-----framework/base/core/jni/
android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,
jobject thiz,
jint stream,
jint index,
jint device)
{
return check_AudioSystem_Command(
AudioSystem::setStreamVolumeIndex(static_cast (stream),
index,
(audio_devices_t)device));
}
对于函数的行惨,不必过多考虑,是上层java传给的。
关键的参数:
index:音量值;
device:如下列举了一笑部分
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,
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
。。。
}
stream:
/* The audio stream for phone calls */
public static final int STREAM_VOICE_CALL = 0;
/* The audio stream for system sounds */
public static final int STREAM_SYSTEM = 1;
/* The audio stream for the phone ring and message alerts */
public static final int STREAM_RING = 2;
/* The audio stream for music playback */
public static final int STREAM_MUSIC = 3;
/* The audio stream for alarms */
public static final int STREAM_ALARM = 4;
/* The audio stream for notifications */
public static final int STREAM_NOTIFICATION = 5;
/* @hide The audio stream for phone calls when connected on bluetooth */
public static final int STREAM_BLUETOOTH_SCO = 6;
/* @hide The audio stream for enforced system sounds in certain countries (e.g camera in Japan) */
public static final int STREAM_SYSTEM_ENFORCED = 7;
/* @hide The audio stream for DTMF tones */
public static final int STREAM_DTMF = 8;
AudioSystem.cpp-----framework/av/media/libmedia/
status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream,
int index,
audio_devices_t device)
{
const sp& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->setStreamVolumeIndex(stream, index, device);
}
看到函数调用了audiopolicyservice里的函数setStreamVolumeIndex;
AudioPolicyService.cpp-----framework/av/media/services/audioflinger
status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream,
int index,
audio_devices_t device)
{
if (mpAudioPolicy == NULL) {
return NO_INIT;
}
if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
if (mpAudioPolicy->set_stream_volume_index_for_device) {
return mpAudioPolicy->set_stream_volume_index_for_device(mpAudioPolicy,
stream,
index,
device);
} else {
return mpAudioPolicy->set_stream_volume_index(mpAudioPolicy, stream, index);
}
}
mpAudioPolicy->set_stream_volume_index_for_device
这里mpAudioPolicy后面讲解,
疑点1,这里它调用的是
audio_policy_hal.cpp中的方法;
audio_policy_hal.cpp----system/core/libcutils/
static int ap_set_stream_volume_index(struct audio_policy *pol,
audio_stream_type_t stream,
int index)
{
struct legacy_audio_policy *lap = to_lap(pol);
return lap->apm->setStreamVolumeIndex((AudioSystem::stream_type)stream,
index,
AUDIO_DEVICE_OUT_DEFAULT);
}
audiopolicymanagerbase.c----hardware/libhardware_legacy/audio
看到四中的apm就猜到调用的仕audiopolicymanagerbase中的函数,(疑点2),进入audiopolicymanagerbase.c中的函数
status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type stream,
int index,
audio_devices_t device)
{
if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) {
return BAD_VALUE;
}
if (!audio_is_output_device(device)) {
return BAD_VALUE;
}
// Force max volume if stream cannot be muted
if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax;
ALOGV("setStreamVolumeIndex() stream %d, device %04x, index %d",
stream, device, index);
// if device is AUDIO_DEVICE_OUT_DEFAULT set default value and
// clear all device specific values
if (device == AUDIO_DEVICE_OUT_DEFAULT) {
mStreams[stream].mIndexCur.clear();
}
mStreams[stream].mIndexCur.add(device, index);
// compute and apply stream volume on all outputs according to connected device
status_t status = NO_ERROR;
for (size_t i = 0; i < mOutputs.size(); i++) {
audio_devices_t curDevice =
getDeviceForVolume(mOutputs.valueAt(i)->device());
if ((device == AUDIO_DEVICE_OUT_DEFAULT) || (device == curDevice)||
status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice);
if (volStatus != NO_ERROR) {
status = volStatus;
}
}
}
return status;
}
调用到函数checkAndSetVolume函数:
status_t AudioPolicyManagerBase::checkAndSetVolume(int stream,
int index,
audio_io_handle_t output,
audio_devices_t device,
int delayMs,
bool force)
{
。。。。
if (voiceVolume != mLastVoiceVolume && output == mPrimaryOutput) {
mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
mLastVoiceVolume = voiceVolume;
}
}
return NO_ERROR;
}
里面的mpClientInterface->setVoiceVolume,mpClientnterface实际上是audiopolicyservice,
即调用的是audioPolicyService->setStreamVolume
audiopolicyservice.cpp---frameworks/av/services/audioflinger
int AudioPolicyService::setStreamVolume(audio_stream_type_t stream,
float volume,
audio_io_handle_t output,
int delayMs)
{
return (int)mAudioCommandThread->volumeCommand(stream, volume,
output, delayMs);
}
status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type_t stream,
float volume,
audio_io_handle_t output,
int delayMs)
{
status_t status = NO_ERROR;
AudioCommand *command = new AudioCommand();
command->mCommand = SET_VOLUME;
VolumeData *data = new VolumeData();
data->mStream = stream;
data->mVolume = volume;
data->mIO = output;
command->mParam = data;
Mutex::Autolock _l(mLock);
insertCommand_l(command, delayMs);
mWaitWorkCV.signal();
if (command->mWaitStatus) {
command->mCond.wait(mLock);
status = command->mStatus;
command->mCond.signal();
delete command;
}
return status;
}
insertCommand_l(command, delayMs);
加入线程队列中,即threadLoop中;
bool AudioPolicyService::AudioCommandThread::threadLoop()
{
nsecs_t waitTime = INT64_MAX;
mLock.lock();
while (!exitPending())
{
while (!mAudioCommands.isEmpty()) {
nsecs_t curTime = systemTime();
if (mAudioCommands[0]->mTime <= curTime) {
AudioCommand *command = mAudioCommands[0];
mAudioCommands.removeAt(0);
mLastCommand = *command;
// SPRD: Delete command after waiting was end
bool deleteAudioCommand = true;
switch (command->mCommand) {
。。。。
case SET_VOLUME: {
VolumeData *data = (VolumeData *)command->mParam;
ALOGV("AudioCommandThread() processing set volume stream %d, \
volume %f, output %d", data->mStream, data->mVolume, data->mIO);
command->mStatus = AudioSystem::setStreamVolume(data->mStream,
data->mVolume,
data->mIO);
if (command->mWaitStatus) {
// SPRD: Delete command after waiting was end
deleteAudioCommand = false;
command->mCond.signal();
command->mCond.waitRelative(mLock, kAudioCommandTimeout);
}
delete data;
}break;
。。。。。
mLock.unlock();
return false;
}
audiosystem.c---frameworks/av/media/libmedia
status_t AudioSystem::setStreamVolume(audio_stream_type_t stream, float value,
audio_io_handle_t output)
{
if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;
const sp& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
af->setStreamVolume(stream, value, output);
return NO_ERROR;
}
通过binder通信,调用audioflinger里的setStreamVolume
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
函数内部,使用mpAudioPolicy的方法,这就需要看下audiopolicyservice的构造函数;
AudioPolicyService::AudioPolicyService()
: BnAudioPolicyService() , mpAudioPolicyDev(NULL) , mpAudioPolicy(NULL)
{
char value[PROPERTY_VALUE_MAX];
const struct hw_module_t *module;
int forced_val;
int rc;
Mutex::Autolock _l(mLock);
// start tone playback thread
mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);
// start audio commands thread
mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
// start output activity command thread
mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
/* instantiate the audio policy manager */
rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);//1.1分析
if (rc)
return;
rc = audio_policy_dev_open(module, &mpAudioPolicyDev);//1.2分析
ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
if (rc)
return;
rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
&mpAudioPolicy);//1.3分析
ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));
if (rc)
return;
rc = mpAudioPolicy->init_check(mpAudioPolicy);
ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));
if (rc)
return;
/* SPRD: maybe set this property better, but here just change the default value @{ */
property_get("ro.camera.sound.forced", value, "1");
forced_val = strtol(value, NULL, 0);
ALOGV("setForceUse() !forced_val=%d ",!forced_val);
mpAudioPolicy->set_can_mute_enforced_audible(mpAudioPolicy, !forced_val);
/* @} */
ALOGI("Loaded audio policy from %s (%s)", module->name, module->id);
// load audio pre processing modules
if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
loadPreProcessorConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
} else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
loadPreProcessorConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
}
}
其中,#define AUDIO_POLICY_HARDWARE_MODULE_ID "audio_policy"
int hw_get_module(const char *id, const struct hw_module_t **module)
上面函数调用Hardware.c--------audio/hardware/libhardware/
int hw_get_module(const char *id, const struct hw_module_t **module){ return hw_get_module_by_class(id, NULL, module);}又调用hw_get_module_by_class,还在这个文件内;
int hw_get_module_by_class(const char *class_id, const char *inst,
const struct hw_module_t **module)//class_id保存"audio_policy",inst为NULL
{
int status;
int i;
const struct hw_module_t *hmi = NULL;
char prop[PATH_MAX];
char path[PATH_MAX];
char name[PATH_MAX];
if (inst)//inst=NULL,走else
snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
else
strlcpy(name, class_id, PATH_MAX);//将"audio_policy"拷贝到name中;
/*
* Here we rely on the fact that calling dlopen multiple times on
* the same .so will simply increment a refcount (and not load
* a new copy of the library).
* We also assume that dlopen() is thread-safe.
*/
/* Loop through the configuration variants looking for a module */
for (i=0 ; i
}
}
status = -ENOENT;
if (i < HAL_VARIANT_KEYS_COUNT+1) {
/* load the module, if this fails, we're doomed, and we should not try
* to load a different variant. */
status = load(class_id, path, module);//定义的load函数,下面分析
}
return status;
}
这个函数,需要高清几个函数的使用:property_get,snprintf,access;dlopen,dlsym。这几个函数会在另外一篇文章中讲解。
/**
* Load the file defined by the variant and if successful
* return the dlopen handle and the hmi.
* @return 0 = success, !0 = failure.
*/
static int load(const char *id,
const char *path,
const struct hw_module_t **pHmi)
{
int status;
void *handle;
struct hw_module_t *hmi;
/*
* load the symbols resolving undefined symbols before
* dlopen returns. Since RTLD_GLOBAL is not or'd in with
* RTLD_NOW the external symbols will not be global
*/
handle = dlopen(path, RTLD_NOW);//打开指定的 文件,即audio_policy.default.so
if (handle == NULL) {
char const *err_str = dlerror();
ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");
status = -EINVAL;
goto done;
}
/* Get the address of the struct hal_module_info. */
const char *sym = HAL_MODULE_INFO_SYM_AS_STR;//#define HAL_MODULE_INFO_SYM_AS_STR "HMI"
hmi = (struct hw_module_t *)dlsym(handle, sym);//根据动态链接库操作句柄与符号,返回符号对应的地址保存给hmi
if (hmi == NULL) {
ALOGE("load: couldn't find symbol %s", sym);
status = -EINVAL;
goto done;
}
/* Check that the id matches */
if (strcmp(id, hmi->id) != 0) {
ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);
status = -EINVAL;
goto done;
}
hmi->dso = handle;
/* success */
status = 0;
done:
if (status != 0) {
hmi = NULL;
if (handle != NULL) {
dlclose(handle);
handle = NULL;
}
} else {
ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
id, path, *pHmi, handle);
}
*pHmi = hmi;//将地址赋值给形参。至此,整个动态库so的加载完成,并将地址返回
return status;
}
未完。。。。。。。。。。。。我还会回来的。。。。。。。。。。。。。。。。。