text:
#define LOG_TAG "AudioPolicyManager7627a"
//#define LOG_NDEBUG 0

//#define VERY_VERBOSE_LOGGING
#ifdef VERY_VERBOSE_LOGGING
#define ALOGVV ALOGV
#else
#define ALOGVV(a...) do { } while(0)
#endif

// A device mask for all audio input devices that are considered "virtual" when evaluating
// active inputs in getActiveInput()
#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL  AUDIO_DEVICE_IN_REMOTE_SUBMIX

#include <utils/Log.h>
#include "AudioPolicyManager.h"
#include <hardware/audio_effect.h>
#include <media/mediarecorder.h>
#include <hardware/audio.h>
#include <math.h>
#include <hardware_legacy/audio_policy_conf.h>
#include <fcntl.h>
#include <cutils/properties.h> // for property_get

namespace android_audio_legacy {

// ----------------------------------------------------------------------------
// AudioPolicyManager for msm7k platform
// Common audio policy manager code is implemented in AudioPolicyManagerBase class
// ----------------------------------------------------------------------------

// ---  class factory

extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
    return new AudioPolicyManager(clientInterface);
}

extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface)
{
    delete interface;
}

audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy, bool fromCache)
{
    uint32_t device = 0;

    if (fromCache) {
        ALOGV("getDeviceForStrategy() from cache strategy %d, device %x",
              strategy, mDeviceForStrategy[strategy]);
        return mDeviceForStrategy[strategy];
    }

    switch (strategy) {

    case STRATEGY_SONIFICATION_RESPECTFUL:
        if (isInCall()) {
            device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/);
        } else if (isStreamActive(AudioSystem::MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
            // while media is playing (or has recently played), use the same device
            device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/);
        } else {
            // when media is not playing anymore, fall back on the sonification behavior
            device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/);
        }

        break;

    case STRATEGY_DTMF:
        if (!isInCall()) {
            // when off call, DTMF strategy follows the same rules as MEDIA strategy
            device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/);
            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 (!isInCall() || 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
            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
            if (mHasA2dp && !isInCall() &&
                    (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) &&
                    (getA2dpOutput() != 0) && !mA2dpSuspended) {
                device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
                if (device) break;
                device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
                if (device) break;
            }
            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
            if (device) break;
            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
            if (device) break;
            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
            if (device) break;
            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
            if (device) break;
            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
            if (device) break;
            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
            if (device) break;
            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE;
            if (device) break;
            device = mDefaultOutputDevice;
            if (device == 0) {
                ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE");
            }
            break;

        case AudioSystem::FORCE_SPEAKER:
            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
            // A2DP speaker when forcing to speaker output
            if (mHasA2dp && !isInCall() &&
                    (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) &&
                    (getA2dpOutput() != 0) && !mA2dpSuspended) {
                device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
                if (device) break;
            }
            device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
            if (device) break;
            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
            if (device) break;
            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
            if (device) break;
            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
            if (device) break;
            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
            if (device) break;
            device = mDefaultOutputDevice;
            if (device == 0) {
                ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER");
            }
            break;
        }
    break;

    case STRATEGY_SONIFICATION:

        // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
        // handleIncallSonification().
        if (isInCall()) {
            device = getDeviceForStrategy(STRATEGY_PHONE, false /*fromCache*/);
            break;
        }
        // FALL THROUGH

    case STRATEGY_ENFORCED_AUDIBLE:
        // strategy STRATEGY_ENFORCED_AUDIBLE uses same routing policy as STRATEGY_SONIFICATION
        // except:
        //   - when in call where it doesn't default to STRATEGY_PHONE behavior
        //   - in countries where not enforced in which case it follows STRATEGY_MEDIA

        if (strategy == STRATEGY_SONIFICATION ||
                !mStreams[AUDIO_STREAM_ENFORCED_AUDIBLE].mCanBeMuted) {
            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
            if (device == 0) {
                ALOGE("getDeviceForStrategy() speaker device not found for STRATEGY_SONIFICATION");
            }
        }
        // The second device used for sonification is the same as the device used by media strategy
        // FALL THROUGH

        // for analog FM alerts should be played on the speaker only
        if(FM_ANALOG == getFMMode())
            break;
    case STRATEGY_MEDIA: {
        uint32_t device2 = 0;
        switch (mForceUse[AudioSystem::FOR_MEDIA]) {
        default:{
        if ((mHasA2dp && (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) &&
                (getA2dpOutput() != 0) && !mA2dpSuspended ) && !(FM_ANALOG == getFMMode())) {
            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;
            }
        }
        if (device2 == 0) {
            device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
        }
        if (device2 == 0) {
            device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
        }
        if (device2 == 0) {
            device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
        }
        if (device2 == 0) {
            device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
        }
        if (device2 == 0) {
            device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
        }
        if (device2 == 0) {
            device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
        }
        if (device2 == 0) {
            device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
        }
        if (device2 == 0) {
            device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
        }

        // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or
        // STRATEGY_ENFORCED_AUDIBLE, 0 otherwise
        device |= device2;
        if (device) break;
        device = mDefaultOutputDevice;
      }
      case AudioSystem::FORCE_SPEAKER:
          device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
          break;
      }
#ifdef QCOM_FM_ENABLED
      if (mAvailableOutputDevices & AudioSystem::DEVICE_OUT_FM) {
         device |= AudioSystem::DEVICE_OUT_FM;
         if(FM_ANALOG == getFMMode()){
           if (device == (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADSET | AudioSystem::DEVICE_OUT_FM))
                device = AudioSystem::DEVICE_OUT_SPEAKER;
           else if(device & AudioSystem::DEVICE_OUT_WIRED_HEADSET)
                device &= ~(device & AudioSystem::DEVICE_OUT_WIRED_HEADSET);
         }
      }
#endif
      // Do not play media stream if in call and the requested device would change the hardware
      // output routing
      if (mPhoneState == AudioSystem::MODE_IN_CALL &&
         !AudioSystem::isA2dpDevice((AudioSystem::audio_devices)device) &&
           device != getDeviceForStrategy(STRATEGY_PHONE) &&
           strategy == STRATEGY_ENFORCED_AUDIBLE) {
          if (!mStreams[AUDIO_STREAM_ENFORCED_AUDIBLE].mCanBeMuted) {
              ALOGV("getDeviceForStrategy() do not change to phone device for ENFORCED_AUDIBLE");
          } else {
              device = getDeviceForStrategy(STRATEGY_PHONE);
              ALOGV("getDeviceForStrategy() incompatible media and phone devices");
          }
	  }
      if (device == 0) {
        ALOGE("getDeviceForStrategy() no device found for STRATEGY_MEDIA");
      }
    } break;

    default:
        ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
        break;
    }

    ALOGV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
    return (audio_devices_t)device;
}

uint32_t AudioPolicyManager::checkDeviceMuteStrategies(AudioOutputDescriptor *outputDesc,
                                                       audio_devices_t prevDevice,
                                                       uint32_t delayMs)
{
    // mute/unmute strategies using an incompatible device combination
    // if muting, wait for the audio in pcm buffer to be drained before proceeding
    // if unmuting, unmute only after the specified delay
    if (outputDesc->isDuplicated()) {
        return 0;
    }

    uint32_t muteWaitMs = 0;
    audio_devices_t device = outputDesc->device();
#ifdef QCOM_FM_ENABLED
    bool shouldMute = (outputDesc->refCount() != 0) &&
                    (AudioSystem::popCount(device) >= (device & AUDIO_DEVICE_OUT_FM ? 3 : 2));
#else
    bool shouldMute = (outputDesc->refCount() != 0);
#endif
    // temporary mute output if device selection changes to avoid volume bursts due to
    // different per device volumes
    bool tempMute = (outputDesc->refCount() != 0) && (getDeviceForVolume(device) != getDeviceForVolume(prevDevice));

    for (size_t i = 0; i < NUM_STRATEGIES; i++) {
        audio_devices_t curDevice = getDeviceForStrategy((routing_strategy)i, false /*fromCache*/);
        bool mute = shouldMute && (curDevice & device) && (curDevice != device);
        bool doMute = false;

        if (mute && !outputDesc->mStrategyMutedByDevice[i]) {
            doMute = true;
            outputDesc->mStrategyMutedByDevice[i] = true;
        } else if (!mute && outputDesc->mStrategyMutedByDevice[i]){
            doMute = true;
            outputDesc->mStrategyMutedByDevice[i] = false;
        }
        if (doMute || tempMute) {
            for (size_t j = 0; j < mOutputs.size(); j++) {
                AudioOutputDescriptor *desc = mOutputs.valueAt(j);
                if ((desc->supportedDevices() & outputDesc->supportedDevices()) == 0) {
                    continue;
                }
                audio_io_handle_t curOutput = mOutputs.keyAt(j);
                ALOGVV("checkDeviceMuteStrategies() %s strategy %d (curDevice %04x) on output %d",
                      mute ? "muting" : "unmuting", i, curDevice, curOutput);
                setStrategyMute((routing_strategy)i, mute, curOutput, mute ? 0 : delayMs);
                if (desc->strategyRefCount((routing_strategy)i) != 0) {
                    if (tempMute) {
                        setStrategyMute((routing_strategy)i, true, curOutput);
                        setStrategyMute((routing_strategy)i, false, curOutput,
                                            desc->latency() * 2, device);
                    }
                    if (tempMute || mute) {
                        if (muteWaitMs < desc->latency()) {
                            muteWaitMs = desc->latency();
                        }
                    }
                }
            }
        }
    }

    // FIXME: should not need to double latency if volume could be applied immediately by the
    // audioflinger mixer. We must account for the delay between now and the next time
    // the audioflinger thread for this output will process a buffer (which corresponds to
    // one buffer size, usually 1/2 or 1/4 of the latency).
    muteWaitMs *= 2;
    // wait for the PCM output buffers to empty before proceeding with the rest of the command
    if (muteWaitMs > delayMs) {
        muteWaitMs -= delayMs;
        usleep(muteWaitMs * 1000);
        return muteWaitMs;
    }
    return 0;
}

