耳机插入上层处理流程分析

耳机插入上层处理流程分析

备注:本文主要分析 KERNEL以上的部分, KERNEL的处理见另外的文章。

1. WiredAccessoryManager

其构造函数中, NEW 了一个mObserver = new WiredAccessoryObserver(); 这个类继承自 UEventObserver, 当KERNEL 检测到耳机状态发生变化时,会回调此类的方法:

    @Override
    public void onUEvent(UEventObserver.UEvent event) {
        if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString());

        try {
            String devPath = event.get("DEVPATH");
            String name = event.get("SWITCH_NAME");
            int state = Integer.parseInt(event.get("SWITCH_STATE"));
            synchronized (mLock) {
                updateStateLocked(devPath, name, state);
            }
        } catch (NumberFormatException e) {
            Slog.e(TAG, "Could not parse switch state from event " + event);
        }
    }

——》

    private void updateStateLocked(String devPath, String name, int state) {
        for (int i = 0; i < mUEventInfo.size(); ++i) {
            UEventInfo uei = mUEventInfo.get(i);
            if (devPath.equals(uei.getDevPath())) {
                updateLocked(name, uei.computeNewHeadsetState(mHeadsetState, state));
                return;
            }
        }
    }

————-》

private void updateLocked(String newName, int newState) {
    // Retain only relevant bits
    int headsetState = newState & SUPPORTED_HEADSETS;
    int usb_headset_anlg = headsetState & BIT_USB_HEADSET_ANLG;
    int usb_headset_dgtl = headsetState & BIT_USB_HEADSET_DGTL;
    int h2w_headset = headsetState & (BIT_HEADSET | BIT_HEADSET_NO_MIC);
    boolean h2wStateChange = true;
    boolean usbStateChange = true;
    if (LOG) Slog.v(TAG, "newName=" + newName
            + " newState=" + newState
            + " headsetState=" + headsetState
            + " prev headsetState=" + mHeadsetState);

    if (mHeadsetState == headsetState) {
        Log.e(TAG, "No state change.");
        return;
    }

    // reject all suspect transitions: only accept state changes from:
    // - a: 0 headset to 1 headset
    // - b: 1 headset to 0 headset
    if (h2w_headset == (BIT_HEADSET | BIT_HEADSET_NO_MIC)) {
        Log.e(TAG, "Invalid combination, unsetting h2w flag");
        h2wStateChange = false;
    }
    // - c: 0 usb headset to 1 usb headset
    // - d: 1 usb headset to 0 usb headset
    if (usb_headset_anlg == BIT_USB_HEADSET_ANLG && usb_headset_dgtl == BIT_USB_HEADSET_DGTL) {
        Log.e(TAG, "Invalid combination, unsetting usb flag");
        usbStateChange = false;
    }
    if (!h2wStateChange && !usbStateChange) {
        Log.e(TAG, "invalid transition, returning ...");
        return;
    }

    mWakeLock.acquire();

    Message msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState,
            mHeadsetState, newName);   // 往HANDLER发消息
    mHandler.sendMessage(msg);

    mHeadsetState = headsetState;
}

———–》

private final Handler mHandler = new Handler(Looper.myLooper(), null, true) {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_NEW_DEVICE_STATE:
                setDevicesState(msg.arg1, msg.arg2, (String)msg.obj);
                mWakeLock.release();
        }
    }
};

——》

private void setDevicesState(
        int headsetState, int prevHeadsetState, String headsetName) {
    synchronized (mLock) {
        int allHeadsets = SUPPORTED_HEADSETS;
        for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) {
            if ((curHeadset & allHeadsets) != 0) {
                setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetName);
                allHeadsets &= ~curHeadset;
            }
        }
    }
}

———–》

