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