1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#define LOG_TAG "AudioPolicyManagerALSA"
19//#define LOG_NDEBUG 0
20#define LOG_NDDEBUG 0
21#include <utils/Log.h>
22
23#include "AudioPolicyManagerALSA.h"
24#include <media/mediarecorder.h>
25
26namespace android_audio_legacy {
27
28// ----------------------------------------------------------------------------
29// AudioPolicyManagerALSA
30// ----------------------------------------------------------------------------
31
32//Compiling error seen if AudioParamer doesn't exist in this file
33
34AudioParameter param;
35
36// ---  class factory
37
38
39extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
40{
41    return new AudioPolicyManager(clientInterface);
42}
43
44extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface)
45{
46    delete interface;
47}
48
49void AudioPolicyManager::setPhoneState(int state) {
50    ALOGV("setPhoneState() state %d", state);
51    audio_devices_t newDevice = AUDIO_DEVICE_NONE;
52    if (state < 0 || state >= AudioSystem::NUM_MODES) {
53        ALOGW("setPhoneState() invalid state %d", state);
54        return;
55    }
56
57    if (state == mPhoneState) {
58        ALOGW("setPhoneState() setting same state %d", state);
59        return;
60    }
61
62    // if leaving call state, handle special case of active streams
63    // pertaining to sonification strategy see handleIncallSonification()
64    if (isInCall()) {
65        ALOGV("setPhoneState() in call state management: new state is %d", state);
66        for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
67            handleIncallSonification(stream, false, true);
68        }
69    }
70
71    // store previous phone state for management of sonification strategy below
72    int oldState = mPhoneState;
73    mPhoneState = state;
74    bool force = false;
75
76    // are we entering or starting a call
77    if (!isStateInCall(oldState) && isStateInCall(state)) {
78        ALOGV("  Entering call in setPhoneState()");
79        // force routing command to audio hardware when starting a call
80        // even if no device change is needed
81        force = true;
82    } else if (isStateInCall(oldState) && !isStateInCall(state)) {
83        ALOGV("  Exiting call in setPhoneState()");
84        // force routing command to audio hardware when exiting a call
85        // even if no device change is needed
86        force = true;
87    } else if (isStateInCall(state) && (state != oldState)) {
88        ALOGV("  Switching between telephony and VoIP in setPhoneState()");
89        // force routing command to audio hardware when switching between telephony and VoIP
90        // even if no device change is needed
91        force = true;
92    }
93
94    // check for device and output changes triggered by new phone state
95    newDevice = getNewDevice(mPrimaryOutput, false /*fromCache*/);
96    checkA2dpSuspend();
97    checkOutputForAllStrategies();
98    updateDevicesAndOutputs();
99
100    AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mPrimaryOutput);
101
102    // force routing command to audio hardware when ending call
103    // even if no device change is needed
104    if (isStateInCall(oldState) && newDevice == AUDIO_DEVICE_NONE) {
105        newDevice = hwOutputDesc->device();
106    }
107
108    // when changing from ring tone to in call mode, mute the ringing tone
109    // immediately and delay the route change to avoid sending the ring tone
110    // tail into the earpiece or headset.
111    int delayMs = 0;
112    if (isStateInCall(state) && oldState == AudioSystem::MODE_RINGTONE) {
113        // delay the device change command by twice the output latency to have some margin
114        // and be sure that audio buffers not yet affected by the mute are out when
115        // we actually apply the route change
116        delayMs = hwOutputDesc->mLatency*2;
117        setStreamMute(AudioSystem::RING, true, mPrimaryOutput);
118    }
119
120    if (isStateInCall(state)) {
121        for (size_t i = 0; i < mOutputs.size(); i++) {
122            AudioOutputDescriptor *desc = mOutputs.valueAt(i);
123            //take the biggest latency for all outputs
124            if (delayMs < desc->mLatency*2) {
125                delayMs = desc->mLatency*2;
126            }
127            //mute STRATEGY_MEDIA on all outputs
128            if (desc->strategyRefCount(STRATEGY_MEDIA) != 0) {
129                setStrategyMute(STRATEGY_MEDIA, true, mOutputs.keyAt(i));
130                setStrategyMute(STRATEGY_MEDIA, false, mOutputs.keyAt(i), MUTE_TIME_MS,
131                    getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/));
132            }
133        }
134    }
135
136    // Ignore the delay to enable voice call on this target as the enabling the
137    // voice call has enough delay to make sure the ringtone audio completely
138    // played out
139    if (state == AudioSystem::MODE_IN_CALL && oldState == AudioSystem::MODE_RINGTONE) {
140        delayMs = 40;
141    }
142
143    // change routing is necessary
144    setOutputDevice(mPrimaryOutput, newDevice, force, delayMs);
145
146    // if entering in call state, handle special case of active streams
147    // pertaining to sonification strategy see handleIncallSonification()
148    if (isStateInCall(state)) {
149        ALOGV("setPhoneState() in call state management: new state is %d", state);
150        // unmute the ringing tone after a sufficient delay if it was muted before
151        // setting output device above
152        if (oldState == AudioSystem::MODE_RINGTONE) {
153            setStreamMute(AudioSystem::RING, false, mPrimaryOutput, MUTE_TIME_MS);
154        }
155        for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
156            handleIncallSonification(stream, true, true);
157        }
158    }
159
160    // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE
161    if (state == AudioSystem::MODE_RINGTONE &&
162        isStreamActive(AudioSystem::MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)) {
163        mLimitRingtoneVolume = true;
164    } else {
165        mLimitRingtoneVolume = false;
166    }
167}
168
169}; // namespace androidi_audio_legacy
170