AudioOutputDescriptor.cpp revision a8ecc2c72ca26389bd6b0162181d60aaeaca8149
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "APM::AudioOutputDescriptor"
18//#define LOG_NDEBUG 0
19
20#include <AudioPolicyInterface.h>
21#include "AudioOutputDescriptor.h"
22#include "IOProfile.h"
23#include "AudioGain.h"
24#include "Volume.h"
25#include "HwModule.h"
26#include <media/AudioPolicy.h>
27
28// A device mask for all audio output devices that are considered "remote" when evaluating
29// active output devices in isStreamActiveRemotely()
30#define APM_AUDIO_OUT_DEVICE_REMOTE_ALL  AUDIO_DEVICE_OUT_REMOTE_SUBMIX
31
32namespace android {
33
34AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port,
35                                             AudioPolicyClientInterface *clientInterface)
36    : mPort(port), mDevice(AUDIO_DEVICE_NONE),
37      mPatchHandle(0), mClientInterface(clientInterface), mId(0)
38{
39    // clear usage count for all stream types
40    for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
41        mRefCount[i] = 0;
42        mCurVolume[i] = -1.0;
43        mMuteCount[i] = 0;
44        mStopTime[i] = 0;
45    }
46    for (int i = 0; i < NUM_STRATEGIES; i++) {
47        mStrategyMutedByDevice[i] = false;
48    }
49    if (port != NULL) {
50        mSamplingRate = port->pickSamplingRate();
51        mFormat = port->pickFormat();
52        mChannelMask = port->pickChannelMask();
53        if (port->mGains.size() > 0) {
54            port->mGains[0]->getDefaultConfig(&mGain);
55        }
56    }
57}
58
59audio_module_handle_t AudioOutputDescriptor::getModuleHandle() const
60{
61    return mPort->getModuleHandle();
62}
63
64audio_port_handle_t AudioOutputDescriptor::getId() const
65{
66    return mId;
67}
68
69audio_devices_t AudioOutputDescriptor::device() const
70{
71    return mDevice;
72}
73
74audio_devices_t AudioOutputDescriptor::supportedDevices()
75{
76    return mDevice;
77}
78
79bool AudioOutputDescriptor::sharesHwModuleWith(
80        const sp<AudioOutputDescriptor> outputDesc)
81{
82    if (outputDesc->isDuplicated()) {
83        return sharesHwModuleWith(outputDesc->subOutput1()) ||
84                    sharesHwModuleWith(outputDesc->subOutput2());
85    } else {
86        return (getModuleHandle() == outputDesc->getModuleHandle());
87    }
88}
89
90void AudioOutputDescriptor::changeRefCount(audio_stream_type_t stream,
91                                                                   int delta)
92{
93    if ((delta + (int)mRefCount[stream]) < 0) {
94        ALOGW("changeRefCount() invalid delta %d for stream %d, refCount %d",
95              delta, stream, mRefCount[stream]);
96        mRefCount[stream] = 0;
97        return;
98    }
99    mRefCount[stream] += delta;
100    ALOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]);
101}
102
103bool AudioOutputDescriptor::isActive(uint32_t inPastMs) const
104{
105    nsecs_t sysTime = 0;
106    if (inPastMs != 0) {
107        sysTime = systemTime();
108    }
109    for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
110        if (i == AUDIO_STREAM_PATCH) {
111            continue;
112        }
113        if (isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) {
114            return true;
115        }
116    }
117    return false;
118}
119
120bool AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream,
121                                           uint32_t inPastMs,
122                                           nsecs_t sysTime) const
123{
124    if (mRefCount[stream] != 0) {
125        return true;
126    }
127    if (inPastMs == 0) {
128        return false;
129    }
130    if (sysTime == 0) {
131        sysTime = systemTime();
132    }
133    if (ns2ms(sysTime - mStopTime[stream]) < inPastMs) {
134        return true;
135    }
136    return false;
137}
138
139
140bool AudioOutputDescriptor::isFixedVolume(audio_devices_t device __unused)
141{
142    return false;
143}
144
145bool AudioOutputDescriptor::setVolume(float volume,
146                                      audio_stream_type_t stream,
147                                      audio_devices_t device __unused,
148                                      uint32_t delayMs,
149                                      bool force)
150{
151    // We actually change the volume if:
152    // - the float value returned by computeVolume() changed
153    // - the force flag is set
154    if (volume != mCurVolume[stream] || force) {
155        ALOGV("setVolume() for stream %d, volume %f, delay %d", stream, volume, delayMs);
156        mCurVolume[stream] = volume;
157        return true;
158    }
159    return false;
160}
161
162void AudioOutputDescriptor::toAudioPortConfig(
163                                                 struct audio_port_config *dstConfig,
164                                                 const struct audio_port_config *srcConfig) const
165{
166    dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK|
167                            AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN;
168    if (srcConfig != NULL) {
169        dstConfig->config_mask |= srcConfig->config_mask;
170    }
171    AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
172
173    dstConfig->id = mId;
174    dstConfig->role = AUDIO_PORT_ROLE_SOURCE;
175    dstConfig->type = AUDIO_PORT_TYPE_MIX;
176    dstConfig->ext.mix.hw_module = getModuleHandle();
177    dstConfig->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT;
178}
179
180void AudioOutputDescriptor::toAudioPort(
181                                                    struct audio_port *port) const
182{
183    mPort->toAudioPort(port);
184    port->id = mId;
185    port->ext.mix.hw_module = getModuleHandle();
186}
187
188status_t AudioOutputDescriptor::dump(int fd)
189{
190    const size_t SIZE = 256;
191    char buffer[SIZE];
192    String8 result;
193
194    snprintf(buffer, SIZE, " ID: %d\n", mId);
195    result.append(buffer);
196    snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
197    result.append(buffer);
198    snprintf(buffer, SIZE, " Format: %08x\n", mFormat);
199    result.append(buffer);
200    snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask);
201    result.append(buffer);
202    snprintf(buffer, SIZE, " Devices %08x\n", device());
203    result.append(buffer);
204    snprintf(buffer, SIZE, " Stream volume refCount muteCount\n");
205    result.append(buffer);
206    for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
207        snprintf(buffer, SIZE, " %02d     %.03f     %02d       %02d\n",
208                 i, mCurVolume[i], mRefCount[i], mMuteCount[i]);
209        result.append(buffer);
210    }
211    write(fd, result.string(), result.size());
212
213    return NO_ERROR;
214}
215
216void AudioOutputDescriptor::log(const char* indent)
217{
218    ALOGI("%sID: %d,0x%X, [rt:%d fmt:0x%X ch:0x%X]",
219          indent, mId, mId, mSamplingRate, mFormat, mChannelMask);
220}
221
222// SwAudioOutputDescriptor implementation
223SwAudioOutputDescriptor::SwAudioOutputDescriptor(const sp<IOProfile>& profile,
224                                                 AudioPolicyClientInterface *clientInterface)
225    : AudioOutputDescriptor(profile, clientInterface),
226    mProfile(profile), mIoHandle(0), mLatency(0),
227    mFlags((audio_output_flags_t)0), mPolicyMix(NULL),
228    mOutput1(0), mOutput2(0), mDirectOpenCount(0), mGlobalRefCount(0)
229{
230    if (profile != NULL) {
231        mFlags = (audio_output_flags_t)profile->getFlags();
232    }
233}
234
235void SwAudioOutputDescriptor::setIoHandle(audio_io_handle_t ioHandle)
236{
237    mId = AudioPort::getNextUniqueId();
238    mIoHandle = ioHandle;
239}
240
241
242status_t SwAudioOutputDescriptor::dump(int fd)
243{
244    const size_t SIZE = 256;
245    char buffer[SIZE];
246    String8 result;
247
248    snprintf(buffer, SIZE, " Latency: %d\n", mLatency);
249    result.append(buffer);
250    snprintf(buffer, SIZE, " Flags %08x\n", mFlags);
251    result.append(buffer);
252    write(fd, result.string(), result.size());
253
254    AudioOutputDescriptor::dump(fd);
255
256    return NO_ERROR;
257}
258
259audio_devices_t SwAudioOutputDescriptor::device() const
260{
261    if (isDuplicated()) {
262        return (audio_devices_t)(mOutput1->mDevice | mOutput2->mDevice);
263    } else {
264        return mDevice;
265    }
266}
267
268bool SwAudioOutputDescriptor::sharesHwModuleWith(
269        const sp<AudioOutputDescriptor> outputDesc)
270{
271    if (isDuplicated()) {
272        return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc);
273    } else if (outputDesc->isDuplicated()){
274        return sharesHwModuleWith(outputDesc->subOutput1()) ||
275                    sharesHwModuleWith(outputDesc->subOutput2());
276    } else {
277        return AudioOutputDescriptor::sharesHwModuleWith(outputDesc);
278    }
279}
280
281audio_devices_t SwAudioOutputDescriptor::supportedDevices()
282{
283    if (isDuplicated()) {
284        return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices());
285    } else {
286        return mProfile->getSupportedDevicesType();
287    }
288}
289
290uint32_t SwAudioOutputDescriptor::latency()
291{
292    if (isDuplicated()) {
293        return (mOutput1->mLatency > mOutput2->mLatency) ? mOutput1->mLatency : mOutput2->mLatency;
294    } else {
295        return mLatency;
296    }
297}
298
299void SwAudioOutputDescriptor::changeRefCount(audio_stream_type_t stream,
300                                                                   int delta)
301{
302    // forward usage count change to attached outputs
303    if (isDuplicated()) {
304        mOutput1->changeRefCount(stream, delta);
305        mOutput2->changeRefCount(stream, delta);
306    }
307    AudioOutputDescriptor::changeRefCount(stream, delta);
308
309    // handle stream-independent ref count
310    uint32_t oldGlobalRefCount = mGlobalRefCount;
311    if ((delta + (int)mGlobalRefCount) < 0) {
312        ALOGW("changeRefCount() invalid delta %d globalRefCount %d", delta, mGlobalRefCount);
313        mGlobalRefCount = 0;
314    } else {
315        mGlobalRefCount += delta;
316    }
317    if ((oldGlobalRefCount == 0) && (mGlobalRefCount > 0)) {
318        if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
319        {
320            mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
321                    MIX_STATE_MIXING);
322        }
323
324    } else if ((oldGlobalRefCount > 0) && (mGlobalRefCount == 0)) {
325        if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
326        {
327            mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
328                    MIX_STATE_IDLE);
329        }
330    }
331}
332
333
334bool SwAudioOutputDescriptor::isFixedVolume(audio_devices_t device)
335{
336    // unit gain if rerouting to external policy
337    if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) {
338        if (mPolicyMix != NULL) {
339            ALOGV("max gain when rerouting for output=%d", mIoHandle);
340            return true;
341        }
342    }
343    return false;
344}
345
346void SwAudioOutputDescriptor::toAudioPortConfig(
347                                                 struct audio_port_config *dstConfig,
348                                                 const struct audio_port_config *srcConfig) const
349{
350
351    ALOG_ASSERT(!isDuplicated(), "toAudioPortConfig() called on duplicated output %d", mIoHandle);
352    AudioOutputDescriptor::toAudioPortConfig(dstConfig, srcConfig);
353
354    dstConfig->ext.mix.handle = mIoHandle;
355}
356
357void SwAudioOutputDescriptor::toAudioPort(
358                                                    struct audio_port *port) const
359{
360    ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle);
361
362    AudioOutputDescriptor::toAudioPort(port);
363
364    toAudioPortConfig(&port->active_config);
365    port->ext.mix.handle = mIoHandle;
366    port->ext.mix.latency_class =
367            mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL;
368}
369
370bool SwAudioOutputDescriptor::setVolume(float volume,
371                                        audio_stream_type_t stream,
372                                        audio_devices_t device,
373                                        uint32_t delayMs,
374                                        bool force)
375{
376    bool changed = AudioOutputDescriptor::setVolume(volume, stream, device, delayMs, force);
377
378    if (changed) {
379        // Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is
380        // enabled
381        float volume = Volume::DbToAmpl(mCurVolume[stream]);
382        if (stream == AUDIO_STREAM_BLUETOOTH_SCO) {
383            mClientInterface->setStreamVolume(
384                    AUDIO_STREAM_VOICE_CALL, volume, mIoHandle, delayMs);
385        }
386        mClientInterface->setStreamVolume(stream, volume, mIoHandle, delayMs);
387    }
388    return changed;
389}
390
391// HwAudioOutputDescriptor implementation
392HwAudioOutputDescriptor::HwAudioOutputDescriptor(const sp<AudioSourceDescriptor>& source,
393                                                 AudioPolicyClientInterface *clientInterface)
394    : AudioOutputDescriptor(source->mDevice, clientInterface),
395      mSource(source)
396{
397}
398
399status_t HwAudioOutputDescriptor::dump(int fd)
400{
401    const size_t SIZE = 256;
402    char buffer[SIZE];
403    String8 result;
404
405    AudioOutputDescriptor::dump(fd);
406
407    snprintf(buffer, SIZE, "Source:\n");
408    result.append(buffer);
409    write(fd, result.string(), result.size());
410    mSource->dump(fd);
411
412    return NO_ERROR;
413}
414
415audio_devices_t HwAudioOutputDescriptor::supportedDevices()
416{
417    return mDevice;
418}
419
420void HwAudioOutputDescriptor::toAudioPortConfig(
421                                                 struct audio_port_config *dstConfig,
422                                                 const struct audio_port_config *srcConfig) const
423{
424    mSource->mDevice->toAudioPortConfig(dstConfig, srcConfig);
425}
426
427void HwAudioOutputDescriptor::toAudioPort(
428                                                    struct audio_port *port) const
429{
430    mSource->mDevice->toAudioPort(port);
431}
432
433
434bool HwAudioOutputDescriptor::setVolume(float volume,
435                                        audio_stream_type_t stream,
436                                        audio_devices_t device,
437                                        uint32_t delayMs,
438                                        bool force)
439{
440    bool changed = AudioOutputDescriptor::setVolume(volume, stream, device, delayMs, force);
441
442    if (changed) {
443      // TODO: use gain controller on source device if any to adjust volume
444    }
445    return changed;
446}
447
448// SwAudioOutputCollection implementation
449bool SwAudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
450{
451    nsecs_t sysTime = systemTime();
452    for (size_t i = 0; i < this->size(); i++) {
453        const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
454        if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
455            return true;
456        }
457    }
458    return false;
459}
460
461bool SwAudioOutputCollection::isStreamActiveRemotely(audio_stream_type_t stream,
462                                                   uint32_t inPastMs) const
463{
464    nsecs_t sysTime = systemTime();
465    for (size_t i = 0; i < size(); i++) {
466        const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
467        if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
468                outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
469            // do not consider re routing (when the output is going to a dynamic policy)
470            // as "remote playback"
471            if (outputDesc->mPolicyMix == NULL) {
472                return true;
473            }
474        }
475    }
476    return false;
477}
478
479audio_io_handle_t SwAudioOutputCollection::getA2dpOutput() const
480{
481    for (size_t i = 0; i < size(); i++) {
482        sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
483        if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) {
484            return this->keyAt(i);
485        }
486    }
487    return 0;
488}
489
490sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getPrimaryOutput() const
491{
492    for (size_t i = 0; i < size(); i++) {
493        const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
494        if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
495            return outputDesc;
496        }
497    }
498    return NULL;
499}
500
501sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getOutputFromId(audio_port_handle_t id) const
502{
503    sp<SwAudioOutputDescriptor> outputDesc = NULL;
504    for (size_t i = 0; i < size(); i++) {
505        outputDesc = valueAt(i);
506        if (outputDesc->getId() == id) {
507            break;
508        }
509    }
510    return outputDesc;
511}
512
513bool SwAudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const
514{
515    for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) {
516        if (s == (size_t) streamToIgnore) {
517            continue;
518        }
519        for (size_t i = 0; i < size(); i++) {
520            const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
521            if (outputDesc->mRefCount[s] != 0) {
522                return true;
523            }
524        }
525    }
526    return false;
527}
528
529audio_devices_t SwAudioOutputCollection::getSupportedDevices(audio_io_handle_t handle) const
530{
531    sp<SwAudioOutputDescriptor> outputDesc = valueFor(handle);
532    audio_devices_t devices = outputDesc->mProfile->getSupportedDevicesType();
533    return devices;
534}
535
536
537status_t SwAudioOutputCollection::dump(int fd) const
538{
539    const size_t SIZE = 256;
540    char buffer[SIZE];
541
542    snprintf(buffer, SIZE, "\nOutputs dump:\n");
543    write(fd, buffer, strlen(buffer));
544    for (size_t i = 0; i < size(); i++) {
545        snprintf(buffer, SIZE, "- Output %d dump:\n", keyAt(i));
546        write(fd, buffer, strlen(buffer));
547        valueAt(i)->dump(fd);
548    }
549
550    return NO_ERROR;
551}
552
553// HwAudioOutputCollection implementation
554bool HwAudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
555{
556    nsecs_t sysTime = systemTime();
557    for (size_t i = 0; i < this->size(); i++) {
558        const sp<HwAudioOutputDescriptor> outputDesc = this->valueAt(i);
559        if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
560            return true;
561        }
562    }
563    return false;
564}
565
566bool HwAudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const
567{
568    for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) {
569        if (s == (size_t) streamToIgnore) {
570            continue;
571        }
572        for (size_t i = 0; i < size(); i++) {
573            const sp<HwAudioOutputDescriptor> outputDesc = valueAt(i);
574            if (outputDesc->mRefCount[s] != 0) {
575                return true;
576            }
577        }
578    }
579    return false;
580}
581
582status_t HwAudioOutputCollection::dump(int fd) const
583{
584    const size_t SIZE = 256;
585    char buffer[SIZE];
586
587    snprintf(buffer, SIZE, "\nOutputs dump:\n");
588    write(fd, buffer, strlen(buffer));
589    for (size_t i = 0; i < size(); i++) {
590        snprintf(buffer, SIZE, "- Output %d dump:\n", keyAt(i));
591        write(fd, buffer, strlen(buffer));
592        valueAt(i)->dump(fd);
593    }
594
595    return NO_ERROR;
596}
597
598}; //namespace android
599