1. 程式人生 > >音訊策略配置檔案分析

音訊策略配置檔案分析

<globalConfiguration speaker_drc_enabled="true"/>
<modules>
    <!-- Primary Audio HAL -->
    <module name="primary" halVersion="2.0">
        <attachedDevices>
            <item>Earpiece</item>
            <item>Speaker</item>
            <item>Built-In Mic</item>
            <item>Built-In Back Mic</item>
            <item>FM Tuner</item>
            <item>In Call-Voice</item>
        </attachedDevices>
        <defaultOutputDevice>Speaker</defaultOutputDevice>
        <mixPorts>
            <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
            </mixPort>
            <mixPort name="low_latency" role="source" flags="AUDIO_OUTPUT_FLAG_FAST">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="44100,48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
            </mixPort>
            <mixPort name="compressed_offload" role="source"
                     flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">
                <profile name="" format="AUDIO_FORMAT_MP3"
                         samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
                         channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
                <profile name="" format="AUDIO_FORMAT_AAC_LC"
                         samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
                         channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
                <profile name="" format="AUDIO_FORMAT_AAC_HE_V1"
                         samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
                         channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
                <profile name="" format="AUDIO_FORMAT_AAC_HE_V2"
                         samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,64000,88200,96000"
                         channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
            </mixPort>
            <mixPort name="voip_rx" role="source"
                     flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_VOIP_RX">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
                <profile name="" format="AUDIO_FORMAT_AMR_NB"
                         samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
                <profile name="" format="AUDIO_FORMAT_AMR_WB"
                         samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
                <profile name="" format="AUDIO_FORMAT_QCELP"
                         samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
                <profile name="" format="AUDIO_FORMAT_EVRC"
                         samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
                <profile name="" format="AUDIO_FORMAT_EVRCB"
                         samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
                <profile name="" format="AUDIO_FORMAT_EVRCWB"
                         samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
                <profile name="" format="AUDIO_FORMAT_EVRCNW"
                         samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
            </mixPort>
            <mixPort name="primary input" role="sink">
                 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
                         channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
                <profile name="" format="AUDIO_FORMAT_AMR_NB"
                         samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
                         channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
                <profile name="" format="AUDIO_FORMAT_AMR_WB"
                         samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
                         channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
                <profile name="" format="AUDIO_FORMAT_QCELP"
                         samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
                         channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
                <profile name="" format="AUDIO_FORMAT_EVRC"
                         samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
                         channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
                <profile name="" format="AUDIO_FORMAT_EVRCB"
                         samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
                         channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
                <profile name="" format="AUDIO_FORMAT_EVRCWB"
                         samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
                         channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
                <profile name="" format="AUDIO_FORMAT_EVRCNW"
                         samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
                         channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
            </mixPort>
        </mixPorts>

        <devicePorts>
            <!-- Output devices declaration, i.e. Sink DEVICE PORT -->
            <devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">
               <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                        samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
            </devicePort>
            <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address="">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
            </devicePort>
            <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
            </devicePort>
            <devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
            </devicePort>
            <devicePort tagName="Line" type="AUDIO_DEVICE_OUT_LINE" role="sink">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
            </devicePort>
            <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
            </devicePort>
            <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
            </devicePort>
            <devicePort tagName="BT SCO Car Kit" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT" role="sink">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
            </devicePort>
            <devicePort tagName="BT SCO All" type="AUDIO_DEVICE_OUT_ALL_SCO" role="sink">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
            </devicePort>
            <devicePort tagName="Proxy" type="AUDIO_DEVICE_OUT_PROXY" role="sink">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="8000,11025,16000,22050,32000,44100,48000,
                         64000,88200,96000,128000,176400,192000" channelMasks="dynamic"/>
            </devicePort>
            <devicePort tagName="FM" type="AUDIO_DEVICE_OUT_FM" role="sink">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>
            </devicePort>

            <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
                         channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
            </devicePort>
            <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
                         channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
            </devicePort>
            <devicePort tagName="In Call-Voice" type="AUDIO_DEVICE_IN_VOICE_CALL" role="source">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT,AUDIO_FORMAT_AMR_NB,AUDIO_FORMAT_AMR_WB,AUDIO_FORMAT_QCELP,
                         AUDIO_FORMAT_EVRC,AUDIO_FORMAT_EVRCB,AUDIO_FORMAT_EVRCWB,AUDIO_FORMAT_EVRCNW"
                         samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
                         channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
            </devicePort>
            <devicePort tagName="FM Tuner" type="AUDIO_DEVICE_IN_FM_TUNER" role="source">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="48000"
                         channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
            </devicePort>
            <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
                         channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
            </devicePort>
            <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source">
                <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                         samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
            </devicePort>
        </devicePorts>
        <!-- route declaration, i.e. list all available sources for a given sink -->
        <routes>
            <route type="mix" sink="Earpiece"
                   sources="primary output,low_latency,compressed_offload,voip_rx,BT SCO Headset Mic"/>
            <route type="mix" sink="Speaker"
                   sources="primary output,low_latency,compressed_offload,voip_rx,BT SCO Headset Mic"/>
            <route type="mix" sink="Wired Headset"
                   sources="primary output,low_latency,compressed_offload,voip_rx,BT SCO Headset Mic"/>
            <route type="mix" sink="Wired Headphones"
                   sources="primary output,low_latency,compressed_offload,voip_rx,BT SCO Headset Mic"/>
            <route type="mix" sink="Line"
                   sources="primary output,low_latency,compressed_offload,voip_rx"/>
            <route type="mix" sink="Proxy"
                   sources="primary output,low_latency,compressed_offload"/>
            <route type="mix" sink="FM"
                   sources="primary output"/>
            <route type="mix" sink="BT SCO All"
                   sources="primary output,low_latency,compressed_offload,voip_rx"/>
            <route type="mix" sink="primary input"
                   sources="Built-In Mic,Wired Headset Mic,BT SCO Headset Mic,Built-In Back Mic,
                   FM Tuner,In Call-Voice"/>
        </routes>

    </module>

