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     if (!(flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
119         pp_out = &mMainOutput;
120         out = new AudioStreamOut(*this, false);
121     } else {
122         pp_out = &mMCOutput;
123         out = new AudioStreamOut(*this, true);
124     }
125 
126     if (out == NULL) {
127         *status = NO_MEMORY;
128         return NULL;
129     }
130 
131     *status = out->set(format, channels, sampleRate);
132 
133     if (*status == NO_ERROR) {
134         *pp_out = out;
135         updateTgtDevices_l();
136     } else {
137         delete out;
138     }
139 
140     return *pp_out;
141 }
142 
closeOutputStream(AudioStreamOut * out)143 void AudioHardwareOutput::closeOutputStream(AudioStreamOut* out) {
144     if (out == NULL)
145         return;
146 
147     // Putting the stream into "standby" should cause it to release all of its
148     // physical outputs.
149     out->standby();
150 
151     {
152         Mutex::Autolock _l(mStreamLock);
153         if (mMainOutput && out == mMainOutput) {
154             delete mMainOutput;
155             mMainOutput = NULL;
156         } else if (mMCOutput && out == mMCOutput) {
157             delete mMCOutput;
158             mMCOutput = NULL;
159         }
160 
161         updateTgtDevices_l();
162     }
163 }
164 
setMasterVolume(float volume)165 status_t AudioHardwareOutput::setMasterVolume(float volume)
166 {
167     Mutex::Autolock _l1(mOutputLock);
168     Mutex::Autolock _l2(mSettingsLock);
169 
170     mSettings.masterVolume = volume;
171 
172     AudioOutputList::iterator I;
173     for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
174         (*I)->setVolume(mSettings.masterVolume);
175 
176     return NO_ERROR;
177 }
178 
getMasterVolume(float * volume)179 status_t AudioHardwareOutput::getMasterVolume(float* volume) {
180 
181     if (NULL == volume)
182         return BAD_VALUE;
183 
184     // Explicit scope for auto-lock pattern.
185     {
186         Mutex::Autolock _l(mSettingsLock);
187         *volume = mSettings.masterVolume;
188     }
189 
190     return NO_ERROR;
191 }
192 
setMasterMute(bool muted)193 status_t AudioHardwareOutput::setMasterMute(bool muted)
194 {
195     Mutex::Autolock _l1(mOutputLock);
196     Mutex::Autolock _l2(mSettingsLock);
197 
198     mSettings.masterMute = muted;
199 
200     AudioOutputList::iterator I;
201     for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
202         (*I)->setMute(mSettings.masterMute);
203 
204     return NO_ERROR;
205 }
206 
getMasterMute(bool * muted)207 status_t AudioHardwareOutput::getMasterMute(bool* muted) {
208     if (NULL == muted)
209         return BAD_VALUE;
210 
211     // Explicit scope for auto-lock pattern.
212     {
213         Mutex::Autolock _l(mSettingsLock);
214         *muted = mSettings.masterMute;
215     }
216 
217     return NO_ERROR;
218 }
219 
setParameters(const char * kvpairs)220 status_t AudioHardwareOutput::setParameters(const char* kvpairs) {
221     AudioParameter param = AudioParameter(String8(kvpairs));
222     status_t status = NO_ERROR;
223     float floatVal;
224     int intVal;
225     Settings initial, s;
226 
227     {
228         // Record the initial state of the settings from inside the lock.  Then
229         // leave the lock in order to parse the changes to be made.
230         Mutex::Autolock _l(mSettingsLock);
231         initial = s = mSettings;
232     }
233 
234     /***************************************************************
235      *                     HDMI Audio Options                      *
236      ***************************************************************/
237     if (param.getInt(kHDMIAllowedParamKey, intVal) == NO_ERROR) {
238         s.hdmi.allowed = (intVal != 0);
239         param.remove(kHDMIAllowedParamKey);
240     }
241 
242     if ((param.getFloat(kHDMIDelayCompParamKey, floatVal) == NO_ERROR) &&
243         (floatVal >= 0.0) &&
244         (floatVal <= AudioOutput::kMaxDelayCompensationMSec)) {
245         uint32_t delay_comp = static_cast<uint32_t>(floatVal * 1000.0);
246         s.hdmi.delayCompUsec = delay_comp;
247         param.remove(kHDMIDelayCompParamKey);
248     }
249 
250     if (param.getInt(kFixedHDMIOutputParamKey, intVal) == NO_ERROR) {
251         s.hdmi.isFixed = (intVal != 0);
252         param.remove(kFixedHDMIOutputParamKey);
253     }
254 
255     if ((param.getFloat(kFixedHDMIOutputLevelParamKey, floatVal) == NO_ERROR)
256         && (floatVal <= 0.0)) {
257         s.hdmi.fixedLvl = floatVal;
258         param.remove(kFixedHDMIOutputLevelParamKey);
259     }
260 
261     /***************************************************************
262      *                       Other Options                         *
263      ***************************************************************/
264     if ((param.getFloat(kVideoDelayCompParamKey, floatVal) == NO_ERROR) &&
265         (floatVal >= 0.0) &&
266         (floatVal <= AudioOutput::kMaxDelayCompensationMSec)) {
267         s.videoDelayCompUsec = static_cast<uint32_t>(floatVal * 1000.0);
268         param.remove(kVideoDelayCompParamKey);
269     }
270 
271     if (param.size())
272         status = BAD_VALUE;
273 
274     // If there was a change made to settings, go ahead and apply it now.
275     bool allowedOutputsChanged = false;
276     if (memcmp(&initial, &s, sizeof(initial)))  {
277         Mutex::Autolock _l1(mOutputLock);
278         Mutex::Autolock _l2(mSettingsLock);
279 
280         if (memcmp(&initial.hdmi, &s.hdmi, sizeof(initial.hdmi)))
281             allowedOutputsChanged = allowedOutputsChanged ||
282                 applyOutputSettings_l(initial.hdmi, s.hdmi, mSettings.hdmi,
283                                       HDMIAudioOutput::classDevMask());
284 
285         if (initial.videoDelayCompUsec != s.videoDelayCompUsec)
286             mSettings.videoDelayCompUsec = s.videoDelayCompUsec;
287 
288         uint32_t tmp = 0;
289         if (mSettings.hdmi.allowed && (tmp < mSettings.hdmi.delayCompUsec))
290             tmp = mSettings.hdmi.delayCompUsec;
291         if (mMaxDelayCompUsec != tmp)
292             mMaxDelayCompUsec = tmp;
293     }
294 
295     if (allowedOutputsChanged) {
296         Mutex::Autolock _l(mStreamLock);
297         updateTgtDevices_l();
298     }
299 
300     return status;
301 }
302 
applyOutputSettings_l(const AudioHardwareOutput::OutputSettings & initial,const AudioHardwareOutput::OutputSettings & current,AudioHardwareOutput::OutputSettings & updateMe,uint32_t outDevMask)303 bool AudioHardwareOutput::applyOutputSettings_l(
304         const AudioHardwareOutput::OutputSettings& initial,
305         const AudioHardwareOutput::OutputSettings& current,
306         AudioHardwareOutput::OutputSettings& updateMe,
307         uint32_t outDevMask) {
308     // ASSERT(holding mOutputLock and mSettingsLock)
309     sp<AudioOutput> out;
310 
311     // Check for a change in the allowed/not-allowed state.  Update if needed
312     // and return true if there was a change made.
313     bool ret = false;
314     if (initial.allowed != current.allowed) {
315         updateMe.allowed = current.allowed;
316         ret = true;
317     }
318 
319     // Look for an instance of the output to be updated in case other changes
320     // were made.
321     AudioOutputList::iterator I;
322     for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) {
323         if (outDevMask == (*I)->devMask()) {
324             out = (*I);
325             break;
326         }
327     }
328 
329     // Update the other settings, if needed.
330     if (initial.delayCompUsec != current.delayCompUsec) {
331         updateMe.delayCompUsec = current.delayCompUsec;
332         if (out != NULL)
333             out->setExternalDelay_uSec(current.delayCompUsec);
334     }
335 
336     if (initial.isFixed != current.isFixed) {
337         updateMe.isFixed = current.isFixed;
338         if (out != NULL)
339             out->setOutputIsFixed(current.isFixed);
340     }
341 
342     if (initial.fixedLvl != current.fixedLvl) {
343         updateMe.fixedLvl = current.fixedLvl;
344         if (out != NULL)
345             out->setFixedOutputLevel(current.fixedLvl);
346     }
347 
348     return ret;
349 }
350 
351 
getParameters(const char * keys)352 char* AudioHardwareOutput::getParameters(const char* keys) {
353     Settings s;
354 
355     // Explicit scope for auto-lock pattern.
356     {
357         // Snapshot the current settings so we don't have to hold the settings
358         // lock while formatting the results.
359         Mutex::Autolock _l(mSettingsLock);
360         s = mSettings;
361     }
362 
363     AudioParameter param = AudioParameter(String8(keys));
364     String8 tmp;
365 
366     /***************************************************************
367      *                     HDMI Audio Options                      *
368      ***************************************************************/
369     if (param.get(kHDMIAllowedParamKey, tmp) == NO_ERROR)
370         param.addInt(kHDMIAllowedParamKey, s.hdmi.allowed ? 1 : 0);
371 
372     if (param.get(kHDMIDelayCompParamKey, tmp) == NO_ERROR)
373         param.addFloat(kHDMIDelayCompParamKey,
374                        static_cast<float>(s.hdmi.delayCompUsec) / 1000.0);
375 
376     if (param.get(kFixedHDMIOutputParamKey, tmp) == NO_ERROR)
377         param.addInt(kFixedHDMIOutputParamKey, s.hdmi.isFixed ? 1 : 0);
378 
379     if (param.get(kFixedHDMIOutputLevelParamKey, tmp) == NO_ERROR)
380         param.addFloat(kFixedHDMIOutputLevelParamKey, s.hdmi.fixedLvl);
381 
382     /***************************************************************
383      *                       Other Options                         *
384      ***************************************************************/
385     if (param.get(kVideoDelayCompParamKey, tmp) == NO_ERROR)
386         param.addFloat(kVideoDelayCompParamKey,
387                        static_cast<float>(s.videoDelayCompUsec) / 1000.0);
388 
389     return strdup(param.toString().string());
390 }
391 
updateRouting(uint32_t devMask)392 void AudioHardwareOutput::updateRouting(uint32_t devMask) {
393     Mutex::Autolock _l(mStreamLock);
394 
395     bool hasHDMI = 0 != (devMask & HDMIAudioOutput::classDevMask());
396     ALOGI("%s: hasHDMI = %d, mHDMIConnected = %d", __func__, hasHDMI, mHDMIConnected);
397     if (mHDMIConnected != hasHDMI) {
398         mHDMIConnected = hasHDMI;
399 
400         if (mHDMIConnected)
401             mHDMIAudioCaps.loadCaps(mHDMICardID);
402         else
403             mHDMIAudioCaps.reset();
404 
405         updateTgtDevices_l();
406     }
407 }
408 
obtainOutput(const AudioStreamOut & tgtStream,uint32_t devMask,sp<AudioOutput> * newOutput)409 status_t AudioHardwareOutput::obtainOutput(const AudioStreamOut& tgtStream,
410                                      uint32_t devMask,
411                                      sp<AudioOutput>* newOutput) {
412     Mutex::Autolock _l1(mOutputLock);
413 
414     // Sanity check the device mask passed to us.  There should exactly one bit
415     // set, no less, no more.
416     if (popcount(devMask) != 1) {
417         ALOGW("bad device mask in obtainOutput, %08x", devMask);
418         return INVALID_OPERATION;
419     }
420 
421     // Start by checking to see if the requested output is currently busy.
422     AudioOutputList::iterator I;
423     for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
424         if (devMask & (*I)->devMask())
425             return OK; // Yup; its busy.
426 
427     // Looks like we don't currently have an output of the requested type.
428     // Figure out which type is being requested and try to construct one.
429     OutputSettings* S = NULL;
430     if (devMask & HDMIAudioOutput::classDevMask()) {
431         *newOutput = new HDMIAudioOutput();
432         S = &mSettings.hdmi;
433     }
434     else {
435         ALOGW("%s stream out requested output of unknown type %08x",
436                 tgtStream.getName(), devMask);
437         return BAD_VALUE;
438     }
439 
440     if (*newOutput == NULL)
441         return NO_MEMORY;
442 
443     status_t res = (*newOutput)->setupForStream(tgtStream);
444     if (res != OK) {
445         ALOGE("%s setupForStream() returned %d",
446               tgtStream.getName(), res);
447         *newOutput = NULL;
448     } else {
449         ALOGI("%s stream out adding %s output.",
450                 tgtStream.getName(), (*newOutput)->getOutputName());
451         mPhysOutputs.push_back(*newOutput);
452 
453         {  // Apply current settings
454             Mutex::Autolock _l2(mSettingsLock);
455             (*newOutput)->setVolume(mSettings.masterVolume);
456             (*newOutput)->setMute(mSettings.masterMute);
457             (*newOutput)->setExternalDelay_uSec(S->delayCompUsec);
458             (*newOutput)->setOutputIsFixed(S->isFixed);
459             (*newOutput)->setFixedOutputLevel(S->fixedLvl);
460         }
461     }
462 
463     return res;
464 }
465 
releaseOutput(const AudioStreamOut & tgtStream,const sp<AudioOutput> & releaseMe)466 void AudioHardwareOutput::releaseOutput(const AudioStreamOut& tgtStream,
467                                         const sp<AudioOutput>& releaseMe) {
468     Mutex::Autolock _l(mOutputLock);
469 
470     ALOGI("%s stream out removing %s output.",
471             tgtStream.getName(), releaseMe->getOutputName());
472 
473     // Immediately release any resources associated with this output (In
474     // particular, make sure to close any ALSA device driver handles ASAP)
475     releaseMe->cleanupResources();
476 
477     // Now, clear our internal bookkeeping.
478     AudioOutputList::iterator I;
479     for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) {
480         if (releaseMe.get() == (*I).get()) {
481             mPhysOutputs.erase(I);
482             break;
483         }
484     }
485 }
486 
updateTgtDevices_l()487 void AudioHardwareOutput::updateTgtDevices_l() {
488     // ASSERT(holding mStreamLock)
489     uint32_t mcMask = 0;
490     uint32_t mainMask = 0;
491 
492     {
493         Mutex::Autolock _l(mSettingsLock);
494         if (mSettings.hdmi.allowed && mHDMIConnected) {
495             if (NULL != mMCOutput)
496                 mcMask |= HDMIAudioOutput::classDevMask();
497             else
498                 mainMask |= HDMIAudioOutput::classDevMask();
499         }
500     }
501 
502     if (NULL != mMainOutput)
503         mMainOutput->setTgtDevices(mainMask);
504 
505     if (NULL != mMCOutput)
506         mMCOutput->setTgtDevices(mcMask);
507 }
508 
standbyStatusUpdate(bool isInStandby,bool isMCStream)509 void AudioHardwareOutput::standbyStatusUpdate(bool isInStandby, bool isMCStream) {
510 
511     Mutex::Autolock _l1(mStreamLock);
512     bool hdmiAllowed;
513     {
514         Mutex::Autolock _l2(mSettingsLock);
515         hdmiAllowed = mSettings.hdmi.allowed;
516     }
517     // If there is no HDMI, do nothing
518     if (hdmiAllowed && mHDMIConnected) {
519         // If a multi-channel stream goes to standy state, we must switch
520         // to stereo stream. If MC comes out of standby, we must switch
521         // back to MC. No special processing needed for main stream.
522         // AudioStreamOut class handles that correctly
523         if (isMCStream) {
524             uint32_t mcMask;
525             uint32_t mainMask;
526             if (isInStandby) {
527                 mainMask = HDMIAudioOutput::classDevMask();
528                 mcMask = 0;
529             } else {
530                 mainMask = 0;
531                 mcMask = HDMIAudioOutput::classDevMask();
532             }
533 
534             if (NULL != mMainOutput)
535                 mMainOutput->setTgtDevices(mainMask);
536 
537             if (NULL != mMCOutput)
538                 mMCOutput->setTgtDevices(mcMask);
539         }
540     }
541 }
542 
543 #define DUMP(a...) \
544     snprintf(buffer, SIZE, a); \
545     buffer[SIZE - 1] = 0; \
546     result.append(buffer);
547 #define B2STR(b) b ? "true" : "false"
548 
dump(int fd)549 status_t AudioHardwareOutput::dump(int fd)
550 {
551     const size_t SIZE = 256;
552     char buffer[SIZE];
553     String8 result;
554     Settings s;
555 
556     // Explicit scope for auto-lock pattern.
557     {
558         // Snapshot the current settings so we don't have to hold the settings
559         // lock while formatting the results.
560         Mutex::Autolock _l(mSettingsLock);
561         s = mSettings;
562     }
563 
564     DUMP("AudioHardwareOutput::dump\n");
565     DUMP("\tMaster Volume          : %0.3f\n", s.masterVolume);
566     DUMP("\tMaster Mute            : %s\n", B2STR(s.masterMute));
567     DUMP("\tHDMI Output Allowed    : %s\n", B2STR(s.hdmi.allowed));
568     DUMP("\tHDMI Delay Comp        : %u uSec\n", s.hdmi.delayCompUsec);
569     DUMP("\tHDMI Output Fixed      : %s\n", B2STR(s.hdmi.isFixed));
570     DUMP("\tHDMI Fixed Level       : %.1f dB\n", s.hdmi.fixedLvl);
571     DUMP("\tVideo Delay Comp       : %u uSec\n", s.videoDelayCompUsec);
572 
573     ::write(fd, result.string(), result.size());
574 
575     // Explicit scope for auto-lock pattern.
576     {
577         Mutex::Autolock _l(mOutputLock);
578         if (mMainOutput)
579             mMainOutput->dump(fd);
580 
581         if (mMCOutput)
582             mMCOutput->dump(fd);
583     }
584 
585     return NO_ERROR;
586 }
587 
588 #undef B2STR
589 #undef DUMP
590 
591 }; // namespace android
592