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 <android-base/stringprintf.h>
21 
22 #include <AudioPolicyInterface.h>
23 #include "AudioOutputDescriptor.h"
24 #include "AudioPolicyMix.h"
25 #include "IOProfile.h"
26 #include "Volume.h"
27 #include "HwModule.h"
28 #include "TypeConverter.h"
29 #include "policy.h"
30 #include <media/AudioGain.h>
31 #include <media/AudioParameter.h>
32 #include <media/AudioPolicy.h>
33 
34 // A device mask for all audio output devices that are considered "remote" when evaluating
35 // active output devices in isStreamActiveRemotely()
36 
37 namespace android {
38 
getAllOutRemoteDevices()39 static const DeviceTypeSet& getAllOutRemoteDevices() {
40     static const DeviceTypeSet allOutRemoteDevices = {AUDIO_DEVICE_OUT_REMOTE_SUBMIX};
41     return allOutRemoteDevices;
42 }
43 
AudioOutputDescriptor(const sp<PolicyAudioPort> & policyAudioPort,AudioPolicyClientInterface * clientInterface)44 AudioOutputDescriptor::AudioOutputDescriptor(const sp<PolicyAudioPort>& policyAudioPort,
45                                              AudioPolicyClientInterface *clientInterface)
46     : mPolicyAudioPort(policyAudioPort), mClientInterface(clientInterface)
47 {
48     if (mPolicyAudioPort.get() != nullptr) {
49         mPolicyAudioPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
50         if (mPolicyAudioPort->asAudioPort()->getGains().size() > 0) {
51             mPolicyAudioPort->asAudioPort()->getGains()[0]->getDefaultConfig(&mGain);
52         }
53     }
54 }
55 
getConfig() const56 audio_config_base_t AudioOutputDescriptor::getConfig() const
57 {
58     const audio_config_base_t config = { .sample_rate = mSamplingRate, .channel_mask = mChannelMask,
59             .format = mFormat };
60     return config;
61 }
62 
getModuleHandle() const63 audio_module_handle_t AudioOutputDescriptor::getModuleHandle() const
64 {
65     return mPolicyAudioPort.get() != nullptr ?
66             mPolicyAudioPort->getModuleHandle() : AUDIO_MODULE_HANDLE_NONE;
67 }
68 
getPatchHandle() const69 audio_patch_handle_t AudioOutputDescriptor::getPatchHandle() const
70 {
71     return mPatchHandle;
72 }
73 
setPatchHandle(audio_patch_handle_t handle)74 void AudioOutputDescriptor::setPatchHandle(audio_patch_handle_t handle)
75 {
76     mPatchHandle = handle;
77 }
78 
sharesHwModuleWith(const sp<AudioOutputDescriptor> & outputDesc)79 bool AudioOutputDescriptor::sharesHwModuleWith(
80         const sp<AudioOutputDescriptor>& outputDesc)
81 {
82     return hasSameHwModuleAs(outputDesc);
83 }
84 
setStopTime(const sp<TrackClientDescriptor> & client,nsecs_t sysTime)85 void AudioOutputDescriptor::setStopTime(const sp<TrackClientDescriptor>& client, nsecs_t sysTime)
86 {
87     mVolumeActivities[client->volumeSource()].setStopTime(sysTime);
88     mRoutingActivities[client->strategy()].setStopTime(sysTime);
89 }
90 
setClientActive(const sp<TrackClientDescriptor> & client,bool active)91 void AudioOutputDescriptor::setClientActive(const sp<TrackClientDescriptor>& client, bool active)
92 {
93     auto clientIter = std::find(begin(mActiveClients), end(mActiveClients), client);
94     if (active == (clientIter != end(mActiveClients))) {
95         ALOGW("%s(%s): ignored active: %d, current stream count %d", __func__,
96               client->toShortString().c_str(), active,
97               mRoutingActivities.at(client->strategy()).getActivityCount());
98         return;
99     }
100     if (active) {
101         mActiveClients.push_back(client);
102     } else {
103         mActiveClients.erase(clientIter);
104     }
105     const int delta = active ? 1 : -1;
106     // If ps is unknown, it is time to track it!
107     mRoutingActivities[client->strategy()].changeActivityCount(delta);
108     mVolumeActivities[client->volumeSource()].changeActivityCount(delta);
109 
110     // Handle non-client-specific activity ref count
111     int32_t oldGlobalActiveCount = mGlobalActiveCount;
112     if (!active && mGlobalActiveCount < 1) {
113         ALOGW("%s(%s): invalid deactivation with globalRefCount %d",
114               __func__, client->toShortString().c_str(), mGlobalActiveCount);
115         mGlobalActiveCount = 1;
116     }
117     mGlobalActiveCount += delta;
118 
119     sp<AudioPolicyMix> policyMix = mPolicyMix.promote();
120     if ((policyMix != NULL) && ((policyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
121         if ((oldGlobalActiveCount == 0) || (mGlobalActiveCount == 0)) {
122             mClientInterface->onDynamicPolicyMixStateUpdate(policyMix->mDeviceAddress,
123                 mGlobalActiveCount > 0 ? MIX_STATE_MIXING : MIX_STATE_IDLE);
124         }
125     }
126     client->setActive(active);
127 }
128 
isClientActive(const sp<TrackClientDescriptor> & client)129 bool AudioOutputDescriptor::isClientActive(const sp<TrackClientDescriptor>& client)
130 {
131     return client != nullptr &&
132             std::find(begin(mActiveClients), end(mActiveClients), client) != end(mActiveClients);
133 }
134 
isActive(VolumeSource vs,uint32_t inPastMs,nsecs_t sysTime) const135 bool AudioOutputDescriptor::isActive(VolumeSource vs, uint32_t inPastMs, nsecs_t sysTime) const
136 {
137     return (vs == VOLUME_SOURCE_NONE) ?
138                 isActive(inPastMs) : (mVolumeActivities.find(vs) != std::end(mVolumeActivities)?
139                 mVolumeActivities.at(vs).isActive(inPastMs, sysTime) : false);
140 }
141 
isActive(uint32_t inPastMs) const142 bool AudioOutputDescriptor::isActive(uint32_t inPastMs) const
143 {
144     nsecs_t sysTime = 0;
145     if (inPastMs != 0) {
146         sysTime = systemTime();
147     }
148     for (const auto &iter : mVolumeActivities) {
149         if (iter.second.isActive(inPastMs, sysTime)) {
150             return true;
151         }
152     }
153     return false;
154 }
155 
isFixedVolume(const DeviceTypeSet & deviceTypes __unused)156 bool AudioOutputDescriptor::isFixedVolume(const DeviceTypeSet& deviceTypes __unused)
157 {
158     return false;
159 }
160 
setVolume(float volumeDb,bool,VolumeSource volumeSource,const StreamTypeVector &,const DeviceTypeSet & deviceTypes,uint32_t delayMs,bool force,bool isVoiceVolSrc)161 bool AudioOutputDescriptor::setVolume(float volumeDb, bool /*muted*/,
162                                       VolumeSource volumeSource,
163                                       const StreamTypeVector &/*streams*/,
164                                       const DeviceTypeSet& deviceTypes,
165                                       uint32_t delayMs,
166                                       bool force,
167                                       bool isVoiceVolSrc)
168 {
169 
170     if (!supportedDevices().containsDeviceAmongTypes(deviceTypes)) {
171         ALOGV("%s output ID %d unsupported device %s",
172                 __func__, getId(), toString(deviceTypes).c_str());
173         return false;
174     }
175     // We actually change the volume if:
176     // - the float value returned by computeVolume() changed
177     // - the force flag is set
178     if (volumeDb != getCurVolume(volumeSource) || force) {
179         ALOGV("%s for volumeSrc %d, volume %f, delay %d", __func__, volumeSource, volumeDb, delayMs);
180         setCurVolume(volumeSource, volumeDb, isVoiceVolSrc);
181         return true;
182     }
183     return false;
184 }
185 
applyAudioPortConfig(const struct audio_port_config * config,audio_port_config * backupConfig)186 status_t AudioOutputDescriptor::applyAudioPortConfig(const struct audio_port_config *config,
187                                                      audio_port_config *backupConfig)
188 {
189     struct audio_port_config localBackupConfig = { .config_mask = config->config_mask };
190     status_t status = NO_ERROR;
191 
192     toAudioPortConfig(&localBackupConfig);
193     if ((status = validationBeforeApplyConfig(config)) == NO_ERROR) {
194         AudioPortConfig::applyAudioPortConfig(config, backupConfig);
195     }
196 
197     if (backupConfig != NULL) {
198         *backupConfig = localBackupConfig;
199     }
200     return status;
201 }
202 
203 
toAudioPortConfig(struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig) const204 void AudioOutputDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
205                                               const struct audio_port_config *srcConfig) const
206 {
207     dstConfig->config_mask = AUDIO_PORT_CONFIG_ALL;
208     if (srcConfig != NULL) {
209         dstConfig->config_mask |= srcConfig->config_mask;
210     }
211     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
212 
213     dstConfig->role = AUDIO_PORT_ROLE_SOURCE;
214     dstConfig->type = AUDIO_PORT_TYPE_MIX;
215     dstConfig->ext.mix.hw_module = getModuleHandle();
216     dstConfig->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT;
217 }
218 
toAudioPort(struct audio_port_v7 * port) const219 void AudioOutputDescriptor::toAudioPort(struct audio_port_v7 *port) const
220 {
221     // Should not be called for duplicated ports, see SwAudioOutputDescriptor::toAudioPortConfig.
222     mPolicyAudioPort->asAudioPort()->toAudioPort(port);
223     port->id = mId;
224     port->ext.mix.hw_module = getModuleHandle();
225 }
226 
clientsList(bool activeOnly,product_strategy_t strategy,bool preferredDeviceOnly) const227 TrackClientVector AudioOutputDescriptor::clientsList(bool activeOnly, product_strategy_t strategy,
228                                                      bool preferredDeviceOnly) const
229 {
230     TrackClientVector clients;
231     for (const auto &client : getClientIterable()) {
232         if ((!activeOnly || client->active())
233             && (strategy == PRODUCT_STRATEGY_NONE || strategy == client->strategy())
234             && (!preferredDeviceOnly ||
235                 (client->hasPreferredDevice() && !client->isPreferredDeviceForExclusiveUse()))) {
236             clients.push_back(client);
237         }
238     }
239     return clients;
240 }
241 
sameExclusivePreferredDevicesCount() const242 size_t AudioOutputDescriptor::sameExclusivePreferredDevicesCount() const
243 {
244     audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
245     size_t count = 0;
246     for (const auto &client : getClientIterable()) {
247         if (client->active()) {
248             if (!(client->hasPreferredDevice() &&
249                     client->isPreferredDeviceForExclusiveUse())) {
250                 return 0;
251             }
252             if (deviceId == AUDIO_PORT_HANDLE_NONE) {
253                 deviceId = client->preferredDeviceId();
254             } else if (deviceId != client->preferredDeviceId()) {
255                 return 0;
256             }
257             count++;
258         }
259     }
260     return count;
261 }
262 
isAnyActive(VolumeSource volumeSourceToIgnore) const263 bool AudioOutputDescriptor::isAnyActive(VolumeSource volumeSourceToIgnore) const
264 {
265     return std::find_if(begin(mActiveClients), end(mActiveClients),
266                         [&volumeSourceToIgnore](const auto &client) {
267         return client->volumeSource() != volumeSourceToIgnore; }) != end(mActiveClients);
268 }
269 
dump(String8 * dst,int spaces,const char * extraInfo) const270 void AudioOutputDescriptor::dump(String8 *dst, int spaces, const char* extraInfo) const
271 {
272     dst->appendFormat("Port ID: %d%s%s\n",
273             mId, extraInfo != nullptr ? "; " : "", extraInfo != nullptr ? extraInfo : "");
274     dst->appendFormat("%*s%s; %d; Channel mask: 0x%x\n", spaces, "",
275             audio_format_to_string(mFormat), mSamplingRate, mChannelMask);
276     dst->appendFormat("%*sDevices: %s\n", spaces, "",
277             devices().toString(true /*includeSensitiveInfo*/).c_str());
278     dst->appendFormat("%*sGlobal active count: %u\n", spaces, "", mGlobalActiveCount);
279     if (!mRoutingActivities.empty()) {
280         dst->appendFormat("%*s- Product Strategies (%zu):\n", spaces - 2, "",
281                 mRoutingActivities.size());
282         for (const auto &iter : mRoutingActivities) {
283             dst->appendFormat("%*sid %d: ", spaces + 1, "", iter.first);
284             iter.second.dump(dst, 0);
285         }
286     }
287     if (!mVolumeActivities.empty()) {
288         dst->appendFormat("%*s- Volume Activities (%zu):\n", spaces - 2, "",
289                 mVolumeActivities.size());
290         for (const auto &iter : mVolumeActivities) {
291             dst->appendFormat("%*sid %d: ", spaces + 1, "", iter.first);
292             iter.second.dump(dst, 0);
293         }
294     }
295     if (getClientCount() != 0) {
296         dst->appendFormat("%*s- AudioTrack clients (%zu):\n", spaces - 2, "", getClientCount());
297         ClientMapHandler<TrackClientDescriptor>::dump(dst, spaces);
298     }
299     if (!mActiveClients.empty()) {
300         dst->appendFormat("%*s- AudioTrack active (stream) clients (%zu):\n", spaces - 2, "",
301                 mActiveClients.size());
302         size_t index = 0;
303         for (const auto& client : mActiveClients) {
304             const std::string prefix = base::StringPrintf(
305                     "%*sid %zu: ", spaces + 1, "", index + 1);
306             dst->appendFormat("%s", prefix.c_str());
307             client->dump(dst, prefix.size());
308         }
309     }
310 }
311 
log(const char * indent)312 void AudioOutputDescriptor::log(const char* indent)
313 {
314     ALOGI("%sID: %d,0x%X, [rt:%d fmt:0x%X ch:0x%X]",
315           indent, mId, mId, mSamplingRate, mFormat, mChannelMask);
316 }
317 
318 // SwAudioOutputDescriptor implementation
SwAudioOutputDescriptor(const sp<IOProfile> & profile,AudioPolicyClientInterface * clientInterface)319 SwAudioOutputDescriptor::SwAudioOutputDescriptor(const sp<IOProfile>& profile,
320                                                  AudioPolicyClientInterface *clientInterface)
321     : AudioOutputDescriptor(profile, clientInterface),
322     mProfile(profile), mIoHandle(AUDIO_IO_HANDLE_NONE), mLatency(0),
323     mOutput1(0), mOutput2(0), mDirectOpenCount(0),
324     mDirectClientSession(AUDIO_SESSION_NONE)
325 {
326     if (profile != nullptr) {
327         // By default, opening the output without immutable flags, the bit-perfect flags should be
328         // applied when the apps explicitly request.
329         mFlags = (audio_output_flags_t)(profile->getFlags() & (~AUDIO_OUTPUT_FLAG_BIT_PERFECT));
330     }
331 }
332 
dump(String8 * dst,int spaces,const char * extraInfo) const333 void SwAudioOutputDescriptor::dump(String8 *dst, int spaces, const char* extraInfo) const
334 {
335     String8 allExtraInfo;
336     if (extraInfo != nullptr) {
337         allExtraInfo.appendFormat("%s; ", extraInfo);
338     }
339     if (mProfile != nullptr) {
340         allExtraInfo.appendFormat("IOProfile name:%s; ", mProfile->getName().c_str());
341     }
342     std::string flagsLiteral = toString(mFlags);
343     allExtraInfo.appendFormat("Latency: %d; 0x%04x", mLatency, mFlags);
344     if (!flagsLiteral.empty()) {
345         allExtraInfo.appendFormat(" (%s)", flagsLiteral.c_str());
346     }
347     AudioOutputDescriptor::dump(dst, spaces, allExtraInfo.c_str());
348 }
349 
devices() const350 DeviceVector SwAudioOutputDescriptor::devices() const
351 {
352     if (isDuplicated()) {
353         DeviceVector devices = mOutput1->devices();
354         devices.merge(mOutput2->devices());
355         return devices;
356     }
357     return mDevices;
358 }
359 
sharesHwModuleWith(const sp<SwAudioOutputDescriptor> & outputDesc)360 bool SwAudioOutputDescriptor::sharesHwModuleWith(
361         const sp<SwAudioOutputDescriptor>& outputDesc)
362 {
363     if (isDuplicated()) {
364         return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc);
365     } else if (outputDesc->isDuplicated()){
366         return sharesHwModuleWith(outputDesc->subOutput1()) ||
367                     sharesHwModuleWith(outputDesc->subOutput2());
368     } else {
369         return AudioOutputDescriptor::sharesHwModuleWith(outputDesc);
370     }
371 }
372 
supportedDevices() const373 DeviceVector SwAudioOutputDescriptor::supportedDevices() const
374 {
375     if (isDuplicated()) {
376         DeviceVector supportedDevices = mOutput1->supportedDevices();
377         supportedDevices.merge(mOutput2->supportedDevices());
378         return supportedDevices;
379     }
380     if (mProfile != nullptr) {
381         return mProfile->getSupportedDevices();
382     }
383     return DeviceVector();
384 }
385 
supportsDevice(const sp<DeviceDescriptor> & device) const386 bool SwAudioOutputDescriptor::supportsDevice(const sp<DeviceDescriptor> &device) const
387 {
388     return supportedDevices().contains(device);
389 }
390 
supportsAllDevices(const DeviceVector & devices) const391 bool SwAudioOutputDescriptor::supportsAllDevices(const DeviceVector &devices) const
392 {
393     return supportedDevices().containsAllDevices(devices);
394 }
395 
supportsAtLeastOne(const DeviceVector & devices) const396 bool SwAudioOutputDescriptor::supportsAtLeastOne(const DeviceVector &devices) const
397 {
398     return filterSupportedDevices(devices).size() > 0;
399 }
400 
supportsDevicesForPlayback(const DeviceVector & devices) const401 bool SwAudioOutputDescriptor::supportsDevicesForPlayback(const DeviceVector &devices) const
402 {
403     // No considering duplicated output
404     // TODO: need to verify if the profile supports the devices combo for playback.
405     return !isDuplicated() && supportsAllDevices(devices);
406 }
407 
filterSupportedDevices(const DeviceVector & devices) const408 DeviceVector SwAudioOutputDescriptor::filterSupportedDevices(const DeviceVector &devices) const
409 {
410     DeviceVector filteredDevices = supportedDevices();
411     return filteredDevices.filter(devices);
412 }
413 
devicesSupportEncodedFormats(const DeviceTypeSet & deviceTypes)414 bool SwAudioOutputDescriptor::devicesSupportEncodedFormats(const DeviceTypeSet& deviceTypes)
415 {
416     if (isDuplicated()) {
417         return (mOutput1->devicesSupportEncodedFormats(deviceTypes)
418                     || mOutput2->devicesSupportEncodedFormats(deviceTypes));
419     } else if (mProfile != nullptr) {
420        return mProfile->devicesSupportEncodedFormats(deviceTypes);
421     }
422     return false;
423 }
424 
containsSingleDeviceSupportingEncodedFormats(const sp<DeviceDescriptor> & device) const425 bool SwAudioOutputDescriptor::containsSingleDeviceSupportingEncodedFormats(
426         const sp<DeviceDescriptor>& device) const
427 {
428     if (isDuplicated()) {
429         return (mOutput1->containsSingleDeviceSupportingEncodedFormats(device) &&
430                 mOutput2->containsSingleDeviceSupportingEncodedFormats(device));
431     }
432     if (mProfile != nullptr) {
433         return mProfile->containsSingleDeviceSupportingEncodedFormats(device);
434     }
435     return false;
436 }
437 
latency()438 uint32_t SwAudioOutputDescriptor::latency()
439 {
440     if (isDuplicated()) {
441         return (mOutput1->mLatency > mOutput2->mLatency) ? mOutput1->mLatency : mOutput2->mLatency;
442     } else {
443         return mLatency;
444     }
445 }
446 
setClientActive(const sp<TrackClientDescriptor> & client,bool active)447 void SwAudioOutputDescriptor::setClientActive(const sp<TrackClientDescriptor>& client, bool active)
448 {
449     // forward usage count change to attached outputs
450     if (isDuplicated()) {
451         mOutput1->setClientActive(client, active);
452         mOutput2->setClientActive(client, active);
453     }
454     AudioOutputDescriptor::setClientActive(client, active);
455 }
456 
isFixedVolume(const DeviceTypeSet & deviceTypes)457 bool SwAudioOutputDescriptor::isFixedVolume(const DeviceTypeSet& deviceTypes)
458 {
459     // unit gain if rerouting to external policy
460     if (isSingleDeviceType(deviceTypes, AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) {
461         if (mPolicyMix != NULL) {
462             ALOGV("max gain when rerouting for output=%d", mIoHandle);
463             return true;
464         }
465     }
466     if (isSingleDeviceType(deviceTypes, AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
467         ALOGV("max gain when output device is telephony tx");
468         return true;
469     }
470     return false;
471 }
472 
toAudioPortConfig(struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig) const473 void SwAudioOutputDescriptor::toAudioPortConfig(
474                                                  struct audio_port_config *dstConfig,
475                                                  const struct audio_port_config *srcConfig) const
476 {
477 
478     ALOG_ASSERT(!isDuplicated(), "toAudioPortConfig() called on duplicated output %d", mIoHandle);
479     AudioOutputDescriptor::toAudioPortConfig(dstConfig, srcConfig);
480 
481     dstConfig->ext.mix.handle = mIoHandle;
482 }
483 
toAudioPort(struct audio_port_v7 * port) const484 void SwAudioOutputDescriptor::toAudioPort(struct audio_port_v7 *port) const
485 {
486     ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle);
487 
488     AudioOutputDescriptor::toAudioPort(port);
489 
490     toAudioPortConfig(&port->active_config);
491     port->ext.mix.handle = mIoHandle;
492     port->ext.mix.latency_class =
493             mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL;
494 }
495 
setSwMute(bool muted,VolumeSource vs,const StreamTypeVector & streamTypes,const DeviceTypeSet & deviceTypes,uint32_t delayMs)496 void SwAudioOutputDescriptor::setSwMute(
497         bool muted, VolumeSource vs, const StreamTypeVector &streamTypes,
498         const DeviceTypeSet& deviceTypes, uint32_t delayMs) {
499     // volume source active and more than one volume source is active, otherwise, no-op or let
500     // setVolume controlling SW and/or HW Gains
501     if (!streamTypes.empty() && isActive(vs) && (getActiveVolumeSources().size() > 1)) {
502         for (const auto& devicePort : devices()) {
503             if (isSingleDeviceType(deviceTypes, devicePort->type()) &&
504                     devicePort->hasGainController(true /*canUseForVolume*/)) {
505                 float volumeAmpl = muted ? 0.0f : Volume::DbToAmpl(0);
506                 ALOGV("%s: output: %d, vs: %d, muted: %d, active vs count: %zu", __func__,
507                       mIoHandle, vs, muted, getActiveVolumeSources().size());
508                 for (const auto &stream : streamTypes) {
509                     mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
510                 }
511                 return;
512             }
513         }
514     }
515 }
516 
setVolume(float volumeDb,bool muted,VolumeSource vs,const StreamTypeVector & streamTypes,const DeviceTypeSet & deviceTypes,uint32_t delayMs,bool force,bool isVoiceVolSrc)517 bool SwAudioOutputDescriptor::setVolume(float volumeDb, bool muted,
518                                         VolumeSource vs, const StreamTypeVector &streamTypes,
519                                         const DeviceTypeSet& deviceTypes,
520                                         uint32_t delayMs,
521                                         bool force,
522                                         bool isVoiceVolSrc)
523 {
524     StreamTypeVector streams = streamTypes;
525     if (!AudioOutputDescriptor::setVolume(
526             volumeDb, muted, vs, streamTypes, deviceTypes, delayMs, force, isVoiceVolSrc)) {
527         return false;
528     }
529     if (streams.empty()) {
530         streams.push_back(AUDIO_STREAM_MUSIC);
531     }
532     for (const auto& devicePort : devices()) {
533         // APM loops on all group, so filter on active group to set the port gain,
534         // let the other groups set the stream volume as per legacy
535         // TODO: Pass in the device address and check against it.
536         if (isSingleDeviceType(deviceTypes, devicePort->type()) &&
537                 devicePort->hasGainController(true) && isActive(vs)) {
538             ALOGV("%s: device %s has gain controller", __func__, devicePort->toString().c_str());
539             // @todo: here we might be in trouble if the SwOutput has several active clients with
540             // different Volume Source (or if we allow several curves within same volume group)
541             //
542             // @todo: default stream volume to max (0) when using HW Port gain?
543             // Allows to set SW Gain on AudioFlinger if:
544             //    -volume group has explicit stream(s) associated
545             //    -volume group with no explicit stream(s) is the only active source on this output
546             // Allows to mute SW Gain on AudioFlinger only for volume group with explicit stream(s)
547             if (!streamTypes.empty() || (getActiveVolumeSources().size() == 1)) {
548                 const bool canMute = muted && (volumeDb != 0.0f) && !streamTypes.empty();
549                 float volumeAmpl = canMute ? 0.0f : Volume::DbToAmpl(0);
550                 for (const auto &stream : streams) {
551                     mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
552                 }
553             }
554             AudioGains gains = devicePort->getGains();
555             int gainMinValueInMb = gains[0]->getMinValueInMb();
556             int gainMaxValueInMb = gains[0]->getMaxValueInMb();
557             int gainStepValueInMb = gains[0]->getStepValueInMb();
558             int gainValueMb = ((volumeDb * 100)/ gainStepValueInMb) * gainStepValueInMb;
559             gainValueMb = std::max(gainMinValueInMb, std::min(gainValueMb, gainMaxValueInMb));
560 
561             audio_port_config config = {};
562             devicePort->toAudioPortConfig(&config);
563             config.config_mask = AUDIO_PORT_CONFIG_GAIN;
564             config.gain.mode = gains[0]->getMode();
565             config.gain.values[0] = gainValueMb;
566             return mClientInterface->setAudioPortConfig(&config, 0) == NO_ERROR;
567         }
568     }
569     // Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is enabled
570     float volumeAmpl = Volume::DbToAmpl(getCurVolume(vs));
571     if (hasStream(streams, AUDIO_STREAM_BLUETOOTH_SCO)) {
572         mClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volumeAmpl, mIoHandle, delayMs);
573         VolumeSource callVolSrc = getVoiceSource();
574         if (callVolSrc != VOLUME_SOURCE_NONE) {
575             setCurVolume(callVolSrc, getCurVolume(vs), true);
576         }
577     }
578     for (const auto &stream : streams) {
579         ALOGV("%s output %d for volumeSource %d, volume %f, delay %d stream=%s", __func__,
580               mIoHandle, vs, volumeDb, delayMs, toString(stream).c_str());
581         mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
582     }
583     return true;
584 }
585 
open(const audio_config_t * halConfig,const audio_config_base_t * mixerConfig,const DeviceVector & devices,audio_stream_type_t stream,audio_output_flags_t flags,audio_io_handle_t * output)586 status_t SwAudioOutputDescriptor::open(const audio_config_t *halConfig,
587                                        const audio_config_base_t *mixerConfig,
588                                        const DeviceVector &devices,
589                                        audio_stream_type_t stream,
590                                        audio_output_flags_t flags,
591                                        audio_io_handle_t *output)
592 {
593     mDevices = devices;
594     sp<DeviceDescriptor> device = devices.getDeviceForOpening();
595     LOG_ALWAYS_FATAL_IF(device == nullptr,
596                         "%s failed to get device descriptor for opening "
597                         "with the requested devices, all device types: %s",
598                         __func__, dumpDeviceTypes(devices.types()).c_str());
599 
600     if (mProfile == nullptr) {
601         ALOGE("%s : Cannot open descriptor without a profile ", __func__);
602         return INVALID_OPERATION;
603     }
604 
605     audio_config_t lHalConfig;
606     if (halConfig == nullptr) {
607         lHalConfig = AUDIO_CONFIG_INITIALIZER;
608         lHalConfig.sample_rate = mSamplingRate;
609         lHalConfig.channel_mask = mChannelMask;
610         lHalConfig.format = mFormat;
611     } else {
612         lHalConfig = *halConfig;
613     }
614 
615     // if the selected profile is offloaded and no offload info was specified,
616     // create a default one
617     if ((mProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
618             lHalConfig.offload_info.format == AUDIO_FORMAT_DEFAULT) {
619         flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD);
620         lHalConfig.offload_info = AUDIO_INFO_INITIALIZER;
621         lHalConfig.offload_info.sample_rate = lHalConfig.sample_rate;
622         lHalConfig.offload_info.channel_mask = lHalConfig.channel_mask;
623         lHalConfig.offload_info.format = lHalConfig.format;
624         lHalConfig.offload_info.stream_type = stream;
625     }
626 
627     audio_config_base_t lMixerConfig;
628     if (mixerConfig == nullptr) {
629         lMixerConfig = AUDIO_CONFIG_BASE_INITIALIZER;
630         lMixerConfig.sample_rate = lHalConfig.sample_rate;
631         lMixerConfig.channel_mask = lHalConfig.channel_mask;
632         lMixerConfig.format = lHalConfig.format;
633     } else {
634         lMixerConfig = *mixerConfig;
635     }
636 
637     mFlags = (audio_output_flags_t)(mFlags | flags);
638 
639     // If no mixer config is specified for a spatializer output, default to 5.1 for proper
640     // configuration of the final downmixer or spatializer
641     if ((mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0
642             && mixerConfig == nullptr) {
643         lMixerConfig.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
644     }
645 
646     ALOGV("opening output for device %s profile %p name %s",
647           mDevices.toString().c_str(), mProfile.get(), mProfile->getName().c_str());
648 
649     status_t status = mClientInterface->openOutput(mProfile->getModuleHandle(),
650                                                    output,
651                                                    &lHalConfig,
652                                                    &lMixerConfig,
653                                                    device,
654                                                    &mLatency,
655                                                    mFlags);
656 
657     if (status == NO_ERROR) {
658         LOG_ALWAYS_FATAL_IF(*output == AUDIO_IO_HANDLE_NONE,
659                             "%s openOutput returned output handle %d for device %s, "
660                             "selected device %s for opening",
661                             __FUNCTION__, *output, devices.toString().c_str(),
662                             device->toString().c_str());
663         mSamplingRate = lHalConfig.sample_rate;
664         mChannelMask = lHalConfig.channel_mask;
665         mFormat = lHalConfig.format;
666         mMixerChannelMask = lMixerConfig.channel_mask;
667         mId = PolicyAudioPort::getNextUniqueId();
668         mIoHandle = *output;
669         mProfile->curOpenCount++;
670     }
671 
672     return status;
673 }
674 
start()675 status_t SwAudioOutputDescriptor::start()
676 {
677     if (isDuplicated()) {
678         status_t status = mOutput1->start();
679         if (status != NO_ERROR) {
680             return status;
681         }
682         status = mOutput2->start();
683         if (status != NO_ERROR) {
684             mOutput1->stop();
685             return status;
686         }
687         return NO_ERROR;
688     }
689     if (mProfile != nullptr && !isActive()) {
690         if (!mProfile->canStartNewIo()) {
691             return INVALID_OPERATION;
692         }
693         mProfile->curActiveCount++;
694     }
695     return NO_ERROR;
696 }
697 
stop()698 void SwAudioOutputDescriptor::stop()
699 {
700     if (isDuplicated()) {
701         mOutput1->stop();
702         mOutput2->stop();
703         return;
704     }
705 
706     if (mProfile != nullptr && !isActive()) {
707         LOG_ALWAYS_FATAL_IF(mProfile->curActiveCount < 1,
708                             "%s invalid profile active count %u",
709                             __func__, mProfile->curActiveCount);
710         mProfile->curActiveCount--;
711     }
712 }
713 
close()714 void SwAudioOutputDescriptor::close()
715 {
716     if (mIoHandle != AUDIO_IO_HANDLE_NONE) {
717         // clean up active clients if any (can happen if close() is called to force
718         // clients to reconnect
719         for (const auto &client : getClientIterable()) {
720             if (client->active()) {
721                 ALOGW("%s client with port ID %d still active on output %d",
722                       __func__, client->portId(), mId);
723                 setClientActive(client, false);
724                 stop();
725             }
726         }
727 
728         mClientInterface->closeOutput(mIoHandle);
729         if (mProfile != nullptr) {
730             LOG_ALWAYS_FATAL_IF(mProfile->curOpenCount < 1, "%s profile open count %u",
731                                 __FUNCTION__, mProfile->curOpenCount);
732             mProfile->curOpenCount--;
733         }
734         mIoHandle = AUDIO_IO_HANDLE_NONE;
735     }
736 }
737 
openDuplicating(const sp<SwAudioOutputDescriptor> & output1,const sp<SwAudioOutputDescriptor> & output2,audio_io_handle_t * ioHandle)738 status_t SwAudioOutputDescriptor::openDuplicating(const sp<SwAudioOutputDescriptor>& output1,
739                                                   const sp<SwAudioOutputDescriptor>& output2,
740                                                   audio_io_handle_t *ioHandle)
741 {
742     // open a duplicating output thread for the new output and the primary output
743     // Note: openDuplicateOutput() API expects the output handles in the reverse order from the
744     // numbering in SwAudioOutputDescriptor mOutput1 and mOutput2
745     *ioHandle = mClientInterface->openDuplicateOutput(output2->mIoHandle, output1->mIoHandle);
746     if (*ioHandle == AUDIO_IO_HANDLE_NONE) {
747         return INVALID_OPERATION;
748     }
749 
750     mId = PolicyAudioPort::getNextUniqueId();
751     mIoHandle = *ioHandle;
752     mOutput1 = output1;
753     mOutput2 = output2;
754     mSamplingRate = output2->mSamplingRate;
755     mFormat = output2->mFormat;
756     mChannelMask = output2->mChannelMask;
757     mLatency = output2->mLatency;
758 
759     return NO_ERROR;
760 }
761 
getRecommendedMuteDurationMs() const762 uint32_t SwAudioOutputDescriptor::getRecommendedMuteDurationMs() const
763 {
764     if (isDuplicated()) {
765         return std::max(mOutput1->getRecommendedMuteDurationMs(),
766                 mOutput2->getRecommendedMuteDurationMs());
767     }
768     if (mProfile != nullptr) {
769         return mProfile->recommendedMuteDurationMs;
770     }
771     return 0;
772 }
773 
setTracksInvalidatedStatusByStrategy(product_strategy_t strategy)774 void SwAudioOutputDescriptor::setTracksInvalidatedStatusByStrategy(product_strategy_t strategy) {
775     for (const auto &client : getClientIterable()) {
776         if (strategy == client->strategy()) {
777             client->setIsInvalid();
778         }
779     }
780 }
781 
setDevices(const android::DeviceVector & devices)782 void SwAudioOutputDescriptor::setDevices(const android::DeviceVector &devices) {
783     if ((mFlags & AUDIO_OUTPUT_FLAG_BIT_PERFECT) == AUDIO_OUTPUT_FLAG_BIT_PERFECT) {
784         for (auto device : mDevices) {
785             device->setPreferredConfig(nullptr);
786         }
787         auto config = getConfig();
788         for (auto device : devices) {
789             device->setPreferredConfig(&config);
790         }
791     }
792     mDevices = devices;
793 }
794 
isUsageActiveOnDevice(audio_usage_t usage,sp<android::DeviceDescriptor> device) const795 bool SwAudioOutputDescriptor::isUsageActiveOnDevice(audio_usage_t usage,
796                                                     sp<android::DeviceDescriptor> device) const {
797     if (device != nullptr && !mDevices.contains(device)) {
798         return false;
799     }
800     return std::any_of(mActiveClients.begin(), mActiveClients.end(),
801                        [usage](sp<TrackClientDescriptor> client) {
802                            return client->attributes().usage == usage; });
803 }
804 
805 // HwAudioOutputDescriptor implementation
HwAudioOutputDescriptor(const sp<SourceClientDescriptor> & source,AudioPolicyClientInterface * clientInterface)806 HwAudioOutputDescriptor::HwAudioOutputDescriptor(const sp<SourceClientDescriptor>& source,
807                                                  AudioPolicyClientInterface *clientInterface)
808     : AudioOutputDescriptor(source->srcDevice(), clientInterface),
809       mSource(source)
810 {
811 }
812 
dump(String8 * dst,int spaces,const char * extraInfo) const813 void HwAudioOutputDescriptor::dump(String8 *dst, int spaces, const char* extraInfo) const
814 {
815     AudioOutputDescriptor::dump(dst, spaces, extraInfo);
816     dst->appendFormat("%*sSource:\n", spaces, "");
817     mSource->dump(dst, spaces);
818 }
819 
toAudioPortConfig(struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig) const820 void HwAudioOutputDescriptor::toAudioPortConfig(
821                                                  struct audio_port_config *dstConfig,
822                                                  const struct audio_port_config *srcConfig) const
823 {
824     mSource->srcDevice()->toAudioPortConfig(dstConfig, srcConfig);
825 }
826 
toAudioPort(struct audio_port_v7 * port) const827 void HwAudioOutputDescriptor::toAudioPort(struct audio_port_v7 *port) const
828 {
829     mSource->srcDevice()->toAudioPort(port);
830 }
831 
832 
setVolume(float volumeDb,bool muted,VolumeSource volumeSource,const StreamTypeVector & streams,const DeviceTypeSet & deviceTypes,uint32_t delayMs,bool force,bool isVoiceVolSrc)833 bool HwAudioOutputDescriptor::setVolume(float volumeDb, bool muted,
834                                         VolumeSource volumeSource, const StreamTypeVector &streams,
835                                         const DeviceTypeSet& deviceTypes,
836                                         uint32_t delayMs,
837                                         bool force,
838                                         bool isVoiceVolSrc)
839 {
840     bool changed = AudioOutputDescriptor::setVolume(
841             volumeDb, muted, volumeSource, streams, deviceTypes, delayMs, force, isVoiceVolSrc);
842 
843     if (changed) {
844       // TODO: use gain controller on source device if any to adjust volume
845     }
846     return changed;
847 }
848 
849 // SwAudioOutputCollection implementation
isActive(VolumeSource volumeSource,uint32_t inPastMs) const850 bool SwAudioOutputCollection::isActive(VolumeSource volumeSource, uint32_t inPastMs) const
851 {
852     nsecs_t sysTime = systemTime();
853     for (size_t i = 0; i < this->size(); i++) {
854         const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
855         if (outputDesc->isActive(volumeSource, inPastMs, sysTime)) {
856             return true;
857         }
858     }
859     return false;
860 }
861 
isActiveLocally(VolumeSource volumeSource,uint32_t inPastMs) const862 bool SwAudioOutputCollection::isActiveLocally(VolumeSource volumeSource, uint32_t inPastMs) const
863 {
864     nsecs_t sysTime = systemTime();
865     for (size_t i = 0; i < this->size(); i++) {
866         const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
867         if (outputDesc->isActive(volumeSource, inPastMs, sysTime)
868                 && (!(outputDesc->devices()
869                         .containsDeviceAmongTypes(getAllOutRemoteDevices())
870                         || outputDesc->devices()
871                             .onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX)))) {
872             return true;
873         }
874     }
875     return false;
876 }
877 
isActiveRemotely(VolumeSource volumeSource,uint32_t inPastMs) const878 bool SwAudioOutputCollection::isActiveRemotely(VolumeSource volumeSource, uint32_t inPastMs) const
879 {
880     nsecs_t sysTime = systemTime();
881     for (size_t i = 0; i < size(); i++) {
882         const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
883         if (outputDesc->devices().containsDeviceAmongTypes(getAllOutRemoteDevices()) &&
884                 outputDesc->isActive(volumeSource, inPastMs, sysTime)) {
885             // do not consider re routing (when the output is going to a dynamic policy)
886             // as "remote playback"
887             if (outputDesc->mPolicyMix == NULL) {
888                 return true;
889             }
890         }
891     }
892     return false;
893 }
894 
isStrategyActiveOnSameModule(product_strategy_t ps,const sp<SwAudioOutputDescriptor> & desc,uint32_t inPastMs,nsecs_t sysTime) const895 bool SwAudioOutputCollection::isStrategyActiveOnSameModule(product_strategy_t ps,
896                                                            const sp<SwAudioOutputDescriptor>& desc,
897                                                            uint32_t inPastMs, nsecs_t sysTime) const
898 {
899     for (size_t i = 0; i < size(); i++) {
900         const sp<SwAudioOutputDescriptor> otherDesc = valueAt(i);
901         if (desc->sharesHwModuleWith(otherDesc) &&
902                 otherDesc->isStrategyActive(ps, inPastMs, sysTime)) {
903             if (desc == otherDesc
904                     || !otherDesc->devices()
905                             .onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
906                 return true;
907             }
908         }
909     }
910     return false;
911 }
912 
isStrategyActive(product_strategy_t ps) const913 bool SwAudioOutputCollection::isStrategyActive(product_strategy_t ps) const
914 {
915     for (size_t i = 0; i < size(); i++) {
916         if (valueAt(i)->isStrategyActive(ps)) {
917             return true;
918         }
919     }
920     return false;
921 }
922 
getA2dpOutput() const923 audio_io_handle_t SwAudioOutputCollection::getA2dpOutput() const
924 {
925     for (size_t i = 0; i < size(); i++) {
926         sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
927         if (!outputDesc->isDuplicated() &&
928              outputDesc->devices().containsDeviceAmongTypes(getAudioDeviceOutAllA2dpSet()) &&
929              outputDesc->devicesSupportEncodedFormats(getAudioDeviceOutAllA2dpSet())) {
930             return this->keyAt(i);
931         }
932     }
933     return 0;
934 }
935 
isA2dpOffloadedOnPrimary() const936 bool SwAudioOutputCollection::isA2dpOffloadedOnPrimary() const
937 {
938     sp<SwAudioOutputDescriptor> primaryOutput = getPrimaryOutput();
939 
940     if ((primaryOutput != NULL) && (primaryOutput->mProfile != NULL)
941         && (primaryOutput->mProfile->getModule() != NULL)) {
942         sp<HwModule> primaryHwModule = primaryOutput->mProfile->getModule();
943 
944         for (const auto &outputProfile : primaryHwModule->getOutputProfiles()) {
945             if (outputProfile->supportsDeviceTypes(getAudioDeviceOutAllA2dpSet())) {
946                 return true;
947             }
948         }
949     }
950     return false;
951 }
952 
getPrimaryOutput() const953 sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getPrimaryOutput() const
954 {
955     for (size_t i = 0; i < size(); i++) {
956         const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
957         if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
958             return outputDesc;
959         }
960     }
961     return NULL;
962 }
963 
getOutputFromId(audio_port_handle_t id) const964 sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getOutputFromId(audio_port_handle_t id) const
965 {
966     for (size_t i = 0; i < size(); i++) {
967         const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
968         if (outputDesc->getId() == id) {
969             return outputDesc;
970         }
971     }
972     return NULL;
973 }
974 
getOutputForClient(audio_port_handle_t portId)975 sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getOutputForClient(audio_port_handle_t portId)
976 {
977     for (size_t i = 0; i < size(); i++) {
978         sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
979         if (outputDesc->getClient(portId) != nullptr) {
980             return outputDesc;
981         }
982     }
983     return 0;
984 }
985 
clearSessionRoutesForDevice(const sp<DeviceDescriptor> & disconnectedDevice)986 void SwAudioOutputCollection::clearSessionRoutesForDevice(
987         const sp<DeviceDescriptor> &disconnectedDevice)
988 {
989     for (size_t i = 0; i < size(); i++) {
990         sp<AudioOutputDescriptor> outputDesc = valueAt(i);
991         for (const auto& client : outputDesc->getClientIterable()) {
992             if (client->preferredDeviceId() == disconnectedDevice->getId()) {
993                 client->setPreferredDeviceId(AUDIO_PORT_HANDLE_NONE);
994             }
995         }
996     }
997 }
isAnyDeviceTypeActive(const DeviceTypeSet & deviceTypes) const998 bool SwAudioOutputCollection::isAnyDeviceTypeActive(const DeviceTypeSet& deviceTypes) const {
999     for (size_t i = 0; i < size(); i++) {
1000         const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
1001         if (outputDesc->isActive()
1002                 && outputDesc->devices().containsDeviceAmongTypes(deviceTypes)) {
1003             return true;
1004         }
1005     }
1006     return false;
1007 }
1008 
isConfigurationMatched(const audio_config_base_t & config,audio_output_flags_t flags)1009 bool SwAudioOutputDescriptor::isConfigurationMatched(const audio_config_base_t &config,
1010                                                      audio_output_flags_t flags) {
1011     const uint32_t mustMatchOutputFlags =
1012             AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
1013     return audio_output_flags_is_subset(AudioOutputDescriptor::mFlags, flags, mustMatchOutputFlags)
1014             && mSamplingRate == config.sample_rate
1015             && mChannelMask == config.channel_mask
1016             && mFormat == config.format;
1017 }
1018 
getClientsForStream(audio_stream_type_t streamType) const1019 PortHandleVector SwAudioOutputDescriptor::getClientsForStream(
1020         audio_stream_type_t streamType) const {
1021     PortHandleVector clientsForStream;
1022     for (const auto& client : getClientIterable()) {
1023         if (client->stream() == streamType) {
1024             clientsForStream.push_back(client->portId());
1025         }
1026     }
1027     return clientsForStream;
1028 }
1029 
isUsageActiveOnDevice(audio_usage_t usage,sp<android::DeviceDescriptor> device) const1030 bool SwAudioOutputCollection::isUsageActiveOnDevice(audio_usage_t usage,
1031                                                     sp<android::DeviceDescriptor> device) const {
1032     for (size_t i = 0; i < this->size(); i++) {
1033         const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
1034         if (outputDesc->isUsageActiveOnDevice(usage, device)) {
1035             return true;
1036         }
1037     }
1038     return false;
1039 }
1040 
info() const1041 std::string SwAudioOutputDescriptor::info() const {
1042     std::string result;
1043     result.append("[" );
1044     result.append(AudioOutputDescriptor::info());
1045     result.append("[io:" );
1046     result.append(android::internal::ToString(mIoHandle));
1047     result.append(", " );
1048     result.append(isDuplicated() ? "duplicating" : mProfile->getTagName());
1049     result.append("]]");
1050     return result;
1051 }
1052 
dump(String8 * dst) const1053 void SwAudioOutputCollection::dump(String8 *dst) const
1054 {
1055     dst->appendFormat("\n Outputs (%zu):\n", size());
1056     for (size_t i = 0; i < size(); i++) {
1057         const std::string prefix = base::StringPrintf("  %zu. ", i + 1);
1058         const std::string extraInfo = base::StringPrintf("I/O handle: %d", keyAt(i));
1059         dst->appendFormat("%s", prefix.c_str());
1060         valueAt(i)->dump(dst, prefix.size(), extraInfo.c_str());
1061     }
1062 }
1063 
1064 // HwAudioOutputCollection implementation
isActive(VolumeSource volumeSource,uint32_t inPastMs) const1065 bool HwAudioOutputCollection::isActive(VolumeSource volumeSource, uint32_t inPastMs) const
1066 {
1067     nsecs_t sysTime = systemTime();
1068     for (size_t i = 0; i < this->size(); i++) {
1069         const sp<HwAudioOutputDescriptor> outputDesc = this->valueAt(i);
1070         if (outputDesc->isActive(volumeSource, inPastMs, sysTime)) {
1071             return true;
1072         }
1073     }
1074     return false;
1075 }
1076 
dump(String8 * dst) const1077 void HwAudioOutputCollection::dump(String8 *dst) const
1078 {
1079     dst->appendFormat("\n Outputs (%zu):\n", size());
1080     for (size_t i = 0; i < size(); i++) {
1081         const std::string prefix = base::StringPrintf("  %zu. ", i + 1);
1082         const std::string extraInfo = base::StringPrintf("I/O handle: %d", keyAt(i));
1083         dst->appendFormat("%s", prefix.c_str());
1084         valueAt(i)->dump(dst, prefix.size(), extraInfo.c_str());
1085     }
1086 }
1087 
1088 }; //namespace android
1089