status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
                                                      AudioSystem::device_connection_state state,
                                                      const char *device_address)
{
    SortedVector <audio_io_handle_t> outputs;

    ALOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address);
    // connect/disconnect only 1 device at a time
    if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;

    if (strlen(device_address) >= MAX_DEVICE_ADDRESS_LEN) {
        ALOGE("setDeviceConnectionState() invalid address: %s", device_address);
        return BAD_VALUE;
    }

    // handle output devices
    if (audio_is_output_device(device)) {
        if (!mHasA2dp && audio_is_a2dp_device(device)) {
            ALOGE("setDeviceConnectionState() invalid A2DP device: %x", device);
            return BAD_VALUE;
        }
        if (!mHasUsb && audio_is_usb_device(device)) {
            ALOGE("setDeviceConnectionState() invalid USB audio device: %x", device);
            return BAD_VALUE;
        }
        if (!mHasRemoteSubmix && audio_is_remote_submix_device((audio_devices_t)device)) {
            ALOGE("setDeviceConnectionState() invalid remote submix audio device: %x", device);
            return BAD_VALUE;
        }

        // save a copy of the opened output descriptors before any output is opened or closed
        // by checkOutputsForDevice(). This will be needed by checkOutputForAllStrategies()
        mPreviousOutputs = mOutputs;
        switch (state)
        {
        // handle output device connection
        case AudioSystem::DEVICE_STATE_AVAILABLE:
#ifdef QCOM_FM_ENABLED
            if(device == AudioSystem::DEVICE_OUT_FM){
                char value[PROPERTY_VALUE_MAX];
                fm_modes fmMode = FM_DIGITAL;

                if (property_get("hw.fm.isAnalog", value, NULL)
                && !strcasecmp(value, "true")){
                    fmMode = FM_ANALOG ;
                }

                ALOGD("Current FM mode %d, New Fm Mode %d",getFMMode(),fmMode);

                if (fmMode == getFMMode()){
                    ALOGE("FM is already connected in %d Mode",fmMode);
                    return INVALID_OPERATION;
                } else if (FM_NONE != getFMMode()){
                    ALOGE("Rejctng dev conction:Anlg FM & Dgtl FM Mutuly xclusve");
                    return INVALID_OPERATION;
                }else{
                    setFmMode(fmMode);
                    ALOGW("FM started in %d Mode",fmMode);
                }
            }
#endif
            if (mAvailableOutputDevices & device) {
                ALOGW("setDeviceConnectionState() device already connected: %x", device);
                return INVALID_OPERATION;
            }
            ALOGV("setDeviceConnectionState() connecting device %x", device);

            if (checkOutputsForDevice(device, state, outputs) != NO_ERROR) {
                return INVALID_OPERATION;
            }
            ALOGV("setDeviceConnectionState() checkOutputsForDevice() returned %d outputs",
                  outputs.size());
            // register new device as available
            mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices | device);
            ALOGV("setDeviceConnectionState() connecting device %x", mAvailableOutputDevices);

            if (!outputs.isEmpty()) {
                String8 paramStr;
                if (mHasA2dp && audio_is_a2dp_device(device)) {
                    // handle A2DP device connection
                    AudioParameter param;
                    param.add(String8(AUDIO_PARAMETER_A2DP_SINK_ADDRESS), String8(device_address));
                    paramStr = param.toString();
                    mA2dpDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
                    mA2dpSuspended = false;
                } else if (audio_is_bluetooth_sco_device(device)) {
                    // handle SCO device connection
                    mScoDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
                } else if (mHasUsb && audio_is_usb_device(device)) {
                    // handle USB device connection
                    mUsbCardAndDevice = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
                    paramStr = mUsbCardAndDevice;
                }
                if (!paramStr.isEmpty()) {
                    for (size_t i = 0; i < outputs.size(); i++) {
                        mpClientInterface->setParameters(outputs[i], paramStr);
                    }
                }
            }
            break;
        // handle output device disconnection
        case AudioSystem::DEVICE_STATE_UNAVAILABLE: {
#ifdef QCOM_FM_ENABLED
            if(device == AudioSystem::DEVICE_OUT_FM){
                uint32_t newDevice;
                fm_modes prevFmMode = getFMMode();

                ALOGD("turning off Fm device in Mode %d",getFMMode());
                setFmMode(FM_NONE);
                newDevice = getDeviceForStrategy(STRATEGY_MEDIA, false);
                if((FM_ANALOG == prevFmMode) && ((newDevice & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP) ||
                   (newDevice & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES)||
                   (newDevice & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER))) {
                    ALOGW("setDeviceConnectionState() FM off, switch to Wired Headset");
                    setOutputDevice(mPrimaryOutput, AUDIO_DEVICE_OUT_WIRED_HEADSET, true);
                }
            }
#endif
            if (!(mAvailableOutputDevices & device)) {
                ALOGW("setDeviceConnectionState() device not connected: %x", device);
                return INVALID_OPERATION;
            }

            ALOGV("setDeviceConnectionState() disconnecting device %x", device);
            // remove device from available output devices
            mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices & ~device);

            checkOutputsForDevice((audio_devices_t)device, state, outputs);
            if (mHasA2dp && audio_is_a2dp_device(device)) {
                // handle A2DP device disconnection
                mA2dpDeviceAddress = "";
                mA2dpSuspended = false;
            } else if (audio_is_bluetooth_sco_device(device)) {
                // handle SCO device disconnection
                mScoDeviceAddress = "";
            } else if (mHasUsb && audio_is_usb_device(device)) {
                // handle USB device disconnection
                mUsbCardAndDevice = "";
            }
        } break;

        default:
            ALOGE("setDeviceConnectionState() invalid state: %x", state);
            return BAD_VALUE;
        }

        audio_devices_t newDevice = AudioPolicyManagerBase::getNewDevice(mPrimaryOutput, false /*fromCache*/);
#ifdef QCOM_FM_ENABLED
        if (device == AudioSystem::DEVICE_OUT_FM) {
            if (state == AudioSystem::DEVICE_STATE_AVAILABLE) {
                mOutputs.valueFor(mPrimaryOutput)->changeRefCount(AudioSystem::FM, 1);
            }
            else {
                mOutputs.valueFor(mPrimaryOutput)->changeRefCount(AudioSystem::FM, -1);
            }
            if (newDevice == 0) {
                newDevice = getDeviceForStrategy(STRATEGY_MEDIA, false);
            }
        }
