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 "TypeConverter.h"
28 #include <media/AudioParameter.h>
29 #include <media/AudioPolicy.h>
30
31 // A device mask for all audio output devices that are considered "remote" when evaluating
32 // active output devices in isStreamActiveRemotely()
33 #define APM_AUDIO_OUT_DEVICE_REMOTE_ALL AUDIO_DEVICE_OUT_REMOTE_SUBMIX
34
35 namespace android {
36
AudioOutputDescriptor(const sp<AudioPort> & port,AudioPolicyClientInterface * clientInterface)37 AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port,
38 AudioPolicyClientInterface *clientInterface)
39 : mPort(port), mClientInterface(clientInterface)
40 {
41 if (mPort.get() != nullptr) {
42 mPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
43 if (mPort->mGains.size() > 0) {
44 mPort->mGains[0]->getDefaultConfig(&mGain);
45 }
46 }
47 }
48
getConfig() const49 audio_config_base_t AudioOutputDescriptor::getConfig() const
50 {
51 const audio_config_base_t config = { .sample_rate = mSamplingRate, .channel_mask = mChannelMask,
52 .format = mFormat };
53 return config;
54 }
55
getModuleHandle() const56 audio_module_handle_t AudioOutputDescriptor::getModuleHandle() const
57 {
58 return mPort.get() != nullptr ? mPort->getModuleHandle() : AUDIO_MODULE_HANDLE_NONE;
59 }
60
getPatchHandle() const61 audio_patch_handle_t AudioOutputDescriptor::getPatchHandle() const
62 {
63 return mPatchHandle;
64 }
65
setPatchHandle(audio_patch_handle_t handle)66 void AudioOutputDescriptor::setPatchHandle(audio_patch_handle_t handle)
67 {
68 mPatchHandle = handle;
69 }
70
getId() const71 audio_port_handle_t AudioOutputDescriptor::getId() const
72 {
73 return mId;
74 }
75
sharesHwModuleWith(const sp<AudioOutputDescriptor> & outputDesc)76 bool AudioOutputDescriptor::sharesHwModuleWith(
77 const sp<AudioOutputDescriptor>& outputDesc)
78 {
79 return hasSameHwModuleAs(outputDesc);
80 }
81
setStopTime(const sp<TrackClientDescriptor> & client,nsecs_t sysTime)82 void AudioOutputDescriptor::setStopTime(const sp<TrackClientDescriptor>& client, nsecs_t sysTime)
83 {
84 mVolumeActivities[client->volumeSource()].setStopTime(sysTime);
85 mRoutingActivities[client->strategy()].setStopTime(sysTime);
86 }
87
setClientActive(const sp<TrackClientDescriptor> & client,bool active)88 void AudioOutputDescriptor::setClientActive(const sp<TrackClientDescriptor>& client, bool active)
89 {
90 auto clientIter = std::find(begin(mActiveClients), end(mActiveClients), client);
91 if (active == (clientIter != end(mActiveClients))) {
92 ALOGW("%s(%s): ignored active: %d, current stream count %d", __func__,
93 client->toShortString().c_str(), active,
94 mRoutingActivities.at(client->strategy()).getActivityCount());
95 return;
96 }
97 if (active) {
98 mActiveClients.push_back(client);
99 } else {
100 mActiveClients.erase(clientIter);
101 }
102 const int delta = active ? 1 : -1;
103 // If ps is unknown, it is time to track it!
104 mRoutingActivities[client->strategy()].changeActivityCount(delta);
105 mVolumeActivities[client->volumeSource()].changeActivityCount(delta);
106
107 // Handle non-client-specific activity ref count
108 int32_t oldGlobalActiveCount = mGlobalActiveCount;
109 if (!active && mGlobalActiveCount < 1) {
110 ALOGW("%s(%s): invalid deactivation with globalRefCount %d",
111 __func__, client->toShortString().c_str(), mGlobalActiveCount);
112 mGlobalActiveCount = 1;
113 }
114 mGlobalActiveCount += delta;
115
116 sp<AudioPolicyMix> policyMix = mPolicyMix.promote();
117 if ((policyMix != NULL) && ((policyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
118 if ((oldGlobalActiveCount == 0) || (mGlobalActiveCount == 0)) {
119 mClientInterface->onDynamicPolicyMixStateUpdate(policyMix->mDeviceAddress,
120 mGlobalActiveCount > 0 ? MIX_STATE_MIXING : MIX_STATE_IDLE);
121 }
122 }
123 client->setActive(active);
124 }
125
isActive(VolumeSource vs,uint32_t inPastMs,nsecs_t sysTime) const126 bool AudioOutputDescriptor::isActive(VolumeSource vs, uint32_t inPastMs, nsecs_t sysTime) const
127 {
128 return (vs == VOLUME_SOURCE_NONE) ?
129 isActive(inPastMs) : (mVolumeActivities.find(vs) != std::end(mVolumeActivities)?
130 mVolumeActivities.at(vs).isActive(inPastMs, sysTime) : false);
131 }
132
isActive(uint32_t inPastMs) const133 bool AudioOutputDescriptor::isActive(uint32_t inPastMs) const
134 {
135 nsecs_t sysTime = 0;
136 if (inPastMs != 0) {
137 sysTime = systemTime();
138 }
139 for (const auto &iter : mVolumeActivities) {
140 if (iter.second.isActive(inPastMs, sysTime)) {
141 return true;
142 }
143 }
144 return false;
145 }
146
isFixedVolume(audio_devices_t device __unused)147 bool AudioOutputDescriptor::isFixedVolume(audio_devices_t device __unused)
148 {
149 return false;
150 }
151
setVolume(float volumeDb,VolumeSource volumeSource,const StreamTypeVector &,audio_devices_t,uint32_t delayMs,bool force)152 bool AudioOutputDescriptor::setVolume(float volumeDb,
153 VolumeSource volumeSource,
154 const StreamTypeVector &/*streams*/,
155 audio_devices_t /*device*/,
156 uint32_t delayMs,
157 bool force)
158 {
159 // We actually change the volume if:
160 // - the float value returned by computeVolume() changed
161 // - the force flag is set
162 if (volumeDb != getCurVolume(volumeSource) || force) {
163 ALOGV("%s for volumeSrc %d, volume %f, delay %d", __func__, volumeSource, volumeDb, delayMs);
164 setCurVolume(volumeSource, volumeDb);
165 return true;
166 }
167 return false;
168 }
169
toAudioPortConfig(struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig) const170 void AudioOutputDescriptor::toAudioPortConfig(
171 struct audio_port_config *dstConfig,
172 const struct audio_port_config *srcConfig) const
173 {
174 dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK|
175 AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN;
176 if (srcConfig != NULL) {
177 dstConfig->config_mask |= srcConfig->config_mask;
178 }
179 AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
180
181 dstConfig->id = mId;
182 dstConfig->role = AUDIO_PORT_ROLE_SOURCE;
183 dstConfig->type = AUDIO_PORT_TYPE_MIX;
184 dstConfig->ext.mix.hw_module = getModuleHandle();
185 dstConfig->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT;
186 }
187
toAudioPort(struct audio_port * port) const188 void AudioOutputDescriptor::toAudioPort(struct audio_port *port) const
189 {
190 // Should not be called for duplicated ports, see SwAudioOutputDescriptor::toAudioPortConfig.
191 mPort->toAudioPort(port);
192 port->id = mId;
193 port->ext.mix.hw_module = getModuleHandle();
194 }
195
clientsList(bool activeOnly,product_strategy_t strategy,bool preferredDeviceOnly) const196 TrackClientVector AudioOutputDescriptor::clientsList(bool activeOnly, product_strategy_t strategy,
197 bool preferredDeviceOnly) const
198 {
199 TrackClientVector clients;
200 for (const auto &client : getClientIterable()) {
201 if ((!activeOnly || client->active())
202 && (strategy == PRODUCT_STRATEGY_NONE || strategy == client->strategy())
203 && (!preferredDeviceOnly ||
204 (client->hasPreferredDevice() && !client->isPreferredDeviceForExclusiveUse()))) {
205 clients.push_back(client);
206 }
207 }
208 return clients;
209 }
210
isAnyActive(VolumeSource volumeSourceToIgnore) const211 bool AudioOutputDescriptor::isAnyActive(VolumeSource volumeSourceToIgnore) const
212 {
213 return std::find_if(begin(mActiveClients), end(mActiveClients),
214 [&volumeSourceToIgnore](const auto &client) {
215 return client->volumeSource() != volumeSourceToIgnore; }) != end(mActiveClients);
216 }
217
dump(String8 * dst) const218 void AudioOutputDescriptor::dump(String8 *dst) const
219 {
220 dst->appendFormat(" ID: %d\n", mId);
221 dst->appendFormat(" Sampling rate: %d\n", mSamplingRate);
222 dst->appendFormat(" Format: %08x\n", mFormat);
223 dst->appendFormat(" Channels: %08x\n", mChannelMask);
224 dst->appendFormat(" Devices: %s\n", devices().toString().c_str());
225 dst->appendFormat(" Global active count: %u\n", mGlobalActiveCount);
226 for (const auto &iter : mRoutingActivities) {
227 dst->appendFormat(" Product Strategy id: %d", iter.first);
228 iter.second.dump(dst, 4);
229 }
230 for (const auto &iter : mVolumeActivities) {
231 dst->appendFormat(" Volume Activities id: %d", iter.first);
232 iter.second.dump(dst, 4);
233 }
234 dst->append(" AudioTrack Clients:\n");
235 ClientMapHandler<TrackClientDescriptor>::dump(dst);
236 dst->append("\n");
237 if (!mActiveClients.empty()) {
238 dst->append(" AudioTrack active (stream) clients:\n");
239 size_t index = 0;
240 for (const auto& client : mActiveClients) {
241 client->dump(dst, 2, index++);
242 }
243 dst->append(" \n");
244 }
245 }
246
log(const char * indent)247 void AudioOutputDescriptor::log(const char* indent)
248 {
249 ALOGI("%sID: %d,0x%X, [rt:%d fmt:0x%X ch:0x%X]",
250 indent, mId, mId, mSamplingRate, mFormat, mChannelMask);
251 }
252
253 // SwAudioOutputDescriptor implementation
SwAudioOutputDescriptor(const sp<IOProfile> & profile,AudioPolicyClientInterface * clientInterface)254 SwAudioOutputDescriptor::SwAudioOutputDescriptor(const sp<IOProfile>& profile,
255 AudioPolicyClientInterface *clientInterface)
256 : AudioOutputDescriptor(profile, clientInterface),
257 mProfile(profile), mIoHandle(AUDIO_IO_HANDLE_NONE), mLatency(0),
258 mFlags((audio_output_flags_t)0),
259 mOutput1(0), mOutput2(0), mDirectOpenCount(0),
260 mDirectClientSession(AUDIO_SESSION_NONE)
261 {
262 if (profile != NULL) {
263 mFlags = (audio_output_flags_t)profile->getFlags();
264 }
265 }
266
dump(String8 * dst) const267 void SwAudioOutputDescriptor::dump(String8 *dst) const
268 {
269 dst->appendFormat(" Latency: %d\n", mLatency);
270 dst->appendFormat(" Flags %08x\n", mFlags);
271 AudioOutputDescriptor::dump(dst);
272 }
273
devices() const274 DeviceVector SwAudioOutputDescriptor::devices() const
275 {
276 if (isDuplicated()) {
277 DeviceVector devices = mOutput1->devices();
278 devices.merge(mOutput2->devices());
279 return devices;
280 }
281 return mDevices;
282 }
283
sharesHwModuleWith(const sp<SwAudioOutputDescriptor> & outputDesc)284 bool SwAudioOutputDescriptor::sharesHwModuleWith(
285 const sp<SwAudioOutputDescriptor>& outputDesc)
286 {
287 if (isDuplicated()) {
288 return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc);
289 } else if (outputDesc->isDuplicated()){
290 return sharesHwModuleWith(outputDesc->subOutput1()) ||
291 sharesHwModuleWith(outputDesc->subOutput2());
292 } else {
293 return AudioOutputDescriptor::sharesHwModuleWith(outputDesc);
294 }
295 }
296
supportedDevices() const297 DeviceVector SwAudioOutputDescriptor::supportedDevices() const
298 {
299 if (isDuplicated()) {
300 DeviceVector supportedDevices = mOutput1->supportedDevices();
301 supportedDevices.merge(mOutput2->supportedDevices());
302 return supportedDevices;
303 }
304 return mProfile->getSupportedDevices();
305 }
306
supportsDevice(const sp<DeviceDescriptor> & device) const307 bool SwAudioOutputDescriptor::supportsDevice(const sp<DeviceDescriptor> &device) const
308 {
309 return supportedDevices().contains(device);
310 }
311
supportsAllDevices(const DeviceVector & devices) const312 bool SwAudioOutputDescriptor::supportsAllDevices(const DeviceVector &devices) const
313 {
314 return supportedDevices().containsAllDevices(devices);
315 }
316
filterSupportedDevices(const DeviceVector & devices) const317 DeviceVector SwAudioOutputDescriptor::filterSupportedDevices(const DeviceVector &devices) const
318 {
319 DeviceVector filteredDevices = supportedDevices();
320 return filteredDevices.filter(devices);
321 }
322
deviceSupportsEncodedFormats(audio_devices_t device)323 bool SwAudioOutputDescriptor::deviceSupportsEncodedFormats(audio_devices_t device)
324 {
325 if (isDuplicated()) {
326 return (mOutput1->deviceSupportsEncodedFormats(device)
327 || mOutput2->deviceSupportsEncodedFormats(device));
328 } else {
329 return mProfile->deviceSupportsEncodedFormats(device);
330 }
331 }
332
latency()333 uint32_t SwAudioOutputDescriptor::latency()
334 {
335 if (isDuplicated()) {
336 return (mOutput1->mLatency > mOutput2->mLatency) ? mOutput1->mLatency : mOutput2->mLatency;
337 } else {
338 return mLatency;
339 }
340 }
341
setClientActive(const sp<TrackClientDescriptor> & client,bool active)342 void SwAudioOutputDescriptor::setClientActive(const sp<TrackClientDescriptor>& client, bool active)
343 {
344 // forward usage count change to attached outputs
345 if (isDuplicated()) {
346 mOutput1->setClientActive(client, active);
347 mOutput2->setClientActive(client, active);
348 }
349 AudioOutputDescriptor::setClientActive(client, active);
350 }
351
isFixedVolume(audio_devices_t device)352 bool SwAudioOutputDescriptor::isFixedVolume(audio_devices_t device)
353 {
354 // unit gain if rerouting to external policy
355 if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) {
356 if (mPolicyMix != NULL) {
357 ALOGV("max gain when rerouting for output=%d", mIoHandle);
358 return true;
359 }
360 }
361 if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
362 ALOGV("max gain when output device is telephony tx");
363 return true;
364 }
365 return false;
366 }
367
toAudioPortConfig(struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig) const368 void SwAudioOutputDescriptor::toAudioPortConfig(
369 struct audio_port_config *dstConfig,
370 const struct audio_port_config *srcConfig) const
371 {
372
373 ALOG_ASSERT(!isDuplicated(), "toAudioPortConfig() called on duplicated output %d", mIoHandle);
374 AudioOutputDescriptor::toAudioPortConfig(dstConfig, srcConfig);
375
376 dstConfig->ext.mix.handle = mIoHandle;
377 }
378
toAudioPort(struct audio_port * port) const379 void SwAudioOutputDescriptor::toAudioPort(
380 struct audio_port *port) const
381 {
382 ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle);
383
384 AudioOutputDescriptor::toAudioPort(port);
385
386 toAudioPortConfig(&port->active_config);
387 port->ext.mix.handle = mIoHandle;
388 port->ext.mix.latency_class =
389 mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL;
390 }
391
setVolume(float volumeDb,VolumeSource vs,const StreamTypeVector & streamTypes,audio_devices_t device,uint32_t delayMs,bool force)392 bool SwAudioOutputDescriptor::setVolume(float volumeDb,
393 VolumeSource vs, const StreamTypeVector &streamTypes,
394 audio_devices_t device,
395 uint32_t delayMs,
396 bool force)
397 {
398 StreamTypeVector streams = streamTypes;
399 if (!AudioOutputDescriptor::setVolume(volumeDb, vs, streamTypes, device, delayMs, force)) {
400 return false;
401 }
402 if (streams.empty()) {
403 streams.push_back(AUDIO_STREAM_MUSIC);
404 }
405 for (const auto& devicePort : devices()) {
406 // APM loops on all group, so filter on active group to set the port gain,
407 // let the other groups set the stream volume as per legacy
408 // TODO: Pass in the device address and check against it.
409 if (device == devicePort->type() &&
410 devicePort->hasGainController(true) && isActive(vs)) {
411 ALOGV("%s: device %s has gain controller", __func__, devicePort->toString().c_str());
412 // @todo: here we might be in trouble if the SwOutput has several active clients with
413 // different Volume Source (or if we allow several curves within same volume group)
414 //
415 // @todo: default stream volume to max (0) when using HW Port gain?
416 float volumeAmpl = Volume::DbToAmpl(0);
417 for (const auto &stream : streams) {
418 mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
419 }
420
421 AudioGains gains = devicePort->getGains();
422 int gainMinValueInMb = gains[0]->getMinValueInMb();
423 int gainMaxValueInMb = gains[0]->getMaxValueInMb();
424 int gainStepValueInMb = gains[0]->getStepValueInMb();
425 int gainValueMb = ((volumeDb * 100)/ gainStepValueInMb) * gainStepValueInMb;
426 gainValueMb = std::max(gainMinValueInMb, std::min(gainValueMb, gainMaxValueInMb));
427
428 audio_port_config config = {};
429 devicePort->toAudioPortConfig(&config);
430 config.config_mask = AUDIO_PORT_CONFIG_GAIN;
431 config.gain.values[0] = gainValueMb;
432 return mClientInterface->setAudioPortConfig(&config, 0) == NO_ERROR;
433 }
434 }
435 // Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is enabled
436 float volumeAmpl = Volume::DbToAmpl(getCurVolume(vs));
437 if (hasStream(streams, AUDIO_STREAM_BLUETOOTH_SCO)) {
438 mClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volumeAmpl, mIoHandle, delayMs);
439 }
440 for (const auto &stream : streams) {
441 ALOGV("%s output %d for volumeSource %d, volume %f, delay %d stream=%s", __func__,
442 mIoHandle, vs, volumeDb, delayMs, toString(stream).c_str());
443 mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
444 }
445 return true;
446 }
447
open(const audio_config_t * config,const DeviceVector & devices,audio_stream_type_t stream,audio_output_flags_t flags,audio_io_handle_t * output)448 status_t SwAudioOutputDescriptor::open(const audio_config_t *config,
449 const DeviceVector &devices,
450 audio_stream_type_t stream,
451 audio_output_flags_t flags,
452 audio_io_handle_t *output)
453 {
454 mDevices = devices;
455 const String8& address = devices.getFirstValidAddress();
456 audio_devices_t device = devices.types();
457
458 audio_config_t lConfig;
459 if (config == nullptr) {
460 lConfig = AUDIO_CONFIG_INITIALIZER;
461 lConfig.sample_rate = mSamplingRate;
462 lConfig.channel_mask = mChannelMask;
463 lConfig.format = mFormat;
464 } else {
465 lConfig = *config;
466 }
467
468 // if the selected profile is offloaded and no offload info was specified,
469 // create a default one
470 if ((mProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
471 lConfig.offload_info.format == AUDIO_FORMAT_DEFAULT) {
472 flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD);
473 lConfig.offload_info = AUDIO_INFO_INITIALIZER;
474 lConfig.offload_info.sample_rate = lConfig.sample_rate;
475 lConfig.offload_info.channel_mask = lConfig.channel_mask;
476 lConfig.offload_info.format = lConfig.format;
477 lConfig.offload_info.stream_type = stream;
478 lConfig.offload_info.duration_us = -1;
479 lConfig.offload_info.has_video = true; // conservative
480 lConfig.offload_info.is_streaming = true; // likely
481 }
482
483 mFlags = (audio_output_flags_t)(mFlags | flags);
484
485 ALOGV("opening output for device %s profile %p name %s",
486 mDevices.toString().c_str(), mProfile.get(), mProfile->getName().string());
487
488 status_t status = mClientInterface->openOutput(mProfile->getModuleHandle(),
489 output,
490 &lConfig,
491 &device,
492 address,
493 &mLatency,
494 mFlags);
495 LOG_ALWAYS_FATAL_IF(mDevices.types() != device,
496 "%s openOutput returned device %08x when given device %08x",
497 __FUNCTION__, mDevices.types(), device);
498
499 if (status == NO_ERROR) {
500 LOG_ALWAYS_FATAL_IF(*output == AUDIO_IO_HANDLE_NONE,
501 "%s openOutput returned output handle %d for device %08x",
502 __FUNCTION__, *output, device);
503 mSamplingRate = lConfig.sample_rate;
504 mChannelMask = lConfig.channel_mask;
505 mFormat = lConfig.format;
506 mId = AudioPort::getNextUniqueId();
507 mIoHandle = *output;
508 mProfile->curOpenCount++;
509 }
510
511 return status;
512 }
513
start()514 status_t SwAudioOutputDescriptor::start()
515 {
516 if (isDuplicated()) {
517 status_t status = mOutput1->start();
518 if (status != NO_ERROR) {
519 return status;
520 }
521 status = mOutput2->start();
522 if (status != NO_ERROR) {
523 mOutput1->stop();
524 return status;
525 }
526 return NO_ERROR;
527 }
528 if (!isActive()) {
529 if (!mProfile->canStartNewIo()) {
530 return INVALID_OPERATION;
531 }
532 mProfile->curActiveCount++;
533 }
534 return NO_ERROR;
535 }
536
stop()537 void SwAudioOutputDescriptor::stop()
538 {
539 if (isDuplicated()) {
540 mOutput1->stop();
541 mOutput2->stop();
542 return;
543 }
544
545 if (!isActive()) {
546 LOG_ALWAYS_FATAL_IF(mProfile->curActiveCount < 1,
547 "%s invalid profile active count %u",
548 __func__, mProfile->curActiveCount);
549 mProfile->curActiveCount--;
550 }
551 }
552
close()553 void SwAudioOutputDescriptor::close()
554 {
555 if (mIoHandle != AUDIO_IO_HANDLE_NONE) {
556 // clean up active clients if any (can happen if close() is called to force
557 // clients to reconnect
558 for (const auto &client : getClientIterable()) {
559 if (client->active()) {
560 ALOGW("%s client with port ID %d still active on output %d",
561 __func__, client->portId(), mId);
562 setClientActive(client, false);
563 stop();
564 }
565 }
566
567 AudioParameter param;
568 param.add(String8("closing"), String8("true"));
569 mClientInterface->setParameters(mIoHandle, param.toString());
570
571 mClientInterface->closeOutput(mIoHandle);
572
573 LOG_ALWAYS_FATAL_IF(mProfile->curOpenCount < 1, "%s profile open count %u",
574 __FUNCTION__, mProfile->curOpenCount);
575 mProfile->curOpenCount--;
576 mIoHandle = AUDIO_IO_HANDLE_NONE;
577 }
578 }
579
openDuplicating(const sp<SwAudioOutputDescriptor> & output1,const sp<SwAudioOutputDescriptor> & output2,audio_io_handle_t * ioHandle)580 status_t SwAudioOutputDescriptor::openDuplicating(const sp<SwAudioOutputDescriptor>& output1,
581 const sp<SwAudioOutputDescriptor>& output2,
582 audio_io_handle_t *ioHandle)
583 {
584 // open a duplicating output thread for the new output and the primary output
585 // Note: openDuplicateOutput() API expects the output handles in the reverse order from the
586 // numbering in SwAudioOutputDescriptor mOutput1 and mOutput2
587 *ioHandle = mClientInterface->openDuplicateOutput(output2->mIoHandle, output1->mIoHandle);
588 if (*ioHandle == AUDIO_IO_HANDLE_NONE) {
589 return INVALID_OPERATION;
590 }
591
592 mId = AudioPort::getNextUniqueId();
593 mIoHandle = *ioHandle;
594 mOutput1 = output1;
595 mOutput2 = output2;
596 mSamplingRate = output2->mSamplingRate;
597 mFormat = output2->mFormat;
598 mChannelMask = output2->mChannelMask;
599 mLatency = output2->mLatency;
600
601 return NO_ERROR;
602 }
603
604 // HwAudioOutputDescriptor implementation
HwAudioOutputDescriptor(const sp<SourceClientDescriptor> & source,AudioPolicyClientInterface * clientInterface)605 HwAudioOutputDescriptor::HwAudioOutputDescriptor(const sp<SourceClientDescriptor>& source,
606 AudioPolicyClientInterface *clientInterface)
607 : AudioOutputDescriptor(source->srcDevice(), clientInterface),
608 mSource(source)
609 {
610 }
611
dump(String8 * dst) const612 void HwAudioOutputDescriptor::dump(String8 *dst) const
613 {
614 AudioOutputDescriptor::dump(dst);
615 dst->append("Source:\n");
616 mSource->dump(dst, 0, 0);
617 }
618
toAudioPortConfig(struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig) const619 void HwAudioOutputDescriptor::toAudioPortConfig(
620 struct audio_port_config *dstConfig,
621 const struct audio_port_config *srcConfig) const
622 {
623 mSource->srcDevice()->toAudioPortConfig(dstConfig, srcConfig);
624 }
625
toAudioPort(struct audio_port * port) const626 void HwAudioOutputDescriptor::toAudioPort(
627 struct audio_port *port) const
628 {
629 mSource->srcDevice()->toAudioPort(port);
630 }
631
632
setVolume(float volumeDb,VolumeSource volumeSource,const StreamTypeVector & streams,audio_devices_t device,uint32_t delayMs,bool force)633 bool HwAudioOutputDescriptor::setVolume(float volumeDb,
634 VolumeSource volumeSource, const StreamTypeVector &streams,
635 audio_devices_t device,
636 uint32_t delayMs,
637 bool force)
638 {
639 bool changed =
640 AudioOutputDescriptor::setVolume(volumeDb, volumeSource, streams, device, delayMs, force);
641
642 if (changed) {
643 // TODO: use gain controller on source device if any to adjust volume
644 }
645 return changed;
646 }
647
648 // SwAudioOutputCollection implementation
isActive(VolumeSource volumeSource,uint32_t inPastMs) const649 bool SwAudioOutputCollection::isActive(VolumeSource volumeSource, uint32_t inPastMs) const
650 {
651 nsecs_t sysTime = systemTime();
652 for (size_t i = 0; i < this->size(); i++) {
653 const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
654 if (outputDesc->isActive(volumeSource, inPastMs, sysTime)) {
655 return true;
656 }
657 }
658 return false;
659 }
660
isActiveLocally(VolumeSource volumeSource,uint32_t inPastMs) const661 bool SwAudioOutputCollection::isActiveLocally(VolumeSource volumeSource, uint32_t inPastMs) const
662 {
663 nsecs_t sysTime = systemTime();
664 for (size_t i = 0; i < this->size(); i++) {
665 const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
666 if (outputDesc->isActive(volumeSource, inPastMs, sysTime)
667 && ((outputDesc->devices().types() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) == 0)) {
668 return true;
669 }
670 }
671 return false;
672 }
673
isActiveRemotely(VolumeSource volumeSource,uint32_t inPastMs) const674 bool SwAudioOutputCollection::isActiveRemotely(VolumeSource volumeSource, uint32_t inPastMs) const
675 {
676 nsecs_t sysTime = systemTime();
677 for (size_t i = 0; i < size(); i++) {
678 const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
679 if (((outputDesc->devices().types() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
680 outputDesc->isActive(volumeSource, inPastMs, sysTime)) {
681 // do not consider re routing (when the output is going to a dynamic policy)
682 // as "remote playback"
683 if (outputDesc->mPolicyMix == NULL) {
684 return true;
685 }
686 }
687 }
688 return false;
689 }
690
isStrategyActiveOnSameModule(product_strategy_t ps,const sp<SwAudioOutputDescriptor> & desc,uint32_t inPastMs,nsecs_t sysTime) const691 bool SwAudioOutputCollection::isStrategyActiveOnSameModule(product_strategy_t ps,
692 const sp<SwAudioOutputDescriptor>& desc,
693 uint32_t inPastMs, nsecs_t sysTime) const
694 {
695 for (size_t i = 0; i < size(); i++) {
696 const sp<SwAudioOutputDescriptor> otherDesc = valueAt(i);
697 if (desc->sharesHwModuleWith(otherDesc) &&
698 otherDesc->isStrategyActive(ps, inPastMs, sysTime)) {
699 return true;
700 }
701 }
702 return false;
703 }
704
getA2dpOutput() const705 audio_io_handle_t SwAudioOutputCollection::getA2dpOutput() const
706 {
707 for (size_t i = 0; i < size(); i++) {
708 sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
709 if (!outputDesc->isDuplicated() &&
710 outputDesc->devices().types() & AUDIO_DEVICE_OUT_ALL_A2DP &&
711 outputDesc->deviceSupportsEncodedFormats(
712 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)) {
713 return this->keyAt(i);
714 }
715 }
716 return 0;
717 }
718
isA2dpOffloadedOnPrimary() const719 bool SwAudioOutputCollection::isA2dpOffloadedOnPrimary() const
720 {
721 sp<SwAudioOutputDescriptor> primaryOutput = getPrimaryOutput();
722
723 if ((primaryOutput != NULL) && (primaryOutput->mProfile != NULL)
724 && (primaryOutput->mProfile->getModule() != NULL)) {
725 sp<HwModule> primaryHwModule = primaryOutput->mProfile->getModule();
726
727 for (const auto &outputProfile : primaryHwModule->getOutputProfiles()) {
728 if (outputProfile->supportsDeviceTypes(AUDIO_DEVICE_OUT_ALL_A2DP)) {
729 return true;
730 }
731 }
732 }
733 return false;
734 }
735
isA2dpSupported() const736 bool SwAudioOutputCollection::isA2dpSupported() const
737 {
738 return (isA2dpOffloadedOnPrimary() || (getA2dpOutput() != 0));
739 }
740
getPrimaryOutput() const741 sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getPrimaryOutput() const
742 {
743 for (size_t i = 0; i < size(); i++) {
744 const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
745 if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
746 return outputDesc;
747 }
748 }
749 return NULL;
750 }
751
getOutputFromId(audio_port_handle_t id) const752 sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getOutputFromId(audio_port_handle_t id) const
753 {
754 for (size_t i = 0; i < size(); i++) {
755 const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
756 if (outputDesc->getId() == id) {
757 return outputDesc;
758 }
759 }
760 return NULL;
761 }
762
getOutputForClient(audio_port_handle_t portId)763 sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getOutputForClient(audio_port_handle_t portId)
764 {
765 for (size_t i = 0; i < size(); i++) {
766 sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
767 if (outputDesc->getClient(portId) != nullptr) {
768 return outputDesc;
769 }
770 }
771 return 0;
772 }
773
clearSessionRoutesForDevice(const sp<DeviceDescriptor> & disconnectedDevice)774 void SwAudioOutputCollection::clearSessionRoutesForDevice(
775 const sp<DeviceDescriptor> &disconnectedDevice)
776 {
777 for (size_t i = 0; i < size(); i++) {
778 sp<AudioOutputDescriptor> outputDesc = valueAt(i);
779 for (const auto& client : outputDesc->getClientIterable()) {
780 if (client->preferredDeviceId() == disconnectedDevice->getId()) {
781 client->setPreferredDeviceId(AUDIO_PORT_HANDLE_NONE);
782 }
783 }
784 }
785 }
786
dump(String8 * dst) const787 void SwAudioOutputCollection::dump(String8 *dst) const
788 {
789 dst->append("\nOutputs dump:\n");
790 for (size_t i = 0; i < size(); i++) {
791 dst->appendFormat("- Output %d dump:\n", keyAt(i));
792 valueAt(i)->dump(dst);
793 }
794 }
795
796 // HwAudioOutputCollection implementation
isActive(VolumeSource volumeSource,uint32_t inPastMs) const797 bool HwAudioOutputCollection::isActive(VolumeSource volumeSource, uint32_t inPastMs) const
798 {
799 nsecs_t sysTime = systemTime();
800 for (size_t i = 0; i < this->size(); i++) {
801 const sp<HwAudioOutputDescriptor> outputDesc = this->valueAt(i);
802 if (outputDesc->isActive(volumeSource, inPastMs, sysTime)) {
803 return true;
804 }
805 }
806 return false;
807 }
808
dump(String8 * dst) const809 void HwAudioOutputCollection::dump(String8 *dst) const
810 {
811 dst->append("\nOutputs dump:\n");
812 for (size_t i = 0; i < size(); i++) {
813 dst->appendFormat("- Output %d dump:\n", keyAt(i));
814 valueAt(i)->dump(dst);
815 }
816 }
817
818 }; //namespace android
819