Android Framework 音频子系统(14)音量调节之音量键处理流程

该系列文章总纲链接:专题分纲目录 Android Framework 音频子系统​​​​​​​


本章关键点总结 & 说明:

本章节主要关注➕ 以上思维导图左上 音量调节 中 流程分析的音量键处理 部分 即可。主要分析了音量键处理流程主要分成3个部分:

  1. 从输入子系统 到 音频子系统的处理(直到AudioService.adjustSuggestedStreamVolume)
  2. 音频处理流程(从AudioService.adjustSuggestedStreamVolume开始的分析到发送了MSG_SET_DEVICE_VOLUME给mAudioHandler去处理。)
  3. 处理消息MSG_SET_DEVICE_VOLUME

1 从输入子系统 到 音频子系统的处理(直到AudioService.adjustSuggestedStreamVolume)

在有了输入输出子系统的基础上,我们开始分析按键的处理,按键会从inputReader的getEvent 到 inputDisptacher最后到ViewRootimpl中的ViewPostImeInputStage::processKeyEvent方法(这里参考专题分纲目录 Android Framework 输入子系统),这里的processKeyEvent代码如下所示:

private int processKeyEvent(QueuedInputEvent q) {
    final KeyEvent event = (KeyEvent)q.mEvent;
    //...
    // Apply the fallback event policy.
    if (mFallbackEventHandler.dispatchKeyEvent(event)) {
        return FINISH_HANDLED;
    }
    //...
    // Handle automatic focus changes...
    //...
    return FORWARD;
}

这里的mFallbackEventHandler<=等价=>PhoneFallbackEventHandler,即音量键的处理将交给PhoneFallbackEventHandler,它的dispatchKeyEvent代码实现如下:

public boolean dispatchKeyEvent(KeyEvent event) {

    final int action = event.getAction();
    final int keyCode = event.getKeyCode();

    if (action == KeyEvent.ACTION_DOWN) {
        return onKeyDown(keyCode, event);
    } else {
        return onKeyUp(keyCode, event);
    }
}

onKeyDown和onKeyUp的代码实现如下:

boolean onKeyDown(int keyCode, KeyEvent event) {
    final KeyEvent.DispatcherState dispatcher = mView.getKeyDispatcherState();
    switch (keyCode) {
        case KeyEvent.KEYCODE_VOLUME_UP:
        case KeyEvent.KEYCODE_VOLUME_DOWN:
        case KeyEvent.KEYCODE_VOLUME_MUTE: {
            MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(event, false);
            return true;
        }
        //...
    }
    //...
}

boolean onKeyUp(int keyCode, KeyEvent event) {
    final KeyEvent.DispatcherState dispatcher = mView.getKeyDispatcherState();
    if (dispatcher != null) {
        dispatcher.handleUpEvent(event);
    }

    switch (keyCode) {
        case KeyEvent.KEYCODE_VOLUME_UP:
        case KeyEvent.KEYCODE_VOLUME_DOWN:
        case KeyEvent.KEYCODE_VOLUME_MUTE: {
            if (!event.isCanceled()) {
                //MediaSessionLegacyHelper.getHelper(mContext)<=等价=>MediaSessionLegacyHelper
                MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(event, false);
            }
            return true;
        }
        //...
    }
    //...
}

这里会调用MediaSessionLegacyHelper的sendVolumeKeyEvent方法,代码实现如下:

public void sendVolumeKeyEvent(KeyEvent keyEvent, boolean musicOnly) {
    //...
    if (down || up) {
        //...
        if (direction != 0) {
            // If this is action up we want to send a beep for non-music events
            if (up) {
                direction = 0;
            }
            mSessionManager.dispatchAdjustVolume(AudioManager.USE_DEFAULT_STREAM_TYPE,
                    direction, flags);
        } else if (isMute) {
            if (down) {
                mSessionManager.dispatchAdjustVolume(AudioManager.USE_DEFAULT_STREAM_TYPE,
                        MediaSessionManager.DIRECTION_MUTE, flags);
            }
            mSessionManager.dispatchAdjustVolume(AudioManager.USE_DEFAULT_STREAM_TYPE,
                    0 /* direction, causes UI to show on down */, flags);
        }
    }
}

这里继续分析mSessionManager.dispatchAdjustVolume的实现,代码如下:

public void dispatchAdjustVolume(int suggestedStream, int direction, int flags) {
    try {
        mService.dispatchAdjustVolume(suggestedStream, direction, flags);
    } catch (RemoteException e) {
        Log.e(TAG, "Failed to send adjust volume.", e);
    }
}