#endif
        setOutputDevice(mPrimaryOutput, newDevice);
        checkA2dpSuspend();
        AudioPolicyManagerBase::checkOutputForAllStrategies();
        // outputs must be closed after checkOutputForAllStrategies() is executed
        if (!outputs.isEmpty()) {
            for (size_t i = 0; i < outputs.size(); i++) {
                // close unused outputs after device disconnection or direct outputs that have been
                // opened by checkOutputsForDevice() to query dynamic parameters
                if ((state == AudioSystem::DEVICE_STATE_UNAVAILABLE) ||
                    ((mOutputs.valueFor(outputs[i])->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) &&
                    !((mOutputs.valueFor(outputs[i])->mFlags & AUDIO_OUTPUT_FLAG_LPA)||
                     (mOutputs.valueFor(outputs[i])->mFlags & AUDIO_OUTPUT_FLAG_TUNNEL) ||
                     (mOutputs.valueFor(outputs[i])->mFlags & AUDIO_OUTPUT_FLAG_VOIP_RX)))) {
                          closeOutput(outputs[i]);
                }
            }
        }

        updateDevicesAndOutputs();
        for (size_t i = 0; i < mOutputs.size(); i++) {
            setOutputDevice(mOutputs.keyAt(i), getNewDevice(mOutputs.keyAt(i), true /*fromCache*/),
                            true,
                            0);
        }

        if (device == AUDIO_DEVICE_OUT_WIRED_HEADSET) {
            device = AUDIO_DEVICE_IN_WIRED_HEADSET;
        } else if (device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO ||
                   device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET ||
                   device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
            device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
        } else {
            return NO_ERROR;
        }
    }
    // handle input devices
    if (audio_is_input_device(device)) {

        switch (state)
        {
        // handle input device connection
        case AudioSystem::DEVICE_STATE_AVAILABLE: {
            if (mAvailableInputDevices & device) {
                ALOGW("setDeviceConnectionState() device already connected: %d", device);
                return INVALID_OPERATION;
            }
            mAvailableInputDevices = mAvailableInputDevices | (device & ~AUDIO_DEVICE_BIT_IN);
            }
            break;

        // handle input device disconnection
        case AudioSystem::DEVICE_STATE_UNAVAILABLE: {
            if (!(mAvailableInputDevices & device)) {
                ALOGW("setDeviceConnectionState() device not connected: %d", device);
                return INVALID_OPERATION;
            }
            mAvailableInputDevices = (audio_devices_t) (mAvailableInputDevices & ~device);
            } break;

        default:
            ALOGE("setDeviceConnectionState() invalid state: %x", state);
            return BAD_VALUE;
        }

        audio_io_handle_t activeInput = getActiveInput();
        if (activeInput != 0) {
            AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput);
            audio_devices_t newDevice = getDeviceForInputSource(inputDesc->mInputSource);
            if ((newDevice != AUDIO_DEVICE_NONE) && (newDevice != inputDesc->mDevice)) {
                ALOGV("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;
    }

    ALOGW("setDeviceConnectionState() invalid device: %x", device);
    return BAD_VALUE;
}

AudioSystem::device_connection_state AudioPolicyManager::getDeviceConnectionState(audio_devices_t device,
                                                  const char *device_address)
{
    AudioSystem::device_connection_state state = AudioSystem::DEVICE_STATE_UNAVAILABLE;
    String8 address = String8(device_address);
    if (audio_is_output_device(device)) {
        if (device & mAvailableOutputDevices) {
            if (audio_is_a2dp_device(device) &&
                (!mHasA2dp || (address != "" && mA2dpDeviceAddress != address))) {
                return state;
            }
            if (audio_is_bluetooth_sco_device(device) &&
                address != "" && mScoDeviceAddress != address) {
                return state;
            }
            if (audio_is_usb_device(device) &&
                (!mHasUsb || (address != "" && mUsbCardAndDevice != address))) {
                ALOGE("getDeviceConnectionState() invalid device: %x", device);
                return state;
            }
            if (audio_is_remote_submix_device((audio_devices_t)device) && !mHasRemoteSubmix) {
                return state;
            }
            state = AudioSystem::DEVICE_STATE_AVAILABLE;
        }
    } else if (audio_is_input_device(device)) {
        if (device & mAvailableInputDevices) {
            state = AudioSystem::DEVICE_STATE_AVAILABLE;
        }
    }

    return state;
}

audio_io_handle_t AudioPolicyManager::getInput(int inputSource,
                                    uint32_t samplingRate,
                                    uint32_t format,
                                    uint32_t channelMask,
                                    AudioSystem::audio_in_acoustics acoustics)
{
    audio_io_handle_t input = 0;
    audio_devices_t device = getDeviceForInputSource(inputSource);

    ALOGV("getInput() inputSource %d, samplingRate %d, format %d, channelMask %x, acoustics %x",
          inputSource, samplingRate, format, channelMask, acoustics);

    if (device == AUDIO_DEVICE_NONE) {
        ALOGW("getInput() could not find device for inputSource %d", inputSource);
        return 0;
    }

    // adapt channel selection to input source
    switch(inputSource) {
    case AUDIO_SOURCE_VOICE_UPLINK:
        channelMask |= AudioSystem::CHANNEL_IN_VOICE_UPLINK;
        break;
    case AUDIO_SOURCE_VOICE_DOWNLINK:
        channelMask |= AudioSystem::CHANNEL_IN_VOICE_DNLINK;
        break;
    case AUDIO_SOURCE_VOICE_CALL:
        channelMask |= (AudioSystem::CHANNEL_IN_VOICE_UPLINK | AudioSystem::CHANNEL_IN_VOICE_DNLINK);
        break;
    default:
        break;
    }

    IOProfile *profile = getInputProfile(device,
                                         samplingRate,
                                         format,
                                         channelMask);
    if (profile == NULL) {
        ALOGW("getInput() could not find profile for device %04x, samplingRate %d, format %d,"
                "channelMask %04x",
                device, samplingRate, format, channelMask);
        return 0;
    }

    if (profile->mModule->mHandle == 0) {
        ALOGE("getInput(): HW module %s not opened", profile->mModule->mName);
        return 0;
    }

    AudioInputDescriptor *inputDesc = new AudioInputDescriptor(profile);

    inputDesc->mInputSource = inputSource;
    inputDesc->mDevice = device;
    inputDesc->mSamplingRate = samplingRate;
    inputDesc->mFormat = (audio_format_t)format;
    inputDesc->mChannelMask = (audio_channel_mask_t)channelMask;
    inputDesc->mRefCount = 0;
    input = mpClientInterface->openInput(profile->mModule->mHandle,
                                    &inputDesc->mDevice,
                                    &inputDesc->mSamplingRate,
                                    &inputDesc->mFormat,
                                    &inputDesc->mChannelMask);

    // only accept input with the exact requested set of parameters
    if (input == 0 ||
        (samplingRate != inputDesc->mSamplingRate) ||
        (format != inputDesc->mFormat) ||
        (channelMask != inputDesc->mChannelMask)) {
        ALOGV("getInput() failed opening input: samplingRate %d, format %d, channelMask %d",
                samplingRate, format, channelMask);
        if (input != 0) {
            mpClientInterface->closeInput(input);
        }
        delete inputDesc;
        return 0;
    }
    mInputs.add(input, inputDesc);
    return input;
}

void AudioPolicyManager::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
{
    ALOGV("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) {
            ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);
            return;
        }
        forceVolumeReeval = true;
        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_ANALOG_DOCK &&
            config != AudioSystem::FORCE_DIGITAL_DOCK && config != AudioSystem::FORCE_NONE &&
            config != AudioSystem::FORCE_NO_BT_A2DP) {
            ALOGW("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) {
            ALOGW("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 &&
            config != AudioSystem::FORCE_ANALOG_DOCK &&
            config != AudioSystem::FORCE_DIGITAL_DOCK) {
            ALOGW("setForceUse() invalid config %d for FOR_DOCK", config);
        }
        forceVolumeReeval = true;
        mForceUse[usage] = config;
        break;
    case AudioSystem::FOR_SYSTEM:
        if (config != AudioSystem::FORCE_NONE &&
            config != AudioSystem::FORCE_SYSTEM_ENFORCED) {
            ALOGW("setForceUse() invalid config %d for FOR_SYSTEM", config);
        }
        forceVolumeReeval = true;
        mForceUse[usage] = config;
        break;
    default:
        ALOGW("setForceUse() invalid usage %d", usage);
        break;
    }

    // check for device and output changes triggered by new force usage
    checkA2dpSuspend();
    checkOutputForAllStrategies();
    updateDevicesAndOutputs();
    for (size_t i = 0; i < mOutputs.size(); i++) {
        audio_io_handle_t output = mOutputs.keyAt(i);
        audio_devices_t newDevice = getNewDevice(output, true /*fromCache*/);
        setOutputDevice(output, newDevice, (newDevice != AUDIO_DEVICE_NONE));
        if (forceVolumeReeval && (newDevice != AUDIO_DEVICE_NONE)) {
            applyStreamVolumes(output, newDevice, 0, true);
        }
    }

    audio_io_handle_t activeInput = getActiveInput();
    if (activeInput != 0) {
        AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput);
        audio_devices_t newDevice = getDeviceForInputSource(inputDesc->mInputSource);
        if ((newDevice != AUDIO_DEVICE_NONE) && (newDevice != inputDesc->mDevice)) {
            ALOGV("setForceUse() 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());
        }
    }

}

AudioPolicyManagerBase::IOProfile *AudioPolicyManager::getProfileForDirectOutput(
                                                               audio_devices_t device,
                                                               uint32_t samplingRate,
                                                               uint32_t format,
                                                               uint32_t channelMask,
                                                               audio_output_flags_t flags)
{

    for (size_t i = 0; i < mHwModules.size(); i++) {
        if (mHwModules[i]->mHandle == 0) {
            continue;
        }
        for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) {
           AudioPolicyManagerBase::IOProfile *profile = mHwModules[i]->mOutputProfiles[j];
           if (isCompatibleProfile(profile, device, samplingRate, format,
                                           channelMask,
                                           (audio_output_flags_t)(flags|AUDIO_OUTPUT_FLAG_DIRECT))) {
               if (mAvailableOutputDevices & profile->mSupportedDevices) {
                   return mHwModules[i]->mOutputProfiles[j];
               }
           }
        }
    }
    return 0;
}

bool AudioPolicyManager::isCompatibleProfile(AudioPolicyManagerBase::IOProfile *profile,
                                             audio_devices_t device,
                                             uint32_t samplingRate,
                                             uint32_t format,
                                             uint32_t channelMask,
                                            audio_output_flags_t flags)
{
    if ((profile->mSupportedDevices & device) != device) {
        return false;
    }
    if (profile->mFlags != flags) {
        return false;
    }
    if (samplingRate != 0) {
        size_t i;
        for (i = 0; i < profile->mSamplingRates.size(); i++)
        {
            if (profile->mSamplingRates[i] == samplingRate) {
                break;
            }
        }
        if (i == profile->mSamplingRates.size()) {
            return false;
        }
    }
    if (format != 0) {
        size_t i;
        for (i = 0; i < profile->mFormats.size(); i++)
        {
            if (profile->mFormats[i] == format) {
                break;
            }
        }
        if (i == profile->mFormats.size()) {
            return false;
        }
    }
    if (channelMask != 0) {
        size_t i;
       for (i = 0; i < profile->mChannelMasks.size(); i++)
        {
            if (profile->mChannelMasks[i] == channelMask) {
                break;
            }
        }
        if (i == profile->mChannelMasks.size()) {
            return false;
        }
    }
    ALOGD(" profile found: device %x, flags %x, samplingrate %d,\
            format %x, channelMask %d",
            device, flags, samplingRate, format, channelMask);
    return true;
}

