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 "AudioPolicyMix.h"
23 #include "IOProfile.h"
24 #include "AudioGain.h"
25 #include "Volume.h"
26 #include "HwModule.h"
27 #include <media/AudioParameter.h>
28 #include <media/AudioPolicy.h>
29
30 // A device mask for all audio output devices that are considered "remote" when evaluating
31 // active output devices in isStreamActiveRemotely()
32 #define APM_AUDIO_OUT_DEVICE_REMOTE_ALL AUDIO_DEVICE_OUT_REMOTE_SUBMIX
33
34 namespace android {
35
AudioOutputDescriptor(const sp<AudioPort> & port,AudioPolicyClientInterface * clientInterface)36 AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port,
37 AudioPolicyClientInterface *clientInterface)
38 : mPort(port), mDevice(AUDIO_DEVICE_NONE),
39 mClientInterface(clientInterface), mPatchHandle(AUDIO_PATCH_HANDLE_NONE), mId(0)
40 {
41 // clear usage count for all stream types
42 for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
43 mRefCount[i] = 0;
44 mCurVolume[i] = -1.0;
45 mMuteCount[i] = 0;
46 mStopTime[i] = 0;
47 }
48 for (int i = 0; i < NUM_STRATEGIES; i++) {
49 mStrategyMutedByDevice[i] = false;
50 }
51 if (mPort.get() != nullptr) {
52 mPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
53 if (mPort->mGains.size() > 0) {
54 mPort->mGains[0]->getDefaultConfig(&mGain);
55 }
56 }
57 }
58
getModuleHandle() const59 audio_module_handle_t AudioOutputDescriptor::getModuleHandle() const
60 {
61 return mPort.get() != nullptr ? mPort->getModuleHandle() : AUDIO_MODULE_HANDLE_NONE;
62 }
63
getId() const64 audio_port_handle_t AudioOutputDescriptor::getId() const
65 {
66 return mId;
67 }
68
device() const69 audio_devices_t AudioOutputDescriptor::device() const
70 {
71 return mDevice;
72 }
73
supportedDevices()74 audio_devices_t AudioOutputDescriptor::supportedDevices()
75 {
76 return mDevice;
77 }
78
sharesHwModuleWith(const sp<AudioOutputDescriptor> & outputDesc)79 bool 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 hasSameHwModuleAs(outputDesc);
87 }
88 }
89
changeRefCount(audio_stream_type_t stream,int delta)90 void 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
isActive(uint32_t inPastMs) const103 bool 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
isStreamActive(audio_stream_type_t stream,uint32_t inPastMs,nsecs_t sysTime) const120 bool 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
isFixedVolume(audio_devices_t device __unused)140 bool AudioOutputDescriptor::isFixedVolume(audio_devices_t device __unused)
141 {
142 return false;
143 }
144
setVolume(float volume,audio_stream_type_t stream,audio_devices_t device __unused,uint32_t delayMs,bool force)145 bool 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
toAudioPortConfig(struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig) const162 void 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
toAudioPort(struct audio_port * port) const180 void AudioOutputDescriptor::toAudioPort(struct audio_port *port) const
181 {
182 // Should not be called for duplicated ports, see SwAudioOutputDescriptor::toAudioPortConfig.
183 mPort->toAudioPort(port);
184 port->id = mId;
185 port->ext.mix.hw_module = getModuleHandle();
186 }
187
dump(int fd)188 status_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
log(const char * indent)216 void 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
SwAudioOutputDescriptor(const sp<IOProfile> & profile,AudioPolicyClientInterface * clientInterface)223 SwAudioOutputDescriptor::SwAudioOutputDescriptor(const sp<IOProfile>& profile,
224 AudioPolicyClientInterface *clientInterface)
225 : AudioOutputDescriptor(profile, clientInterface),
226 mProfile(profile), mIoHandle(AUDIO_IO_HANDLE_NONE), mLatency(0),
227 mFlags((audio_output_flags_t)0), mPolicyMix(NULL),
228 mOutput1(0), mOutput2(0), mDirectOpenCount(0),
229 mDirectClientSession(AUDIO_SESSION_NONE), mGlobalRefCount(0)
230 {
231 if (profile != NULL) {
232 mFlags = (audio_output_flags_t)profile->getFlags();
233 }
234 }
235
dump(int fd)236 status_t SwAudioOutputDescriptor::dump(int fd)
237 {
238 const size_t SIZE = 256;
239 char buffer[SIZE];
240 String8 result;
241
242 snprintf(buffer, SIZE, " Latency: %d\n", mLatency);
243 result.append(buffer);
244 snprintf(buffer, SIZE, " Flags %08x\n", mFlags);
245 result.append(buffer);
246 write(fd, result.string(), result.size());
247
248 AudioOutputDescriptor::dump(fd);
249
250 return NO_ERROR;
251 }
252
device() const253 audio_devices_t SwAudioOutputDescriptor::device() const
254 {
255 if (isDuplicated()) {
256 return (audio_devices_t)(mOutput1->mDevice | mOutput2->mDevice);
257 } else {
258 return mDevice;
259 }
260 }
261
sharesHwModuleWith(const sp<AudioOutputDescriptor> & outputDesc)262 bool SwAudioOutputDescriptor::sharesHwModuleWith(
263 const sp<AudioOutputDescriptor>& outputDesc)
264 {
265 if (isDuplicated()) {
266 return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc);
267 } else if (outputDesc->isDuplicated()){
268 return sharesHwModuleWith(outputDesc->subOutput1()) ||
269 sharesHwModuleWith(outputDesc->subOutput2());
270 } else {
271 return AudioOutputDescriptor::sharesHwModuleWith(outputDesc);
272 }
273 }
274
supportedDevices()275 audio_devices_t SwAudioOutputDescriptor::supportedDevices()
276 {
277 if (isDuplicated()) {
278 return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices());
279 } else {
280 return mProfile->getSupportedDevicesType();
281 }
282 }
283
latency()284 uint32_t SwAudioOutputDescriptor::latency()
285 {
286 if (isDuplicated()) {
287 return (mOutput1->mLatency > mOutput2->mLatency) ? mOutput1->mLatency : mOutput2->mLatency;
288 } else {
289 return mLatency;
290 }
291 }
292
changeRefCount(audio_stream_type_t stream,int delta)293 void SwAudioOutputDescriptor::changeRefCount(audio_stream_type_t stream,
294 int delta)
295 {
296 // forward usage count change to attached outputs
297 if (isDuplicated()) {
298 mOutput1->changeRefCount(stream, delta);
299 mOutput2->changeRefCount(stream, delta);
300 }
301 AudioOutputDescriptor::changeRefCount(stream, delta);
302
303 // handle stream-independent ref count
304 uint32_t oldGlobalRefCount = mGlobalRefCount;
305 if ((delta + (int)mGlobalRefCount) < 0) {
306 ALOGW("changeRefCount() invalid delta %d globalRefCount %d", delta, mGlobalRefCount);
307 mGlobalRefCount = 0;
308 } else {
309 mGlobalRefCount += delta;
310 }
311 sp<AudioPolicyMix> policyMix = mPolicyMix.promote();
312 if ((oldGlobalRefCount == 0) && (mGlobalRefCount > 0)) {
313 if ((policyMix != NULL) && ((policyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
314 {
315 mClientInterface->onDynamicPolicyMixStateUpdate(policyMix->mDeviceAddress,
316 MIX_STATE_MIXING);
317 }
318
319 } else if ((oldGlobalRefCount > 0) && (mGlobalRefCount == 0)) {
320 if ((policyMix != NULL) && ((policyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
321 {
322 mClientInterface->onDynamicPolicyMixStateUpdate(policyMix->mDeviceAddress,
323 MIX_STATE_IDLE);
324 }
325 }
326 }
327
328
isFixedVolume(audio_devices_t device)329 bool SwAudioOutputDescriptor::isFixedVolume(audio_devices_t device)
330 {
331 // unit gain if rerouting to external policy
332 if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) {
333 if (mPolicyMix != NULL) {
334 ALOGV("max gain when rerouting for output=%d", mIoHandle);
335 return true;
336 }
337 }
338 if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
339 ALOGV("max gain when output device is telephony tx");
340 return true;
341 }
342 return false;
343 }
344
toAudioPortConfig(struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig) const345 void SwAudioOutputDescriptor::toAudioPortConfig(
346 struct audio_port_config *dstConfig,
347 const struct audio_port_config *srcConfig) const
348 {
349
350 ALOG_ASSERT(!isDuplicated(), "toAudioPortConfig() called on duplicated output %d", mIoHandle);
351 AudioOutputDescriptor::toAudioPortConfig(dstConfig, srcConfig);
352
353 dstConfig->ext.mix.handle = mIoHandle;
354 }
355
toAudioPort(struct audio_port * port) const356 void SwAudioOutputDescriptor::toAudioPort(
357 struct audio_port *port) const
358 {
359 ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle);
360
361 AudioOutputDescriptor::toAudioPort(port);
362
363 toAudioPortConfig(&port->active_config);
364 port->ext.mix.handle = mIoHandle;
365 port->ext.mix.latency_class =
366 mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL;
367 }
368
setVolume(float volume,audio_stream_type_t stream,audio_devices_t device,uint32_t delayMs,bool force)369 bool SwAudioOutputDescriptor::setVolume(float volume,
370 audio_stream_type_t stream,
371 audio_devices_t device,
372 uint32_t delayMs,
373 bool force)
374 {
375 bool changed = AudioOutputDescriptor::setVolume(volume, stream, device, delayMs, force);
376
377 if (changed) {
378 // Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is
379 // enabled
380 float volume = Volume::DbToAmpl(mCurVolume[stream]);
381 if (stream == AUDIO_STREAM_BLUETOOTH_SCO) {
382 mClientInterface->setStreamVolume(
383 AUDIO_STREAM_VOICE_CALL, volume, mIoHandle, delayMs);
384 }
385 mClientInterface->setStreamVolume(stream, volume, mIoHandle, delayMs);
386 }
387 return changed;
388 }
389
open(const audio_config_t * config,audio_devices_t device,const String8 & address,audio_stream_type_t stream,audio_output_flags_t flags,audio_io_handle_t * output)390 status_t SwAudioOutputDescriptor::open(const audio_config_t *config,
391 audio_devices_t device,
392 const String8& address,
393 audio_stream_type_t stream,
394 audio_output_flags_t flags,
395 audio_io_handle_t *output)
396 {
397 audio_config_t lConfig;
398 if (config == nullptr) {
399 lConfig = AUDIO_CONFIG_INITIALIZER;
400 lConfig.sample_rate = mSamplingRate;
401 lConfig.channel_mask = mChannelMask;
402 lConfig.format = mFormat;
403 } else {
404 lConfig = *config;
405 }
406
407 mDevice = device;
408 // if the selected profile is offloaded and no offload info was specified,
409 // create a default one
410 if ((mProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
411 lConfig.offload_info.format == AUDIO_FORMAT_DEFAULT) {
412 flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD);
413 lConfig.offload_info = AUDIO_INFO_INITIALIZER;
414 lConfig.offload_info.sample_rate = lConfig.sample_rate;
415 lConfig.offload_info.channel_mask = lConfig.channel_mask;
416 lConfig.offload_info.format = lConfig.format;
417 lConfig.offload_info.stream_type = stream;
418 lConfig.offload_info.duration_us = -1;
419 lConfig.offload_info.has_video = true; // conservative
420 lConfig.offload_info.is_streaming = true; // likely
421 }
422
423 mFlags = (audio_output_flags_t)(mFlags | flags);
424
425 ALOGV("opening output for device %08x address %s profile %p name %s",
426 mDevice, address.string(), mProfile.get(), mProfile->getName().string());
427
428 status_t status = mClientInterface->openOutput(mProfile->getModuleHandle(),
429 output,
430 &lConfig,
431 &mDevice,
432 address,
433 &mLatency,
434 mFlags);
435 LOG_ALWAYS_FATAL_IF(mDevice != device,
436 "%s openOutput returned device %08x when given device %08x",
437 __FUNCTION__, mDevice, device);
438
439 if (status == NO_ERROR) {
440 LOG_ALWAYS_FATAL_IF(*output == AUDIO_IO_HANDLE_NONE,
441 "%s openOutput returned output handle %d for device %08x",
442 __FUNCTION__, *output, device);
443 mSamplingRate = lConfig.sample_rate;
444 mChannelMask = lConfig.channel_mask;
445 mFormat = lConfig.format;
446 mId = AudioPort::getNextUniqueId();
447 mIoHandle = *output;
448 mProfile->curOpenCount++;
449 }
450
451 return status;
452 }
453
start()454 status_t SwAudioOutputDescriptor::start()
455 {
456 if (isDuplicated()) {
457 status_t status = mOutput1->start();
458 if (status != NO_ERROR) {
459 return status;
460 }
461 status = mOutput2->start();
462 if (status != NO_ERROR) {
463 mOutput1->stop();
464 return status;
465 }
466 return NO_ERROR;
467 }
468 if (!isActive()) {
469 if (!mProfile->canStartNewIo()) {
470 return INVALID_OPERATION;
471 }
472 mProfile->curActiveCount++;
473 }
474 return NO_ERROR;
475 }
476
stop()477 void SwAudioOutputDescriptor::stop()
478 {
479 if (isDuplicated()) {
480 mOutput1->stop();
481 mOutput2->stop();
482 return;
483 }
484
485 if (!isActive()) {
486 LOG_ALWAYS_FATAL_IF(mProfile->curActiveCount < 1,
487 "%s invalid profile active count %u",
488 __func__, mProfile->curActiveCount);
489 mProfile->curActiveCount--;
490 }
491 }
492
close()493 void SwAudioOutputDescriptor::close()
494 {
495 if (mIoHandle != AUDIO_IO_HANDLE_NONE) {
496 AudioParameter param;
497 param.add(String8("closing"), String8("true"));
498 mClientInterface->setParameters(mIoHandle, param.toString());
499
500 mClientInterface->closeOutput(mIoHandle);
501
502 LOG_ALWAYS_FATAL_IF(mProfile->curOpenCount < 1, "%s profile open count %u",
503 __FUNCTION__, mProfile->curOpenCount);
504 // do not call stop() here as stop() is supposed to be called after changeRefCount(-1)
505 // and we don't know how many streams are still active at this time
506 if (isActive()) {
507 mProfile->curActiveCount--;
508 }
509 mProfile->curOpenCount--;
510 mIoHandle = AUDIO_IO_HANDLE_NONE;
511 }
512 }
513
openDuplicating(const sp<SwAudioOutputDescriptor> & output1,const sp<SwAudioOutputDescriptor> & output2,audio_io_handle_t * ioHandle)514 status_t SwAudioOutputDescriptor::openDuplicating(const sp<SwAudioOutputDescriptor>& output1,
515 const sp<SwAudioOutputDescriptor>& output2,
516 audio_io_handle_t *ioHandle)
517 {
518 // open a duplicating output thread for the new output and the primary output
519 // Note: openDuplicateOutput() API expects the output handles in the reverse order from the
520 // numbering in SwAudioOutputDescriptor mOutput1 and mOutput2
521 *ioHandle = mClientInterface->openDuplicateOutput(output2->mIoHandle, output1->mIoHandle);
522 if (*ioHandle == AUDIO_IO_HANDLE_NONE) {
523 return INVALID_OPERATION;
524 }
525
526 mId = AudioPort::getNextUniqueId();
527 mIoHandle = *ioHandle;
528 mOutput1 = output1;
529 mOutput2 = output2;
530 mSamplingRate = output2->mSamplingRate;
531 mFormat = output2->mFormat;
532 mChannelMask = output2->mChannelMask;
533 mLatency = output2->mLatency;
534
535 return NO_ERROR;
536 }
537
538 // HwAudioOutputDescriptor implementation
HwAudioOutputDescriptor(const sp<AudioSourceDescriptor> & source,AudioPolicyClientInterface * clientInterface)539 HwAudioOutputDescriptor::HwAudioOutputDescriptor(const sp<AudioSourceDescriptor>& source,
540 AudioPolicyClientInterface *clientInterface)
541 : AudioOutputDescriptor(source->mDevice, clientInterface),
542 mSource(source)
543 {
544 }
545
dump(int fd)546 status_t HwAudioOutputDescriptor::dump(int fd)
547 {
548 const size_t SIZE = 256;
549 char buffer[SIZE];
550 String8 result;
551
552 AudioOutputDescriptor::dump(fd);
553
554 snprintf(buffer, SIZE, "Source:\n");
555 result.append(buffer);
556 write(fd, result.string(), result.size());
557 mSource->dump(fd);
558
559 return NO_ERROR;
560 }
561
supportedDevices()562 audio_devices_t HwAudioOutputDescriptor::supportedDevices()
563 {
564 return mDevice;
565 }
566
toAudioPortConfig(struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig) const567 void HwAudioOutputDescriptor::toAudioPortConfig(
568 struct audio_port_config *dstConfig,
569 const struct audio_port_config *srcConfig) const
570 {
571 mSource->mDevice->toAudioPortConfig(dstConfig, srcConfig);
572 }
573
toAudioPort(struct audio_port * port) const574 void HwAudioOutputDescriptor::toAudioPort(
575 struct audio_port *port) const
576 {
577 mSource->mDevice->toAudioPort(port);
578 }
579
580
setVolume(float volume,audio_stream_type_t stream,audio_devices_t device,uint32_t delayMs,bool force)581 bool HwAudioOutputDescriptor::setVolume(float volume,
582 audio_stream_type_t stream,
583 audio_devices_t device,
584 uint32_t delayMs,
585 bool force)
586 {
587 bool changed = AudioOutputDescriptor::setVolume(volume, stream, device, delayMs, force);
588
589 if (changed) {
590 // TODO: use gain controller on source device if any to adjust volume
591 }
592 return changed;
593 }
594
595 // SwAudioOutputCollection implementation
isStreamActive(audio_stream_type_t stream,uint32_t inPastMs) const596 bool SwAudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
597 {
598 nsecs_t sysTime = systemTime();
599 for (size_t i = 0; i < this->size(); i++) {
600 const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
601 if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
602 return true;
603 }
604 }
605 return false;
606 }
607
isStreamActiveLocally(audio_stream_type_t stream,uint32_t inPastMs) const608 bool SwAudioOutputCollection::isStreamActiveLocally(audio_stream_type_t stream, uint32_t inPastMs) const
609 {
610 nsecs_t sysTime = systemTime();
611 for (size_t i = 0; i < this->size(); i++) {
612 const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
613 if (outputDesc->isStreamActive(stream, inPastMs, sysTime)
614 && ((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) == 0)) {
615 return true;
616 }
617 }
618 return false;
619 }
620
isStreamActiveRemotely(audio_stream_type_t stream,uint32_t inPastMs) const621 bool SwAudioOutputCollection::isStreamActiveRemotely(audio_stream_type_t stream,
622 uint32_t inPastMs) const
623 {
624 nsecs_t sysTime = systemTime();
625 for (size_t i = 0; i < size(); i++) {
626 const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
627 if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
628 outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
629 // do not consider re routing (when the output is going to a dynamic policy)
630 // as "remote playback"
631 if (outputDesc->mPolicyMix == NULL) {
632 return true;
633 }
634 }
635 }
636 return false;
637 }
638
getA2dpOutput() const639 audio_io_handle_t SwAudioOutputCollection::getA2dpOutput() const
640 {
641 for (size_t i = 0; i < size(); i++) {
642 sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
643 if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) {
644 return this->keyAt(i);
645 }
646 }
647 return 0;
648 }
649
isA2dpOffloadedOnPrimary() const650 bool SwAudioOutputCollection::isA2dpOffloadedOnPrimary() const
651 {
652 sp<SwAudioOutputDescriptor> primaryOutput = getPrimaryOutput();
653
654 if ((primaryOutput != NULL) && (primaryOutput->mProfile != NULL)
655 && (primaryOutput->mProfile->mModule != NULL)) {
656 sp<HwModule> primaryHwModule = primaryOutput->mProfile->mModule;
657 Vector <sp<IOProfile>> primaryHwModuleOutputProfiles =
658 primaryHwModule->getOutputProfiles();
659 for (size_t i = 0; i < primaryHwModuleOutputProfiles.size(); i++) {
660 if (primaryHwModuleOutputProfiles[i]->supportDevice(AUDIO_DEVICE_OUT_ALL_A2DP)) {
661 return true;
662 }
663 }
664 }
665 return false;
666 }
667
isA2dpSupported() const668 bool SwAudioOutputCollection::isA2dpSupported() const
669 {
670 return (isA2dpOffloadedOnPrimary() || (getA2dpOutput() != 0));
671 }
672
getPrimaryOutput() const673 sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getPrimaryOutput() const
674 {
675 for (size_t i = 0; i < size(); i++) {
676 const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
677 if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
678 return outputDesc;
679 }
680 }
681 return NULL;
682 }
683
getOutputFromId(audio_port_handle_t id) const684 sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getOutputFromId(audio_port_handle_t id) const
685 {
686 sp<SwAudioOutputDescriptor> outputDesc = NULL;
687 for (size_t i = 0; i < size(); i++) {
688 outputDesc = valueAt(i);
689 if (outputDesc->getId() == id) {
690 break;
691 }
692 }
693 return outputDesc;
694 }
695
isAnyOutputActive(audio_stream_type_t streamToIgnore) const696 bool SwAudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const
697 {
698 for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) {
699 if (s == (size_t) streamToIgnore) {
700 continue;
701 }
702 for (size_t i = 0; i < size(); i++) {
703 const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
704 if (outputDesc->mRefCount[s] != 0) {
705 return true;
706 }
707 }
708 }
709 return false;
710 }
711
getSupportedDevices(audio_io_handle_t handle) const712 audio_devices_t SwAudioOutputCollection::getSupportedDevices(audio_io_handle_t handle) const
713 {
714 sp<SwAudioOutputDescriptor> outputDesc = valueFor(handle);
715 audio_devices_t devices = outputDesc->mProfile->getSupportedDevicesType();
716 return devices;
717 }
718
719
dump(int fd) const720 status_t SwAudioOutputCollection::dump(int fd) const
721 {
722 const size_t SIZE = 256;
723 char buffer[SIZE];
724
725 snprintf(buffer, SIZE, "\nOutputs dump:\n");
726 write(fd, buffer, strlen(buffer));
727 for (size_t i = 0; i < size(); i++) {
728 snprintf(buffer, SIZE, "- Output %d dump:\n", keyAt(i));
729 write(fd, buffer, strlen(buffer));
730 valueAt(i)->dump(fd);
731 }
732
733 return NO_ERROR;
734 }
735
736 // HwAudioOutputCollection implementation
isStreamActive(audio_stream_type_t stream,uint32_t inPastMs) const737 bool HwAudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
738 {
739 nsecs_t sysTime = systemTime();
740 for (size_t i = 0; i < this->size(); i++) {
741 const sp<HwAudioOutputDescriptor> outputDesc = this->valueAt(i);
742 if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
743 return true;
744 }
745 }
746 return false;
747 }
748
isAnyOutputActive(audio_stream_type_t streamToIgnore) const749 bool HwAudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const
750 {
751 for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) {
752 if (s == (size_t) streamToIgnore) {
753 continue;
754 }
755 for (size_t i = 0; i < size(); i++) {
756 const sp<HwAudioOutputDescriptor> outputDesc = valueAt(i);
757 if (outputDesc->mRefCount[s] != 0) {
758 return true;
759 }
760 }
761 }
762 return false;
763 }
764
dump(int fd) const765 status_t HwAudioOutputCollection::dump(int fd) const
766 {
767 const size_t SIZE = 256;
768 char buffer[SIZE];
769
770 snprintf(buffer, SIZE, "\nOutputs dump:\n");
771 write(fd, buffer, strlen(buffer));
772 for (size_t i = 0; i < size(); i++) {
773 snprintf(buffer, SIZE, "- Output %d dump:\n", keyAt(i));
774 write(fd, buffer, strlen(buffer));
775 valueAt(i)->dump(fd);
776 }
777
778 return NO_ERROR;
779 }
780
781 }; //namespace android
782