Audio音量調節是一級一級調節,而且分不同的流類型,如響鈴,通話,多媒體等。不同的裝置(藍牙裝置)的設定方法有所差別。
sdk的api,設定相應流的音量。不同的流index的範圍不一樣
//--->frameworks/base/media/java/android/media/AudioManager.java
public void setStreamVolume(int streamType, int index, int flags) {
IAudioService service = getService();
try {
service.setStreamVolume(streamType, index, flags,
getContext().getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Dead object in setStreamVolume", e);
}
}
java層Service實作,volume的調節的實作是用state模式來實作,可能需要原子性或不同的模式下調節音量的操作不同。
//--->frameworks/base/services/core/java/com/android/server/audio/AudioService.java
private void setStreamVolume(int streamType, int index, int flags,
String callingPackage,String caller, int uid) {
...(檢查參數)
...(轉換參數)
// 擷取裝置
final int device = getDeviceForStream(streamType);
...(特殊處理a2dp)
...(檢查uid,實體按鍵調節音量需要判斷目前使用者?)
synchronized (mSafeMediaVolumeState) {
mPendingVolumeCommand = null;
oldIndex = streamState.getIndex(device);
index = rescaleIndex(index * 10, streamType, streamTypeAlias);
...(特殊處理a2dp)
...(特殊處理HDMI)
...(設定一些标志位,如标記一些不可調節音量的裝置)
//檢查目前是否可設定音量
if (!checkSafeMediaVolume(streamTypeAlias, index, device)) {
// 不可以則生成PendingCommand,等待合适的時機
mVolumeController.postDisplaySafeVolumeWarning(flags);
mPendingVolumeCommand = new StreamVolumeCommand(
streamType, index, flags, device);
} else {
// 設定音量
onSetStreamVolume(streamType, index, flags, device,
caller);
index = mStreamStates[streamType].getIndex(device);
}
}
// 發送更新音量資訊
sendVolumeUpdate(streamType, oldIndex, index, flags);
}
private void onSetStreamVolume(int streamType, int index, int flags,
int device,String caller) {
final int stream = mStreamVolumeAlias[streamType];
// 設定音量
setStreamVolumeInt(stream, index, device, false, caller);
...(判斷音量是否為0,調節模式(靜音或響鈴))
mStreamStates[stream].mute(index == 0);
}
private void setStreamVolumeInt(int streamType,int index,int device,
boolean force,String caller) {
VolumeStreamState streamState = mStreamStates[streamType];
if (streamState.setIndex(index, device, caller) || force) {
// Post message to set system volume (it in turn will post a message
// to persist).
sendMsg(mAudioHandler,MSG_SET_DEVICE_VOLUME,SENDMSG_QUEUE,device,
0,streamState,0);
}
}
@Override
public void handleMessage(Message msg) {
...
switch (msg.what) {
case MSG_SET_DEVICE_VOLUME:
setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);
break;
...
}
...
}
private void setDeviceVolume(VolumeStreamState streamState, int device) {
synchronized (VolumeStreamState.class) {
// 設定音量
streamState.applyDeviceVolume_syncVSS(device);
...(Apply change to all streams using this one as alias)
}
// Post a persist volume msg
sendMsg(mAudioHandler,MSG_PERSIST_VOLUME,SENDMSG_QUEUE,device,0,
streamState,PERSIST_DELAY);
}
public void applyDeviceVolume_syncVSS(int device) {
int index;
if (mIsMuted) {
index = 0;
} else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0
&& mAvrcpAbsVolSupported) || ((device & mFullVolumeDevices) != 0)) {
index = (mIndexMax + 5)/10;
} else {
index = (getIndex(device) + 5)/10;
}
AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
}
AudioSystem的setStreamVolumeIndex是個native函數,從這裡到跳到c++代碼
//--->frameworks/base/media/java/android/media/AudioSystem.java
public static native int setStreamVolumeIndex(int stream, int index,
int device);
1
2
3
jni的代碼沒做處理,直接轉發給c++層的AudioSystem
//--->frameworks/base/core/jni/android_media_AudioSystem.cpp
static JNINativeMethod gMethods[] = { ...
{"setStreamVolumeIndex","(III)I", (void *)android_media_AudioSystem_setStreamVolumeIndex},
...};
static jint android_media_AudioSystem_setStreamVolumeIndex(
JNIEnv *env,jobject thiz,jint stream,jint index,jint device)
{
return (jint) check_AudioSystem_Command(AudioSystem::setStreamVolumeIndex(
static_cast <audio_stream_type_t>(stream),index,(audio_devices_t)device));
}
AudioSystem又踢給AudioPolicyService(這裡是binder通信,從這裡跳到服務端處理)
//--->frameworks/av/media/libmedia/AudioSystem.cpp
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);
}
AudioPolicyService做了些權限和參數檢查,轉發給AudioPolicyManager
//---frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp
status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream,
int index,audio_devices_t device)
{
if (mAudioPolicyManager == NULL) return NO_INIT;
if (!settingsAllowed()) return PERMISSION_DENIED;
if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) return BAD_VALUE;
Mutex::Autolock _l(mLock);
return mAudioPolicyManager->setStreamVolumeIndex(stream,index,device);
}
AudioPolicyManager的處理比較複雜,主要是包括了音頻政策的判斷
//--->frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
int index,audio_devices_t device)
{
...(檢查音量及裝置是否為audio裝置)
...(政策判斷)
if ((device != AUDIO_DEVICE_OUT_DEFAULT) &&
(device & (strategyDevice | accessibilityDevice)) == 0) {
return NO_ERROR;
}
...(設定每個輸出裝置的音量)
status_t volStatus = checkAndSetVolume(stream, index, desc, curDevice);
...
}
status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream,int index,
const sp<AudioOutputDescriptor>& outputDesc,audio_devices_t device,int delayMs,bool force)
{
...(do not change actual stream volume if the stream is muted)
...(do not change in call volume if bluetooth is connected and vice versa)
// 聲音等級與真正參數的轉換
float volumeDb = computeVolume(stream, index, device);
// 設定輸出裝置的聲音
outputDesc->setVolume(volumeDb, stream, device, delayMs, force);
// 設定通話的音量??
if (stream == AUDIO_STREAM_VOICE_CALL || stream == AUDIO_STREAM_BLUETOOTH_SCO) {
...
mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
...
}
}
return NO_ERROR;
}
AudioOutputDescriptor是音頻裝置描述符,outputDesc是SwAudioOutputDescriptor類型。
//--->/frameworks/av/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
bool AudioOutputDescriptor::setVolume(float volume,audio_stream_type_t stream,
audio_devices_t device __unused,uint32_t delayMs,bool force)
{
// We actually change the volume if:
// - the float value returned by computeVolume() changed
// - the force flag is set
if (volume != mCurVolume[stream] || force) {
ALOGV("setVolume() for stream %d, volume %f, delay %d", stream, volume, delayMs);
mCurVolume[stream] = volume;
return true;
}
return false;
}
bool SwAudioOutputDescriptor::setVolume(float volume,audio_stream_type_t stream,
audio_devices_t device,uint32_t delayMs,bool force)
{
bool changed = AudioOutputDescriptor::setVolume(volume, stream, device,
delayMs, force);
if (changed) {
// Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is
// enabled
float volume = Volume::DbToAmpl(mCurVolume[stream]);
if (stream == AUDIO_STREAM_BLUETOOTH_SCO) {
mClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volume,
mIoHandle, delayMs);
}
mClientInterface->setStreamVolume(stream, volume, mIoHandle, delayMs);
}
return changed;
}
AudioOutputDescriptor的mClientInterface是AudioPolicyService,是以會轉到AudioPolicyService的setStreamVolume
AudioPolicyService異步執行這個操作,最後會轉到AudioSystem的setStreamVolume。
//--->frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp
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)
{
...(封裝了一下data跟command)
return sendCommand(command, delayMs);
}
status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs) {...(一些指令隊列的操作)}
// 處理函數
bool AudioPolicyService::AudioCommandThread::threadLoop()
{
...
while (!exitPending())
{
...
switch (command->mCommand) {
...
case SET_VOLUME:
...(Lock)
VolumeData *data = (VolumeData *)command->mParam.get();
command->mStatus = AudioSystem::setStreamVolume(data->mStream,
data->mVolume,data->mIO);
break;
...
}
}
AudioSystem又轉到AudioFlinger
//--->frameworks/av/media/libmedia/AudioSystem.cpp
status_t AudioSystem::setStreamVolume(audio_stream_type_t stream, float value,
audio_io_handle_t output)
{
...(權限參數檢查)
af->setStreamVolume(stream, value, output);
return NO_ERROR;
}
AudioFlinger會去擷取output對應的PlaybackThread并設定PlaybackThread的音量,如果output == AUDIO_IO_HANDLE_NONE,則設定所有PlaybackThread的音量。
//--->frameworks/av/services/audioflinger/AudioFlinger.cpp
status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
audio_io_handle_t output)
{
...(權限檢查)
...(流類型檢查)
AutoMutex lock(mLock);
...(擷取對應裝置的PlaybackTread)
// ???
mStreamTypes[stream].volume = value;
if (thread == NULL) { // output == AUDIO_IO_HANDLE_NONE
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
}
} else {
thread->setStreamVolume(stream, value);
}
return NO_ERROR;
}
PlaybackThread設定mStreamTypes的volume。并喚醒PlaybackThread線程
void AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
{
Mutex::Autolock _l(mLock);
mStreamTypes[stream].volume = value;
broadcast_l();
}
不同類型的Thread貌似有不同使用方法 MixerThread是在prepareTracks_l裡使用,最後會設定AudioMixer的參數
//--->frameworks/av/services/audioflinger/Threads.cpp
AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
Vector< sp<Track> > *tracksToRemove) {
...
// FastTrack
track->mCachedVolume = masterVolume * mStreamTypes[track->streamType()].volume;
...
// NormalTrack
// 這裡涉及到了左右聲道的音量的計算
// compute volume for this track
uint32_t vl, vr; // in U8.24 integer format
float vlf, vrf, vaf; // in [0.0, 1.0] float format
float typeVolume = mStreamTypes[track->streamType()].volume;
float v = masterVolume * typeVolume;
...
//計算完設定混音器的參數
mAudioMixer->setParameter(name, param, AudioMixer::VOLUME0, &vlf);
mAudioMixer->setParameter(name, param, AudioMixer::VOLUME1, &vrf);
mAudioMixer->setParameter(name, param, AudioMixer::AUXLEVEL, &vaf);
...
}
// 最後會調用到mAudioMixer的setVolumeRampVariables
static inline bool setVolumeRampVariables(float newVolume, int32_t ramp,
int16_t *pIntSetVolume, int32_t *pIntPrevVolume, int32_t *pIntVolumeInc,
float *pSetVolume, float *pPrevVolume, float *pVolumeInc){...}
DirectOutputThread在processVolume_l裡使用(processVolume_l在prepareTracks_l中被調用)
processVolume_l直接設定了輸出裝置的volume
//--->frameworks/av/services/audioflinger/Threads.cpp
void AudioFlinger::DirectOutputThread::processVolume_l(Track *track, bool lastTrack) {
...
float typeVolume = mStreamTypes[track->streamType()].volume;
float v = mMasterVolume * typeVolume;
...(一系列的設定)
if (mOutput->stream->set_volume) {
mOutput->stream->set_volume(mOutput->stream, left, right);
}
}
轉載位址:https://blog.csdn.net/axlecho/article/details/78510496