private void setDeviceStateLocked(int headset,
        int headsetState, int prevHeadsetState, String headsetName) {
    if ((headsetState & headset) != (prevHeadsetState & headset)) {
        int device;
        int state;

        if ((headsetState & headset) != 0) {
            state = 1;
        } else {
            state = 0;
        }

        if (headset == BIT_HEADSET) {
            device = AudioManager.DEVICE_OUT_WIRED_HEADSET;
        } else if (headset == BIT_HEADSET_NO_MIC){
            device = AudioManager.DEVICE_OUT_WIRED_HEADPHONE;
        } else if (headset == BIT_USB_HEADSET_ANLG) {
            device = AudioManager.DEVICE_OUT_ANLG_DOCK_HEADSET;
        } else if (headset == BIT_USB_HEADSET_DGTL) {
            device = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET;
        } else if (headset == BIT_HDMI_AUDIO) {
            device = AudioManager.DEVICE_OUT_AUX_DIGITAL;
        } else {
            Slog.e(TAG, "setDeviceState() invalid headset type: "+headset);
            return;
        }

        if (LOG)
            Slog.v(TAG, "device "+headsetName+((state == 1) ? " connected" : " disconnected"));
        //ALPS00708321:add for AB=00->01, set device BIT_HEADSET will ingore and music will pause when plug in 
        // headset complete,so need delay to confirm set device BIT_HEADSET to Audio
        if(prevHeadsetState == BIT_HEADSET_NO_MIC && headsetState == BIT_HEADSET && state == 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // Ingore
            }
        }
        mAudioManager.setWiredDeviceConnectionState(device, state, headsetName); 
        // audio service 端处理

        illegal_state = getIllegalHeadset();
        if(49 == illegal_state) {
            mHandler.postDelayed(new Runnable(){
                public void run(){
                    illegal_state = getIllegalHeadset();
                        if(49 == illegal_state){
                            Slog.d(TAG, "show illegal Headset msg+++++++++++++");
                            showheadsetToast();
                            illegal_state = 0;
                        }else{
                            Slog.d(TAG, "don't show illegal Headset msg+++++++++++++");
                            illegal_state = 0;
                        }
                }
            },500);
        //illegal_state = 0;
        }
    }
}

audioservice 端处理

——–》

public void setWiredDeviceConnectionState(int device, int state, String name) {
    synchronized (mConnectedDevices) {
        int delay = checkSendBecomingNoisyIntent(device, state);
        queueMsgUnderWakeLock(mAudioHandler,
                MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
                device,
                state,
                name,
                delay);
    }
}

—————》

case MSG_SET_WIRED_DEVICE_CONNECTION_STATE:
                onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj);
                mAudioEventWakeLock.release();
                break;

—————–》

