1ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen/*
2ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen**
3ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** Copyright 2014, The Android Open Source Project
4ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen**
5ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** Licensed under the Apache License, Version 2.0 (the "License");
6ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** you may not use this file except in compliance with the License.
7ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** You may obtain a copy of the License at
8ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen**
9ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen**     http://www.apache.org/licenses/LICENSE-2.0
10ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen**
11ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** Unless required by applicable law or agreed to in writing, software
12ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** distributed under the License is distributed on an "AS IS" BASIS,
13ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** See the License for the specific language governing permissions and
15ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** limitations under the License.
16ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen*/
17ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
18c3ed98f08d4380cc03d2e9f33cf7cf9300a6fb69Phil Burk#define LOG_TAG "AudioHAL_AudioHardwareOutput"
19ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
20ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#include <utils/Log.h>
21ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
22ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#include <stdint.h>
23ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#include <limits.h>
24ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#include <math.h>
25ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
26ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#include <common_time/local_clock.h>
27ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#include <cutils/properties.h>
28ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
29ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#include "AudioHardwareOutput.h"
30ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#include "AudioStreamOut.h"
31ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#include "HDMIAudioOutput.h"
32ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
33ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chennamespace android {
34ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
35ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen// Global singleton.
36ae089528c7e3a8107be65657e52276dd068c1039Mike J. ChenAudioHardwareOutput gAudioHardwareOutput;
37ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
38ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen// HDMI options.
39ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenconst String8 AudioHardwareOutput::kHDMIAllowedParamKey(
40ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        "atv.hdmi_audio.allowed");
41ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenconst String8 AudioHardwareOutput::kHDMIDelayCompParamKey(
42ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        "atv.hdmi.audio_delay");
43ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenconst String8 AudioHardwareOutput::kFixedHDMIOutputParamKey(
44ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        "atv.hdmi.fixed_volume");
45ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenconst String8 AudioHardwareOutput::kFixedHDMIOutputLevelParamKey(
46ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        "atv.hdmi.fixed_level");
47ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
48ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen// Video delay comp hack options (not exposed to user level)
49ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenconst String8 AudioHardwareOutput::kVideoDelayCompParamKey(
50ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        "atv.video.delay_comp");
51ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
52ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen// Defaults for settings.
53ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioHardwareOutput::OutputSettings::setDefaults()
54ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{
55ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    allowed = true;
56ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    delayCompUsec = 0;
57ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    isFixed = false;
58ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    fixedLvl = 0.0f;
59ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
60ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
61ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioHardwareOutput::Settings::setDefaults() {
62ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    hdmi.setDefaults();
63ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
64ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    masterVolume = 0.60;
65ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    masterMute = false;
66ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
67ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // Default this to 16mSec or so.  Since audio start times are not sync'ed to
68ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // to the VBI, there should be a +/-0.5 output frame rate error in the AV
69ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // sync, even under the best of circumstances.
70ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    //
71ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // In practice, the android core seems to have a hard time hitting its frame
72ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // cadence consistently.  Sometimes the frames are on time, and sometimes
73ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // they are even a little early, but more often than not, the frames are
74ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // late by about a full output frame time.
75ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    //
76ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // ATV pretty much always uses a 60fps output rate, and the only thing
77ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // consuming the latency estimate provided by the HAL is the path handling
78ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // AV sync.  For now, we can fudge this number to move things back in the
79ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // direction of correct by providing a setting for video delay compensation
80ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // which will be subtracted from the latency estimate and defaulting it to
81ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // a reasonable middle gound (12mSec in this case).
82ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    videoDelayCompUsec = 12000;
83ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
84ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
85ae089528c7e3a8107be65657e52276dd068c1039Mike J. ChenAudioHardwareOutput::AudioHardwareOutput()
86ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen  : mMainOutput(NULL)
87ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen  , mMCOutput(NULL)
88ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen  , mHDMIConnected(false)
89ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen  , mMaxDelayCompUsec(0)
90ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{
91ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    mSettings.setDefaults();
92ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    mHDMICardID = find_alsa_card_by_name(kHDMI_ALSADeviceName);
93ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
94ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
95ae089528c7e3a8107be65657e52276dd068c1039Mike J. ChenAudioHardwareOutput::~AudioHardwareOutput()
96ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{
97ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    closeOutputStream(mMainOutput);
98ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    closeOutputStream(mMCOutput);
99ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
100ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
101ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioHardwareOutput::initCheck() {
102ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    return NO_ERROR;
103ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
104ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
105ae089528c7e3a8107be65657e52276dd068c1039Mike J. ChenAudioStreamOut* AudioHardwareOutput::openOutputStream(
106ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        uint32_t devices,
107ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        audio_format_t *format,
108ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        uint32_t *channels,
109ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        uint32_t *sampleRate,
110ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        audio_output_flags_t flags,
111ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        status_t *status) {
112ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    (void) devices;
113ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    AutoMutex lock(mStreamLock);
114ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
115ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    AudioStreamOut** pp_out;
116ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    AudioStreamOut* out;
117ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
118c3ed98f08d4380cc03d2e9f33cf7cf9300a6fb69Phil Burk    bool isIec958NonAudio = (flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) != 0;
119ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (!(flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
120ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        pp_out = &mMainOutput;
121c3ed98f08d4380cc03d2e9f33cf7cf9300a6fb69Phil Burk        out = new AudioStreamOut(*this, false, isIec958NonAudio);
122ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    } else {
123ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        pp_out = &mMCOutput;
124c3ed98f08d4380cc03d2e9f33cf7cf9300a6fb69Phil Burk        out = new AudioStreamOut(*this, true, isIec958NonAudio);
125ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
126ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
127ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (out == NULL) {
128ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        *status = NO_MEMORY;
129ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        return NULL;
130ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
131ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
132ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    *status = out->set(format, channels, sampleRate);
133ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
134ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (*status == NO_ERROR) {
135ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        *pp_out = out;
136ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        updateTgtDevices_l();
137ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    } else {
138ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        delete out;
139ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
140ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
141ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    return *pp_out;
142ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
143ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
144ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioHardwareOutput::closeOutputStream(AudioStreamOut* out) {
145ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (out == NULL)
146ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        return;
147ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
148ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // Putting the stream into "standby" should cause it to release all of its
149ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // physical outputs.
150ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    out->standby();
151ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
152ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    {
153ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        Mutex::Autolock _l(mStreamLock);
154ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        if (mMainOutput && out == mMainOutput) {
155ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            delete mMainOutput;
156ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            mMainOutput = NULL;
157ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        } else if (mMCOutput && out == mMCOutput) {
158ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            delete mMCOutput;
159ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            mMCOutput = NULL;
160ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        }
161ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
162ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        updateTgtDevices_l();
163ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
164ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
165ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
166ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioHardwareOutput::setMasterVolume(float volume)
167ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{
168ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    Mutex::Autolock _l1(mOutputLock);
169ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    Mutex::Autolock _l2(mSettingsLock);
170ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
171ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    mSettings.masterVolume = volume;
172ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
173ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    AudioOutputList::iterator I;
174ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
175ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        (*I)->setVolume(mSettings.masterVolume);
176ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
177ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    return NO_ERROR;
178ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
179ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
180ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioHardwareOutput::getMasterVolume(float* volume) {
181ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
182ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (NULL == volume)
183ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        return BAD_VALUE;
184ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
185ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // Explicit scope for auto-lock pattern.
186ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    {
187ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        Mutex::Autolock _l(mSettingsLock);
188ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        *volume = mSettings.masterVolume;
189ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
190ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
191ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    return NO_ERROR;
192ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
193ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
194ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioHardwareOutput::setMasterMute(bool muted)
195ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{
196ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    Mutex::Autolock _l1(mOutputLock);
197ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    Mutex::Autolock _l2(mSettingsLock);
198ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
199ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    mSettings.masterMute = muted;
200ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
201ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    AudioOutputList::iterator I;
202ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
203ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        (*I)->setMute(mSettings.masterMute);
204ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
205ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    return NO_ERROR;
206ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
207ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
208ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioHardwareOutput::getMasterMute(bool* muted) {
209ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (NULL == muted)
210ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        return BAD_VALUE;
211ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
212ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // Explicit scope for auto-lock pattern.
213ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    {
214ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        Mutex::Autolock _l(mSettingsLock);
215ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        *muted = mSettings.masterMute;
216ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
217ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
218ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    return NO_ERROR;
219ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
220ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
221ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioHardwareOutput::setParameters(const char* kvpairs) {
222ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    AudioParameter param = AudioParameter(String8(kvpairs));
223ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    status_t status = NO_ERROR;
224ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    float floatVal;
225ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    int intVal;
226ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    Settings initial, s;
227ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
228ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    {
229ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        // Record the initial state of the settings from inside the lock.  Then
230ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        // leave the lock in order to parse the changes to be made.
231ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        Mutex::Autolock _l(mSettingsLock);
232ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        initial = s = mSettings;
233ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
234ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
235ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    /***************************************************************
236ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen     *                     HDMI Audio Options                      *
237ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen     ***************************************************************/
238ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (param.getInt(kHDMIAllowedParamKey, intVal) == NO_ERROR) {
239ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        s.hdmi.allowed = (intVal != 0);
240ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        param.remove(kHDMIAllowedParamKey);
241ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
242ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
243ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if ((param.getFloat(kHDMIDelayCompParamKey, floatVal) == NO_ERROR) &&
244ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        (floatVal >= 0.0) &&
245ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        (floatVal <= AudioOutput::kMaxDelayCompensationMSec)) {
246ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        uint32_t delay_comp = static_cast<uint32_t>(floatVal * 1000.0);
247ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        s.hdmi.delayCompUsec = delay_comp;
248ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        param.remove(kHDMIDelayCompParamKey);
249ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
250ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
251ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (param.getInt(kFixedHDMIOutputParamKey, intVal) == NO_ERROR) {
252ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        s.hdmi.isFixed = (intVal != 0);
253ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        param.remove(kFixedHDMIOutputParamKey);
254ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
255ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
256ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if ((param.getFloat(kFixedHDMIOutputLevelParamKey, floatVal) == NO_ERROR)
257ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        && (floatVal <= 0.0)) {
258ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        s.hdmi.fixedLvl = floatVal;
259ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        param.remove(kFixedHDMIOutputLevelParamKey);
260ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
261ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
262ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    /***************************************************************
263ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen     *                       Other Options                         *
264ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen     ***************************************************************/
265ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if ((param.getFloat(kVideoDelayCompParamKey, floatVal) == NO_ERROR) &&
266ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        (floatVal >= 0.0) &&
267ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        (floatVal <= AudioOutput::kMaxDelayCompensationMSec)) {
268ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        s.videoDelayCompUsec = static_cast<uint32_t>(floatVal * 1000.0);
269ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        param.remove(kVideoDelayCompParamKey);
270ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
271ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
272ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (param.size())
273ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        status = BAD_VALUE;
274ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
275ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // If there was a change made to settings, go ahead and apply it now.
276ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    bool allowedOutputsChanged = false;
277ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (memcmp(&initial, &s, sizeof(initial)))  {
278ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        Mutex::Autolock _l1(mOutputLock);
279ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        Mutex::Autolock _l2(mSettingsLock);
280ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
281ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        if (memcmp(&initial.hdmi, &s.hdmi, sizeof(initial.hdmi)))
282ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            allowedOutputsChanged = allowedOutputsChanged ||
283ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen                applyOutputSettings_l(initial.hdmi, s.hdmi, mSettings.hdmi,
284ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen                                      HDMIAudioOutput::classDevMask());
285ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
286ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        if (initial.videoDelayCompUsec != s.videoDelayCompUsec)
287ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            mSettings.videoDelayCompUsec = s.videoDelayCompUsec;
288ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
289ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        uint32_t tmp = 0;
290ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        if (mSettings.hdmi.allowed && (tmp < mSettings.hdmi.delayCompUsec))
291ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            tmp = mSettings.hdmi.delayCompUsec;
292ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        if (mMaxDelayCompUsec != tmp)
293ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            mMaxDelayCompUsec = tmp;
294ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
295ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
296ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (allowedOutputsChanged) {
297ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        Mutex::Autolock _l(mStreamLock);
298ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        updateTgtDevices_l();
299ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
300ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
301ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    return status;
302ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
303ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
304ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenbool AudioHardwareOutput::applyOutputSettings_l(
305ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        const AudioHardwareOutput::OutputSettings& initial,
306ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        const AudioHardwareOutput::OutputSettings& current,
307ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        AudioHardwareOutput::OutputSettings& updateMe,
308ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        uint32_t outDevMask) {
309ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // ASSERT(holding mOutputLock and mSettingsLock)
310ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    sp<AudioOutput> out;
311ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
312ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // Check for a change in the allowed/not-allowed state.  Update if needed
313ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // and return true if there was a change made.
314ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    bool ret = false;
315ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (initial.allowed != current.allowed) {
316ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        updateMe.allowed = current.allowed;
317ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        ret = true;
318ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
319ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
320ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // Look for an instance of the output to be updated in case other changes
321ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // were made.
322ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    AudioOutputList::iterator I;
323ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) {
324ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        if (outDevMask == (*I)->devMask()) {
325ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            out = (*I);
326ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            break;
327ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        }
328ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
329ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
330ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // Update the other settings, if needed.
331ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (initial.delayCompUsec != current.delayCompUsec) {
332ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        updateMe.delayCompUsec = current.delayCompUsec;
333ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        if (out != NULL)
334ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            out->setExternalDelay_uSec(current.delayCompUsec);
335ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
336ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
337ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (initial.isFixed != current.isFixed) {
338ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        updateMe.isFixed = current.isFixed;
339ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        if (out != NULL)
340ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            out->setOutputIsFixed(current.isFixed);
341ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
342ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
343ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (initial.fixedLvl != current.fixedLvl) {
344ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        updateMe.fixedLvl = current.fixedLvl;
345ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        if (out != NULL)
346ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            out->setFixedOutputLevel(current.fixedLvl);
347ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
348ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
349ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    return ret;
350ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
351ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
352ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
353ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenchar* AudioHardwareOutput::getParameters(const char* keys) {
354ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    Settings s;
355ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
356ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // Explicit scope for auto-lock pattern.
357ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    {
358ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        // Snapshot the current settings so we don't have to hold the settings
359ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        // lock while formatting the results.
360ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        Mutex::Autolock _l(mSettingsLock);
361ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        s = mSettings;
362ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
363ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
364ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    AudioParameter param = AudioParameter(String8(keys));
365ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    String8 tmp;
366ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
367ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    /***************************************************************
368ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen     *                     HDMI Audio Options                      *
369ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen     ***************************************************************/
370ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (param.get(kHDMIAllowedParamKey, tmp) == NO_ERROR)
371ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        param.addInt(kHDMIAllowedParamKey, s.hdmi.allowed ? 1 : 0);
372ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
373ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (param.get(kHDMIDelayCompParamKey, tmp) == NO_ERROR)
374ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        param.addFloat(kHDMIDelayCompParamKey,
375ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen                       static_cast<float>(s.hdmi.delayCompUsec) / 1000.0);
376ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
377ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (param.get(kFixedHDMIOutputParamKey, tmp) == NO_ERROR)
378ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        param.addInt(kFixedHDMIOutputParamKey, s.hdmi.isFixed ? 1 : 0);
379ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
380ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (param.get(kFixedHDMIOutputLevelParamKey, tmp) == NO_ERROR)
381ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        param.addFloat(kFixedHDMIOutputLevelParamKey, s.hdmi.fixedLvl);
382ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
383ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    /***************************************************************
384ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen     *                       Other Options                         *
385ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen     ***************************************************************/
386ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (param.get(kVideoDelayCompParamKey, tmp) == NO_ERROR)
387ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        param.addFloat(kVideoDelayCompParamKey,
388ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen                       static_cast<float>(s.videoDelayCompUsec) / 1000.0);
389ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
390ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    return strdup(param.toString().string());
391ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
392ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
393ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioHardwareOutput::updateRouting(uint32_t devMask) {
394ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    Mutex::Autolock _l(mStreamLock);
395ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
396ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    bool hasHDMI = 0 != (devMask & HDMIAudioOutput::classDevMask());
397ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    ALOGI("%s: hasHDMI = %d, mHDMIConnected = %d", __func__, hasHDMI, mHDMIConnected);
398ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (mHDMIConnected != hasHDMI) {
399ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        mHDMIConnected = hasHDMI;
400ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
401ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        if (mHDMIConnected)
402ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            mHDMIAudioCaps.loadCaps(mHDMICardID);
403ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        else
404ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            mHDMIAudioCaps.reset();
405ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
406ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        updateTgtDevices_l();
407ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
408ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
409ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
410ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioHardwareOutput::obtainOutput(const AudioStreamOut& tgtStream,
411ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen                                     uint32_t devMask,
412ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen                                     sp<AudioOutput>* newOutput) {
413ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    Mutex::Autolock _l1(mOutputLock);
414ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
415ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // Sanity check the device mask passed to us.  There should exactly one bit
416ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // set, no less, no more.
417ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (popcount(devMask) != 1) {
418ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        ALOGW("bad device mask in obtainOutput, %08x", devMask);
419ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        return INVALID_OPERATION;
420ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
421ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
422ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // Start by checking to see if the requested output is currently busy.
423ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    AudioOutputList::iterator I;
424ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
425ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        if (devMask & (*I)->devMask())
426ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            return OK; // Yup; its busy.
427ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
428ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // Looks like we don't currently have an output of the requested type.
429ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // Figure out which type is being requested and try to construct one.
430ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    OutputSettings* S = NULL;
431ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (devMask & HDMIAudioOutput::classDevMask()) {
432ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        *newOutput = new HDMIAudioOutput();
433ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        S = &mSettings.hdmi;
434ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
435ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    else {
436ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        ALOGW("%s stream out requested output of unknown type %08x",
437ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen                tgtStream.getName(), devMask);
438ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        return BAD_VALUE;
439ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
440ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
441ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (*newOutput == NULL)
442ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        return NO_MEMORY;
443ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
444ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    status_t res = (*newOutput)->setupForStream(tgtStream);
445ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (res != OK) {
446ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        ALOGE("%s setupForStream() returned %d",
447ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen              tgtStream.getName(), res);
448ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        *newOutput = NULL;
449ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    } else {
450ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        ALOGI("%s stream out adding %s output.",
451ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen                tgtStream.getName(), (*newOutput)->getOutputName());
452ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        mPhysOutputs.push_back(*newOutput);
453ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
454ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        {  // Apply current settings
455ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            Mutex::Autolock _l2(mSettingsLock);
456ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            (*newOutput)->setVolume(mSettings.masterVolume);
457ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            (*newOutput)->setMute(mSettings.masterMute);
458ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            (*newOutput)->setExternalDelay_uSec(S->delayCompUsec);
459ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            (*newOutput)->setOutputIsFixed(S->isFixed);
460ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            (*newOutput)->setFixedOutputLevel(S->fixedLvl);
461ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        }
462ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
463ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
464ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    return res;
465ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
466ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
467ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioHardwareOutput::releaseOutput(const AudioStreamOut& tgtStream,
468ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen                                        const sp<AudioOutput>& releaseMe) {
469ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    Mutex::Autolock _l(mOutputLock);
470ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
471ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    ALOGI("%s stream out removing %s output.",
472ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            tgtStream.getName(), releaseMe->getOutputName());
473ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
474ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // Immediately release any resources associated with this output (In
475ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // particular, make sure to close any ALSA device driver handles ASAP)
476ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    releaseMe->cleanupResources();
477ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
478ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // Now, clear our internal bookkeeping.
479ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    AudioOutputList::iterator I;
480ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) {
481ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        if (releaseMe.get() == (*I).get()) {
482ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            mPhysOutputs.erase(I);
483ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            break;
484ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        }
485ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
486ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
487ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
488ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioHardwareOutput::updateTgtDevices_l() {
489ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // ASSERT(holding mStreamLock)
490ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    uint32_t mcMask = 0;
491ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    uint32_t mainMask = 0;
492ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
493ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    {
494ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        Mutex::Autolock _l(mSettingsLock);
495ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        if (mSettings.hdmi.allowed && mHDMIConnected) {
496ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            if (NULL != mMCOutput)
497ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen                mcMask |= HDMIAudioOutput::classDevMask();
498ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            else
499ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen                mainMask |= HDMIAudioOutput::classDevMask();
500ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        }
501ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
502ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
503ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (NULL != mMainOutput)
504ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        mMainOutput->setTgtDevices(mainMask);
505ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
506ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    if (NULL != mMCOutput)
507ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        mMCOutput->setTgtDevices(mcMask);
508ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
509ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
510282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Guptavoid AudioHardwareOutput::standbyStatusUpdate(bool isInStandby, bool isMCStream) {
511282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta
512282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta    Mutex::Autolock _l1(mStreamLock);
513460bd5771278272645f575ba17db6c2a546ad545Eric Laurent    bool hdmiAllowed;
514460bd5771278272645f575ba17db6c2a546ad545Eric Laurent    {
515460bd5771278272645f575ba17db6c2a546ad545Eric Laurent        Mutex::Autolock _l2(mSettingsLock);
516460bd5771278272645f575ba17db6c2a546ad545Eric Laurent        hdmiAllowed = mSettings.hdmi.allowed;
517460bd5771278272645f575ba17db6c2a546ad545Eric Laurent    }
518282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta    // If there is no HDMI, do nothing
519460bd5771278272645f575ba17db6c2a546ad545Eric Laurent    if (hdmiAllowed && mHDMIConnected) {
520282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta        // If a multi-channel stream goes to standy state, we must switch
521282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta        // to stereo stream. If MC comes out of standby, we must switch
522282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta        // back to MC. No special processing needed for main stream.
523282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta        // AudioStreamOut class handles that correctly
524282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta        if (isMCStream) {
525282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta            uint32_t mcMask;
526282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta            uint32_t mainMask;
527282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta            if (isInStandby) {
528282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta                mainMask = HDMIAudioOutput::classDevMask();
529282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta                mcMask = 0;
530282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta            } else {
531282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta                mainMask = 0;
532282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta                mcMask = HDMIAudioOutput::classDevMask();
533282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta            }
534282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta
535282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta            if (NULL != mMainOutput)
536282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta                mMainOutput->setTgtDevices(mainMask);
537282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta
538282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta            if (NULL != mMCOutput)
539282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta                mMCOutput->setTgtDevices(mcMask);
540282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta        }
541282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta    }
542282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta}
543282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta
544ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#define DUMP(a...) \
545ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    snprintf(buffer, SIZE, a); \
546ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    buffer[SIZE - 1] = 0; \
547ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    result.append(buffer);
548ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#define B2STR(b) b ? "true" : "false"
549ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
550ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioHardwareOutput::dump(int fd)
551ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{
552ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    const size_t SIZE = 256;
553ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    char buffer[SIZE];
554ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    String8 result;
555ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    Settings s;
556ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
557ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // Explicit scope for auto-lock pattern.
558ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    {
559ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        // Snapshot the current settings so we don't have to hold the settings
560ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        // lock while formatting the results.
561ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        Mutex::Autolock _l(mSettingsLock);
562ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        s = mSettings;
563ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
564ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
565ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    DUMP("AudioHardwareOutput::dump\n");
566ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    DUMP("\tMaster Volume          : %0.3f\n", s.masterVolume);
567ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    DUMP("\tMaster Mute            : %s\n", B2STR(s.masterMute));
568ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    DUMP("\tHDMI Output Allowed    : %s\n", B2STR(s.hdmi.allowed));
569ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    DUMP("\tHDMI Delay Comp        : %u uSec\n", s.hdmi.delayCompUsec);
570ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    DUMP("\tHDMI Output Fixed      : %s\n", B2STR(s.hdmi.isFixed));
571ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    DUMP("\tHDMI Fixed Level       : %.1f dB\n", s.hdmi.fixedLvl);
572ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    DUMP("\tVideo Delay Comp       : %u uSec\n", s.videoDelayCompUsec);
573ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
574ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    ::write(fd, result.string(), result.size());
575ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
576ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    // Explicit scope for auto-lock pattern.
577ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    {
578ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        Mutex::Autolock _l(mOutputLock);
579ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        if (mMainOutput)
580ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            mMainOutput->dump(fd);
581ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
582ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen        if (mMCOutput)
583ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen            mMCOutput->dump(fd);
584ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    }
585ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
586ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen    return NO_ERROR;
587ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}
588ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
589ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#undef B2STR
590ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#undef DUMP
591ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen
592ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen}; // namespace android
593