audio-audioflinger-应用音量到活跃流

好的,这是一个非常深入的问题。我们来详细分析 AudioFlinger 如何将应用设置的音量应用到活跃的音频流上。

  1. 整体音量应用流程

应用设置音量 → AudioManager → AudioService → AudioSystem → AudioFlinger

AudioPolicyService (音量曲线管理) → AudioFlinger (混音处理)

AudioFlinger::PlaybackThread → 应用音量 + 设备音量 + 主音量

AudioMixer → 音量应用 → 输出到HAL

  1. 详细源码调用流程

步骤1: 应用层设置音量

// 应用调用

AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);

// frameworks/base/media/java/android/media/AudioManager.java

public void setStreamVolume(int streamType, int index, int flags) {

// 通过Binder调用AudioService

IAudioService service = getService();

service.setStreamVolume(streamType, index, flags, getContext().getOpPackageName());

}

步骤2: AudioService处理

// frameworks/base/services/core/java/com/android/server/audio/AudioService.java

public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {

// 1. 权限检查和音量范围验证

ensureValidStreamType(streamType);

index = rescaleIndex(index, streamType);

复制代码
// 2. 获取对应流的音量控制器
VolumeStreamState streamState = mStreamStates[streamType];

// 3. 设置设备索引
int device = getDeviceForStream(streamType);
streamState.setIndex(index, device, callingPackage);

// 4. 通知AudioSystem
mAudioSystem.setStreamVolumeIndex(streamType, index, device);

// 5. 发送音量更新广播
sendBroadcastToAll(new Intent(AudioManager.VOLUME_CHANGED_ACTION));

}

步骤3: AudioSystem到AudioFlinger

// frameworks/av/media/libaudioclient/AudioSystem.cpp

status_t AudioSystem::setStreamVolume(audio_stream_type_t stream, float value, audio_io_handle_t output) {

// 通过Binder调用AudioFlinger

const sp& af = AudioSystem::get_audio_flinger();

return af->setStreamVolume(stream, value, output);

}

步骤4: AudioFlinger接收音量设置

// frameworks/av/services/audioflinger/AudioFlinger.cpp

status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value, audio_io_handle_t output) {

// 1. 检查权限和参数有效性

if (!isStreamValid(stream)) return BAD_VALUE;

复制代码
// 2. 查找对应的播放线程
sp<PlaybackThread> thread = getPlaybackThread_l(output);
if (thread == 0) return BAD_VALUE;

// 3. 在线程中设置流音量
return thread->setStreamVolume(stream, value);

}

  1. PlaybackThread中的音量管理

PlaybackThread音量设置

// frameworks/av/services/audioflinger/Threads.cpp

status_t AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value) {

Mutex::Autolock _l(mLock);

复制代码
// 1. 存储流音量
mStreamTypes[stream].volume = value;

// 2. 立即应用到所有活跃的Track
for (size_t i = 0; i < mActiveTracks.size(); ++i) {
    sp<Track> track = mActiveTracks[i];
    if (track->streamType() == stream) {
        // 重新计算Track的音量
        track->setFinalVolume_l();
    }
}

// 3. 广播音量变化
broadcast_l();
return NO_ERROR;

}

Track音量计算

// frameworks/av/services/audioflinger/Tracks.cpp

void AudioFlinger::PlaybackThread::Track::setFinalVolume_l() {

// 1. 获取流类型音量

float streamVolume = mThread->mStreamTypes[mStreamType].volume;

复制代码
// 2. 获取主音量
float masterVolume = mThread->masterVolume();

// 3. 应用音频策略音量曲线
float volumeDb = AudioSystem::linearToLog(streamVolume * mVolume[0] * mVolume[1]);

// 4. 考虑静音状态
if (mThread->isStreamMuted(mStreamType)) {
    volumeDb = AUDIO_MIN_VOLUME;
}

// 5. 设置最终音量
mFinalVolume = AudioSystem::logToLinear(volumeDb) * masterVolume;

ALOGV("setFinalVolume_l: stream=%d, streamVol=%.3f, master=%.3f, final=%.3f",
      mStreamType, streamVolume, masterVolume, mFinalVolume);

}

  1. 混音时的音量应用

MixerThread处理

// frameworks/av/services/audioflinger/Threads.cpp - MixerThread

bool AudioFlinger::MixerThread::threadLoop() {

while (!exitPending()) {

// 1. 准备混音

processConfigEvents();

复制代码
    // 2. 准备活跃的Tracks
    prepareTracks_l(&tracks, &outputBuffer);
    
    // 3. 执行混音
    mAudioMixer->process();
    
    // 4. 输出到HAL
    threadLoop_write();
}
return false;

}