这里的service是SessionManagerImpl类型,对应的dispatchAdjustVolume代码实现如下:

public void dispatchAdjustVolume(int suggestedStream, int delta, int flags) {
    final int pid = Binder.getCallingPid();
    final int uid = Binder.getCallingUid();
    final long token = Binder.clearCallingIdentity();
    try {
        synchronized (mLock) {
            MediaSessionRecord session = mPriorityStack
                    .getDefaultVolumeSession(mCurrentUserId);
            dispatchAdjustVolumeLocked(suggestedStream, delta, flags, session);
        }
    } finally {
        Binder.restoreCallingIdentity(token);
    }
}

继续分析dispatchAdjustVolumeLocked,代码实现如下:

private void dispatchAdjustVolumeLocked(int suggestedStream, int direction, int flags,
        MediaSessionRecord session) {
    boolean preferSuggestedStream = false;
    if (isValidLocalStreamType(suggestedStream)
            && AudioSystem.isStreamActive(suggestedStream, 0)) {
        preferSuggestedStream = true;
    }
    if (session == null || preferSuggestedStream) {
        if ((flags & AudioManager.FLAG_ACTIVE_MEDIA_ONLY) != 0
                && !AudioSystem.isStreamActive(AudioManager.STREAM_MUSIC, 0)) {
            return;
        }
        try {
            String packageName = getContext().getOpPackageName();
            if (mUseMasterVolume) {
                boolean isMasterMute = mAudioService.isMasterMute();
                if (direction == MediaSessionManager.DIRECTION_MUTE) {
                    mAudioService.setMasterMute(!isMasterMute, flags, packageName, mICallback);
                } else {
                    mAudioService.adjustMasterVolume(direction, flags, packageName);
                    if (isMasterMute && direction != 0) {
                        mAudioService.setMasterMute(false, flags, packageName, mICallback);
                    }
                }
            } else {
                boolean isStreamMute = mAudioService.isStreamMute(suggestedStream);
                if (direction == MediaSessionManager.DIRECTION_MUTE) {
                    mAudioManager.setStreamMute(suggestedStream, !isStreamMute);
                } else {
                    mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream,
                            flags, packageName);
                    // Do not call setStreamMute when direction = 0 which is used just to
                    // show the UI.
                    if (isStreamMute && direction != 0) {
                        mAudioManager.setStreamMute(suggestedStream, false);
                    }
                }
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Error adjusting default volume.", e);
        }
    } else {
        session.adjustVolume(direction, flags, getContext().getPackageName(),
                UserHandle.myUserId(), true);
    }
}

这里最后调用到了AudioService.adjustSuggestedStreamVolume。从输入子系统进入到音频子系统。


2 音频处理流程(从AudioService.adjustSuggestedStreamVolume到发送消息MSG_SET_DEVICE_VOLUME)

private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
        String callingPackage, int uid) {
    int streamType;
    if (mVolumeControlStream != -1) {
        streamType = mVolumeControlStream;
    } else {
        //关键点1:获取推荐的streamType,这里根据建议的流类型与AudioService的实际情况,返回一个值
        streamType = getActiveStreamType(suggestedStreamType);
    }
    //...
    //关键点2
    adjustStreamVolume(streamType, direction, flags, callingPackage, uid);
}

分析getActiveStreamType,代码实现如下:

private int getActiveStreamType(int suggestedStreamType) {
    switch (mPlatformType) {
    case PLATFORM_VOICE://针对Phone
        if (isInCommunication()) {
            //通话中,如果用蓝牙耳机就设置STREAM_BLUETOOTH_SCO,否则设置STREAM_VOICE_CALL
            if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
                    == AudioSystem.FORCE_BT_SCO) {
                return AudioSystem.STREAM_BLUETOOTH_SCO;
            } else {
                return AudioSystem.STREAM_VOICE_CALL;
            }
        } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
            if (isAfMusicActiveRecently(StreamOverride.sDelayMs)) {
                return AudioSystem.STREAM_MUSIC;
                } else :
                    return AudioSystem.STREAM_RING;
            }
        } else if (isAfMusicActiveRecently(0)) {
            return AudioSystem.STREAM_MUSIC;
        }
        break;
    case PLATFORM_TELEVISION://电视
        if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
                // TV always defaults to STREAM_MUSIC
                return AudioSystem.STREAM_MUSIC;
        }
        break;
    default://平板或者其他设备。
        if (isInCommunication()) {
            if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
                    == AudioSystem.FORCE_BT_SCO) {
                return AudioSystem.STREAM_BLUETOOTH_SCO;
            } else {
                return AudioSystem.STREAM_VOICE_CALL;
            }
        } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_NOTIFICATION,
                StreamOverride.sDelayMs) ||
                AudioSystem.isStreamActive(AudioSystem.STREAM_RING,
                        StreamOverride.sDelayMs)) {
            return AudioSystem.STREAM_NOTIFICATION;
        } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
            if (isAfMusicActiveRecently(StreamOverride.sDelayMs)) {
                return AudioSystem.STREAM_MUSIC;
            } else {
                return AudioSystem.STREAM_NOTIFICATION;
            }
        }
        break;
    }
    return suggestedStreamType;
}

