• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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