AudioMixer中的音量处理

// frameworks/av/services/audioflinger/AudioMixer.cpp

void AudioMixer::process() {

for (size_t i = 0; i < mActiveTracks.size(); ++i) {

int name = mActiveTracks[i];

track_t* track = &mTracks[name];

复制代码
    // 应用音量到每个Track
    if (track->needsVolume) {
        // 设置音量参数
        uint32_t vl = uint32_t(track->volume[0] * track->mFinalVolume * 0x1000);
        uint32_t vr = uint32_t(track->volume[1] * track->mFinalVolume * 0x1000);
        
        // 调用DSP处理函数应用音量
        track->hook(track, outputBuffer, numFrames);
    }
}

}

  1. 音量曲线和策略管理

AudioPolicyService参与

// frameworks/av/services/audiopolicy/AudioPolicyService.cpp

float AudioPolicyService::getStreamVolume(audio_stream_type_t stream,

audio_devices_t device,

audio_output_flags_t flags) {

// 1. 获取音量曲线

VolumeCurve curve = getVolumeCurve(stream, device);

复制代码
// 2. 应用音量曲线转换
float volumeDb = curve.mapVolume(mStreams[stream].getVolumeIndex());

// 3. 考虑安全音量限制
volumeDb = applyAllVolumes(volumeDb, stream, device);

return volumeDb;

}

音量曲线映射

// frameworks/av/services/audiopolicy/engine/VolumeCurve.cpp

float VolumeCurve::mapVolume(int index) const {

// 将音量索引转换为dB值

if (index <= mIndexMin) {

return mDbMin;

} else if (index >= mIndexMax) {

return mDbMax;

}

复制代码
// 线性或分段线性插值
float fraction = float(index - mIndexMin) / float(mIndexMax - mIndexMin);
return mDbMin + fraction * (mDbMax - mDbMin);

}

  1. 实时音量调整机制

淡入淡出处理

// frameworks/av/services/audioflinger/Tracks.cpp

void AudioFlinger::PlaybackThread::Track::setVolume(float left, float right) {

sp thread = mThread.promote();

if (thread != 0) {

Mutex::Autolock _l(thread->mLock);

复制代码
    // 设置目标音量
    mVolume[0] = left;
    mVolume[1] = right;
    
    // 如果需要淡入淡出
    if (mFramesCount == 0) {
        // 立即设置
        mFinalVolume = calculateFinalVolume();
    } else {
        // 启动淡入淡出
        startVolumeRamp();
    }
}

}

void AudioFlinger::PlaybackThread::Track::startVolumeRamp() {

// 计算淡入淡出步长

uint32_t sampleRate = mSampleRate;

uint32_t rampFrames = uint32_t((mRampDuration * sampleRate) / 1000);

复制代码
if (rampFrames > 0) {
    mVolumeInc[0] = (mVolume[0] - mPrevVolume[0]) / rampFrames;
    mVolumeInc[1] = (mVolume[1] - mPrevVolume[1]) / rampFrames;
    mRampFrames = rampFrames;
}

}

  1. 多设备音量管理

设备特定音量

// frameworks/av/services/audioflinger/AudioFlinger.cpp

status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream,

float value, audio_io_handle_t output,

audio_devices_t device) {

// 1. 查找对应设备和输出的线程

sp thread = checkPlaybackThread_l(output);

if (thread == 0) return BAD_VALUE;

复制代码
// 2. 设置设备特定的音量
if (device == AUDIO_DEVICE_NONE) {
    device = thread->outDevice();
}

// 3. 存储设备音量
mStreams[stream].setVolume(device, value);

// 4. 应用到活跃流
return thread->setStreamVolume(stream, value, device);

}

  1. 关键设计特点

  2. 分层音量控制

应用音量 → 流音量 → 设备音量 → 主音量 → 最终音量

  1. 实时性保证

• 音量变化立即生效

• 淡入淡出避免爆音

• 锁保护确保线程安全

  1. 策略灵活性

• 可配置的音量曲线

• 设备特定的音量设置

• 安全音量限制

  1. 性能优化

• 预计算最终音量

• 向量化音量处理

• 最小化锁竞争

这个流程展示了Android音频系统如何高效、灵活地管理应用音量,确保多应用、多设备的音频混合能够正确应用各自的音量设置。

相关推荐
阿巴斯甜11 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker12 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq952713 小时前
Andorid Google 登录接入文档
android
黄林晴14 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿1 天前
Android MediaPlayer 笔记
android
Jony_1 天前
Android 启动优化方案
android
阿巴斯甜1 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇1 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_1 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android