status_t AudioPolicyManager::checkOutputsForDevice(audio_devices_t device,
                                                       AudioSystem::device_connection_state state,
                                                       SortedVector<audio_io_handle_t>& outputs)
{
    AudioOutputDescriptor *desc;

    if (state == AudioSystem::DEVICE_STATE_AVAILABLE) {
        // first list already open outputs that can be routed to this device
        for (size_t i = 0; i < mOutputs.size(); i++) {
            desc = mOutputs.valueAt(i);
            if (!desc->isDuplicated() && (desc->mProfile->mSupportedDevices & device)) {
                ALOGV("checkOutputsForDevice(): adding opened output %d", mOutputs.keyAt(i));
                outputs.add(mOutputs.keyAt(i));
            }
        }
        // then look for output profiles that can be routed to this device
        SortedVector<IOProfile *> profiles;
        for (size_t i = 0; i < mHwModules.size(); i++)
        {
            if (mHwModules[i]->mHandle == 0) {
                continue;
            }
            for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
            {
                if (mHwModules[i]->mOutputProfiles[j]->mSupportedDevices & device) {
                    ALOGV("checkOutputsForDevice(): adding profile %d from module %d", j, i);
                    profiles.add(mHwModules[i]->mOutputProfiles[j]);
                }
            }
        }

        if (profiles.isEmpty() && outputs.isEmpty()) {
            ALOGW("checkOutputsForDevice(): No output available for device %04x", device);
            return BAD_VALUE;
        }

        // open outputs for matching profiles if needed. Direct outputs are also opened to
        // query for dynamic parameters and will be closed later by setDeviceConnectionState()
        for (ssize_t profile_index = 0; profile_index < (ssize_t)profiles.size(); profile_index++) {
            IOProfile *profile = profiles[profile_index];

            // nothing to do if one output is already opened for this profile
            size_t j;
            for (j = 0; j < mOutputs.size(); j++) {
                desc = mOutputs.valueAt(j);
                if (!desc->isDuplicated() && desc->mProfile == profile) {
                    break;
                }
            }
            if (j != mOutputs.size()) {
                continue;
            }

            ALOGV("opening output for device %08x", device);
            desc = new AudioOutputDescriptor(profile);
            desc->mDevice = device;
            audio_io_handle_t output = 0;
            if (!(desc->mFlags & AUDIO_OUTPUT_FLAG_LPA || desc->mFlags & AUDIO_OUTPUT_FLAG_TUNNEL ||
                desc->mFlags & AUDIO_OUTPUT_FLAG_VOIP_RX)) {
                output =  mpClientInterface->openOutput(profile->mModule->mHandle,
                                                        &desc->mDevice,
                                                        &desc->mSamplingRate,
                                                        &desc->mFormat,
                                                        &desc->mChannelMask,
                                                        &desc->mLatency,
                                                        desc->mFlags);
            }
            if (output != 0) {
                if (desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) {
                    String8 reply;
                    char *value;
                    if (profile->mSamplingRates[0] == 0) {
                        reply = mpClientInterface->getParameters(output,
                                                String8(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES));
                        ALOGV("checkOutputsForDevice() direct output sup sampling rates %s",
                                  reply.string());
                        value = strpbrk((char *)reply.string(), "=");
                        if (value != NULL) {
                            loadSamplingRates(value, profile);
                        }
                    }
                    if (profile->mFormats[0] == 0) {
                        reply = mpClientInterface->getParameters(output,
                                                       String8(AUDIO_PARAMETER_STREAM_SUP_FORMATS));
                        ALOGV("checkOutputsForDevice() direct output sup formats %s",
                                  reply.string());
                        value = strpbrk((char *)reply.string(), "=");
                        if (value != NULL) {
                            loadFormats(value, profile);
                        }
                    }
                    if (profile->mChannelMasks[0] == 0) {
                        reply = mpClientInterface->getParameters(output,
                                                      String8(AUDIO_PARAMETER_STREAM_SUP_CHANNELS));
                        ALOGV("checkOutputsForDevice() direct output sup channel masks %s",
                                  reply.string());
                        value = strpbrk((char *)reply.string(), "=");
                        if (value != NULL) {
                            loadOutChannels(value + 1, profile);
                        }
                    }
                    if (((profile->mSamplingRates[0] == 0) &&
                             (profile->mSamplingRates.size() < 2)) ||
                         ((profile->mFormats[0] == 0) &&
                             (profile->mFormats.size() < 2)) ||
                         ((profile->mFormats[0] == 0) &&
                             (profile->mChannelMasks.size() < 2))) {
                        ALOGW("checkOutputsForDevice() direct output missing param");
                        output = 0;
                    } else {
                        addOutput(output, desc);
                    }
                } else {
                    audio_io_handle_t duplicatedOutput = 0;
                    // add output descriptor
                    addOutput(output, desc);
                    // set initial stream volume for device
                    applyStreamVolumes(output, device, 0, true);

                    //TODO: configure audio effect output stage here

                    // open a duplicating output thread for the new output and the primary output
                    duplicatedOutput = mpClientInterface->openDuplicateOutput(output,
                                                                              mPrimaryOutput);
                    if (duplicatedOutput != 0) {
                        // add duplicated output descriptor
                        AudioOutputDescriptor *dupOutputDesc = new AudioOutputDescriptor(NULL);
                        dupOutputDesc->mOutput1 = mOutputs.valueFor(mPrimaryOutput);
                        dupOutputDesc->mOutput2 = mOutputs.valueFor(output);
                        dupOutputDesc->mSamplingRate = desc->mSamplingRate;
                        dupOutputDesc->mFormat = desc->mFormat;
                        dupOutputDesc->mChannelMask = desc->mChannelMask;
                        dupOutputDesc->mLatency = desc->mLatency;
                        addOutput(duplicatedOutput, dupOutputDesc);
                        applyStreamVolumes(duplicatedOutput, device, 0, true);
                    } else {
                        ALOGW("checkOutputsForDevice() could not open dup output for %d and %d",
                                mPrimaryOutput, output);
                        mpClientInterface->closeOutput(output);
                        mOutputs.removeItem(output);
                        output = 0;
                    }
                }
            }
            if (output == 0) {
                ALOGW("checkOutputsForDevice() could not open output for device %x", device);
                delete desc;
                profiles.removeAt(profile_index);
                profile_index--;
            } else {
                outputs.add(output);
                ALOGV("checkOutputsForDevice(): adding output %d", output);
            }
        }

        if (profiles.isEmpty()) {
            ALOGW("checkOutputsForDevice(): No output available for device %04x", device);
            return BAD_VALUE;
        }
    } else {
        // check if one opened output is not needed any more after disconnecting one device
        for (size_t i = 0; i < mOutputs.size(); i++) {
            desc = mOutputs.valueAt(i);
            if (!desc->isDuplicated() &&
                    !(desc->mProfile->mSupportedDevices & mAvailableOutputDevices)) {
                ALOGV("checkOutputsForDevice(): disconnecting adding output %d", mOutputs.keyAt(i));
                outputs.add(mOutputs.keyAt(i));
            }
        }
        for (size_t i = 0; i < mHwModules.size(); i++)
        {
            if (mHwModules[i]->mHandle == 0) {
                continue;
            }
            for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
            {
                IOProfile *profile = mHwModules[i]->mOutputProfiles[j];
                if ((profile->mSupportedDevices & device) &&
                        (profile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {
                    ALOGV("checkOutputsForDevice(): clearing direct output profile %d on module %d",
                          j, i);
                    if (profile->mSamplingRates[0] == 0) {
                        profile->mSamplingRates.clear();
                        profile->mSamplingRates.add(0);
                    }
                    if (profile->mFormats[0] == 0) {
                        profile->mFormats.clear();
                        profile->mFormats.add((audio_format_t)0);
                    }
                    if (profile->mChannelMasks[0] == 0) {
                        profile->mChannelMasks.clear();
                        profile->mChannelMasks.add((audio_channel_mask_t)0);
                    }
                }
            }
        }
    }
    return NO_ERROR;
}

audio_devices_t AudioPolicyManager::getDeviceForInputSource(int inputSource)
{
    uint32_t device = AUDIO_DEVICE_NONE;

    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 & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
            device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
        } else if (mAvailableInputDevices & AUDIO_DEVICE_IN_WIRED_HEADSET) {
            device = AUDIO_DEVICE_IN_WIRED_HEADSET;
        } else if (mAvailableInputDevices & AUDIO_DEVICE_IN_BUILTIN_MIC) {
            device = AUDIO_DEVICE_IN_BUILTIN_MIC;
        }
        break;
    case AUDIO_SOURCE_VOICE_COMMUNICATION:
        device = AUDIO_DEVICE_IN_COMMUNICATION;
        break;
    case AUDIO_SOURCE_CAMCORDER:
        if (mAvailableInputDevices & AUDIO_DEVICE_IN_BACK_MIC) {
            device = AUDIO_DEVICE_IN_BACK_MIC;
        } else if (mAvailableInputDevices & AUDIO_DEVICE_IN_BUILTIN_MIC) {
            device = AUDIO_DEVICE_IN_BUILTIN_MIC;
        }
        break;
    case AUDIO_SOURCE_VOICE_UPLINK:
    case AUDIO_SOURCE_VOICE_DOWNLINK:
    case AUDIO_SOURCE_VOICE_CALL:
        if (mAvailableInputDevices & AUDIO_DEVICE_IN_VOICE_CALL) {
            device = AUDIO_DEVICE_IN_VOICE_CALL;
        }
        break;
    case AUDIO_SOURCE_REMOTE_SUBMIX:
        if (mAvailableInputDevices & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
            device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
        }
        break;

#ifdef QCOM_FM_ENABLED
    case AUDIO_SOURCE_FM_RX:
        device = AudioSystem::DEVICE_IN_FM_RX;
        break;
    case AUDIO_SOURCE_FM_RX_A2DP:
        device = AudioSystem::DEVICE_IN_FM_RX_A2DP;
        break;
#endif
    default:
        ALOGW("getDeviceForInputSource() invalid input source %d", inputSource);
        break;
    }
    ALOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device);
    return device;
}

status_t AudioPolicyManager::startOutput(audio_io_handle_t output,
                                             AudioSystem::stream_type stream,
                                             int session)
{
    ALOGV("startOutput() output %d, stream %d, session %d", output, stream, session);
    ssize_t index = mOutputs.indexOfKey(output);
    if (index < 0) {
        ALOGW("startOutput() unknow output %d", output);
        return BAD_VALUE;
    }

    AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);

    // increment 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
    // necessary for a correct control of hardware output routing by startOutput() and stopOutput()
    outputDesc->changeRefCount(stream, 1);

    if (outputDesc->mRefCount[stream] == 1) {
        audio_devices_t prevDevice = outputDesc->device();
        audio_devices_t newDevice = AudioPolicyManagerBase::getNewDevice(output, false /*fromCache*/);
        routing_strategy strategy = AudioPolicyManagerBase::getStrategy(stream);
        bool shouldWait = (strategy == STRATEGY_SONIFICATION) ||
                            (strategy == STRATEGY_SONIFICATION_RESPECTFUL);
        uint32_t waitMs = 0;
        bool force = false;
        uint32_t muteWaitMs;
        for (size_t i = 0; i < mOutputs.size(); i++) {
            AudioOutputDescriptor *desc = mOutputs.valueAt(i);
            if (desc != outputDesc) {
                // force a device change if any other output is managed by the same hw
                // module and has a current device selection that differs from selected device.
                // In this case, the audio HAL must receive the new device selection so that it can
                // change the device currently selected by the other active output.
                if (outputDesc->sharesHwModuleWith(desc) &&
                    desc->device() != newDevice) {
                    force = true;
                }
                // wait for audio on other active outputs to be presented when starting
                // a notification so that audio focus effect can propagate.
                if (shouldWait && (desc->refCount() != 0) && (waitMs < desc->latency())) {
                    waitMs = desc->latency();
                }
            }
        }
    uint32_t NewDevice = (uint32_t)AudioPolicyManagerBase::getNewDevice(output, true);
#ifdef QCOM_FM_ENABLED
    if((stream == AudioSystem::SYSTEM) && (FM_ANALOG == getFMMode())
    && (NewDevice == AudioSystem::DEVICE_OUT_FM))
    {
        NewDevice |= AudioSystem::DEVICE_OUT_WIRED_HEADSET;
        ALOGE("Selecting AnlgFM + CODEC device %x",NewDevice);
        muteWaitMs = setOutputDevice(output, (audio_devices_t)NewDevice, true);
    }
    else
#endif
        muteWaitMs = setOutputDevice(output, (audio_devices_t)NewDevice, force);

        // handle special case for sonification while in call
        if (isInCall()) {
            AudioPolicyManagerBase::handleIncallSonification(stream, true, false);
        }

        // apply volume rules for current stream and device if necessary
        checkAndSetVolume(stream,
                          mStreams[stream].getVolumeIndex(newDevice),
                          output,
                          newDevice);

        // update the outputs if starting an output with a stream that can affect notification
        // routing
        handleNotificationRoutingForStream(stream);
        if (waitMs > muteWaitMs) {
            usleep((waitMs - muteWaitMs) * 2 * 1000);
        }
    }
    return NO_ERROR;
}

