| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define LOG_TAG "AudioPolicyManagerALSA" |
| //#define LOG_NDEBUG 0 |
| #define LOG_NDDEBUG 0 |
| #include <utils/Log.h> |
| |
| #include "AudioPolicyManagerALSA.h" |
| #include <media/mediarecorder.h> |
| |
| namespace android_audio_legacy { |
| |
| // ---------------------------------------------------------------------------- |
| // AudioPolicyManagerALSA |
| // ---------------------------------------------------------------------------- |
| |
| //Compiling error seen if AudioParamer doesn't exist in this file |
| |
| AudioParameter param; |
| |
| // --- class factory |
| |
| |
| extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface) |
| { |
| return new AudioPolicyManager(clientInterface); |
| } |
| |
| extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface) |
| { |
| delete interface; |
| } |
| |
| void AudioPolicyManager::setPhoneState(int state) { |
| ALOGV("setPhoneState() state %d", state); |
| audio_devices_t newDevice = AUDIO_DEVICE_NONE; |
| if (state < 0 || state >= AudioSystem::NUM_MODES) { |
| ALOGW("setPhoneState() invalid state %d", state); |
| return; |
| } |
| |
| if (state == mPhoneState) { |
| ALOGW("setPhoneState() setting same state %d", state); |
| return; |
| } |
| |
| // if leaving call state, handle special case of active streams |
| // pertaining to sonification strategy see handleIncallSonification() |
| if (isInCall()) { |
| ALOGV("setPhoneState() in call state management: new state is %d", state); |
| for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { |
| handleIncallSonification(stream, false, true); |
| } |
| } |
| |
| // store previous phone state for management of sonification strategy below |
| int oldState = mPhoneState; |
| mPhoneState = state; |
| bool force = false; |
| |
| // are we entering or starting a call |
| if (!isStateInCall(oldState) && isStateInCall(state)) { |
| ALOGV(" Entering call in setPhoneState()"); |
| // force routing command to audio hardware when starting a call |
| // even if no device change is needed |
| force = true; |
| } else if (isStateInCall(oldState) && !isStateInCall(state)) { |
| ALOGV(" Exiting call in setPhoneState()"); |
| // force routing command to audio hardware when exiting a call |
| // even if no device change is needed |
| force = true; |
| } else if (isStateInCall(state) && (state != oldState)) { |
| ALOGV(" Switching between telephony and VoIP in setPhoneState()"); |
| // force routing command to audio hardware when switching between telephony and VoIP |
| // even if no device change is needed |
| force = true; |
| } |
| |
| // check for device and output changes triggered by new phone state |
| newDevice = getNewDevice(mPrimaryOutput, false /*fromCache*/); |
| checkA2dpSuspend(); |
| checkOutputForAllStrategies(); |
| updateDevicesAndOutputs(); |
| |
| AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mPrimaryOutput); |
| |
| // force routing command to audio hardware when ending call |
| // even if no device change is needed |
| if (isStateInCall(oldState) && newDevice == AUDIO_DEVICE_NONE) { |
| newDevice = hwOutputDesc->device(); |
| } |
| |
| // when changing from ring tone to in call mode, mute the ringing tone |
| // immediately and delay the route change to avoid sending the ring tone |
| // tail into the earpiece or headset. |
| int delayMs = 0; |
| if (isStateInCall(state) && oldState == AudioSystem::MODE_RINGTONE) { |
| // delay the device change command by twice the output latency to have some margin |
| // and be sure that audio buffers not yet affected by the mute are out when |
| // we actually apply the route change |
| delayMs = hwOutputDesc->mLatency*2; |
| setStreamMute(AudioSystem::RING, true, mPrimaryOutput); |
| } |
| |
| if (isStateInCall(state)) { |
| for (size_t i = 0; i < mOutputs.size(); i++) { |
| AudioOutputDescriptor *desc = mOutputs.valueAt(i); |
| //take the biggest latency for all outputs |
| if (delayMs < desc->mLatency*2) { |
| delayMs = desc->mLatency*2; |
| } |
| //mute STRATEGY_MEDIA on all outputs |
| if (desc->strategyRefCount(STRATEGY_MEDIA) != 0) { |
| setStrategyMute(STRATEGY_MEDIA, true, mOutputs.keyAt(i)); |
| setStrategyMute(STRATEGY_MEDIA, false, mOutputs.keyAt(i), MUTE_TIME_MS, |
| getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/)); |
| } |
| } |
| } |
| |
| // Ignore the delay to enable voice call on this target as the enabling the |
| // voice call has enough delay to make sure the ringtone audio completely |
| // played out |
| if (state == AudioSystem::MODE_IN_CALL && oldState == AudioSystem::MODE_RINGTONE) { |
| delayMs = 40; |
| } |
| |
| // change routing is necessary |
| setOutputDevice(mPrimaryOutput, newDevice, force, delayMs); |
| |
| // if entering in call state, handle special case of active streams |
| // pertaining to sonification strategy see handleIncallSonification() |
| if (isStateInCall(state)) { |
| ALOGV("setPhoneState() in call state management: new state is %d", state); |
| // unmute the ringing tone after a sufficient delay if it was muted before |
| // setting output device above |
| if (oldState == AudioSystem::MODE_RINGTONE) { |
| setStreamMute(AudioSystem::RING, false, mPrimaryOutput, MUTE_TIME_MS); |
| } |
| for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { |
| handleIncallSonification(stream, true, true); |
| } |
| } |
| |
| // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE |
| if (state == AudioSystem::MODE_RINGTONE && |
| isStreamActive(AudioSystem::MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)) { |
| mLimitRingtoneVolume = true; |
| } else { |
| mLimitRingtoneVolume = false; |
| } |
| } |
| |
| }; // namespace androidi_audio_legacy |