</modules>

Primary模組支援的輸出裝置按位與0x212007F

    AUDIO_DEVICE_OUT_EARPIECE                  = 0x1,
    AUDIO_DEVICE_OUT_SPEAKER                   = 0x2,
    AUDIO_DEVICE_OUT_WIRED_HEADSET             = 0x4,
    AUDIO_DEVICE_OUT_WIRED_HEADPHONE           = 0x8,
    AUDIO_DEVICE_OUT_BLUETOOTH_SCO             = 0x10,
    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET     = 0x20
, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40, AUDIO_DEVICE_OUT_ALL_SCO = 0x70 AUDIO_DEVICE_OUT_LINE = 0x20000, AUDIO_DEVICE_OUT_FM = 0x100000, AUDIO_DEVICE_OUT_PROXY = 0x2000000,

Primary模組支援的輸入裝置按位與0x800020DC

    AUDIO_DEVICE_BIT_IN                   = 0x80000000
, AUDIO_DEVICE_IN_BUILTIN_MIC = AUDIO_DEVICE_BIT_IN | 0x4, AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = AUDIO_DEVICE_BIT_IN | 0x8, AUDIO_DEVICE_IN_WIRED_HEADSET = AUDIO_DEVICE_BIT_IN | 0x10, AUDIO_DEVICE_IN_VOICE_CALL = AUDIO_DEVICE_BIT_IN | 0x40, AUDIO_DEVICE_IN_BACK_MIC = AUDIO_DEVICE_BIT_IN | 0x80, AUDIO_DEVICE_IN_FM_TUNER = AUDIO_DEVICE_BIT_IN | 0x2000,

預設模組
HW module primary, output profiles 4, input profiles 1
output devices 0x212007f, name primary output, avaiable 0x3 //支援所有輸出裝置
output devices 0x202007f, name low_latency, avaiable 0x3 //不支援AUDIO_DEVICE_OUT_FM
output devices 0x202007f, name compressed_offload, avaiable 0x3 //不支援AUDIO_DEVICE_OUT_FM
output devices 0x2007f, name voip_rx, avaiable 0x3 //不支援AUDIO_DEVICE_OUT_PROXY和AUDIO_DEVICE_OUT_FM
input devices 0x800020dc, name primary input, availabe 0x21c4 //支援所有輸入裝置

每個profile是否支援某種裝置取決於兩個方面:
一是必須有定義該裝置的devicePort宣告;
二是必須有該mixPort到devicePort的路由;