status_t AudioPolicyManager::stopOutput(audio_io_handle_t output,
                                            AudioSystem::stream_type stream,
                                            int session)
{
    ALOGV("stopOutput() output %d, stream %d, session %d", output, stream, session);
    ssize_t index = mOutputs.indexOfKey(output);
    if (index < 0) {
        ALOGW("stopOutput() unknow output %d", output);
        return BAD_VALUE;
    }

    AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);

    // handle special case for sonification while in call
    if (isInCall()) {
        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 stream was stopped - see isStreamActive()
        if (outputDesc->mRefCount[stream] == 0) {
            outputDesc->mStopTime[stream] = systemTime();
            audio_devices_t newDevice = getNewDevice(output, false /*fromCache*/);
            // delay the device switch by twice the latency because stopOutput() is executed when
            // the track stop() command is received and at that time the audio track buffer can
            // still contain data that needs to be drained. The latency only covers the audio HAL
            // and kernel buffers. Also the latency does not always include additional delay in the
            // audio path (audio DSP, CODEC ...)
         if(FM_ANALOG == getFMMode())
            setOutputDevice(output, newDevice,true);
        else
            setOutputDevice(output, newDevice, false, outputDesc->mLatency*2);

            // force restoring the device selection on other active outputs if it differs from the
            // one being selected for this output
            for (size_t i = 0; i < mOutputs.size(); i++) {
                audio_io_handle_t curOutput = mOutputs.keyAt(i);
                AudioOutputDescriptor *desc = mOutputs.valueAt(i);
                if (curOutput != output &&
                        desc->refCount() != 0 &&
                        outputDesc->sharesHwModuleWith(desc) &&
                        newDevice != desc->device()) {
                    setOutputDevice(curOutput,
                                    getNewDevice(curOutput, false /*fromCache*/),
                                    true,
                                    outputDesc->mLatency*2);
                }
            }
            // update the outputs if stopping one with a stream that can affect notification routing
            handleNotificationRoutingForStream(stream);
        }
        return NO_ERROR;
    } else {
        ALOGW("stopOutput() refcount is already 0 for output %d", output);
        return INVALID_OPERATION;
    }
}

uint32_t AudioPolicyManager::setOutputDevice(audio_io_handle_t output, audio_devices_t device, bool force, int delayMs)
{
    ALOGV("setOutputDevice() output %d device %04x delayMs %d", output, device, delayMs);
    uint32_t muteWaitMs = 0;
    AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
    AudioParameter param;

    if (outputDesc->isDuplicated()) {
        muteWaitMs = setOutputDevice(outputDesc->mOutput1->mId, device, force, delayMs);
        muteWaitMs += setOutputDevice(outputDesc->mOutput2->mId, device, force, delayMs);
        return muteWaitMs;
    }
    // filter devices according to output selected
    device = (audio_devices_t)(device & outputDesc->mProfile->mSupportedDevices);

    audio_devices_t prevDevice = outputDesc->mDevice;

    ALOGV("setOutputDevice() prevDevice %04x", prevDevice);

    if (device != 0) {
        outputDesc->mDevice = device;
    }
    muteWaitMs = checkDeviceMuteStrategies(outputDesc, prevDevice, delayMs);

    // Do not change the routing if:
    //  - the requested 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) {
        ALOGV("setOutputDevice() setting null device for output %d", output);
        return muteWaitMs;
    }

    ALOGV("setOutputDevice() changing device");
    // do the routing
    param.addInt(String8(AudioParameter::keyRouting), (int)device);
    mpClientInterface->setParameters(output, param.toString(), delayMs);

    // update stream volumes according to new device
    applyStreamVolumes(output, device, delayMs);

    return muteWaitMs;
}

audio_devices_t AudioPolicyManager::getDeviceForVolume(audio_devices_t device)
{
    if (device == 0) {
        // this happens when forcing a route update and no track is active on an output.
        // In this case the returned category is not important.
        device =  AUDIO_DEVICE_OUT_SPEAKER;
    } else if (AudioSystem::popCount(device) > 1) {
        // Multiple device selection is either:
        //  - speaker + one other device: give priority to speaker in this case.
        //  - one A2DP device + another device: happens with duplicated output. In this case
        // retain the device on the A2DP output as the other must not correspond to an active
        // selection if not the speaker.
        if (device & AUDIO_DEVICE_OUT_SPEAKER) {
            device = AUDIO_DEVICE_OUT_SPEAKER;
        }
#ifdef QCOM_FM_ENABLED
        else if (device & AUDIO_DEVICE_OUT_FM) {
            device = AUDIO_DEVICE_OUT_FM;
        }
#endif
        else if((device & AUDIO_DEVICE_OUT_WIRED_HEADSET) != 0) {
            device = AUDIO_DEVICE_OUT_WIRED_HEADSET;
        }
        else {
            device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP);
        }
    }

    ALOGW_IF(AudioSystem::popCount(device) != 1,
            "getDeviceForVolume() invalid device combination: %08x",
            device);

    return device;
}

status_t AudioPolicyManager::checkAndSetVolume(int stream, int index, audio_io_handle_t output, audio_devices_t device, int delayMs, bool force)
{
    // do not change actual stream volume if the stream is muted
    if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) {
        ALOGVV("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)) {
        ALOGV("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);
    // We actually change the volume if:
    // - the float value returned by computeVolume() changed
    // - the force flag is set
    if (volume != mOutputs.valueFor(output)->mCurVolume[stream]
#ifdef QCOM_FM_ENABLED
            || (stream == AudioSystem::FM)
#endif
            || force) {
        mOutputs.valueFor(output)->mCurVolume[stream] = volume;
        ALOGVV("checkAndSetVolume() 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) {
            // 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;
            // Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is
            // enabled
            if (stream == AudioSystem::BLUETOOTH_SCO) {
                mpClientInterface->setStreamVolume(AudioSystem::VOICE_CALL, volume, output, delayMs);
            }
        }

        mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs);
    }

    if (stream == AudioSystem::VOICE_CALL ||
        stream == AudioSystem::BLUETOOTH_SCO) {
        float voiceVolume;
        // Force voice volume to max for bluetooth SCO as volume is managed by the headset
        if (stream == AudioSystem::VOICE_CALL) {
            voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
        } else {
            voiceVolume = 1.0;
        }

        if ((voiceVolume != mLastVoiceVolume && output == mPrimaryOutput)
#ifdef QCOM_FM_ENABLED
	    && (!(mAvailableOutputDevices & AudioSystem::DEVICE_OUT_FM))
#endif
            ) {
            mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
            mLastVoiceVolume = voiceVolume;
        }
#ifdef QCOM_FM_ENABLED
    } else if ((stream == AudioSystem::FM) && (mAvailableOutputDevices & AudioSystem::DEVICE_OUT_FM)) {
        float fmVolume = -1.0;
        fmVolume = (float)index/(float)mStreams[stream].mIndexMax;
        if (fmVolume >= 0 && output == mPrimaryOutput) {
            mpClientInterface->setFmVolume(fmVolume, delayMs);
            mLastVoiceVolume = fmVolume;
        }
#endif
      }
    return NO_ERROR;
}

void AudioPolicyManager::handleNotificationRoutingForStream(AudioSystem::stream_type stream) {
    switch(stream) {
    case AudioSystem::MUSIC:
        checkOutputForStrategy(STRATEGY_SONIFICATION_RESPECTFUL);
        updateDevicesAndOutputs();
        break;
    default:
        break;
    }
}

}; // namespace android

redpajama_set_name: RedPajamaGithub


