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