• Android系统分析之Audio音频流, 音频策略, 输出设备之间的关系


    音频流, 音频策略, 输出设备之间的关系

    只针对 AudioManager.STREAM_VOICE_CALL 音频流类型进行分析

    涉及到的类:

    hardware/libhardware_legacy/audio/AudioPolicyManagerBase.cpp
    frameworks/base/media/java/android/media/AudioManager.java
    frameworks/base/media/java/android/media/AudioService.java
    frameworks/base/media/java/android/media/AudioSystem.java
    

    涉及到的方法及执行顺序:

    AudioPolicyManagerBase.getStrategy(AudioSystem::stream_type stream);
    AudioPolicyManagerBase.getDeviceForStrategy(routing_strategy strategy, bool fromCache);
    

    一. 通过音频流的类型获取对应的音频策略

    AudioPolicyManagerBase.cpp:
    
    AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy(AudioSystem::stream_type stream) {
        // stream to strategy mapping
        switch (stream) {
        case AudioSystem::VOICE_CALL:
        case AudioSystem::BLUETOOTH_SCO:
            return STRATEGY_PHONE;
        ...
        }
    }
    

    二. 通过音频策略获取到对应的输出设备

    AudioPolicyManagerBase.cpp:
    
    audio_devices_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy, bool fromCache) {
        uint32_t device = AUDIO_DEVICE_NONE;
        ... // 省略
        switch (strategy) {
        ... // 省略
        case STRATEGY_PHONE:
            // for phone strategy, we first consider the forced use and then the available devices by order
            // of priority
            switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) { // 判断是否有设置在通讯过程中, 强制使用某种输出设备
            case AudioSystem::FORCE_BT_SCO: // 强制使用蓝牙, 作为输出设备
                if (!isInCall() || strategy != STRATEGY_DTMF) {
                    device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
                    if (device) break;
                }
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
                if (device) break;
                // if SCO device is requested but no SCO device is available, fall back to default case
                // FALL THROUGH
    
            default:    // FORCE_NONE 没有设置通讯过程中, 强制使用某种输出设备
                // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
                if (mHasA2dp && !isInCall() &&
                        (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) &&
                        (getA2dpOutput() != 0) && !mA2dpSuspended) {
                    device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
                    if (device) break;
                    device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
                    if (device) break;
                }
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
                if (device) break;
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADSET;
                if (device) break;
                if (mPhoneState != AudioSystem::MODE_IN_CALL) {
                    device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
                    if (device) break;
                    device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
                    if (device) break;
                    device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
                    if (device) break;
                    device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
                    if (device) break;
                    device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
                    if (device) break;
                }
    			// 没有设置通讯过程中, 音频的输出设备, 则默认使用听筒作为输出设备
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_EARPIECE;
                if (device) break;
                device = mDefaultOutputDevice;
                if (device == AUDIO_DEVICE_NONE) {
                    ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE");
                }
                break;
    
            case AudioSystem::FORCE_SPEAKER: // 强制使用扬声器, 作为输出设备
                // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
                // A2DP speaker when forcing to speaker output
                if (mHasA2dp && !isInCall() &&
                        (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) &&
                        (getA2dpOutput() != 0) && !mA2dpSuspended) {
                    device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
                    if (device) break;
                }
                if (mPhoneState != AudioSystem::MODE_IN_CALL) {
                    device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
                    if (device) break;
                    device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
                    if (device) break;
                    device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
                    if (device) break;
                    device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
                    if (device) break;
                    device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
                    if (device) break;
                }
                device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_SPEAKER;
                if (device) break;
                device = mDefaultOutputDevice;
                if (device == AUDIO_DEVICE_NONE) {
                    ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER");
                }
                break;
            }
        break;
    	// 关于上面default位置的问题, 如果每个case选择(包括default)最终都有break语句, 则default的位置不影响执行顺序
    	// 当每个case选择(包括default)不一定有break语句时, 如果输入不满足其他选择, 最终执行default. 程序会从default处从上向下执行, 直到遇到break语句停止
    	// 此处的default位置并不影响执行顺序
    	... // 省略
        }
        return device;
    }
    

    三. 音频流, 音频策略, 输出设备之间的关系

    音频的流类型决定音频的策略, 音频的策略决定输出设备. 但是最终的输出设备的确定, 受强制设置输出设备影响.

    四. 分析AudioManager.setSpeakerphoneOn(boolean on)方法, 查看强制设置对音频输出设备选择的影响

    涉及到的类及方法:

    1. AudioManager.setSpeakerphoneOn(boolean on);
    2. AudioService.setSpeakerphoneOn(boolean on);
    3. AudioService.AudioHandler.setForceUse(int usage, int config);
    4. AudioSystem.setForceUse(int usage, int config);
    5. AudioPolicyManagerBase.setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config);
    
    4.1. AudioManager.java:
    public void setSpeakerphoneOn(boolean on){
        IAudioService service = getService();
        service.setSpeakerphoneOn(on);
    }
    
    4.2. AudioService.java:
    public void setSpeakerphoneOn(boolean on){
        if (on) {
            if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
                    sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
                            AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, null, 0);
            }
            mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
        } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){
            mForcedUseForComm = AudioSystem.FORCE_NONE;
        }
        // 从此处可以看到 setSpeakerphoneOn(boolean on) 只针对 AudioSystem.FOR_COMMUNICATION 有效
    	// 而 AudioSystem.FOR_COMMUNICATION 最终影响到的是输出设备的选择
        sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
                AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0);
    }
    
    private class AudioHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
    	    switch (msg.what) {
    		case MSG_SET_FORCE_USE:
            case MSG_SET_FORCE_BT_A2DP_USE:
                setForceUse(msg.arg1, msg.arg2);
                break;
    		}
    	}
        private void setForceUse(int usage, int config) {
            AudioSystem.setForceUse(usage, config);
        }    	
    }
    
    4.3. AudioSystem.java:
    public static native int setForceUse(int usage, int config);
    
    4.4. AudioPolicyManagerBase.cpp:
    void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config) {
        bool forceVolumeReeval = false;
        switch(usage) {
        case AudioSystem::FOR_COMMUNICATION:
            if (config != AudioSystem::FORCE_SPEAKER && config != AudioSystem::FORCE_BT_SCO &&
                config != AudioSystem::FORCE_NONE) {
                ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);
                return;
            }
            forceVolumeReeval = true;
    		// 保存设置到数组中, 最终在 getDeviceForStrategy(routing_strategy strategy, bool fromCache) 中被调用
            mForceUse[usage] = config;
            break;
        ... // 省略
        }
        ... // 省略
    }
  • 相关阅读:
    swift函数
    Swift数据类型
    swift的特点
    图片适配、九宫切图
    iOS中视图控制器的生命周期
    CocoaPods的安装与使用
    SQLite3的使用
    Pickers应用程序
    多视图应用
    OC对象的三大特性:封装、继承和 多态
  • 原文地址:https://www.cnblogs.com/firmly-believe/p/10991077.html
Copyright © 2020-2023  润新知