分析adjustStreamVolume,代码实现如下:

private void adjustStreamVolume(int streamType, int direction, int flags,
        String callingPackage, int uid) {
    //...
    ensureValidDirection(direction);//确认 调整的音量方向
    ensureValidStreamType(streamType);//确认 调整的stream类型  
    
    int streamTypeAlias = mStreamVolumeAlias[streamType];
    //VolumeStreamState类,保存与一个流类型所有音量相关的信息
    VolumeStreamState streamState = mStreamStates[streamTypeAlias];
    final int device = getDeviceForStream(streamTypeAlias);
    //...
    flags &= ~AudioManager.FLAG_FIXED_VOLUME;
    if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
           ((device & mFixedVolumeDevices) != 0)) {
        flags |= AudioManager.FLAG_FIXED_VOLUME;
        if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
                (device & mSafeMediaVolumeDevices) != 0) {
            step = mSafeMediaVolumeIndex;
        } else {
            step = streamState.getMaxIndex();
        }
        if (aliasIndex != 0) {
            aliasIndex = step;
        }
    } else {
        // convert one UI step (+/-1) into a number of internal units on the stream alias
        //这里将音量值的变化量从源 stream类型变换到目标stream类型,
        //由于不同的流类型的音量调节范围不同,所以这个转换是必需的
        step = rescaleIndex(10, streamType, streamTypeAlias);
    }

    if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
            (streamTypeAlias == getMasterStreamType())) {
        int ringerMode = getRingerModeInternal();
        if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
            flags &= ~AudioManager.FLAG_VIBRATE;
        }
        final int result = checkForRingerModeChange(aliasIndex, direction, step);
        //布尔变量,用来表示是否有必要继续设置音量值
        adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
        if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
            flags |= AudioManager.FLAG_SHOW_SILENT_HINT;
        }
        if ((result & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0) {
            flags |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
        }
    }
    //取出调整前的音量值。这个值会在sendVolumeUpdate()调用
    int oldIndex = mStreamStates[streamType].getIndex(device);

    if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
        //...
        /*判断streamState.adjustIndex 返回值,如果音量值在调整之后并没有发生变化
         *比如到了最大值,就不需要继续后面的操作了
         */
        if ((direction == AudioManager.ADJUST_RAISE) &&
                !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
            mVolumeController.postDisplaySafeVolumeWarning(flags);
        } else if (streamState.adjustIndex(direction * step, device)) {
            //通过sendMsg()发送消息MSG_SET_DEVICE_VOLUME到mAudioHandler
            sendMsg(mAudioHandler,
                    MSG_SET_DEVICE_VOLUME,
                    SENDMSG_QUEUE,
                    device,
                    0,
                    streamState,
                    0);
        }
        //...
    }
    //...
    int index = mStreamStates[streamType].getIndex(device);
    //通知外界音量值发生了变化
    sendVolumeUpdate(streamType, oldIndex, index, flags);
}

这离经过一系列处理后,最终发送了MSG_SET_DEVICE_VOLUME给mAudioHandler去处理。


3 处理消息MSG_SET_DEVICE_VOLUME

这里开始分析处理消息MSG_SET_DEVICE_VOLUME的流程mAudioHandler的handleMessage处理如下:

@Override
public void handleMessage(Message msg) {
    switch (msg.what) {

        case MSG_SET_DEVICE_VOLUME:
            setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);
            break;
		//...
        case MSG_PERSIST_MICROPHONE_MUTE:
            Settings.System.putIntForUser(mContentResolver,
                                         Settings.System.MICROPHONE_MUTE,
                                         msg.arg1,
                                         msg.arg2);
            break;
    }
}

