diff options
Diffstat (limited to 'libs/audioflinger/AudioPolicyManagerBase.cpp')
| -rw-r--r-- | libs/audioflinger/AudioPolicyManagerBase.cpp | 1972 | 
1 files changed, 0 insertions, 1972 deletions
| diff --git a/libs/audioflinger/AudioPolicyManagerBase.cpp b/libs/audioflinger/AudioPolicyManagerBase.cpp deleted file mode 100644 index c8b3f487a02c..000000000000 --- a/libs/audioflinger/AudioPolicyManagerBase.cpp +++ /dev/null @@ -1,1972 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - *      http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "AudioPolicyManagerBase" -//#define LOG_NDEBUG 0 -#include <utils/Log.h> -#include <hardware_legacy/AudioPolicyManagerBase.h> -#include <media/mediarecorder.h> - -namespace android { - - -// ---------------------------------------------------------------------------- -// AudioPolicyInterface implementation -// ---------------------------------------------------------------------------- - - -status_t AudioPolicyManagerBase::setDeviceConnectionState(AudioSystem::audio_devices device, -                                                  AudioSystem::device_connection_state state, -                                                  const char *device_address) -{ - -    LOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address); - -    // connect/disconnect only 1 device at a time -    if (AudioSystem::popCount(device) != 1) return BAD_VALUE; - -    if (strlen(device_address) >= MAX_DEVICE_ADDRESS_LEN) { -        LOGE("setDeviceConnectionState() invalid address: %s", device_address); -        return BAD_VALUE; -    } - -    // handle output devices -    if (AudioSystem::isOutputDevice(device)) { - -#ifndef WITH_A2DP -        if (AudioSystem::isA2dpDevice(device)) { -            LOGE("setDeviceConnectionState() invalid device: %x", device); -            return BAD_VALUE; -        } -#endif - -        switch (state) -        { -        // handle output device connection -        case AudioSystem::DEVICE_STATE_AVAILABLE: -            if (mAvailableOutputDevices & device) { -                LOGW("setDeviceConnectionState() device already connected: %x", device); -                return INVALID_OPERATION; -            } -            LOGV("setDeviceConnectionState() connecting device %x", device); - -            // register new device as available -            mAvailableOutputDevices |= device; - -#ifdef WITH_A2DP -            // handle A2DP device connection -            if (AudioSystem::isA2dpDevice(device)) { -                status_t status = handleA2dpConnection(device, device_address); -                if (status != NO_ERROR) { -                    mAvailableOutputDevices &= ~device; -                    return status; -                } -            } else -#endif -            { -                if (AudioSystem::isBluetoothScoDevice(device)) { -                    LOGV("setDeviceConnectionState() BT SCO  device, address %s", device_address); -                    // keep track of SCO device address -                    mScoDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN); -#ifdef WITH_A2DP -                    if (mA2dpOutput != 0 && -                        mPhoneState != AudioSystem::MODE_NORMAL) { -                        mpClientInterface->suspendOutput(mA2dpOutput); -                    } -#endif -                } -            } -            break; -        // handle output device disconnection -        case AudioSystem::DEVICE_STATE_UNAVAILABLE: { -            if (!(mAvailableOutputDevices & device)) { -                LOGW("setDeviceConnectionState() device not connected: %x", device); -                return INVALID_OPERATION; -            } - - -            LOGV("setDeviceConnectionState() disconnecting device %x", device); -            // remove device from available output devices -            mAvailableOutputDevices &= ~device; - -#ifdef WITH_A2DP -            // handle A2DP device disconnection -            if (AudioSystem::isA2dpDevice(device)) { -                status_t status = handleA2dpDisconnection(device, device_address); -                if (status != NO_ERROR) { -                    mAvailableOutputDevices |= device; -                    return status; -                } -            } else -#endif -            { -                if (AudioSystem::isBluetoothScoDevice(device)) { -                    mScoDeviceAddress = ""; -#ifdef WITH_A2DP -                    if (mA2dpOutput != 0 && -                        mPhoneState != AudioSystem::MODE_NORMAL) { -                        mpClientInterface->restoreOutput(mA2dpOutput); -                    } -#endif -                } -            } -            } break; - -        default: -            LOGE("setDeviceConnectionState() invalid state: %x", state); -            return BAD_VALUE; -        } - -        // request routing change if necessary -        uint32_t newDevice = getNewDevice(mHardwareOutput, false); -#ifdef WITH_A2DP -        checkOutputForAllStrategies(newDevice); -        // A2DP outputs must be closed after checkOutputForAllStrategies() is executed -        if (state == AudioSystem::DEVICE_STATE_UNAVAILABLE && AudioSystem::isA2dpDevice(device)) { -            closeA2dpOutputs(); -        } -#endif -        updateDeviceForStrategy(); -        setOutputDevice(mHardwareOutput, newDevice); - -        if (device == AudioSystem::DEVICE_OUT_WIRED_HEADSET) { -            device = AudioSystem::DEVICE_IN_WIRED_HEADSET; -        } else if (device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO || -                   device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET || -                   device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) { -            device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET; -        } else { -            return NO_ERROR; -        } -    } -    // handle input devices -    if (AudioSystem::isInputDevice(device)) { - -        switch (state) -        { -        // handle input device connection -        case AudioSystem::DEVICE_STATE_AVAILABLE: { -            if (mAvailableInputDevices & device) { -                LOGW("setDeviceConnectionState() device already connected: %d", device); -                return INVALID_OPERATION; -            } -            mAvailableInputDevices |= device; -            } -            break; - -        // handle input device disconnection -        case AudioSystem::DEVICE_STATE_UNAVAILABLE: { -            if (!(mAvailableInputDevices & device)) { -                LOGW("setDeviceConnectionState() device not connected: %d", device); -                return INVALID_OPERATION; -            } -            mAvailableInputDevices &= ~device; -            } break; - -        default: -            LOGE("setDeviceConnectionState() invalid state: %x", state); -            return BAD_VALUE; -        } - -        audio_io_handle_t activeInput = getActiveInput(); -        if (activeInput != 0) { -            AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput); -            uint32_t newDevice = getDeviceForInputSource(inputDesc->mInputSource); -            if (newDevice != inputDesc->mDevice) { -                LOGV("setDeviceConnectionState() changing device from %x to %x for input %d", -                        inputDesc->mDevice, newDevice, activeInput); -                inputDesc->mDevice = newDevice; -                AudioParameter param = AudioParameter(); -                param.addInt(String8(AudioParameter::keyRouting), (int)newDevice); -                mpClientInterface->setParameters(activeInput, param.toString()); -            } -        } - -        return NO_ERROR; -    } - -    LOGW("setDeviceConnectionState() invalid device: %x", device); -    return BAD_VALUE; -} - -AudioSystem::device_connection_state AudioPolicyManagerBase::getDeviceConnectionState(AudioSystem::audio_devices device, -                                                  const char *device_address) -{ -    AudioSystem::device_connection_state state = AudioSystem::DEVICE_STATE_UNAVAILABLE; -    String8 address = String8(device_address); -    if (AudioSystem::isOutputDevice(device)) { -        if (device & mAvailableOutputDevices) { -#ifdef WITH_A2DP -            if (AudioSystem::isA2dpDevice(device) && -                address != "" && mA2dpDeviceAddress != address) { -                return state; -            } -#endif -            if (AudioSystem::isBluetoothScoDevice(device) && -                address != "" && mScoDeviceAddress != address) { -                return state; -            } -            state = AudioSystem::DEVICE_STATE_AVAILABLE; -        } -    } else if (AudioSystem::isInputDevice(device)) { -        if (device & mAvailableInputDevices) { -            state = AudioSystem::DEVICE_STATE_AVAILABLE; -        } -    } - -    return state; -} - -void AudioPolicyManagerBase::setPhoneState(int state) -{ -    LOGV("setPhoneState() state %d", state); -    uint32_t newDevice = 0; -    if (state < 0 || state >= AudioSystem::NUM_MODES) { -        LOGW("setPhoneState() invalid state %d", state); -        return; -    } - -    if (state == mPhoneState ) { -        LOGW("setPhoneState() setting same state %d", state); -        return; -    } - -    // if leaving call state, handle special case of active streams -    // pertaining to sonification strategy see handleIncallSonification() -    if (mPhoneState == AudioSystem::MODE_IN_CALL) { -        LOGV("setPhoneState() in call state management: new state is %d", state); -        for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { -            handleIncallSonification(stream, false, true); -        } -    } - -    // store previous phone state for management of sonification strategy below -    int oldState = mPhoneState; -    mPhoneState = state; -    bool force = false; - -    // are we entering or starting a call -    if ((oldState != AudioSystem::MODE_IN_CALL) && (state == AudioSystem::MODE_IN_CALL)) { -        LOGV("  Entering call in setPhoneState()"); -        // force routing command to audio hardware when starting a call -        // even if no device change is needed -        force = true; -    } else if ((oldState == AudioSystem::MODE_IN_CALL) && (state != AudioSystem::MODE_IN_CALL)) { -        LOGV("  Exiting call in setPhoneState()"); -        // force routing command to audio hardware when exiting a call -        // even if no device change is needed -        force = true; -    } - -    // check for device and output changes triggered by new phone state -    newDevice = getNewDevice(mHardwareOutput, false); -#ifdef WITH_A2DP -    checkOutputForAllStrategies(newDevice); -    // suspend A2DP output if a SCO device is present. -    if (mA2dpOutput != 0 && mScoDeviceAddress != "") { -        if (oldState == AudioSystem::MODE_NORMAL) { -            mpClientInterface->suspendOutput(mA2dpOutput); -        } else if (state == AudioSystem::MODE_NORMAL) { -            mpClientInterface->restoreOutput(mA2dpOutput); -        } -    } -#endif -    updateDeviceForStrategy(); - -    AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput); - -    // force routing command to audio hardware when ending call -    // even if no device change is needed -    if (oldState == AudioSystem::MODE_IN_CALL && newDevice == 0) { -        newDevice = hwOutputDesc->device(); -    } - -    // when changing from ring tone to in call mode, mute the ringing tone -    // immediately and delay the route change to avoid sending the ring tone -    // tail into the earpiece or headset. -    int delayMs = 0; -    if (state == AudioSystem::MODE_IN_CALL && oldState == AudioSystem::MODE_RINGTONE) { -        // delay the device change command by twice the output latency to have some margin -        // and be sure that audio buffers not yet affected by the mute are out when -        // we actually apply the route change -        delayMs = hwOutputDesc->mLatency*2; -        setStreamMute(AudioSystem::RING, true, mHardwareOutput); -    } - -    // change routing is necessary -    setOutputDevice(mHardwareOutput, newDevice, force, delayMs); - -    // if entering in call state, handle special case of active streams -    // pertaining to sonification strategy see handleIncallSonification() -    if (state == AudioSystem::MODE_IN_CALL) { -        LOGV("setPhoneState() in call state management: new state is %d", state); -        // unmute the ringing tone after a sufficient delay if it was muted before -        // setting output device above -        if (oldState == AudioSystem::MODE_RINGTONE) { -            setStreamMute(AudioSystem::RING, false, mHardwareOutput, MUTE_TIME_MS); -        } -        for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { -            handleIncallSonification(stream, true, true); -        } -    } - -    // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE -    if (state == AudioSystem::MODE_RINGTONE && -        (hwOutputDesc->mRefCount[AudioSystem::MUSIC] || -        (systemTime() - mMusicStopTime) < seconds(SONIFICATION_HEADSET_MUSIC_DELAY))) { -        mLimitRingtoneVolume = true; -    } else { -        mLimitRingtoneVolume = false; -    } -} - -void AudioPolicyManagerBase::setRingerMode(uint32_t mode, uint32_t mask) -{ -    LOGV("setRingerMode() mode %x, mask %x", mode, mask); - -    mRingerMode = mode; -} - -void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config) -{ -    LOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mPhoneState); - -    bool forceVolumeReeval = false; -    switch(usage) { -    case AudioSystem::FOR_COMMUNICATION: -        if (config != AudioSystem::FORCE_SPEAKER && config != AudioSystem::FORCE_BT_SCO && -            config != AudioSystem::FORCE_NONE) { -            LOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config); -            return; -        } -        mForceUse[usage] = config; -        break; -    case AudioSystem::FOR_MEDIA: -        if (config != AudioSystem::FORCE_HEADPHONES && config != AudioSystem::FORCE_BT_A2DP && -            config != AudioSystem::FORCE_WIRED_ACCESSORY && config != AudioSystem::FORCE_NONE) { -            LOGW("setForceUse() invalid config %d for FOR_MEDIA", config); -            return; -        } -        mForceUse[usage] = config; -        break; -    case AudioSystem::FOR_RECORD: -        if (config != AudioSystem::FORCE_BT_SCO && config != AudioSystem::FORCE_WIRED_ACCESSORY && -            config != AudioSystem::FORCE_NONE) { -            LOGW("setForceUse() invalid config %d for FOR_RECORD", config); -            return; -        } -        mForceUse[usage] = config; -        break; -    case AudioSystem::FOR_DOCK: -        if (config != AudioSystem::FORCE_NONE && config != AudioSystem::FORCE_BT_CAR_DOCK && -            config != AudioSystem::FORCE_BT_DESK_DOCK && config != AudioSystem::FORCE_WIRED_ACCESSORY) { -            LOGW("setForceUse() invalid config %d for FOR_DOCK", config); -        } -        forceVolumeReeval = true; -        mForceUse[usage] = config; -        break; -    default: -        LOGW("setForceUse() invalid usage %d", usage); -        break; -    } - -    // check for device and output changes triggered by new phone state -    uint32_t newDevice = getNewDevice(mHardwareOutput, false); -#ifdef WITH_A2DP -    checkOutputForAllStrategies(newDevice); -#endif -    updateDeviceForStrategy(); -    setOutputDevice(mHardwareOutput, newDevice); -    if (forceVolumeReeval) { -        applyStreamVolumes(mHardwareOutput, newDevice); -    } -} - -AudioSystem::forced_config AudioPolicyManagerBase::getForceUse(AudioSystem::force_use usage) -{ -    return mForceUse[usage]; -} - -void AudioPolicyManagerBase::setSystemProperty(const char* property, const char* value) -{ -    LOGV("setSystemProperty() property %s, value %s", property, value); -    if (strcmp(property, "ro.camera.sound.forced") == 0) { -        if (atoi(value)) { -            LOGV("ENFORCED_AUDIBLE cannot be muted"); -            mStreams[AudioSystem::ENFORCED_AUDIBLE].mCanBeMuted = false; -        } else { -            LOGV("ENFORCED_AUDIBLE can be muted"); -            mStreams[AudioSystem::ENFORCED_AUDIBLE].mCanBeMuted = true; -        } -    } -} - -audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type stream, -                                    uint32_t samplingRate, -                                    uint32_t format, -                                    uint32_t channels, -                                    AudioSystem::output_flags flags) -{ -    audio_io_handle_t output = 0; -    uint32_t latency = 0; -    routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream); -    uint32_t device = getDeviceForStrategy(strategy); -    LOGV("getOutput() stream %d, samplingRate %d, format %d, channels %x, flags %x", stream, samplingRate, format, channels, flags); - -#ifdef AUDIO_POLICY_TEST -    if (mCurOutput != 0) { -        LOGV("getOutput() test output mCurOutput %d, samplingRate %d, format %d, channels %x, mDirectOutput %d", -                mCurOutput, mTestSamplingRate, mTestFormat, mTestChannels, mDirectOutput); - -        if (mTestOutputs[mCurOutput] == 0) { -            LOGV("getOutput() opening test output"); -            AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(); -            outputDesc->mDevice = mTestDevice; -            outputDesc->mSamplingRate = mTestSamplingRate; -            outputDesc->mFormat = mTestFormat; -            outputDesc->mChannels = mTestChannels; -            outputDesc->mLatency = mTestLatencyMs; -            outputDesc->mFlags = (AudioSystem::output_flags)(mDirectOutput ? AudioSystem::OUTPUT_FLAG_DIRECT : 0); -            outputDesc->mRefCount[stream] = 0; -            mTestOutputs[mCurOutput] = mpClientInterface->openOutput(&outputDesc->mDevice, -                                            &outputDesc->mSamplingRate, -                                            &outputDesc->mFormat, -                                            &outputDesc->mChannels, -                                            &outputDesc->mLatency, -                                            outputDesc->mFlags); -            if (mTestOutputs[mCurOutput]) { -                AudioParameter outputCmd = AudioParameter(); -                outputCmd.addInt(String8("set_id"),mCurOutput); -                mpClientInterface->setParameters(mTestOutputs[mCurOutput],outputCmd.toString()); -                addOutput(mTestOutputs[mCurOutput], outputDesc); -            } -        } -        return mTestOutputs[mCurOutput]; -    } -#endif //AUDIO_POLICY_TEST - -    // open a direct output if required by specified parameters -    if (needsDirectOuput(stream, samplingRate, format, channels, flags, device)) { - -        LOGV("getOutput() opening direct output device %x", device); -        AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(); -        outputDesc->mDevice = device; -        outputDesc->mSamplingRate = samplingRate; -        outputDesc->mFormat = format; -        outputDesc->mChannels = channels; -        outputDesc->mLatency = 0; -        outputDesc->mFlags = (AudioSystem::output_flags)(flags | AudioSystem::OUTPUT_FLAG_DIRECT); -        outputDesc->mRefCount[stream] = 0; -        output = mpClientInterface->openOutput(&outputDesc->mDevice, -                                        &outputDesc->mSamplingRate, -                                        &outputDesc->mFormat, -                                        &outputDesc->mChannels, -                                        &outputDesc->mLatency, -                                        outputDesc->mFlags); - -        // only accept an output with the requeted parameters -        if (output == 0 || -            (samplingRate != 0 && samplingRate != outputDesc->mSamplingRate) || -            (format != 0 && format != outputDesc->mFormat) || -            (channels != 0 && channels != outputDesc->mChannels)) { -            LOGV("getOutput() failed opening direct output: samplingRate %d, format %d, channels %d", -                    samplingRate, format, channels); -            if (output != 0) { -                mpClientInterface->closeOutput(output); -            } -            delete outputDesc; -            return 0; -        } -        addOutput(output, outputDesc); -        return output; -    } - -    if (channels != 0 && channels != AudioSystem::CHANNEL_OUT_MONO && -        channels != AudioSystem::CHANNEL_OUT_STEREO) { -        return 0; -    } -    // open a non direct output - -    // get which output is suitable for the specified stream. The actual routing change will happen -    // when startOutput() will be called -    uint32_t a2dpDevice = device & AudioSystem::DEVICE_OUT_ALL_A2DP; -    if (AudioSystem::popCount((AudioSystem::audio_devices)device) == 2) { -#ifdef WITH_A2DP -        if (a2dpUsedForSonification() && a2dpDevice != 0) { -            // if playing on 2 devices among which one is A2DP, use duplicated output -            LOGV("getOutput() using duplicated output"); -            LOGW_IF((mA2dpOutput == 0), "getOutput() A2DP device in multiple %x selected but A2DP output not opened", device); -            output = mDuplicatedOutput; -        } else -#endif -        { -            // if playing on 2 devices among which none is A2DP, use hardware output -            output = mHardwareOutput; -        } -        LOGV("getOutput() using output %d for 2 devices %x", output, device); -    } else { -#ifdef WITH_A2DP -        if (a2dpDevice != 0) { -            // if playing on A2DP device, use a2dp output -            LOGW_IF((mA2dpOutput == 0), "getOutput() A2DP device %x selected but A2DP output not opened", device); -            output = mA2dpOutput; -        } else -#endif -        { -            // if playing on not A2DP device, use hardware output -            output = mHardwareOutput; -        } -    } - - -    LOGW_IF((output ==0), "getOutput() could not find output for stream %d, samplingRate %d, format %d, channels %x, flags %x", -                stream, samplingRate, format, channels, flags); - -    return output; -} - -status_t AudioPolicyManagerBase::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream) -{ -    LOGV("startOutput() output %d, stream %d", output, stream); -    ssize_t index = mOutputs.indexOfKey(output); -    if (index < 0) { -        LOGW("startOutput() unknow output %d", output); -        return BAD_VALUE; -    } - -    AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index); -    routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream); - -#ifdef WITH_A2DP -    if (mA2dpOutput != 0  && !a2dpUsedForSonification() && strategy == STRATEGY_SONIFICATION) { -        setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput); -    } -#endif - -    // incremenent usage count for this stream on the requested output: -    // NOTE that the usage count is the same for duplicated output and hardware output which is -    // necassary for a correct control of hardware output routing by startOutput() and stopOutput() -    outputDesc->changeRefCount(stream, 1); - -    setOutputDevice(output, getNewDevice(output)); - -    // handle special case for sonification while in call -    if (mPhoneState == AudioSystem::MODE_IN_CALL) { -        handleIncallSonification(stream, true, false); -    } - -    // apply volume rules for current stream and device if necessary -    checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, outputDesc->device()); - -    return NO_ERROR; -} - -status_t AudioPolicyManagerBase::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream) -{ -    LOGV("stopOutput() output %d, stream %d", output, stream); -    ssize_t index = mOutputs.indexOfKey(output); -    if (index < 0) { -        LOGW("stopOutput() unknow output %d", output); -        return BAD_VALUE; -    } - -    AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index); -    routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream); - -    // handle special case for sonification while in call -    if (mPhoneState == AudioSystem::MODE_IN_CALL) { -        handleIncallSonification(stream, false, false); -    } - -    if (outputDesc->mRefCount[stream] > 0) { -        // decrement usage count of this stream on the output -        outputDesc->changeRefCount(stream, -1); -        // store time at which the last music track was stopped - see computeVolume() -        if (stream == AudioSystem::MUSIC) { -            mMusicStopTime = systemTime(); -        } - -        setOutputDevice(output, getNewDevice(output)); - -#ifdef WITH_A2DP -        if (mA2dpOutput != 0 && !a2dpUsedForSonification() && strategy == STRATEGY_SONIFICATION) { -            setStrategyMute(STRATEGY_MEDIA, false, mA2dpOutput, mOutputs.valueFor(mHardwareOutput)->mLatency*2); -        } -#endif -        if (output != mHardwareOutput) { -            setOutputDevice(mHardwareOutput, getNewDevice(mHardwareOutput), true); -        } -        return NO_ERROR; -    } else { -        LOGW("stopOutput() refcount is already 0 for output %d", output); -        return INVALID_OPERATION; -    } -} - -void AudioPolicyManagerBase::releaseOutput(audio_io_handle_t output) -{ -    LOGV("releaseOutput() %d", output); -    ssize_t index = mOutputs.indexOfKey(output); -    if (index < 0) { -        LOGW("releaseOutput() releasing unknown output %d", output); -        return; -    } - -#ifdef AUDIO_POLICY_TEST -    int testIndex = testOutputIndex(output); -    if (testIndex != 0) { -        AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index); -        if (outputDesc->refCount() == 0) { -            mpClientInterface->closeOutput(output); -            delete mOutputs.valueAt(index); -            mOutputs.removeItem(output); -            mTestOutputs[testIndex] = 0; -        } -        return; -    } -#endif //AUDIO_POLICY_TEST - -    if (mOutputs.valueAt(index)->mFlags & AudioSystem::OUTPUT_FLAG_DIRECT) { -        mpClientInterface->closeOutput(output); -        delete mOutputs.valueAt(index); -        mOutputs.removeItem(output); -    } -} - -audio_io_handle_t AudioPolicyManagerBase::getInput(int inputSource, -                                    uint32_t samplingRate, -                                    uint32_t format, -                                    uint32_t channels, -                                    AudioSystem::audio_in_acoustics acoustics) -{ -    audio_io_handle_t input = 0; -    uint32_t device = getDeviceForInputSource(inputSource); - -    LOGV("getInput() inputSource %d, samplingRate %d, format %d, channels %x, acoustics %x", inputSource, samplingRate, format, channels, acoustics); - -    if (device == 0) { -        return 0; -    } - -    // adapt channel selection to input source -    switch(inputSource) { -    case AUDIO_SOURCE_VOICE_UPLINK: -        channels = AudioSystem::CHANNEL_IN_VOICE_UPLINK; -        break; -    case AUDIO_SOURCE_VOICE_DOWNLINK: -        channels = AudioSystem::CHANNEL_IN_VOICE_DNLINK; -        break; -    case AUDIO_SOURCE_VOICE_CALL: -        channels = (AudioSystem::CHANNEL_IN_VOICE_UPLINK | AudioSystem::CHANNEL_IN_VOICE_DNLINK); -        break; -    default: -        break; -    } - -    AudioInputDescriptor *inputDesc = new AudioInputDescriptor(); - -    inputDesc->mInputSource = inputSource; -    inputDesc->mDevice = device; -    inputDesc->mSamplingRate = samplingRate; -    inputDesc->mFormat = format; -    inputDesc->mChannels = channels; -    inputDesc->mAcoustics = acoustics; -    inputDesc->mRefCount = 0; -    input = mpClientInterface->openInput(&inputDesc->mDevice, -                                    &inputDesc->mSamplingRate, -                                    &inputDesc->mFormat, -                                    &inputDesc->mChannels, -                                    inputDesc->mAcoustics); - -    // only accept input with the exact requested set of parameters -    if (input == 0 || -        (samplingRate != inputDesc->mSamplingRate) || -        (format != inputDesc->mFormat) || -        (channels != inputDesc->mChannels)) { -        LOGV("getInput() failed opening input: samplingRate %d, format %d, channels %d", -                samplingRate, format, channels); -        if (input != 0) { -            mpClientInterface->closeInput(input); -        } -        delete inputDesc; -        return 0; -    } -    mInputs.add(input, inputDesc); -    return input; -} - -status_t AudioPolicyManagerBase::startInput(audio_io_handle_t input) -{ -    LOGV("startInput() input %d", input); -    ssize_t index = mInputs.indexOfKey(input); -    if (index < 0) { -        LOGW("startInput() unknow input %d", input); -        return BAD_VALUE; -    } -    AudioInputDescriptor *inputDesc = mInputs.valueAt(index); - -#ifdef AUDIO_POLICY_TEST -    if (mTestInput == 0) -#endif //AUDIO_POLICY_TEST -    { -        // refuse 2 active AudioRecord clients at the same time -        if (getActiveInput() != 0) { -            LOGW("startInput() input %d failed: other input already started", input); -            return INVALID_OPERATION; -        } -    } - -    AudioParameter param = AudioParameter(); -    param.addInt(String8(AudioParameter::keyRouting), (int)inputDesc->mDevice); - -    // use Voice Recognition mode or not for this input based on input source -    int vr_enabled = inputDesc->mInputSource == AUDIO_SOURCE_VOICE_RECOGNITION ? 1 : 0; -    param.addInt(String8("vr_mode"), vr_enabled); -    LOGV("AudioPolicyManager::startInput(%d), setting vr_mode to %d", inputDesc->mInputSource, vr_enabled); - -    mpClientInterface->setParameters(input, param.toString()); - -    inputDesc->mRefCount = 1; -    return NO_ERROR; -} - -status_t AudioPolicyManagerBase::stopInput(audio_io_handle_t input) -{ -    LOGV("stopInput() input %d", input); -    ssize_t index = mInputs.indexOfKey(input); -    if (index < 0) { -        LOGW("stopInput() unknow input %d", input); -        return BAD_VALUE; -    } -    AudioInputDescriptor *inputDesc = mInputs.valueAt(index); - -    if (inputDesc->mRefCount == 0) { -        LOGW("stopInput() input %d already stopped", input); -        return INVALID_OPERATION; -    } else { -        AudioParameter param = AudioParameter(); -        param.addInt(String8(AudioParameter::keyRouting), 0); -        mpClientInterface->setParameters(input, param.toString()); -        inputDesc->mRefCount = 0; -        return NO_ERROR; -    } -} - -void AudioPolicyManagerBase::releaseInput(audio_io_handle_t input) -{ -    LOGV("releaseInput() %d", input); -    ssize_t index = mInputs.indexOfKey(input); -    if (index < 0) { -        LOGW("releaseInput() releasing unknown input %d", input); -        return; -    } -    mpClientInterface->closeInput(input); -    delete mInputs.valueAt(index); -    mInputs.removeItem(input); -    LOGV("releaseInput() exit"); -} - -void AudioPolicyManagerBase::initStreamVolume(AudioSystem::stream_type stream, -                                            int indexMin, -                                            int indexMax) -{ -    LOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax); -    if (indexMin < 0 || indexMin >= indexMax) { -        LOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d", stream , indexMin, indexMax); -        return; -    } -    mStreams[stream].mIndexMin = indexMin; -    mStreams[stream].mIndexMax = indexMax; -} - -status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type stream, int index) -{ - -    if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) { -        return BAD_VALUE; -    } - -    // Force max volume if stream cannot be muted -    if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax; - -    LOGV("setStreamVolumeIndex() stream %d, index %d", stream, index); -    mStreams[stream].mIndexCur = index; - -    // compute and apply stream volume on all outputs according to connected device -    status_t status = NO_ERROR; -    for (size_t i = 0; i < mOutputs.size(); i++) { -        status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), mOutputs.valueAt(i)->device()); -        if (volStatus != NO_ERROR) { -            status = volStatus; -        } -    } -    return status; -} - -status_t AudioPolicyManagerBase::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index) -{ -    if (index == 0) { -        return BAD_VALUE; -    } -    LOGV("getStreamVolumeIndex() stream %d", stream); -    *index =  mStreams[stream].mIndexCur; -    return NO_ERROR; -} - -status_t AudioPolicyManagerBase::dump(int fd) -{ -    const size_t SIZE = 256; -    char buffer[SIZE]; -    String8 result; - -    snprintf(buffer, SIZE, "\nAudioPolicyManager Dump: %p\n", this); -    result.append(buffer); -    snprintf(buffer, SIZE, " Hardware Output: %d\n", mHardwareOutput); -    result.append(buffer); -#ifdef WITH_A2DP -    snprintf(buffer, SIZE, " A2DP Output: %d\n", mA2dpOutput); -    result.append(buffer); -    snprintf(buffer, SIZE, " Duplicated Output: %d\n", mDuplicatedOutput); -    result.append(buffer); -    snprintf(buffer, SIZE, " A2DP device address: %s\n", mA2dpDeviceAddress.string()); -    result.append(buffer); -#endif -    snprintf(buffer, SIZE, " SCO device address: %s\n", mScoDeviceAddress.string()); -    result.append(buffer); -    snprintf(buffer, SIZE, " Output devices: %08x\n", mAvailableOutputDevices); -    result.append(buffer); -    snprintf(buffer, SIZE, " Input devices: %08x\n", mAvailableInputDevices); -    result.append(buffer); -    snprintf(buffer, SIZE, " Phone state: %d\n", mPhoneState); -    result.append(buffer); -    snprintf(buffer, SIZE, " Ringer mode: %d\n", mRingerMode); -    result.append(buffer); -    snprintf(buffer, SIZE, " Force use for communications %d\n", mForceUse[AudioSystem::FOR_COMMUNICATION]); -    result.append(buffer); -    snprintf(buffer, SIZE, " Force use for media %d\n", mForceUse[AudioSystem::FOR_MEDIA]); -    result.append(buffer); -    snprintf(buffer, SIZE, " Force use for record %d\n", mForceUse[AudioSystem::FOR_RECORD]); -    result.append(buffer); -    snprintf(buffer, SIZE, " Force use for dock %d\n", mForceUse[AudioSystem::FOR_DOCK]); -    result.append(buffer); -    write(fd, result.string(), result.size()); - -    snprintf(buffer, SIZE, "\nOutputs dump:\n"); -    write(fd, buffer, strlen(buffer)); -    for (size_t i = 0; i < mOutputs.size(); i++) { -        snprintf(buffer, SIZE, "- Output %d dump:\n", mOutputs.keyAt(i)); -        write(fd, buffer, strlen(buffer)); -        mOutputs.valueAt(i)->dump(fd); -    } - -    snprintf(buffer, SIZE, "\nInputs dump:\n"); -    write(fd, buffer, strlen(buffer)); -    for (size_t i = 0; i < mInputs.size(); i++) { -        snprintf(buffer, SIZE, "- Input %d dump:\n", mInputs.keyAt(i)); -        write(fd, buffer, strlen(buffer)); -        mInputs.valueAt(i)->dump(fd); -    } - -    snprintf(buffer, SIZE, "\nStreams dump:\n"); -    write(fd, buffer, strlen(buffer)); -    snprintf(buffer, SIZE, " Stream  Index Min  Index Max  Index Cur  Can be muted\n"); -    write(fd, buffer, strlen(buffer)); -    for (size_t i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) { -        snprintf(buffer, SIZE, " %02d", i); -        mStreams[i].dump(buffer + 3, SIZE); -        write(fd, buffer, strlen(buffer)); -    } - -    return NO_ERROR; -} - -// ---------------------------------------------------------------------------- -// AudioPolicyManagerBase -// ---------------------------------------------------------------------------- - -AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface) -    : -#ifdef AUDIO_POLICY_TEST -    Thread(false), -#endif //AUDIO_POLICY_TEST -    mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0), mMusicStopTime(0), mLimitRingtoneVolume(false) -{ -    mpClientInterface = clientInterface; - -    for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) { -        mForceUse[i] = AudioSystem::FORCE_NONE; -    } - -    // devices available by default are speaker, ear piece and microphone -    mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE | -                        AudioSystem::DEVICE_OUT_SPEAKER; -    mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC; - -#ifdef WITH_A2DP -    mA2dpOutput = 0; -    mDuplicatedOutput = 0; -    mA2dpDeviceAddress = String8(""); -#endif -    mScoDeviceAddress = String8(""); - -    // open hardware output -    AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(); -    outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER; -    mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice, -                                    &outputDesc->mSamplingRate, -                                    &outputDesc->mFormat, -                                    &outputDesc->mChannels, -                                    &outputDesc->mLatency, -                                    outputDesc->mFlags); - -    if (mHardwareOutput == 0) { -        LOGE("Failed to initialize hardware output stream, samplingRate: %d, format %d, channels %d", -                outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannels); -    } else { -        addOutput(mHardwareOutput, outputDesc); -        setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER, true); -    } - -    updateDeviceForStrategy(); -#ifdef AUDIO_POLICY_TEST -    AudioParameter outputCmd = AudioParameter(); -    outputCmd.addInt(String8("set_id"), 0); -    mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString()); - -    mTestDevice = AudioSystem::DEVICE_OUT_SPEAKER; -    mTestSamplingRate = 44100; -    mTestFormat = AudioSystem::PCM_16_BIT; -    mTestChannels =  AudioSystem::CHANNEL_OUT_STEREO; -    mTestLatencyMs = 0; -    mCurOutput = 0; -    mDirectOutput = false; -    for (int i = 0; i < NUM_TEST_OUTPUTS; i++) { -        mTestOutputs[i] = 0; -    } - -    const size_t SIZE = 256; -    char buffer[SIZE]; -    snprintf(buffer, SIZE, "AudioPolicyManagerTest"); -    run(buffer, ANDROID_PRIORITY_AUDIO); -#endif //AUDIO_POLICY_TEST -} - -AudioPolicyManagerBase::~AudioPolicyManagerBase() -{ -#ifdef AUDIO_POLICY_TEST -    exit(); -#endif //AUDIO_POLICY_TEST -   for (size_t i = 0; i < mOutputs.size(); i++) { -        mpClientInterface->closeOutput(mOutputs.keyAt(i)); -        delete mOutputs.valueAt(i); -   } -   mOutputs.clear(); -   for (size_t i = 0; i < mInputs.size(); i++) { -        mpClientInterface->closeInput(mInputs.keyAt(i)); -        delete mInputs.valueAt(i); -   } -   mInputs.clear(); -} - -#ifdef AUDIO_POLICY_TEST -bool AudioPolicyManagerBase::threadLoop() -{ -    LOGV("entering threadLoop()"); -    while (!exitPending()) -    { -        String8 command; -        int valueInt; -        String8 value; - -        Mutex::Autolock _l(mLock); -        mWaitWorkCV.waitRelative(mLock, milliseconds(50)); - -        command = mpClientInterface->getParameters(0, String8("test_cmd_policy")); -        AudioParameter param = AudioParameter(command); - -        if (param.getInt(String8("test_cmd_policy"), valueInt) == NO_ERROR && -            valueInt != 0) { -            LOGV("Test command %s received", command.string()); -            String8 target; -            if (param.get(String8("target"), target) != NO_ERROR) { -                target = "Manager"; -            } -            if (param.getInt(String8("test_cmd_policy_output"), valueInt) == NO_ERROR) { -                param.remove(String8("test_cmd_policy_output")); -                mCurOutput = valueInt; -            } -            if (param.get(String8("test_cmd_policy_direct"), value) == NO_ERROR) { -                param.remove(String8("test_cmd_policy_direct")); -                if (value == "false") { -                    mDirectOutput = false; -                } else if (value == "true") { -                    mDirectOutput = true; -                } -            } -            if (param.getInt(String8("test_cmd_policy_input"), valueInt) == NO_ERROR) { -                param.remove(String8("test_cmd_policy_input")); -                mTestInput = valueInt; -            } - -            if (param.get(String8("test_cmd_policy_format"), value) == NO_ERROR) { -                param.remove(String8("test_cmd_policy_format")); -                int format = AudioSystem::INVALID_FORMAT; -                if (value == "PCM 16 bits") { -                    format = AudioSystem::PCM_16_BIT; -                } else if (value == "PCM 8 bits") { -                    format = AudioSystem::PCM_8_BIT; -                } else if (value == "Compressed MP3") { -                    format = AudioSystem::MP3; -                } -                if (format != AudioSystem::INVALID_FORMAT) { -                    if (target == "Manager") { -                        mTestFormat = format; -                    } else if (mTestOutputs[mCurOutput] != 0) { -                        AudioParameter outputParam = AudioParameter(); -                        outputParam.addInt(String8("format"), format); -                        mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString()); -                    } -                } -            } -            if (param.get(String8("test_cmd_policy_channels"), value) == NO_ERROR) { -                param.remove(String8("test_cmd_policy_channels")); -                int channels = 0; - -                if (value == "Channels Stereo") { -                    channels =  AudioSystem::CHANNEL_OUT_STEREO; -                } else if (value == "Channels Mono") { -                    channels =  AudioSystem::CHANNEL_OUT_MONO; -                } -                if (channels != 0) { -                    if (target == "Manager") { -                        mTestChannels = channels; -                    } else if (mTestOutputs[mCurOutput] != 0) { -                        AudioParameter outputParam = AudioParameter(); -                        outputParam.addInt(String8("channels"), channels); -                        mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString()); -                    } -                } -            } -            if (param.getInt(String8("test_cmd_policy_sampleRate"), valueInt) == NO_ERROR) { -                param.remove(String8("test_cmd_policy_sampleRate")); -                if (valueInt >= 0 && valueInt <= 96000) { -                    int samplingRate = valueInt; -                    if (target == "Manager") { -                        mTestSamplingRate = samplingRate; -                    } else if (mTestOutputs[mCurOutput] != 0) { -                        AudioParameter outputParam = AudioParameter(); -                        outputParam.addInt(String8("sampling_rate"), samplingRate); -                        mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString()); -                    } -                } -            } - -            if (param.get(String8("test_cmd_policy_reopen"), value) == NO_ERROR) { -                param.remove(String8("test_cmd_policy_reopen")); - -                mpClientInterface->closeOutput(mHardwareOutput); -                delete mOutputs.valueFor(mHardwareOutput); -                mOutputs.removeItem(mHardwareOutput); - -                AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(); -                outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER; -                mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice, -                                                &outputDesc->mSamplingRate, -                                                &outputDesc->mFormat, -                                                &outputDesc->mChannels, -                                                &outputDesc->mLatency, -                                                outputDesc->mFlags); -                if (mHardwareOutput == 0) { -                    LOGE("Failed to reopen hardware output stream, samplingRate: %d, format %d, channels %d", -                            outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannels); -                } else { -                    AudioParameter outputCmd = AudioParameter(); -                    outputCmd.addInt(String8("set_id"), 0); -                    mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString()); -                    addOutput(mHardwareOutput, outputDesc); -                } -            } - - -            mpClientInterface->setParameters(0, String8("test_cmd_policy=")); -        } -    } -    return false; -} - -void AudioPolicyManagerBase::exit() -{ -    { -        AutoMutex _l(mLock); -        requestExit(); -        mWaitWorkCV.signal(); -    } -    requestExitAndWait(); -} - -int AudioPolicyManagerBase::testOutputIndex(audio_io_handle_t output) -{ -    for (int i = 0; i < NUM_TEST_OUTPUTS; i++) { -        if (output == mTestOutputs[i]) return i; -    } -    return 0; -} -#endif //AUDIO_POLICY_TEST - -// --- - -void AudioPolicyManagerBase::addOutput(audio_io_handle_t id, AudioOutputDescriptor *outputDesc) -{ -    outputDesc->mId = id; -    mOutputs.add(id, outputDesc); -} - - -#ifdef WITH_A2DP -status_t AudioPolicyManagerBase::handleA2dpConnection(AudioSystem::audio_devices device, -                                                 const char *device_address) -{ -    // when an A2DP device is connected, open an A2DP and a duplicated output -    LOGV("opening A2DP output for device %s", device_address); -    AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(); -    outputDesc->mDevice = device; -    mA2dpOutput = mpClientInterface->openOutput(&outputDesc->mDevice, -                                            &outputDesc->mSamplingRate, -                                            &outputDesc->mFormat, -                                            &outputDesc->mChannels, -                                            &outputDesc->mLatency, -                                            outputDesc->mFlags); -    if (mA2dpOutput) { -        // add A2DP output descriptor -        addOutput(mA2dpOutput, outputDesc); -        // set initial stream volume for A2DP device -        applyStreamVolumes(mA2dpOutput, device); -        if (a2dpUsedForSonification()) { -            mDuplicatedOutput = mpClientInterface->openDuplicateOutput(mA2dpOutput, mHardwareOutput); -        } -        if (mDuplicatedOutput != 0 || -            !a2dpUsedForSonification()) { -            // If both A2DP and duplicated outputs are open, send device address to A2DP hardware -            // interface -            AudioParameter param; -            param.add(String8("a2dp_sink_address"), String8(device_address)); -            mpClientInterface->setParameters(mA2dpOutput, param.toString()); -            mA2dpDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN); - -            if (a2dpUsedForSonification()) { -                // add duplicated output descriptor -                AudioOutputDescriptor *dupOutputDesc = new AudioOutputDescriptor(); -                dupOutputDesc->mOutput1 = mOutputs.valueFor(mHardwareOutput); -                dupOutputDesc->mOutput2 = mOutputs.valueFor(mA2dpOutput); -                dupOutputDesc->mSamplingRate = outputDesc->mSamplingRate; -                dupOutputDesc->mFormat = outputDesc->mFormat; -                dupOutputDesc->mChannels = outputDesc->mChannels; -                dupOutputDesc->mLatency = outputDesc->mLatency; -                addOutput(mDuplicatedOutput, dupOutputDesc); -                applyStreamVolumes(mDuplicatedOutput, device); -            } -        } else { -            LOGW("getOutput() could not open duplicated output for %d and %d", -                    mHardwareOutput, mA2dpOutput); -            mpClientInterface->closeOutput(mA2dpOutput); -            mOutputs.removeItem(mA2dpOutput); -            mA2dpOutput = 0; -            delete outputDesc; -            return NO_INIT; -        } -    } else { -        LOGW("setDeviceConnectionState() could not open A2DP output for device %x", device); -        delete outputDesc; -        return NO_INIT; -    } -    AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput); - -    if (mScoDeviceAddress != "") { -        // It is normal to suspend twice if we are both in call, -        // and have the hardware audio output routed to BT SCO -        if (mPhoneState != AudioSystem::MODE_NORMAL) { -            mpClientInterface->suspendOutput(mA2dpOutput); -        } -        if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)hwOutputDesc->device())) { -            mpClientInterface->suspendOutput(mA2dpOutput); -        } -    } - -    if (!a2dpUsedForSonification()) { -        // mute music on A2DP output if a notification or ringtone is playing -        uint32_t refCount = hwOutputDesc->strategyRefCount(STRATEGY_SONIFICATION); -        for (uint32_t i = 0; i < refCount; i++) { -            setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput); -        } -    } -    return NO_ERROR; -} - -status_t AudioPolicyManagerBase::handleA2dpDisconnection(AudioSystem::audio_devices device, -                                                    const char *device_address) -{ -    if (mA2dpOutput == 0) { -        LOGW("setDeviceConnectionState() disconnecting A2DP and no A2DP output!"); -        return INVALID_OPERATION; -    } - -    if (mA2dpDeviceAddress != device_address) { -        LOGW("setDeviceConnectionState() disconnecting unknow A2DP sink address %s", device_address); -        return INVALID_OPERATION; -    } - -    // mute media strategy to avoid outputting sound on hardware output while music stream -    // is switched from A2DP output and before music is paused by music application -    setStrategyMute(STRATEGY_MEDIA, true, mHardwareOutput); -    setStrategyMute(STRATEGY_MEDIA, false, mHardwareOutput, MUTE_TIME_MS); - -    if (!a2dpUsedForSonification()) { -        // unmute music on A2DP output if a notification or ringtone is playing -        uint32_t refCount = mOutputs.valueFor(mHardwareOutput)->strategyRefCount(STRATEGY_SONIFICATION); -        for (uint32_t i = 0; i < refCount; i++) { -            setStrategyMute(STRATEGY_MEDIA, false, mA2dpOutput); -        } -    } -    mA2dpDeviceAddress = ""; -    return NO_ERROR; -} - -void AudioPolicyManagerBase::closeA2dpOutputs() -{ -    LOGV("setDeviceConnectionState() closing A2DP and duplicated output!"); - -    if (mDuplicatedOutput != 0) { -        mpClientInterface->closeOutput(mDuplicatedOutput); -        delete mOutputs.valueFor(mDuplicatedOutput); -        mOutputs.removeItem(mDuplicatedOutput); -        mDuplicatedOutput = 0; -    } -    if (mA2dpOutput != 0) { -        AudioParameter param; -        param.add(String8("closing"), String8("true")); -        mpClientInterface->setParameters(mA2dpOutput, param.toString()); -        mpClientInterface->closeOutput(mA2dpOutput); -        delete mOutputs.valueFor(mA2dpOutput); -        mOutputs.removeItem(mA2dpOutput); -        mA2dpOutput = 0; -    } -} - -void AudioPolicyManagerBase::checkOutputForStrategy(routing_strategy strategy, uint32_t &newDevice) -{ -    uint32_t prevDevice = getDeviceForStrategy(strategy); -    uint32_t curDevice = getDeviceForStrategy(strategy, false); -    bool a2dpWasUsed = AudioSystem::isA2dpDevice((AudioSystem::audio_devices)(prevDevice & ~AudioSystem::DEVICE_OUT_SPEAKER)); -    bool a2dpIsUsed = AudioSystem::isA2dpDevice((AudioSystem::audio_devices)(curDevice & ~AudioSystem::DEVICE_OUT_SPEAKER)); -    AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput); -    AudioOutputDescriptor *a2dpOutputDesc; - -    if (a2dpWasUsed && !a2dpIsUsed) { -        bool dupUsed = a2dpUsedForSonification() && a2dpWasUsed && (AudioSystem::popCount(prevDevice) == 2); - -        if (dupUsed) { -            LOGV("checkOutputForStrategy() moving strategy %d to duplicated", strategy); -            a2dpOutputDesc = mOutputs.valueFor(mDuplicatedOutput); -        } else { -            LOGV("checkOutputForStrategy() moving strategy %d to a2dp", strategy); -            a2dpOutputDesc = mOutputs.valueFor(mA2dpOutput); -        } - -        for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) { -            if (getStrategy((AudioSystem::stream_type)i) == strategy) { -                mpClientInterface->setStreamOutput((AudioSystem::stream_type)i, mHardwareOutput); -                int refCount = a2dpOutputDesc->mRefCount[i]; -                // in the case of duplicated output, the ref count is first incremented -                // and then decremented on hardware output tus keeping its value -                hwOutputDesc->changeRefCount((AudioSystem::stream_type)i, refCount); -                a2dpOutputDesc->changeRefCount((AudioSystem::stream_type)i,-refCount); -            } -        } -        // do not change newDevice if it was already set before this call by a previous call to -        // getNewDevice() or checkOutputForStrategy() for a strategy with higher priority -        if (newDevice == 0 && hwOutputDesc->isUsedByStrategy(strategy)) { -            newDevice = getDeviceForStrategy(strategy, false); -        } -    } -    if (a2dpIsUsed && !a2dpWasUsed) { -        bool dupUsed = a2dpUsedForSonification() && a2dpIsUsed && (AudioSystem::popCount(curDevice) == 2); -        audio_io_handle_t a2dpOutput; - -        if (dupUsed) { -            LOGV("checkOutputForStrategy() moving strategy %d from duplicated", strategy); -            a2dpOutputDesc = mOutputs.valueFor(mDuplicatedOutput); -            a2dpOutput = mDuplicatedOutput; -        } else { -            LOGV("checkOutputForStrategy() moving strategy %d from a2dp", strategy); -            a2dpOutputDesc = mOutputs.valueFor(mA2dpOutput); -            a2dpOutput = mA2dpOutput; -        } - -        for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) { -            if (getStrategy((AudioSystem::stream_type)i) == strategy) { -                mpClientInterface->setStreamOutput((AudioSystem::stream_type)i, a2dpOutput); -                int refCount = hwOutputDesc->mRefCount[i]; -                // in the case of duplicated output, the ref count is first incremented -                // and then decremented on hardware output tus keeping its value -                a2dpOutputDesc->changeRefCount((AudioSystem::stream_type)i, refCount); -                hwOutputDesc->changeRefCount((AudioSystem::stream_type)i,-refCount); -            } -        } -    } -} - -void AudioPolicyManagerBase::checkOutputForAllStrategies(uint32_t &newDevice) -{ -    // Check strategies in order of priority so that once newDevice is set -    // for a given strategy it is not modified by subsequent calls to -    // checkOutputForStrategy() -    checkOutputForStrategy(STRATEGY_PHONE, newDevice); -    checkOutputForStrategy(STRATEGY_SONIFICATION, newDevice); -    checkOutputForStrategy(STRATEGY_MEDIA, newDevice); -    checkOutputForStrategy(STRATEGY_DTMF, newDevice); -} - -#endif - -uint32_t AudioPolicyManagerBase::getNewDevice(audio_io_handle_t output, bool fromCache) -{ -    uint32_t device = 0; - -    AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output); -    // check the following by order of priority to request a routing change if necessary: -    // 1: we are in call or the strategy phone is active on the hardware output: -    //      use device for strategy phone -    // 2: the strategy sonification is active on the hardware output: -    //      use device for strategy sonification -    // 3: the strategy media is active on the hardware output: -    //      use device for strategy media -    // 4: the strategy DTMF is active on the hardware output: -    //      use device for strategy DTMF -    if (mPhoneState == AudioSystem::MODE_IN_CALL || -        outputDesc->isUsedByStrategy(STRATEGY_PHONE)) { -        device = getDeviceForStrategy(STRATEGY_PHONE, fromCache); -    } else if (outputDesc->isUsedByStrategy(STRATEGY_SONIFICATION)) { -        device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache); -    } else if (outputDesc->isUsedByStrategy(STRATEGY_MEDIA)) { -        device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache); -    } else if (outputDesc->isUsedByStrategy(STRATEGY_DTMF)) { -        device = getDeviceForStrategy(STRATEGY_DTMF, fromCache); -    } - -    LOGV("getNewDevice() selected device %x", device); -    return device; -} - -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; -    case AudioSystem::RING: -    case AudioSystem::NOTIFICATION: -    case AudioSystem::ALARM: -    case AudioSystem::ENFORCED_AUDIBLE: -        return STRATEGY_SONIFICATION; -    case AudioSystem::DTMF: -        return STRATEGY_DTMF; -    default: -        LOGE("unknown stream type"); -    case AudioSystem::SYSTEM: -        // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs -        // while key clicks are played produces a poor result -    case AudioSystem::TTS: -    case AudioSystem::MUSIC: -        return STRATEGY_MEDIA; -    } -} - -uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy, bool fromCache) -{ -    uint32_t device = 0; - -    if (fromCache) { -        LOGV("getDeviceForStrategy() from cache strategy %d, device %x", strategy, mDeviceForStrategy[strategy]); -        return mDeviceForStrategy[strategy]; -    } - -    switch (strategy) { -    case STRATEGY_DTMF: -        if (mPhoneState != AudioSystem::MODE_IN_CALL) { -            // when off call, DTMF strategy follows the same rules as MEDIA strategy -            device = getDeviceForStrategy(STRATEGY_MEDIA, false); -            break; -        } -        // when in call, DTMF and PHONE strategies follow the same rules -        // FALL THROUGH - -    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 (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) { -                device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT; -                if (device) break; -            } -            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET; -            if (device) break; -            device = mAvailableOutputDevices & AudioSystem::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 -            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE; -            if (device) break; -            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET; -            if (device) break; -#ifdef WITH_A2DP -            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP -            if (mPhoneState != AudioSystem::MODE_IN_CALL) { -                device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP; -                if (device) break; -                device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; -                if (device) break; -            } -#endif -            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE; -            if (device == 0) { -                LOGE("getDeviceForStrategy() earpiece device not found"); -            } -            break; - -        case AudioSystem::FORCE_SPEAKER: -            if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) { -                device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT; -                if (device) break; -            } -#ifdef WITH_A2DP -            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to -            // A2DP speaker when forcing to speaker output -            if (mPhoneState != AudioSystem::MODE_IN_CALL) { -                device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; -                if (device) break; -            } -#endif -            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; -            if (device == 0) { -                LOGE("getDeviceForStrategy() speaker device not found"); -            } -            break; -        } -    break; - -    case STRATEGY_SONIFICATION: - -        // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by -        // handleIncallSonification(). -        if (mPhoneState == AudioSystem::MODE_IN_CALL) { -            device = getDeviceForStrategy(STRATEGY_PHONE, false); -            break; -        } -        device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; -        if (device == 0) { -            LOGE("getDeviceForStrategy() speaker device not found"); -        } -        // The second device used for sonification is the same as the device used by media strategy -        // FALL THROUGH - -    case STRATEGY_MEDIA: { -        uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL; -        if (device2 == 0) { -            device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE; -        } -        if (device2 == 0) { -            device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET; -        } -#ifdef WITH_A2DP -        if (mA2dpOutput != 0) { -            if (strategy == STRATEGY_SONIFICATION && !a2dpUsedForSonification()) { -                break; -            } -            if (device2 == 0) { -                device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP; -            } -            if (device2 == 0) { -                device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; -            } -            if (device2 == 0) { -                device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; -            } -        } -#endif -        if (device2 == 0) { -            device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; -        } - -        // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION, 0 otherwise -        device |= device2; -        if (device == 0) { -            LOGE("getDeviceForStrategy() speaker device not found"); -        } -        } break; - -    default: -        LOGW("getDeviceForStrategy() unknown strategy: %d", strategy); -        break; -    } - -    LOGV("getDeviceForStrategy() strategy %d, device %x", strategy, device); -    return device; -} - -void AudioPolicyManagerBase::updateDeviceForStrategy() -{ -    for (int i = 0; i < NUM_STRATEGIES; i++) { -        mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false); -    } -} - -void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, uint32_t device, bool force, int delayMs) -{ -    LOGV("setOutputDevice() output %d device %x delayMs %d", output, device, delayMs); -    AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output); - - -    if (outputDesc->isDuplicated()) { -        setOutputDevice(outputDesc->mOutput1->mId, device, force, delayMs); -        setOutputDevice(outputDesc->mOutput2->mId, device, force, delayMs); -        return; -    } -#ifdef WITH_A2DP -    // filter devices according to output selected -    if (output == mA2dpOutput) { -        device &= AudioSystem::DEVICE_OUT_ALL_A2DP; -    } else { -        device &= ~AudioSystem::DEVICE_OUT_ALL_A2DP; -    } -#endif - -    uint32_t prevDevice = (uint32_t)outputDesc->device(); -    // Do not change the routing if: -    //  - the requestede device is 0 -    //  - the requested device is the same as current device and force is not specified. -    // Doing this check here allows the caller to call setOutputDevice() without conditions -    if ((device == 0 || device == prevDevice) && !force) { -        LOGV("setOutputDevice() setting same device %x or null device for output %d", device, output); -        return; -    } - -    outputDesc->mDevice = device; -    // mute media streams if both speaker and headset are selected -    if (output == mHardwareOutput && AudioSystem::popCount(device) == 2) { -        setStrategyMute(STRATEGY_MEDIA, true, output); -        // wait for the PCM output buffers to empty before proceeding with the rest of the command -        usleep(outputDesc->mLatency*2*1000); -    } -#ifdef WITH_A2DP -    // suspend A2DP output if SCO device is selected -    if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)device)) { -         if (mA2dpOutput != 0) { -             mpClientInterface->suspendOutput(mA2dpOutput); -         } -    } -#endif -    // do the routing -    AudioParameter param = AudioParameter(); -    param.addInt(String8(AudioParameter::keyRouting), (int)device); -    mpClientInterface->setParameters(mHardwareOutput, param.toString(), delayMs); -    // update stream volumes according to new device -    applyStreamVolumes(output, device, delayMs); - -#ifdef WITH_A2DP -    // if disconnecting SCO device, restore A2DP output -    if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)prevDevice)) { -         if (mA2dpOutput != 0) { -             LOGV("restore A2DP output"); -             mpClientInterface->restoreOutput(mA2dpOutput); -         } -    } -#endif -    // if changing from a combined headset + speaker route, unmute media streams -    if (output == mHardwareOutput && AudioSystem::popCount(prevDevice) == 2) { -        setStrategyMute(STRATEGY_MEDIA, false, output, delayMs); -    } -} - -uint32_t AudioPolicyManagerBase::getDeviceForInputSource(int inputSource) -{ -    uint32_t device; - -    switch(inputSource) { -    case AUDIO_SOURCE_DEFAULT: -    case AUDIO_SOURCE_MIC: -    case AUDIO_SOURCE_VOICE_RECOGNITION: -        if (mForceUse[AudioSystem::FOR_RECORD] == AudioSystem::FORCE_BT_SCO && -            mAvailableInputDevices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) { -            device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET; -        } else if (mAvailableInputDevices & AudioSystem::DEVICE_IN_WIRED_HEADSET) { -            device = AudioSystem::DEVICE_IN_WIRED_HEADSET; -        } else { -            device = AudioSystem::DEVICE_IN_BUILTIN_MIC; -        } -        break; -    case AUDIO_SOURCE_CAMCORDER: -        if (hasBackMicrophone()) { -            device = AudioSystem::DEVICE_IN_BACK_MIC; -        } else { -            device = AudioSystem::DEVICE_IN_BUILTIN_MIC; -        } -        break; -    case AUDIO_SOURCE_VOICE_UPLINK: -    case AUDIO_SOURCE_VOICE_DOWNLINK: -    case AUDIO_SOURCE_VOICE_CALL: -        device = AudioSystem::DEVICE_IN_VOICE_CALL; -        break; -    default: -        LOGW("getInput() invalid input source %d", inputSource); -        device = 0; -        break; -    } -    LOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device); -    return device; -} - -audio_io_handle_t AudioPolicyManagerBase::getActiveInput() -{ -    for (size_t i = 0; i < mInputs.size(); i++) { -        if (mInputs.valueAt(i)->mRefCount > 0) { -            return mInputs.keyAt(i); -        } -    } -    return 0; -} - -float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_handle_t output, uint32_t device) -{ -    float volume = 1.0; -    AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output); -    StreamDescriptor &streamDesc = mStreams[stream]; - -    if (device == 0) { -        device = outputDesc->device(); -    } - -    int volInt = (100 * (index - streamDesc.mIndexMin)) / (streamDesc.mIndexMax - streamDesc.mIndexMin); -    volume = AudioSystem::linearToLog(volInt); - -    // if a headset is connected, apply the following rules to ring tones and notifications -    // to avoid sound level bursts in user's ears: -    // - always attenuate ring tones and notifications volume by 6dB -    // - if music is playing, always limit the volume to current music volume, -    // with a minimum threshold at -36dB so that notification is always perceived. -    if ((device & -        (AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP | -        AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | -        AudioSystem::DEVICE_OUT_WIRED_HEADSET | -        AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) && -        (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) && -        streamDesc.mCanBeMuted) { -        volume *= SONIFICATION_HEADSET_VOLUME_FACTOR; -        // when the phone is ringing we must consider that music could have been paused just before -        // by the music application and behave as if music was active if the last music track was -        // just stopped -        if (outputDesc->mRefCount[AudioSystem::MUSIC] || mLimitRingtoneVolume) { -            float musicVol = computeVolume(AudioSystem::MUSIC, mStreams[AudioSystem::MUSIC].mIndexCur, output, device); -            float minVol = (musicVol > SONIFICATION_HEADSET_VOLUME_MIN) ? musicVol : SONIFICATION_HEADSET_VOLUME_MIN; -            if (volume > minVol) { -                volume = minVol; -                LOGV("computeVolume limiting volume to %f musicVol %f", minVol, musicVol); -            } -        } -    } - -    return volume; -} - -status_t AudioPolicyManagerBase::checkAndSetVolume(int stream, int index, audio_io_handle_t output, uint32_t device, int delayMs, bool force) -{ - -    // do not change actual stream volume if the stream is muted -    if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) { -        LOGV("checkAndSetVolume() stream %d muted count %d", stream, mOutputs.valueFor(output)->mMuteCount[stream]); -        return NO_ERROR; -    } - -    // do not change in call volume if bluetooth is connected and vice versa -    if ((stream == AudioSystem::VOICE_CALL && mForceUse[AudioSystem::FOR_COMMUNICATION] == AudioSystem::FORCE_BT_SCO) || -        (stream == AudioSystem::BLUETOOTH_SCO && mForceUse[AudioSystem::FOR_COMMUNICATION] != AudioSystem::FORCE_BT_SCO)) { -        LOGV("checkAndSetVolume() cannot set stream %d volume with force use = %d for comm", -             stream, mForceUse[AudioSystem::FOR_COMMUNICATION]); -        return INVALID_OPERATION; -    } - -    float volume = computeVolume(stream, index, output, device); -    // do not set volume if the float value did not change -    if (volume != mOutputs.valueFor(output)->mCurVolume[stream] || force) { -        mOutputs.valueFor(output)->mCurVolume[stream] = volume; -        LOGV("setStreamVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs); -        if (stream == AudioSystem::VOICE_CALL || -            stream == AudioSystem::DTMF || -            stream == AudioSystem::BLUETOOTH_SCO) { -            float voiceVolume = -1.0; -            // offset value to reflect actual hardware volume that never reaches 0 -            // 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java) -            volume = 0.01 + 0.99 * volume; -            if (stream == AudioSystem::VOICE_CALL) { -                voiceVolume = (float)index/(float)mStreams[stream].mIndexMax; -            } else if (stream == AudioSystem::BLUETOOTH_SCO) { -                voiceVolume = 1.0; -            } -            if (voiceVolume >= 0 && output == mHardwareOutput) { -                mpClientInterface->setVoiceVolume(voiceVolume, delayMs); -            } -        } -        mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs); -    } - -    return NO_ERROR; -} - -void AudioPolicyManagerBase::applyStreamVolumes(audio_io_handle_t output, uint32_t device, int delayMs) -{ -    LOGV("applyStreamVolumes() for output %d and device %x", output, device); - -    for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { -        checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, device, delayMs); -    } -} - -void AudioPolicyManagerBase::setStrategyMute(routing_strategy strategy, bool on, audio_io_handle_t output, int delayMs) -{ -    LOGV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output); -    for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { -        if (getStrategy((AudioSystem::stream_type)stream) == strategy) { -            setStreamMute(stream, on, output, delayMs); -        } -    } -} - -void AudioPolicyManagerBase::setStreamMute(int stream, bool on, audio_io_handle_t output, int delayMs) -{ -    StreamDescriptor &streamDesc = mStreams[stream]; -    AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output); - -    LOGV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d", stream, on, output, outputDesc->mMuteCount[stream]); - -    if (on) { -        if (outputDesc->mMuteCount[stream] == 0) { -            if (streamDesc.mCanBeMuted) { -                checkAndSetVolume(stream, 0, output, outputDesc->device(), delayMs); -            } -        } -        // increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored -        outputDesc->mMuteCount[stream]++; -    } else { -        if (outputDesc->mMuteCount[stream] == 0) { -            LOGW("setStreamMute() unmuting non muted stream!"); -            return; -        } -        if (--outputDesc->mMuteCount[stream] == 0) { -            checkAndSetVolume(stream, streamDesc.mIndexCur, output, outputDesc->device(), delayMs); -        } -    } -} - -void AudioPolicyManagerBase::handleIncallSonification(int stream, bool starting, bool stateChange) -{ -    // if the stream pertains to sonification strategy and we are in call we must -    // mute the stream if it is low visibility. If it is high visibility, we must play a tone -    // in the device used for phone strategy and play the tone if the selected device does not -    // interfere with the device used for phone strategy -    // if stateChange is true, we are called from setPhoneState() and we must mute or unmute as -    // many times as there are active tracks on the output - -    if (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) { -        AudioOutputDescriptor *outputDesc = mOutputs.valueFor(mHardwareOutput); -        LOGV("handleIncallSonification() stream %d starting %d device %x stateChange %d", -                stream, starting, outputDesc->mDevice, stateChange); -        if (outputDesc->mRefCount[stream]) { -            int muteCount = 1; -            if (stateChange) { -                muteCount = outputDesc->mRefCount[stream]; -            } -            if (AudioSystem::isLowVisibility((AudioSystem::stream_type)stream)) { -                LOGV("handleIncallSonification() low visibility, muteCount %d", muteCount); -                for (int i = 0; i < muteCount; i++) { -                    setStreamMute(stream, starting, mHardwareOutput); -                } -            } else { -                LOGV("handleIncallSonification() high visibility"); -                if (outputDesc->device() & getDeviceForStrategy(STRATEGY_PHONE)) { -                    LOGV("handleIncallSonification() high visibility muted, muteCount %d", muteCount); -                    for (int i = 0; i < muteCount; i++) { -                        setStreamMute(stream, starting, mHardwareOutput); -                    } -                } -                if (starting) { -                    mpClientInterface->startTone(ToneGenerator::TONE_SUP_CALL_WAITING, AudioSystem::VOICE_CALL); -                } else { -                    mpClientInterface->stopTone(); -                } -            } -        } -    } -} - -bool AudioPolicyManagerBase::needsDirectOuput(AudioSystem::stream_type stream, -                                    uint32_t samplingRate, -                                    uint32_t format, -                                    uint32_t channels, -                                    AudioSystem::output_flags flags, -                                    uint32_t device) -{ -   return ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) || -          (format !=0 && !AudioSystem::isLinearPCM(format))); -} - -// --- AudioOutputDescriptor class implementation - -AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor() -    : mId(0), mSamplingRate(0), mFormat(0), mChannels(0), mLatency(0), -    mFlags((AudioSystem::output_flags)0), mDevice(0), mOutput1(0), mOutput2(0) -{ -    // clear usage count for all stream types -    for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) { -        mRefCount[i] = 0; -        mCurVolume[i] = -1.0; -        mMuteCount[i] = 0; -    } -} - -uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::device() -{ -    uint32_t device = 0; -    if (isDuplicated()) { -        device = mOutput1->mDevice | mOutput2->mDevice; -    } else { -        device = mDevice; -    } -    return device; -} - -void AudioPolicyManagerBase::AudioOutputDescriptor::changeRefCount(AudioSystem::stream_type stream, int delta) -{ -    // forward usage count change to attached outputs -    if (isDuplicated()) { -        mOutput1->changeRefCount(stream, delta); -        mOutput2->changeRefCount(stream, delta); -    } -    if ((delta + (int)mRefCount[stream]) < 0) { -        LOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", delta, stream, mRefCount[stream]); -        mRefCount[stream] = 0; -        return; -    } -    mRefCount[stream] += delta; -    LOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]); -} - -uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::refCount() -{ -    uint32_t refcount = 0; -    for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) { -        refcount += mRefCount[i]; -    } -    return refcount; -} - -uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::strategyRefCount(routing_strategy strategy) -{ -    uint32_t refCount = 0; -    for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) { -        if (getStrategy((AudioSystem::stream_type)i) == strategy) { -            refCount += mRefCount[i]; -        } -    } -    return refCount; -} - - -status_t AudioPolicyManagerBase::AudioOutputDescriptor::dump(int fd) -{ -    const size_t SIZE = 256; -    char buffer[SIZE]; -    String8 result; - -    snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate); -    result.append(buffer); -    snprintf(buffer, SIZE, " Format: %d\n", mFormat); -    result.append(buffer); -    snprintf(buffer, SIZE, " Channels: %08x\n", mChannels); -    result.append(buffer); -    snprintf(buffer, SIZE, " Latency: %d\n", mLatency); -    result.append(buffer); -    snprintf(buffer, SIZE, " Flags %08x\n", mFlags); -    result.append(buffer); -    snprintf(buffer, SIZE, " Devices %08x\n", device()); -    result.append(buffer); -    snprintf(buffer, SIZE, " Stream volume refCount muteCount\n"); -    result.append(buffer); -    for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) { -        snprintf(buffer, SIZE, " %02d     %.03f     %02d       %02d\n", i, mCurVolume[i], mRefCount[i], mMuteCount[i]); -        result.append(buffer); -    } -    write(fd, result.string(), result.size()); - -    return NO_ERROR; -} - -// --- AudioInputDescriptor class implementation - -AudioPolicyManagerBase::AudioInputDescriptor::AudioInputDescriptor() -    : mSamplingRate(0), mFormat(0), mChannels(0), -     mAcoustics((AudioSystem::audio_in_acoustics)0), mDevice(0), mRefCount(0) -{ -} - -status_t AudioPolicyManagerBase::AudioInputDescriptor::dump(int fd) -{ -    const size_t SIZE = 256; -    char buffer[SIZE]; -    String8 result; - -    snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate); -    result.append(buffer); -    snprintf(buffer, SIZE, " Format: %d\n", mFormat); -    result.append(buffer); -    snprintf(buffer, SIZE, " Channels: %08x\n", mChannels); -    result.append(buffer); -    snprintf(buffer, SIZE, " Acoustics %08x\n", mAcoustics); -    result.append(buffer); -    snprintf(buffer, SIZE, " Devices %08x\n", mDevice); -    result.append(buffer); -    snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount); -    result.append(buffer); -    write(fd, result.string(), result.size()); - -    return NO_ERROR; -} - -// --- StreamDescriptor class implementation - -void AudioPolicyManagerBase::StreamDescriptor::dump(char* buffer, size_t size) -{ -    snprintf(buffer, size, "      %02d         %02d         %02d         %d\n", -            mIndexMin, -            mIndexMax, -            mIndexCur, -            mCanBeMuted); -} - - -}; // namespace android | 