如name為low_latency的profile不支援裝置AUDIO_DEVICE_OUT_FM,其原因是因為沒有low_latency到AUDIO_DEVICE_OUT_FM的路由,系統只有primary output到AUDIO_DEVICE_OUT_FM的路由。

//定義輸出流
<mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
         samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
//定義輸出裝置
<devicePort tagName="FM" type="AUDIO_DEVICE_OUT_FM" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
         samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO"/>
</devicePort>
//定義輸出流的輸出裝置的路由
<route type="mix" sink="FM" sources="primary output"/>

藍芽模組
HW module a2dp, output profiles 1, input profiles 1
output devices 0x380, name a2dp output, avaiable 0x3
input devices 0x80020000, name a2dp input, availabe 0x21c4

USB模組
HW module usb, output profiles 2, input profiles 1
output devices 0x2000, name usb_accessory output, avaiable 0x3
output devices 0x4000, name usb_device output, avaiable 0x3
input devices 0x80001000, name usb_device input, availabe 0x21c4

通過audio_policy_configuration.xml檔案初始化輸入輸出系統。

AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
    mUidCached = getuid();
    mpClientInterface = clientInterface;
    bool speakerDrcEnabled = false;
    mVolumeCurves = new VolumeCurvesCollection();
    AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
                             mDefaultOutputDevice, speakerDrcEnabled,
                             static_cast<VolumeCurvesCollection *>(mVolumeCurves));
    PolicySerializer serializer;
    if (serializer.deserialize(AUDIO_POLICY_XML_CONFIG_FILE, config) != NO_ERROR) {
        ALOGE("could not load audio policy configuration file, setting defaults");
        config.setDefault();
    }
    // must be done after reading the policy (since conditionned by Speaker Drc Enabling)
    mVolumeCurves->initializeVolumeCurves(speakerDrcEnabled);
    // Once policy config has been parsed, retrieve an instance of the engine and initialize it.
    audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance();
    // Retrieve the Policy Manager Interface
    mEngine = engineInstance->queryInterface<AudioPolicyManagerInterface>();
    mEngine->setObserver(this);
    status_t status = mEngine->initCheck();
    (void) status;

    audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types();
    audio_devices_t inputDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
    // 依次載入 HwModule 並開啟其所含 profile 的 outputStream 及 inputStream
    for (size_t i = 0; i < mHwModules.size(); i++) {
        mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->getName());
        if (mHwModules[i]->mHandle == 0) {
            ALOGW("could not open HW module %s", mHwModules[i]->getName());
            continue;
        }
        //開啟所有可用的輸出裝置
        for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
        {
            const sp<IOProfile> outProfile = mHwModules[i]->mOutputProfiles[j];

            if (!outProfile->hasSupportedDevices()) {
                ALOGW("Output profile contains no device on module %s", mHwModules[i]->getName());
                continue;
            }
            if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_TTS) != 0) {
                mTtsOutputAvailable = true;
            }
            //不開啟direct型別的輸出裝置
            if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
                continue;
            }
            audio_devices_t profileType = outProfile->getSupportedDevicesType();
            if ((profileType & mDefaultOutputDevice->type()) != AUDIO_DEVICE_NONE) {
                //使用預設輸出裝置speaker
                profileType = mDefaultOutputDevice->type();
            } else {
                //返回第一個匹配的裝置
                profileType = outProfile->getSupportedDeviceForType(outputDeviceTypes);
            }
            if ((profileType & outputDeviceTypes) == 0) {
                continue;
            }
            sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,
                                                                                 mpClientInterface);
            const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
            const DeviceVector &devicesForType = supportedDevices.getDevicesFromType(profileType);
            String8 address = devicesForType.size() > 0 ? devicesForType.itemAt(0)->mAddress
                    : String8("");

            outputDesc->mDevice = profileType;
            audio_config_t config = AUDIO_CONFIG_INITIALIZER;
            config.sample_rate = outputDesc->mSamplingRate;
            config.channel_mask = outputDesc->mChannelMask;
            config.format = outputDesc->mFormat;
            audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
            status_t status = mpClientInterface->openOutput(outProfile->getModuleHandle(),
                                                            &output,
                                                            &config,
                                                            &outputDesc->mDevice,
                                                            address,
                                                            &outputDesc->mLatency,
                                                            outputDesc->mFlags);

            if (status != NO_ERROR) {
                ALOGW("Cannot open output stream for device %08x on hw module %s",
                      outputDesc->mDevice,
                      mHwModules[i]->getName());
            } else {
                outputDesc->mSamplingRate = config.sample_rate;
                outputDesc->mChannelMask = config.channel_mask;
                outputDesc->mFormat = config.format;

                for (size_t k = 0; k  < supportedDevices.size(); k++) {
                    ssize_t index = mAvailableOutputDevices.indexOf(supportedDevices[k]);
                    // give a valid ID to an attached device once confirmed it is reachable
                    if (index >= 0 && !mAvailableOutputDevices[index]->isAttached()) {
                        mAvailableOutputDevices[index]->attach(mHwModules[i]);
                    }
                }
                if (mPrimaryOutput == 0 &&
                        outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
                    mPrimaryOutput = outputDesc;
                }
                addOutput(output, outputDesc);
                setOutputDevice(outputDesc,
                                outputDesc->mDevice,
                                true,
                                0,
                                NULL,
                                address.string());
            }
        }
        //開啟所有可用的輸入裝置
        for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++)
        {
            const sp<IOProfile> inProfile = mHwModules[i]->mInputProfiles[j];

            if (!inProfile->hasSupportedDevices()) {
                ALOGW("Input profile contains no device on module %s", mHwModules[i]->getName());
                continue;
            }
            //返回第一個匹配的輸入裝置
            audio_devices_t profileType = inProfile->getSupportedDeviceForType(inputDeviceTypes);
           if ((profileType & inputDeviceTypes) == 0) {
                continue;
            }
            sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(inProfile);
            inputDesc->mDevice = profileType;

            // find the address
            DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromType(profileType);
            //   the inputs vector must be of size 1, but we don't want to crash here
            String8 address = inputDevices.size() > 0 ? inputDevices.itemAt(0)->mAddress : String8("");

            audio_config_t config = AUDIO_CONFIG_INITIALIZER;
            config.sample_rate = inputDesc->mSamplingRate;
            config.channel_mask = inputDesc->mChannelMask;
            config.format = inputDesc->mFormat;
            audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
            status_t status = mpClientInterface->openInput(inProfile->getModuleHandle(),
                                                           &input,
                                                           &config,
                                                           &inputDesc->mDevice,
                                                           address,
                                                           AUDIO_SOURCE_MIC,
                                                           AUDIO_INPUT_FLAG_NONE);

            if (status == NO_ERROR) {
                const DeviceVector &supportedDevices = inProfile->getSupportedDevices();
                for (size_t k = 0; k  < supportedDevices.size(); k++) {
                    ssize_t index =  mAvailableInputDevices.indexOf(supportedDevices[k]);
                    // give a valid ID to an attached device once confirmed it is reachable
                    if (index >= 0) {
                        sp<DeviceDescriptor> devDesc = mAvailableInputDevices[index];
                        if (!devDesc->isAttached()) {
                            devDesc->attach(mHwModules[i]);
                            devDesc->importAudioPort(inProfile);
                        }
                    }
                }
                mpClientInterface->closeInput(input);
            } else {
                ALOGW("Cannot open input stream for device %08x on hw module %s",
                      inputDesc->mDevice,
                      mHwModules[i]->getName());
            }
        }
    }
    // make sure all attached devices have been allocated a unique ID
    for (size_t i = 0; i  < mAvailableOutputDevices.size();) {
        if (!mAvailableOutputDevices[i]->isAttached()) {
            ALOGW("Output device %08x unreachable", mAvailableOutputDevices[i]->type());
            mAvailableOutputDevices.remove(mAvailableOutputDevices[i]);
            continue;
        }
        // The device is now validated and can be appended to the available devices of the engine
        mEngine->setDeviceConnectionState(mAvailableOutputDevices[i],
                                          AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
        i++;
    }
    for (size_t i = 0; i  < mAvailableInputDevices.size();) {
        if (!mAvailableInputDevices[i]->isAttached()) {
            ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->type());
            mAvailableInputDevices.remove(mAvailableInputDevices[i]);
            continue;
        }
        // The device is now validated and can be appended to the available devices of the engine
        mEngine->setDeviceConnectionState(mAvailableInputDevices[i],
                                          AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
        i++;
    }
    // make sure default device is reachable
    if (mDefaultOutputDevice == 0 || mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) {
        ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->type());
    }
    updateDevicesAndOutputs();
}