这里继续分析setDeviceVolume的实现, 代码如下:

private void setDeviceVolume(VolumeStreamState streamState, int device) {

    synchronized (VolumeStreamState.class) {
        // Apply volume
        streamState.applyDeviceVolume_syncVSS(device);

        // Apply change to all streams using this one as alias
        int numStreamTypes = AudioSystem.getNumStreamTypes();
        for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
            if (streamType != streamState.mStreamType &&
                    mStreamVolumeAlias[streamType] == streamState.mStreamType) {
                int streamDevice = getDeviceForStream(streamType);
                if ((device != streamDevice) && mAvrcpAbsVolSupported &&
                        ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
                    mStreamStates[streamType].applyDeviceVolume_syncVSS(device);
                }
                mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice);
            }
        }
    }
    //...
}

这里applyDeviceVolume_syncVSS代码实现如下:

// must be called while synchronized VolumeStreamState.class
public void applyDeviceVolume_syncVSS(int device) {
    int index;
    if (isMuted_syncVSS()) {
        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);
}

这里继续分析setStreamVolumeIndex的实现,setStreamVolumeIndex是JNI函数,映射关系为:

    {"setStreamVolumeIndex","(III)I",   (void *)android_media_AudioSystem_setStreamVolumeIndex},

所映射的是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::setStreamVolumeIndex的实现,代码如下:

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);
}

这里调用的是AudioPolicyManager的setStreamVolumeIndex方法,代码实现如下:

status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
                                                      int index,
                                                      audio_devices_t device)
{
    //...
    // Force max volume if stream cannot be muted
    if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax;
    if (device == AUDIO_DEVICE_OUT_DEFAULT) {
        mStreams[stream].mIndexCur.clear();
    }
    mStreams[stream].mIndexCur.add(device, index);

    // update volume on all outputs whose current device is also selected by the same
    // strategy as the device specified by the caller
    audio_devices_t strategyDevice = getDeviceForStrategy(getStrategy(stream), true /*fromCache*/);


    //FIXME: AUDIO_STREAM_ACCESSIBILITY volume follows AUDIO_STREAM_MUSIC for now
    audio_devices_t accessibilityDevice = AUDIO_DEVICE_NONE;
    if (stream == AUDIO_STREAM_MUSIC) {
        mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexCur.add(device, index);
        accessibilityDevice = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, true /*fromCache*/);
    }
    if ((device != AUDIO_DEVICE_OUT_DEFAULT) &&
            (device & (strategyDevice | accessibilityDevice)) == 0) {
        return NO_ERROR;
    }
    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) || ((curDevice & strategyDevice) != 0)) {
            status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice);
            if (volStatus != NO_ERROR) {
                status = volStatus;
            }
        }
        if ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & accessibilityDevice) != 0)) {
            status_t volStatus = checkAndSetVolume(AUDIO_STREAM_ACCESSIBILITY,
                                                   index, mOutputs.keyAt(i), curDevice);
        }
    }
    return status;
}

这里会调用checkAndSetVolume方法,代码实现如下:

status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream,
                                                   int index,
                                                   audio_io_handle_t output,
                                                   audio_devices_t device,
                                                   int delayMs,
                                                   bool force)
{
    //...
    // We actually change the volume if:
    // - the float value returned by computeVolume() changed
    // - the force flag is set
    if (volume != mOutputs.valueFor(output)->mCurVolume[stream] ||
            force) {
        mOutputs.valueFor(output)->mCurVolume[stream] = volume;
        if (stream == AUDIO_STREAM_BLUETOOTH_SCO) {
            mpClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volume, output, delayMs);
        }
        mpClientInterface->setStreamVolume(stream, volume, output, delayMs);
    }

    if (stream == AUDIO_STREAM_VOICE_CALL ||
        stream == AUDIO_STREAM_BLUETOOTH_SCO) {
        float voiceVolume;
        if (stream == AUDIO_STREAM_VOICE_CALL) {
            voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
        } else {
            voiceVolume = 1.0;
        }

        if (voiceVolume != mLastVoiceVolume && output == mPrimaryOutput) {
            mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
            mLastVoiceVolume = voiceVolume;
        }
    }

    return NO_ERROR;
}