private void onSetWiredDeviceConnectionState(int device, int state, String name)
{
    synchronized (mConnectedDevices) {
    Log.d(TAG,"onSetWiredDeviceConnectionState:" + "device:" + device + ",state:" + state);
        /**
         * M: do not broadcast if headset is connected for ALPS00850163 @{
         */
        boolean shouldNotify = true;
        if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
                (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) {
            /// M: safe media @{
            mHeadsetOrHeadphoneOn = false;
            /// @}
            /**
             * M: do not setForceUse if headset is connected for 
             * ALPS00657344 @{
             */
            boolean isHeadphoneOff = (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
            boolean isHeadsetOn = mConnectedDevices
                    .containsKey(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
            if (isHeadphoneOff && isHeadsetOn) {
                shouldNotify = false;
                Log.d(TAG, "onSetWiredDeviceConnectionState() no need to setForceUse");
            }
            if (shouldNotify) {
                setBluetoothA2dpOnInt(true);
            }
            /** @} */
        }
        boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0);
        handleDeviceConnection((state == 1), device, (isUsb ? name : "")); 重点在这里
        if (state != 0) {
            if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
                (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE)) {
                /// M: safe media @{
                mHeadsetOrHeadphoneOn = true;
                /// @}
                setBluetoothA2dpOnInt(false);
            }
        }
        if (!isUsb) {
            sendDeviceConnectionIntent(device, state, name, shouldNotify);
        }

———————-》

private boolean handleDeviceConnection(boolean connected, int device, String params) {
    synchronized (mConnectedDevices) {
        boolean isConnected = (mConnectedDevices.containsKey(device) &&
                (params.isEmpty() || mConnectedDevices.get(device).equals(params)));
        Log.d(TAG,"handleDeviceConnection:isConnected" + isConnected);

        if (isConnected && !connected) {
            AudioSystem.setDeviceConnectionState(device,
                                          AudioSystem.DEVICE_STATE_UNAVAILABLE,
                                          mConnectedDevices.get(device));
            Log.d(TAG, "handleDeviceConnection remove:" + "connected:" + connected + ",device:"
                    + device);
            mConnectedDevices.remove(device);
            return true;
        } else if (!isConnected && connected) {
            /// M: if mhl is connecting to smartbook,we pass Params_SmartBook to native
            AudioSystem.setDeviceConnectionState(device,   AudioSystem.DEVICE_STATE_AVAILABLE,
                    (device == AudioSystem.DEVICE_OUT_AUX_DIGITAL && whetherSmartBookConnected()) ? Params_SmartBook
                            : params);
            Log.d(TAG, "handleDeviceConnection connect:" + "connected:" + connected
                    + ",device:" + device);
            mConnectedDevices.put(new Integer(device), params);
            return true;
        }
    }
    return false;
}

native service 大概流程分析

————–>

audiosystem.cpp

status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,
                                           audio_policy_dev_state_t state,
                                           const char *device_address)
{
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    const char *address = "";

    if (aps == 0) return PERMISSION_DENIED;

    if (device_address != NULL) {
        address = device_address;
    }

    return aps->setDeviceConnectionState(device, state, address);
}

——–> AudioMTKPolicyManager.cpp

status_t AudioMTKPolicyManager::setDeviceConnectionState(audio_devices_t device,
                                                     AudioSystem::device_connection_state state,
                                                     const char *device_address)
{


        case AudioSystem::DEVICE_STATE_AVAILABLE:
            // register new device as available, 将新设备的标志置位
            mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices | device);
        。。。。。

    checkOutputForAllStrategies();  // 根据策略
    // outputs must be closed after checkOutputForAllStrategies() is executed
    updateDevicesAndOutputs();  设备状态发生了变化,更新每个策略下目前应该对应的输出设备

    for (size_t i = 0; i < mOutputs.size(); i++)
    {
        // do not force device change on duplicated output because if device is 0, it will
        // also force a device 0 for the two outputs it is duplicated to which may override
        // a valid device selection on those outputs.
        setOutputDevice(mOutputs.keyAt(i),
                        getNewDevice(mOutputs.keyAt(i), true /*fromCache*/),
                        !mOutputs.valueAt(i)->isDuplicated(),
                        0);  这个地方传进去的参数是 TRUE, 用上面更新过的策略对应的设备。
    }

此方法后面还有 AUDIO INPUT 对应的处理, 我们假设是3段耳机插入, 略去。

——–》

uint32_t AudioMTKPolicyManager::setOutputDevice(audio_io_handle_t output,
                                            audio_devices_t device,
                                            bool force,
                                            int delayMs)
{
    路由,  mpClientInterface实际上是 audiopolicyservice. 
    param.addInt(String8(AudioParameter::keyRouting), (int)device);
    mpClientInterface->setParameters(output, param.toString(), delayMs);

    设置音量
    applyStreamVolumes(output, device, delayMs);
    实际上 后期 applyStreamVolumes也是调用audiopolicyservice的方法来处理: mpClientInterface->setStreamVolume(AudioSystem::VOICE_CALL, volume, output, delayMs);

}

—————》

void AudioPolicyService::setParameters(audio_io_handle_t ioHandle,
                                   const char *keyValuePairs,
                                   int delayMs)
{
    mAudioCommandThread->parametersCommand(ioHandle, keyValuePairs,
                                           delayMs);
}

mAudioCommandThread 是在 AudioPolicyService 构造函数中 NEW的

————————–》

status_t AudioPolicyService::AudioCommandThread::parametersCommand(audio_io_handle_t ioHandle,
                                                               const char *keyValuePairs,
                                                               int delayMs)
{
    status_t status = NO_ERROR;

    AudioCommand *command = new AudioCommand();
    command->mCommand = SET_PARAMETERS;
    ParametersData *data = new ParametersData();
    data->mIO = ioHandle;
    data->mKeyValuePairs = String8(keyValuePairs);
    command->mParam = data;
#ifdef MTK_AUDIO
    Mutex::Autolock _t(mFunLock); //must get funlock;
#endif
    Mutex::Autolock _l(mLock);
    insertCommand_l(command, delayMs);
 // 将新的命令插入一个序列容器中, 容器定义:Vector <AudioCommand *> mAudioCommands; // list of pending commands
    ALOGD("AudioCommandThread() adding set parameter string %s, io %d ,delay %d",
            keyValuePairs, ioHandle, delayMs);
    mWaitWorkCV.signal();  // 唤醒 AudioCommandThread 线程, 开始处理命名
    if (command->mWaitStatus) {
        command->mCond.wait(mLock);
        status =  command->mStatus;
        command->mCond.signal();   
    }
    return status;
}

——————》

case SET_PARAMETERS: {
                ParametersData *data = (ParametersData *)command->mParam;
                ALOGV("AudioCommandThread() processing set parameters string %s, io %d",
                        data->mKeyValuePairs.string(), data->mIO);

                 AudioParameter param = AudioParameter(data->mKeyValuePairs);
                 float value = 0.0;
                 // use setmastervolume instead of setparameter
                 if((param.getFloat (String8("SetMasterVolume"), value)) == NO_ERROR){
                     MTK_ALOG_D("SET_PARAMETERS SetMasterVolume value = %f",value);
                     AudioSystem::setMasterVolume (value);
                 }
                 else{  又到 AudioSystem 中,
                      command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
                 }

—————》

status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)

{
    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
    if (af == 0) return PERMISSION_DENIED;
    ret = af->setParameters(ioHandle, keyValuePairs);
}

———–》

status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
{
    sp<ThreadBase> thread;
    {
        Mutex::Autolock _l(mLock);
        thread = checkPlaybackThread_l(ioHandle);
        if (thread == 0) {
            thread = checkRecordThread_l(ioHandle);
        } else if (thread == primaryPlaybackThread_l()) {
            // indicate output device change to all input threads for pre processing
            AudioParameter param = AudioParameter(keyValuePairs);
            int value;
            if ((param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) &&
                    (value != 0)) {
                for (size_t i = 0; i < mRecordThreads.size(); i++) {
                    mRecordThreads.valueAt(i)->setParameters(keyValuePairs);
                }
            }
        }
    }
    if (thread != 0) {
        return thread->setParameters(keyValuePairs);
    }
}

—–》

status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
{
    status_t status;

    ALOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
    Mutex::Autolock _l(mLock);

    mNewParameters.add(keyValuePairs);
    mWaitWorkCV.signal();
    // wait condition with timeout in case the thread loop has exited
    // before the request could be processed
    if (mParamCond.waitRelative(mLock, kSetParametersTimeoutNs) == NO_ERROR) {
        status = mParamStatus;
        mWaitWorkCV.signal();
    } else {
        status = TIMED_OUT;
    }
    return status;
}

——–》

bool AudioFlinger::PlaybackThread::threadLoop()
{
    在while loop 在有以下处理
    if (checkForNewParameters_l()) {
            cacheParameters_l();
      }
}

———》

bool AudioFlinger::MixerThread::checkForNewParameters_l()
{
    status = mOutput->stream->common.set_parameters(&mOutput->stream->common,keyValuePair.string());
}
mOutput 就对应到 AUDIO HAL 层设置路由

HAL层路由分析

—》 Audio_hw_hal.cpp (doov6732kk_pra\mediatek\platform\common\hardware\audio\policy_driver): out->stream.common.set_parameters = out_set_parameters; 我们只分析 STREAM OUT, 对于STREAM IN, 也是差不多。

static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
{
        struct legacy_stream_out *out =
            reinterpret_cast<struct legacy_stream_out *>(stream);
    int val;
    String8 s8 = String8(kvpairs);
    AudioParameter parms = AudioParameter(String8(kvpairs));

    /*
    if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
        val = convert_audio_device(val, HAL_API_REV_2_0, HAL_API_REV_1_0);
        parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
        parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
        s8 = parms.toString();
    }
    */

    return out->legacy_out->setParameters(s8);
}

———》

status_t AudioALSAStreamOut::setParameters(const String8 &keyValuePairs)
{

    /// routing
    if (param.getInt(keyRouting, value) == NO_ERROR)
    {
        param.remove(keyRouting);

        mydevice = static_cast<audio_devices_t>(value);
        ALOGD("%s(), mydevice 0x%x", __FUNCTION__, mydevice);

        AudioAutoTimeoutLock _l(mLock);
        if (mStreamOutType == STREAM_OUT_PRIMARY)
        {
            mStreamManager 的方法 routingOutputDevice 来设置硬件路由
            status = mStreamManager->routingOutputDevice(mStreamAttributeSource.output_devices, static_cast<audio_devices_t>(value));
        }
        else if ((mStreamOutType == STREAM_OUT_HDMI_STEREO) || (mStreamOutType == STREAM_OUT_HDMI_MULTI_CHANNEL))
        {
            ALOGD("%s(), HDMI  \"%s\"", __FUNCTION__, param.toString().string());
            status = mStreamManager->routingOutputDevice(mStreamAttributeSource.output_devices, static_cast<audio_devices_t>(value));
        }
        else
        {
            ALOGW("%s(), NUM_STREAM_OUT_TYPE \"%s\"", __FUNCTION__, param.toString().string());
            status = INVALID_OPERATION;
        }

    }

    。。。。
}

————–》

status_t AudioALSAStreamManager::routingOutputDevice(const audio_devices_t current_output_devices, audio_devices_t output_devices)
{
    for (size_t i = 0; i < mStreamOutVector.size(); i++)
        {
            if (mStreamOutVector[i]->getStreamAttribute()->output_devices == current_output_devices) // TODO(Harvey): or add group?
            {
                status = mStreamOutVector[i]->routing(output_devices);  AudioALSAStreamOut的方法 routing
                ASSERT(status == NO_ERROR); 
            }
        }
}

————————————》

status_t AudioALSAStreamOut::routing(audio_devices_t output_devices)
{

    if (mStandby == false)
    {
        ASSERT(output_devices != mStreamAttributeSource.output_devices); // TODO(Harvey): Could remove it after stress test

        ASSERT(mPlaybackHandler != NULL);
        //status = mPlaybackHandler->routing(output_devices);
        //if (status != NO_ERROR)

        if(mPlaybackHandler->getPlaybackHandlerType() == PLAYBACK_HANDLER_OFFLOAD)
        {
            status = pause();
            AudioALSAHardwareResourceManager::getInstance()->stopOutputDevice();  先STOP 
        }
        else
        {
            status = close();
        }
    }

    mStreamAttributeSource.output_devices = output_devices;

    if(mPaused == true)
    {
        if(mPlaybackHandler->getPlaybackHandlerType() == PLAYBACK_HANDLER_OFFLOAD)
        {
            const stream_attribute_t *StreamAttributeTarget = mPlaybackHandler->getStreamAttributeTarget();
            AudioALSAHardwareResourceManager::getInstance()->startOutputDevice(mStreamAttributeSource.output_devices, StreamAttributeTarget->sample_rate); 再start 
            status = resume();
        }
    }

    if (is_lock_in_this_function == true)
    {
        mLock.unlock();
    }

}

AudioALSAHardwareResourceManager 直接通过tiny alsa库调到KERNEL 去了。 KERNEL的东西就不分析了。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值