text:
Lenovo Yoga C640 review: Hard to recommend, but not for the reason you'd think
By Rich Woods Senior Editor for North America Neowin @@TheRichWoods · Jun 20, 2020 12:00 EDT · Hot! with 5 comments
Lenovo's Yoga C640 has an Intel processor this time around, unlike the Snapdragon-powered Yoga C630. It's the entry level for the company's Yoga series of convertibles, starting at $599. For that price, you get an Intel Core i3-10110U, 8GB RAM, and 128GB of storage.
It's a solid build, and just what I'd expect for around $600. The only problem is that I think you could do a bit better with your money. Lenovo also offers the Flex 5 with AMD Ryzen 5 4500U processors for right around the same price, and I'm having trouble why I shouldn't tell you to buy that instead. Not only does it have a far superior processor, but the pen comes included in the box.
Standing on its own, the C640 definitely feels like a winner, with a premium build quality and surprisingly good performance for a dual-core Core i3 processor.
Intel Core i3-10110U (2.1GHz)
306x204.48x16.95mm (12.05x8.05x0.67in), 1.35kg (2.98lbs)
13.3" (1920 x 1080) IPS, 300 nits, anti-glare multi-touch
8GB (DDR4-2666)
(1) USB 3.1 Type-C Gen 1 (with the function of Power Delivery, DisplayPort)
(2) USB 3.1 Type-A Gen 1 (Always On USB)
(1) 3.5mm stereo audio / microphone combo jack
Wi-Fi 2x2, Wi-Fi + Bluetooth 5.0, M.2 card, CNVi
720p HD fixed-focus, TrueBlock privacy shutter
Lenovo speakers with Dolby Atmos certification 2W x 2 dual-array microphone
60WHr
Top: Aluminum
Bottom: PC+30% Glass Fiber
The Lenovo Yoga C640 has that sleek and modern design that I'd expect from a Yoga convertible, made of aluminum and weighing in at less than three pounds. Unfortunately, it's both heavier and thicker than its predecessor, but that's what you'll get when switching from Qualcomm to Intel. Not only does the PC require a fan now, but it also ditches perks like 4G LTE connectivity.
It comes in the Iron Grey color that should be familiar to anyone that follows the Yoga line, and the Yoga logo stamped in the lid should be equally familiar. In other words, there's really nothing new where the design is concerned. It follows all of the Yoga standards that we've seen over the past few years.
With a thicker body, however, comes more ports. Last year's yoga C630 WOS (Windows on Snapdragon) only had a pair of USB 3.1 Gen 1 Type-C ports. This year, it adds back the USB Type-A ports, both of which are USB 3.1 Gen 1. You'll find one on the left side, along with the 3.5mm audio jack and a barrel charging port.
There's another one on the right side, along with a USB 3.1 Gen 1 Type-C port and a power button. There's some bad news here, which is that you can't use the USB Type-C port for charging. This, to me, is inexcusable. Again, this is something that the Flex 5 does offer.
USB Type-C charging is something that's tremendously useful. Even if it doesn't ship with a USB Type-C charger, it's nice to be able to do it. It means that you can use the same charger for different devices, and I can guarantee that at some point in the lifetime of the PC, you'd find that useful.
Display and audio
The Yoga C630 includes a 13.3-inch FHD touchscreen, and the resolution gives you a big enough pixel density for a 13-inch device. The brightness comes in at 300 nits, so you might have an issue in direct sunlight. If you work outdoors a lot, you should definitely look into something that's a little bit brighter. Also, Lenovo calls this screen anti-glare, but it's still pretty glossy.
The display does support pen input, although the pen doesn't come in the box. You'll have to shell out an additional $69.99 for the official Lenovo one, or you can pick up a third-party pen. I normally wouldn't fault Lenovo for not including a pen. To me, it's a common sense way to shave a few dollars off the price and hit that budget price point. However, and I know I keep bringing up the Flex 5, but that does come with the pen.
The bezels are about what you'd expect. They're fairly slim on the sides, while the top and bottom are larger, with the top bezel fitting a webcam. The webcam has a privacy guard built into it, so you don't have to worry about putting a piece of tape over it or anything like that. There's also no IR camera, which can be frustrating to use if you make use of the privacy guard. Luckily, there's a fingerprint sensor for biometric authentication.
The yoga C640 includes dual 2W Dolby Atmos speakers, and I have to say, they sound great in terms of both clarity and volume. The speakers sit on both sides of the keyboard deck, so they fire right up at you. Unfortunately, that also means that if you're using it as a tablet, they're firing away from you, or if you're using it in presentation mode, they're firing down.
Still, these are definitely impressive speakers at the $600 price point. It's something that you won't often see at the entry level.
If you follow my reviews, than you know that I always like Lenovo's keyboards, whether it's on a ThinkPad or a consumer PC. The interesting thing about that preference is that ThinkPads and Lenovo's consumer lineup have completely different keyboards. Frankly, the company is just really good at making keyboards.
The difference is that consumer PCs tend to have shallower keyboards than a ThinkPad. However, they still have the proper resistance to feel comfortable while typing. They're always accurate too, as I never find that I've missed a key stroke, or that I've double-typed a character. The Yoga C640 holds up to this.
If I could wish for an improvement, it would be that the keys be a little bit quieter when typing. This keyboard does have a certain clacking sound that Lenovo has solved in other laptops. Other than that, this is a great keyboard, and to be clear, that's probably the most important feature since that's the primary way of interacting with it.
The other way of interacting with it in laptop mode, of course, is the trackpad. It uses Microsoft Precision drivers, to it's fast, responsive, and supports all of the gestures that you're used to. The size is pretty average, with Lenovo using up the available landscape that it has on a 13-inch laptop.
Also found on the keyboard deck are the speakers to the left and right of the keys, and a fingerprint sensor to the bottom-right. Almost every Lenovo PC I've ever reviewed comes with a fingerprint sensor, and in fact, Lenovo was among the first to use one with its ThinkPad lineup. As always, it's nice to have, especially when there's no IR camera.
Performance and battery life
The Lenovo Yoga C640 that the company sent me includes an Intel Core i3-10110U processor, a dual-core 15W CPU with four threads. As a general rule, I recommend getting at least a Core i5, which has twice as many cores and thus twice as many threads. The good news is that you can get this device with a Core i5-10210U, although at that point, now the price starts at $689.99, and it leaves me wondering even more why you wouldn't go for the Flex 5.
I have to say though, performance was pretty solid for what I expected from a Core i3. It's been a long time since I've used any i3, and my experiences have not been positive. This is more than adequate for basic productivity tasks like writing, checking email, and so on. You'll start running into trouble if you start multitasking with stuff that would require more threads. You'll also want to stay away from any creative work like Photoshop.
Intel's Comet Lake family, which is where the i3-10110U comes from, is still built on a 14nm process, the same as it's been for years. Ice Lake is 10nm, but Intel actually had to turn down the clock speed to get to that size, and it made up for that by using Iris Plus Graphics. Still, the Ice Lake Core i3, the Core i3-1005G1, doesn't have Iris Plus, so Comet Lake is the better choice from all angles.
As far as battery life goes, it's pretty great. Depending on your power settings, you can get a solid eight hours out of it, more if you really stretch it with battery saver. While eight hours is about what you're looking at with average usage and average power settings, I was still able to get it down to about four hours, just by trying to perform some heavy tasks.
For benchmarks, I used PCMark 8 and PCMark 10.
PCMark 8: Home PCMark 8: Creative
PCMark 8: Work PCMark 10
We can compare this to the Dynabook Portégé X30L-G that I recently reviewed, which has a Core i5-10210U. That got 3,616 on Home, 3,511 on Creative, 3,679 on Work, and 3,906 on PCMark 10, so it's a big difference.
Don't get me wrong; the Lenovo Yoga C640 is a solid convertible and offers a lot of value at its $599 starting price point. But again, it just seems to me that there are better options for that price on the market, and some of those options even come from Lenovo. Like I said, the Flex 5 that I'll be reviewing next has a much more powerful AMD Ryzen 5 4500U processor, it actually comes with the pen, and more.
We're also missing out on a bunch of perks that came with last year's yoga C630, such as 4G LTE that came standard. The C640 doesn't even have it as an option. In fact, a more suitable successor is probably the Yoga 5G, but that's neither here nor there. But another issue with switching to Intel is that the C640 is now thicker and heavier than its predecessor.
But the biggest deal-breaker for me is that it doesn't support USB Type-C charging. This is something that should be in every laptop without a dedicated GPU at this point. I can get a $200 smartphone that charges via USB Type-C, so I don't understand why it wouldn't be a feature in a $600 laptop.
Other than that, the Yoga C640 is pretty great, packing the tried and true Yoga design, an impressive FHD display, and a great keyboard. It's a convertible at a $599 price point, and it has pen support. While I love recommending Lenovo PCs, I just don't think I can recommend this one.
Gallery: Lenovo Yoga C640 review
Yoga c640
Follow @TwitterDev
Get this Accredited PRINCE2® Project Management Bundle for only $68.99
Lenovo ThinkPad L13 Yoga unboxing and first impressions
Lenovo unveils new Legion gaming laptops with new Ryzen 5000, RTX 30 mobile, and more
Lenovo refreshes its ThinkBooks with a dual-screen ThinkBook Plus and AMD Ryzen processors
Lenovo's Yoga AIO 7 is an all-in-one with a rotating screen
5 Comments - Add comment

redpajama_set_name: RedPajamaCommonCrawl


text:
Illegal Drug Use Amongst Lawyers
05/07/2016 by Sydney Criminal Lawyers
By Blake O'Connor and Ugur Nedim
Lawyers are meant to fearlessly advance the interests of their clients, whilst respecting the law.
However, a number of cases, studies and reports suggest the legal profession is plagued by illicit drug use.
Last year, the NSW Office of the Director of Public Prosecutions (DPP) launched an investigation into its own lawyers after concerns were raised about illicit drug in its senior ranks. Ironically, these are the same lawyers who regularly prosecute drug cases in NSW.
One lawyer in the team, Lisa Munro, was charged with drug possession after being found with 0.65 grams of cocaine at Potts Point. She pleaded guilty, with the sentencing magistrate emphasising that a "loud and clear" message must be sent about the unacceptability of drug use.
And earlier this year, a Federal Circuit Court Judge's Associate was sentenced to a 12-month good behaviour bond after also being found in the possession of cocaine.
In another recent case, Australian Government Solicitor Nicholas Gouliadites pleaded guilty to supplying 'ice' to an undercover police officer on three occasions at his Sydney office. Mr Gouliadites was a habitual user of the drug, with colleagues reporting that he had overdosed at least once and was "literally falling apart at work".
In yet another recent case, Ugo Parente, a former criminal defence lawyer in Liverpool, was charged with a number of serious drug-related offences, including:
Supplying more than a commercial quantity of a prohibited drug;
Supplying more than an indictable quantity of a prohibited drug;
Supplying a prohibited drug (two counts);
Possessing a prohibited drug; and
Goods in custody.
On searching Mr Parente's home and car, police allegedly found more than 30 Sushi containers filled with the drug GHB.
Position of Trust
Lawyers are entrusted to act in the best interests of their clients, and drug use can affect both general performance and advocacy inside the courtroom – potentially leading to disastrous consequences for clients and their families. As the head of the Psychiatry at St Vincent's Clinic, Dr Fisher, points out:
"Just as (Doctors) can kill a patient, lawyers can cost their clients huge amounts of money and destroy their lives".
He believes more should be done to support and rehabilitate lawyers with drug and alcohol problems.
The fact that lawyers are expected to obey the law, and the potentially catastrophic consequences of drug-affected lawyers running cases inside the courtroom, has led to calls for members of the legal profession to receive tougher sentences for using illegal drugs.
Indeed, for certain types of cases such as fraud, any breach of trust is seen as an 'aggravating factor' for the purpose of sentencing. There is no general rule, however, that lawyers must receive harsher sentences for drug offences – although there is scope for prosecution submissions that the conduct is a reflection of general character, and could have affected clients.
'Extra Curial' Punishment
It should be noted that lawyers can face additional penalties for committing crimes – including having their practising certificates suspended or cancelled. Such penalties are significant given that lawyers study intensely for many years, often accumulating significant debts, to become members of the legal profession in the first place.
Lawyers are expected to act reputably in their professional and personal lives. Any disreputable, dishonest or illegal conduct can lead to proceedings by the relevant Law Society for "unsatisfactory professional conduct" or the more serious offence of "professional misconduct", which can see them permanently "struck off", in addition to penalties they may receive under the general law.
Sydney Criminal Lawyers® is Australia's Leading Criminal Defence firm, Delivering Outstanding Results in all Criminal and Driving cases. Going to Court? Call (02) 9261 8881 for a Free Consultation.
End Immigration Detention: Car Convoy Protest Descends on Villawood
The Role of a Support Person in Court
When It Comes to Punishing Refugees, Dutton Is the New Morrison
The Successful Black Lives Matter Appeal: An Interview With The Wigs' Stephen Lawrence
'Robo Cops' Are Being Used Worldwide – But Does the Public Want Them?
Queensland Considers Tracking Alleged Abusers
SEE PREVIOUS Islamic College Targeted by Hate Criminals
SEE NEXT Queensland Government Accused of Being 'Soft on Crime'