这里最终一定会调用AudioPolicyClient的setStreamVolume(方法,代码实现如下:

status_t AudioPolicyService::AudioPolicyClient::setStreamVolume(audio_stream_type_t stream,
                     float volume, audio_io_handle_t output,
                     int delay_ms)
{
    return mAudioPolicyService->setStreamVolume(stream, volume, output,
                                               delay_ms);
}

这里调用到了AudioPolicyService的setStreamVolume方法,代码实现如下:

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);
}

这里 AudioCommandThread的volumeCommand的代码实现如下

status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type_t stream,
                                                               float volume,
                                                               audio_io_handle_t output,
                                                               int delayMs)
{
    sp<AudioCommand> command = new AudioCommand();
    command->mCommand = SET_VOLUME;
    sp<VolumeData> data = new VolumeData();
    data->mStream = stream;
    data->mVolume = volume;
    data->mIO = output;
    command->mParam = data;
    command->mWaitStatus = true;
    return sendCommand(command, delayMs);
}

关注sendCommand的实现,代码如下:

status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
{
    {
        Mutex::Autolock _l(mLock);
        insertCommand_l(command, delayMs);
        mWaitWorkCV.signal();
    }
    Mutex::Autolock _l(command->mLock);
    while (command->mWaitStatus) {
        nsecs_t timeOutNs = kAudioCommandTimeoutNs + milliseconds(delayMs);
        if (command->mCond.waitRelative(command->mLock, timeOutNs) != NO_ERROR) {
            command->mStatus = TIMED_OUT;
            command->mWaitStatus = false;
        }
    }
    return command->mStatus;
}

这里唤醒了AudioCommandThread对应的线程,看它的threadloop实现,代码如下:

bool AudioPolicyService::AudioCommandThread::threadLoop()
{
    nsecs_t waitTime = INT64_MAX;
    mLock.lock();
    while (!exitPending())
    {
        sp<AudioPolicyService> svc;
        while (!mAudioCommands.isEmpty() && !exitPending()) {
            nsecs_t curTime = systemTime();
            // commands are sorted by increasing time stamp: execute them from index 0 and up
            if (mAudioCommands[0]->mTime <= curTime) {
                sp<AudioCommand> command = mAudioCommands[0];
                mAudioCommands.removeAt(0);
                mLastCommand = command;

                switch (command->mCommand) {
                //...
                //唤醒后开始处理SET_VOLUME命令
                case SET_VOLUME: {
                    VolumeData *data = (VolumeData *)command->mParam.get();
                    command->mStatus = AudioSystem::setStreamVolume(data->mStream,
                                                                    data->mVolume,
                                                                    data->mIO);
                    }break;
                //...
                default:
                    ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
                }
                {
                    Mutex::Autolock _l(command->mLock);
                    if (command->mWaitStatus) {
                        command->mWaitStatus = false;
                        command->mCond.signal();
                    }
                }
                waitTime = INT64_MAX;
            } else {
                waitTime = mAudioCommands[0]->mTime - curTime;
                break;
            }
        }
        mLock.unlock();
        svc.clear();
        mLock.lock();
        if (!exitPending() && mAudioCommands.isEmpty()) {
            // release delayed commands wake lock
            release_wake_lock(mName.string());
            //在这里等待,也在这里被唤醒
            mWaitWorkCV.waitRelative(mLock, waitTime);
        }
    }
    // release delayed commands wake lock before quitting
    if (!mAudioCommands.isEmpty()) {
        release_wake_lock(mName.string());
    }
    mLock.unlock();
    return false;
}

唤醒线程后这里调用了AudioSystem的setStreamVolume方法,代码实现如下:

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;
}

这里调用到了AudioFlinger的setStreamVolume,这个分析流程在Android Framework 音频子系统(13)音量调节之基础 分析过


4 总结流程

从音量键底层上报 到 输入子系统,再由输入子系统上报到音频子系统,由音频子系统进行处理:一般情况下,如果APP没有重写它的处理函数,音量键的处理将交给PhoneFallbackEventHandler来处理,这时会调AudioService.adjustSuggestedStreamVolume来调整"推荐的流"的音量,核心流程如下所示:

  1. 获得"推荐的流":stream = getActiveStreamType(...)
  2. 设置"推荐的流"的音量:设置同属一个alias的其他流的音量,对于不同的设备(电话、TV、平板), mStreamVolumeAlias指向不同的数组
  3. 设置流的音量:设置audioflinger和PlaybackThread中的数组:   mStreamTypes[stream].volume = value;

  

发布了291 篇原创文章 · 获赞 47 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/vviccc/article/details/105452442