volume設定,跳過binder部分(binder請獨立了解)
沒有采用深度優先的方法,容易繞來繞去,就不知道再看什麼了。
采用不斷透調的方法講解,一步一步從上層直逼底層,從整體上了解音量設定過程。
透調中有點難度的調用最後講解。
一、JNI部分
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 <audio_stream_type_t>(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的setStreamVolumeIndex函數,進到audiosystem
二、audiosystem
AudioSystem.cpp-----framework/av/media/libmedia/
status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream,
int index,
audio_devices_t device)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->setStreamVolumeIndex(stream, index, device);
}
這裡采用了binder機制,直接無視它!知道是一種調用方式就可以。
看到函數調用了audiopolicyservice裡的函數setStreamVolumeIndex;
三、audiopolicyservice
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);
}
五、audiopolicymanager
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
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);
}
volumeCommand函數也在這個檔案内
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;
}
調到啊udiosystem的函數
七、audiosystem
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<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
af->setStreamVolume(stream, value, output);
return NO_ERROR;
}
通過binder通信,調用audioflinger裡的setStreamVolume
八、audioflinger
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
調用過程詳細分析:
疑點1、mpAudioPolicy調用的是audio_policy_hal.cpp中的方法分析:
函數内部,使用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);
}
}
1.1分析hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
其中,#define AUDIO_POLICY_HARDWARE_MODULE_ID "audio_policy"
<p>int hw_get_module(const char *id, const struct hw_module_t **module)</p><p>上面函數調用Hardware.c--------audio/hardware/libhardware/</p><p>
</p>
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,還在這個檔案内;
<pre name="code" class="cpp">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<HAL_VARIANT_KEYS_COUNT+1 ; i++) {
if (i < HAL_VARIANT_KEYS_COUNT) {
if (property_get(variant_keys[i], prop, NULL) == 0) {
continue;
}
snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH2, name, prop);
if (access(path, R_OK) == 0) break;
snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH1, name, prop);
if (access(path, R_OK) == 0) break;
} else {
snprintf(path, sizeof(path), "%s/%s.default.so",
HAL_LIBRARY_PATH2, name);
if (access(path, R_OK) == 0) break;
snprintf(path, sizeof(path), "%s/%s.default.so",
HAL_LIBRARY_PATH1, name);//#define HAL_LIBRARY_PATH1 "/system/lib/hw"
//将"/system/lib/hw/audio_policy.default.so"拷貝到path中
if (access(path, R_OK) == 0) break;//判斷是否是可讀檔案,至此,已經确定加載audio_policy.default.so檔案,下面的load将完成加載</u>
}
}
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;
}
未完。。。。。。。。。。。。我還會回來的。。。。。。。。。。。。。。。。。