text:
Home » Blog » other » An-30
Antonov An-30 is a device designed for aerial photography and surveillance of the terrain. By codifying NATO organization is designated "Clank," and my own country is often called "Anastasia". This machine is designed on the basis of passenger An-24, only the last number of profound modifications. It can be used as a military intelligence officer.
History of An-30
This machine was designed in the walls of the Antonov Design Bureau in the summer of 1964 years. The basis of its creation were taken to the operating time of the AN-24. This version was primarily designed for the Air Force and Civil Air Fleet of the Soviet Union. That is why the machine is ready for both military and civilian use. It was equipped with the high-quality camera equipment at the time. Layout machine was ready in 65, and was presented to the customer.
The main difference between An-30 and the original aircraft was the forward part. An-30 is equipped with a glazed cockpit for the navigator, who was engaged in photography. Due to the installation of this cabin, the nose has become much wider. In addition, this upgrade allowed the installation of additional fuel tanks in the center wing and tightly closed the door into the luggage compartment. Also, the fairings under the fuselage of the car were installed. The cockpit began to be placed much higher, which allowed to increase the review for the pilots and the navigator. The management and maintenance of the machine in flight must be made by seven crew members. The device was intended to be equipped with photographic equipment, which would allow shooting on a scale up to 1: 150 000.
The first prototype was made in the design office of Beriev, which was located in Taganrog, at the beginning of 1967. For the first time the device detached from the runway in August 67 year. This prototype was 32 flight. A year later, An-30 passed tests at the Air Force Research Institute. By the summer of 68, all factory testing was completed, under which it was concluded that this unit has 6 thousand flight hours between repairs for 5 years. Tests by the state commission were completed in the summer of 70. In addition, state tests noted the advantage of the new model over the previous aircraft.
Serial manufacturing was started in 1971 year on the territory of the Kiev aircraft plant. Production continued until 1980 year, during this time 125 of such machines was produced. In addition to using An-30 in the territory of the USSR, it was exported to other countries of the world. For the first time the general public An-30 was presented at the air show in Le Bourget in 75. On the basis of a standard machine, a number of modifications were made, which were used to induce precipitation and for meteorological investigations. A machine for studying polar latitudes was also made. It was installed new navigation equipment such as "Toros" and additional fuel tanks to increase the range of flight.
Design features of the AN-30
The machine is designed for cantilever monoplane scheme, in which highly placed wings. Feathering was the vertical structure of the scheme, using the ridges under the body. A set of equipment for shooting and the location of crew members have been developed in two versions: for military and civilian use. The most significant changes were made to the nose compartment bulkhead 11.
An-30 video
Middle compartment machines previously designed for passengers in the An-24, and at the AN-30 were here are five covers for photographic equipment. Glass covers have a heating system that prevents them from freezing in flight. Manhole covers were opened with the help of electric drive. This compartment of the machine is equipped with a special room for display pictures. For the rest of the crew are provided folding bed and wardrobe storage.
Wings are located high and have a trapezoidal shape. The very design of the wing center section and is represented by four consoles. In the middle of the wing flaps set slot-like type, and on consoles - two sections of ailerons. They are equipped with servo tab and additional trimmers. Feathering tail is made in the cantilever scheme and has one fin made of metal.
The chassis of the AN-30 consists of three retractable racks that are installed pneumatic low pressure. Rear racks are cleaned in a special niche for the motors and the front desk - in a niche under the cockpit.
Powerplant scout AN-30 has two turboprop engines of the AI-24, which provide the aircraft at take-off power in 2,5 thousand horsepower. The motors mounted in the gondola of center. They drive the screws The four-feathering type, which are designated as AB-72. Start engine performs autonomous turbogenerator TG brand-16.
In this machine has two fuel systems, that are identical in their construction. Each engine has its own separate fuel tank in the wing. Furthermore, there is another tank in the center section, which can fill the one thousand liters of fuel. All tanks have a soft structure. When a failure of the fuel system can be connected in a single piece with a crane banding.
Electric power is provided by two generators installed on engines. When servicing the aircraft on the ground, there is a turbogenerator of the type TG-16. Two 30SAM batteries are installed on the An-12 board for emergency situations. The machine also has a system that prevents icing of the case with the help of warm air. The cockpit has an oxygen system, which is designed for 7 crew members. The hydraulic system provides chassis operation, flap rotation, windshield wipers. In addition, it can make an emergency stop of the engines. The entire hydraulic system consists of two parts that operate from hydraulic pumps and are driven by an electric motor.
At the moment, the car An-30 continue to actively exploit for surveying and intelligence operations in the CIS. Some devices An-30 reequipping a cargo or passenger plane on 20 seats.
An-30 characteristics:
Modification An-30A
Wingspan, m 29.20
Aircraft Length m 24.26
Height, m 8.32
Wing area, m2 72.46
Weight, kg
empty aircraft 15590
normal takeoff 20300
maximum take-off 23000
Fuel 4820
engine's type 2 TVD Progress AI-24BT + 1 TRD Union RU-19A-300
Power, hp 2 x 2817 + 1x7.65 kN
Maximum speed km / h 540
Cruising speed, km / h 476
Practical range, km 2600
Flight duration, h 6.6
Practical ceiling, m 8000
Crew 7
Stanislas 30 2015 in June 11: 55
I can say that for the time of An-30 really considered the best airplane. This machine during takeoff buzzing, vibrating, but 50-it's quite normal, then create the best machines can not. But even though these shortcomings, I believe that with the AN-30 can not be compared, no modern - Watermelon as "Annushka" best.
Egor 29 2015 in June 22: 04
First flown on An-30 years ago. During the flight, we have not met air pockets, but when the plane was down, a little shake. But the noise of the engines, reminds me of just music. I flew for about an hour, but the most important thing after the flight I did not hurt your ears. I'd like to see these aircraft began to produce again, why invent new machines, if there are already proven. If someone would have to fly on the AN-30 should not be afraid, it's not a modern machine in the computer management.
Slavik 26 2015 in June 19: 28
I flew to the An-30 than once. It's a beautiful aircraft, it flies steadily, especially I like the way it takes off, it does not shake when climbing, and there is no excessive noise. In general, I can say one thing, the car is good, it is a pity that today do not produce such aircraft.
Maksim 24 2015 in June 12: 16
An-30 - it's a miracle - a technique well, at least I think so. The aircraft developed in Kiev, my hometown. I live close to the airport so early in the sky often seen this car. Today in our country there are very few of these aircraft. I myself had the opportunity to fly the An-30 Aunt visit. I was only 10 years and at that age, I did not pay attention to the quality of the aircraft. But I also had to fly the An-30 in a more mature age, and then, I appreciated this machine appreciated!
Prohor 29 May 2015 in 14: 20
Those aircraft that was shot down by Slavic in June last year was the year of issue and 1967 47 years fly off! That's what "Made in USSR" Respect developers! This technique can only destroy an enemy shell.
Airline JAL Express
AeroVironment Switchblade. Specifications. A photo.
CAIG Sky Wing IH. Specifications. A photo.
What kind of stewardess oligarchs take on private jets?
Can our flight attendants post similar photos online?
Bombic photos of flight attendants - Virgin Atlantic
Why do flight attendants not take off their uniforms in bed?
Beautiful photos of stewardesses conquer the Internet
We are waiting in the series!


text:
Epstein Theatre Liverpool
Box Office: 0844 888 4411
Saturday 12 September 2020 Book Now
Darkside: The Pink Floyd Show
Tickets: £21
15 YEAR ANNIVERSARY TOUR
Darkside, The Pink Floyd Show, a tribute to the music of Britain's greatest progressive rock band, makes a welcome return to the Epstein Theatre with the With Friends Surrounded Tour. After 15 years of touring, playing at theatres across the UK, seven musicians will deliver a show with empathy and passion playing tracks from Pink Floyds massive back-catalogue, from the early magical days of founder Syd Barrett through to later iconic albums, renowned for their complex structures, such as Dark Side of The Moon.
The emphasis will be on replicating the experience of Pink Floyd live on stage in the 70's which many believe was Floyd at their very best. The superb Cariss Auburn takes on the role of Clare Torry, who performed Great Gig in the Sky on the original 1973 Pink Floyd album Dark Side of the Moon, recreating this unique enigmatic vocal with its extra-terrestrial soundscape which has been leaving audiences
enthralled.
As would be expected, the show incorporates a spectacular and dramatic laser light show and evocative images and animated sequences projected on a circular screen, which were key features of Pink Floyds live performances.
FOR FLOYD FANS, BY FLOYD FANS.
We Love Little Mix
A Foreigners Journey
Midnight Train To Georgia: A Celebration of Gladys Knight
The Epstein Theatre
Hanover House, 85 Hanover Street
Liverpool, L1 3DZ


The best way to learn about CSG's empowering learning environment is to visit and experience it in person. We offer several event options for prospective families to visit our campus, and also welcome families to schedule individual visits. To schedule an individual visit, go here to find out more.
Saturday, December 1, 2018 - 8:00 a.m. - 11:30 a.m.
Saturday, January 12, 2019 - 8:00 a.m. - 11:30 a.m.
Saturday, February 2, 2019 - 8:00 a.m. - 11:30 a.m.
Saturday, April 6, 2019 - 8:00 a.m - 11:30 a.m.
Saturday, May 11, 2019 - 8:00 a.m. - 11:30 a.m.
To register for an ISEE, go here.
*Thursday Tours not offered in December or January. Please consider a CSG Preview Day during those months!
Potential families will have the opportunity to tour the campus, observe classes in session, and explore the academic, athletic, and arts programs at CSG. A tour is available every Thursday morning at 8:30am, no RSVP required! Come and learn why CSG is the best choice for your daughter's education!
For more information or to schedule an individual visit, contact the Office of Admission at 614.252.0781, ext. 442 or admissions@columbusschoolforgirls.org.
PYC applicants visit in small groups on select Saturday mornings in January and February. Teachers will observe the girls as they explore classroom materials and work with each vistior individually. While the students spend time in the classroom, we invite parents to join Jamie Schiff, Director of the Program for Young Children, in the Mansion Living Room for refreshments and a discussion about our PYC curriculum and program.
Before the visit, we will confirm all details with parents via e-mail. Following your visit, we value the opportunity to share feedback and ensure that our teachers gained an accurate picture of your daughter's current development and strengths.
Applicants will be notified about admission status.


Start the Sv:Katalysator article (http://footwww.academickids.com/encyclopedia/index.php?title=Sv:Katalysator&action=edit).
Search for Sv:Katalysator in other articles.
Look for Sv:Katalysator in Wiktionary, our sister dictionary project.
Look for Sv:Katalysator in the Commons, our repository for free images, music, sound, and video.
If you have created this page in the past few minutes and it has not yet appeared, it may not be visible due to a delay in updating the database. Try purge (http://footwww.academickids.com/encyclopedia/index.php?title=Sv:Katalysator&action=purge), otherwise please wait and check again later before attempting to recreate the page.


Major cryptocurrency exchange Binace has officially announced that it will delist Bitcoin SV starting next week. The exchange stated that as of April 22, it will delist and cease trading on all trading pairs for BSV - on the exchange under the ticker BCHSV. In the post, Binance explained that it regularly reviews assets listed on its platform "To ensure that it [an asset] continues to meet the high level of standard we expect." The firm went on to explain that it only delists a coin after another in-depth review, noting "[w]e believe this best protects all of our users.
The exchange listed responsiveness to its due diligence requests, level and quality of the coin's development and "Evidence of unethical / fraudulent conduct" among the factors that it takes into account before delisting a cryptocurrency. The exchange also noted that it will support withdrawals of the coin until 10:00 a.m. UTC on April 22.
The tweet is presumably a reaction to BSV founder Craig Wright's - infamous in the industry for making multiple claims to be Bitcoin creator Satoshi Nakamoto - recent action against Hodlnaut, the Twitter user behind the Lightning Torch initiative. The community also reacted to CZ's warning by asking various exchanges to delist BSV and creating a #DelistBSV hashtag. Binance is currently the world's fourth largest crypto exchange by adjusted daily trade volume, seeing about $900 million in trades over the 24-hours to press time.


This recipe has been converted from chocolatechocolateandmore.com Lemon Pie Bars.
Place flour and sugar in bowl and mix on Speed 5 for 5 seconds.
Add butter and mix on Speed 5 for 30seconds. Scrape down sides and repeat. Mix will look like bread crumbs but when squeeze should hold together.
Push into a lined slice tin. Use a metal spoon to push down and even. If you have a second slice tin, lay some baking paper over the top of the slice and use your second tin to push down and even the top.
Bake at 160deg for 15 minutes or until light golden.
Add all ingredients to the bowl and mix on Speed 4 for 20 seconds. Pour over the base and cook for 15 minutes or until the top has set.


text:
Келемен Мікеш (1690, Трансільванія — 1761) — угорський політичний діяч і есеїст, відомий своєю діяльністю проти Габсбурзької монархії. Мікеш згадується як «угорський Гете», який прославився завдяки своїм «Листам з Туреччини». З їх допомогою Мікеш заклав основи угорської літературної прози. Він вважається одним з перших угорських прозаїків.

Біографія
Мікес народився в Загоні і виріс в Зебалі (нині жудець Ковасна, Румунія). Він воював з Габсбургами, поки не був змушений втекти в Річ Посполиту, Францію і, в кінцевому рахунку, в Османську імперію. Живучи в турецькому Текірдазі, Мікеш доповнював і публікував свої есе. Після смерті Ракоці ІІ в 1735 році Мікес залишився у вигнанні до самої своєї смерті.

Творчість
Найвідоміша його робота — «Листи з Туреччини», колекція з 207 листів, перший з яких датується 10 жовтня 1717 року, останній — 20 грудня 1758 року. Автор листа — Мікеш Келемен, адресат вигадана графиня Е. Е., яка живе поблизу Константинополя. Мікеш познайомився з французьким жанром класицизму у Франції, мабуть, читаючи листування між  та його двоюрідною сестрою, мадам де Севіньє, що вплинуло на його вибір жанру. Листи описують повсякденне життя вигнанців, але містять також ряд історичних та сучасних доповнень. Спосіб відправлення рукопису до Угорщини був незрозумілим, і з часом з'ясувалося два припущення: згідно з останніми дослідженнями, Ференц Толді та син одного з офіцерів Берчешені привезли документи до Сомбатгейя.

Перше видання збірки було опубліковане Іштваном Кульцаром у 1794 році, і з того часу виходило кілька разів. Він використовував безліч джерел та цікавинок, вплетених у листи, від Біблії до ренесансних томів оповідань (Боккаччо, Маттео Банделло, Маргарет Наварра) до сучасної французької літератури. Стиль твору характеризується легкістю, грайливістю, лагідністю, ясністю, гумором та іронією, подібною до розмови. За словами Антала Серба, листи Майкеса Келемена «починають новий розділ історії душі в угорській літературі: після суворо релігійних і яскраво героїчних душ він знайомить з віком людини».

Примітки

Угорські письменники
Політики Угорщини

redpajama_set_name: RedPajamaWikipedia


text:
Curated by the Cyberinfrastructure for Network Science Center
About Places & Spaces
What is a Science Map?
What is a Macroscope?
Exhibit Team
Mapmakers
Maps & Macroscopes
Call for Macroscopes
Macroscopes
Exhibit Archives
Physical Exhibit
Maps-Only Physical Exhibit
Poster Exhibit
Digital Exhibit
Exhibit Maps
III.7 Mapping the Universe: Space. Time. Discovery!
Languages: English | Español | 汉语 | Deutsch
Chaomei Chen
Jian Zhang
Michael S. Vogeley
J. Richard Gott, III
Lisa Kershner
Created by information scientists Chaomei Chen and Jian Zhang, graphic designer Lisa Kershner, and astrophysicists Michael S. Vogeley, J. Richard Gott III, and Mario Juric, this map represents space, time, and our discoveries of phenomena in both. The image depicts 1) a circular map of the entire universe selectively annotated with discovery dates and the durations of accelerated citation growth; 2) a time spiral of emergent themes from astronomical literature specifically related to the Sloan Digital Sky Survey (SDSS); and 3) an evolving network of novel topics. More than 600,000 astronomical objects, including some of the most distant quasars discovered by the SDSS, are placed on the map according to their right ascension and the natural logarithm of their distance from Earth. Short-term predictions of research trends can be made by linear extrapolation of the current average citation acceleration rate in the SDSS literature of 3.17 years with a standard deviation of 1.8 years. Candidates for points of growth in the near future are suggested in the network and the time spiral.
Chen, Chaomei and R.J. Paul. 2001. "Visualizing a Knowledge Domain's Intellectual Structure." IEEE Computer 34 (3): 65-71.
Chen, Chaomei. 2006. "CiteSpace II: Detecting and Visualizing Emerging Trends and Transient Patterns in Scientific Literature." Journal of the American Society for Information Science and Technology 57 (3): 359–377.
Chen, Chaomei, Jian Zhang, Weizhong Zhu, and Michael S. Vogeley. 2007. "Delineating the Citation Impact of Scientific Discoveries." Paper presented at the IEEE/ACM Joint Conference on Digital Libraries, Vancouver, Canada, June 17–22.
Chen, Chaomei, Jian Zhang, Lisa Kershner, Michael S. Vogeley, J. Richard Gott III, and Mario Juric. 2007. Mapping the Universe: Space, Time, Discovery! Courtesy of Drexel University and Princeton University. In "3rd Iteration (2007): The Power of Forecasts," Places & Spaces: Mapping Science, edited by Katy Börner and
Julie M. Davis. http://scimaps.org.
III.8 Science-Related Wikipedian Activity »
« III.6 113 Years of Physical Review
Acknowledgements: This exhibit is supported by the National Science Foundation under Grant No. IIS-0238261, CHE-0524661, IIS-0534909 and IIS-0715303, the James S. McDonnell Foundation; Thomson Reuters; the Cyberinfrastructure for Network Science Center, University Information Technology Services, and the School of Library and Information Science, all three at Indiana University. Some of the data used to generate the science maps is from the Web of Science by Thomson Reuters and Scopus by Elsevier. Any opinions, findings, and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the National Science Foundation.