Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "APM::AudioOutputDescriptor"
     18 //#define LOG_NDEBUG 0
     19 
     20 #include <AudioPolicyInterface.h>
     21 #include "AudioOutputDescriptor.h"
     22 #include "IOProfile.h"
     23 #include "AudioGain.h"
     24 #include "Volume.h"
     25 #include "HwModule.h"
     26 #include <media/AudioParameter.h>
     27 #include <media/AudioPolicy.h>
     28 
     29 // A device mask for all audio output devices that are considered "remote" when evaluating
     30 // active output devices in isStreamActiveRemotely()
     31 #define APM_AUDIO_OUT_DEVICE_REMOTE_ALL  AUDIO_DEVICE_OUT_REMOTE_SUBMIX
     32 
     33 namespace android {
     34 
     35 AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port,
     36                                              AudioPolicyClientInterface *clientInterface)
     37     : mPort(port), mDevice(AUDIO_DEVICE_NONE),
     38       mClientInterface(clientInterface), mPatchHandle(AUDIO_PATCH_HANDLE_NONE), mId(0)
     39 {
     40     // clear usage count for all stream types
     41     for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
     42         mRefCount[i] = 0;
     43         mCurVolume[i] = -1.0;
     44         mMuteCount[i] = 0;
     45         mStopTime[i] = 0;
     46     }
     47     for (int i = 0; i < NUM_STRATEGIES; i++) {
     48         mStrategyMutedByDevice[i] = false;
     49     }
     50     if (mPort.get() != nullptr) {
     51         mPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
     52         if (mPort->mGains.size() > 0) {
     53             mPort->mGains[0]->getDefaultConfig(&mGain);
     54         }
     55     }
     56 }
     57 
     58 audio_module_handle_t AudioOutputDescriptor::getModuleHandle() const
     59 {
     60     return mPort.get() != nullptr ? mPort->getModuleHandle() : AUDIO_MODULE_HANDLE_NONE;
     61 }
     62 
     63 audio_port_handle_t AudioOutputDescriptor::getId() const
     64 {
     65     return mId;
     66 }
     67 
     68 audio_devices_t AudioOutputDescriptor::device() const
     69 {
     70     return mDevice;
     71 }
     72 
     73 audio_devices_t AudioOutputDescriptor::supportedDevices()
     74 {
     75     return mDevice;
     76 }
     77 
     78 bool AudioOutputDescriptor::sharesHwModuleWith(
     79         const sp<AudioOutputDescriptor>& outputDesc)
     80 {
     81     if (outputDesc->isDuplicated()) {
     82         return sharesHwModuleWith(outputDesc->subOutput1()) ||
     83                     sharesHwModuleWith(outputDesc->subOutput2());
     84     } else {
     85         return hasSameHwModuleAs(outputDesc);
     86     }
     87 }
     88 
     89 void AudioOutputDescriptor::changeRefCount(audio_stream_type_t stream,
     90                                                                    int delta)
     91 {
     92     if ((delta + (int)mRefCount[stream]) < 0) {
     93         ALOGW("changeRefCount() invalid delta %d for stream %d, refCount %d",
     94               delta, stream, mRefCount[stream]);
     95         mRefCount[stream] = 0;
     96         return;
     97     }
     98     mRefCount[stream] += delta;
     99     ALOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]);
    100 }
    101 
    102 bool AudioOutputDescriptor::isActive(uint32_t inPastMs) const
    103 {
    104     nsecs_t sysTime = 0;
    105     if (inPastMs != 0) {
    106         sysTime = systemTime();
    107     }
    108     for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
    109         if (i == AUDIO_STREAM_PATCH) {
    110             continue;
    111         }
    112         if (isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) {
    113             return true;
    114         }
    115     }
    116     return false;
    117 }
    118 
    119 bool AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream,
    120                                            uint32_t inPastMs,
    121                                            nsecs_t sysTime) const
    122 {
    123     if (mRefCount[stream] != 0) {
    124         return true;
    125     }
    126     if (inPastMs == 0) {
    127         return false;
    128     }
    129     if (sysTime == 0) {
    130         sysTime = systemTime();
    131     }
    132     if (ns2ms(sysTime - mStopTime[stream]) < inPastMs) {
    133         return true;
    134     }
    135     return false;
    136 }
    137 
    138 
    139 bool AudioOutputDescriptor::isFixedVolume(audio_devices_t device __unused)
    140 {
    141     return false;
    142 }
    143 
    144 bool AudioOutputDescriptor::setVolume(float volume,
    145                                       audio_stream_type_t stream,
    146                                       audio_devices_t device __unused,
    147                                       uint32_t delayMs,
    148                                       bool force)
    149 {
    150     // We actually change the volume if:
    151     // - the float value returned by computeVolume() changed
    152     // - the force flag is set
    153     if (volume != mCurVolume[stream] || force) {
    154         ALOGV("setVolume() for stream %d, volume %f, delay %d", stream, volume, delayMs);
    155         mCurVolume[stream] = volume;
    156         return true;
    157     }
    158     return false;
    159 }
    160 
    161 void AudioOutputDescriptor::toAudioPortConfig(
    162                                                  struct audio_port_config *dstConfig,
    163                                                  const struct audio_port_config *srcConfig) const
    164 {
    165     dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK|
    166                             AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN;
    167     if (srcConfig != NULL) {
    168         dstConfig->config_mask |= srcConfig->config_mask;
    169     }
    170     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
    171 
    172     dstConfig->id = mId;
    173     dstConfig->role = AUDIO_PORT_ROLE_SOURCE;
    174     dstConfig->type = AUDIO_PORT_TYPE_MIX;
    175     dstConfig->ext.mix.hw_module = getModuleHandle();
    176     dstConfig->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT;
    177 }
    178 
    179 void AudioOutputDescriptor::toAudioPort(struct audio_port *port) const
    180 {
    181     // Should not be called for duplicated ports, see SwAudioOutputDescriptor::toAudioPortConfig.
    182     mPort->toAudioPort(port);
    183     port->id = mId;
    184     port->ext.mix.hw_module = getModuleHandle();
    185 }
    186 
    187 status_t AudioOutputDescriptor::dump(int fd)
    188 {
    189     const size_t SIZE = 256;
    190     char buffer[SIZE];
    191     String8 result;
    192 
    193     snprintf(buffer, SIZE, " ID: %d\n", mId);
    194     result.append(buffer);
    195     snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
    196     result.append(buffer);
    197     snprintf(buffer, SIZE, " Format: %08x\n", mFormat);
    198     result.append(buffer);
    199     snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask);
    200     result.append(buffer);
    201     snprintf(buffer, SIZE, " Devices %08x\n", device());
    202     result.append(buffer);
    203     snprintf(buffer, SIZE, " Stream volume refCount muteCount\n");
    204     result.append(buffer);
    205     for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
    206         snprintf(buffer, SIZE, " %02d     %.03f     %02d       %02d\n",
    207                  i, mCurVolume[i], mRefCount[i], mMuteCount[i]);
    208         result.append(buffer);
    209     }
    210     write(fd, result.string(), result.size());
    211 
    212     return NO_ERROR;
    213 }
    214 
    215 void AudioOutputDescriptor::log(const char* indent)
    216 {
    217     ALOGI("%sID: %d,0x%X, [rt:%d fmt:0x%X ch:0x%X]",
    218           indent, mId, mId, mSamplingRate, mFormat, mChannelMask);
    219 }
    220 
    221 // SwAudioOutputDescriptor implementation
    222 SwAudioOutputDescriptor::SwAudioOutputDescriptor(const sp<IOProfile>& profile,
    223                                                  AudioPolicyClientInterface *clientInterface)
    224     : AudioOutputDescriptor(profile, clientInterface),
    225     mProfile(profile), mIoHandle(AUDIO_IO_HANDLE_NONE), mLatency(0),
    226     mFlags((audio_output_flags_t)0), mPolicyMix(NULL),
    227     mOutput1(0), mOutput2(0), mDirectOpenCount(0),
    228     mDirectClientSession(AUDIO_SESSION_NONE), mGlobalRefCount(0)
    229 {
    230     if (profile != NULL) {
    231         mFlags = (audio_output_flags_t)profile->getFlags();
    232     }
    233 }
    234 
    235 status_t SwAudioOutputDescriptor::dump(int fd)
    236 {
    237     const size_t SIZE = 256;
    238     char buffer[SIZE];
    239     String8 result;
    240 
    241     snprintf(buffer, SIZE, " Latency: %d\n", mLatency);
    242     result.append(buffer);
    243     snprintf(buffer, SIZE, " Flags %08x\n", mFlags);
    244     result.append(buffer);
    245     write(fd, result.string(), result.size());
    246 
    247     AudioOutputDescriptor::dump(fd);
    248 
    249     return NO_ERROR;
    250 }
    251 
    252 audio_devices_t SwAudioOutputDescriptor::device() const
    253 {
    254     if (isDuplicated()) {
    255         return (audio_devices_t)(mOutput1->mDevice | mOutput2->mDevice);
    256     } else {
    257         return mDevice;
    258     }
    259 }
    260 
    261 bool SwAudioOutputDescriptor::sharesHwModuleWith(
    262         const sp<AudioOutputDescriptor>& outputDesc)
    263 {
    264     if (isDuplicated()) {
    265         return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc);
    266     } else if (outputDesc->isDuplicated()){
    267         return sharesHwModuleWith(outputDesc->subOutput1()) ||
    268                     sharesHwModuleWith(outputDesc->subOutput2());
    269     } else {
    270         return AudioOutputDescriptor::sharesHwModuleWith(outputDesc);
    271     }
    272 }
    273 
    274 audio_devices_t SwAudioOutputDescriptor::supportedDevices()
    275 {
    276     if (isDuplicated()) {
    277         return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices());
    278     } else {
    279         return mProfile->getSupportedDevicesType();
    280     }
    281 }
    282 
    283 uint32_t SwAudioOutputDescriptor::latency()
    284 {
    285     if (isDuplicated()) {
    286         return (mOutput1->mLatency > mOutput2->mLatency) ? mOutput1->mLatency : mOutput2->mLatency;
    287     } else {
    288         return mLatency;
    289     }
    290 }
    291 
    292 void SwAudioOutputDescriptor::changeRefCount(audio_stream_type_t stream,
    293                                                                    int delta)
    294 {
    295     // forward usage count change to attached outputs
    296     if (isDuplicated()) {
    297         mOutput1->changeRefCount(stream, delta);
    298         mOutput2->changeRefCount(stream, delta);
    299     }
    300     AudioOutputDescriptor::changeRefCount(stream, delta);
    301 
    302     // handle stream-independent ref count
    303     uint32_t oldGlobalRefCount = mGlobalRefCount;
    304     if ((delta + (int)mGlobalRefCount) < 0) {
    305         ALOGW("changeRefCount() invalid delta %d globalRefCount %d", delta, mGlobalRefCount);
    306         mGlobalRefCount = 0;
    307     } else {
    308         mGlobalRefCount += delta;
    309     }
    310     if ((oldGlobalRefCount == 0) && (mGlobalRefCount > 0)) {
    311         if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
    312         {
    313             mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
    314                     MIX_STATE_MIXING);
    315         }
    316 
    317     } else if ((oldGlobalRefCount > 0) && (mGlobalRefCount == 0)) {
    318         if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
    319         {
    320             mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
    321                     MIX_STATE_IDLE);
    322         }
    323     }
    324 }
    325 
    326 
    327 bool SwAudioOutputDescriptor::isFixedVolume(audio_devices_t device)
    328 {
    329     // unit gain if rerouting to external policy
    330     if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) {
    331         if (mPolicyMix != NULL) {
    332             ALOGV("max gain when rerouting for output=%d", mIoHandle);
    333             return true;
    334         }
    335     }
    336     if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
    337         ALOGV("max gain when output device is telephony tx");
    338         return true;
    339     }
    340     return false;
    341 }
    342 
    343 void SwAudioOutputDescriptor::toAudioPortConfig(
    344                                                  struct audio_port_config *dstConfig,
    345                                                  const struct audio_port_config *srcConfig) const
    346 {
    347 
    348     ALOG_ASSERT(!isDuplicated(), "toAudioPortConfig() called on duplicated output %d", mIoHandle);
    349     AudioOutputDescriptor::toAudioPortConfig(dstConfig, srcConfig);
    350 
    351     dstConfig->ext.mix.handle = mIoHandle;
    352 }
    353 
    354 void SwAudioOutputDescriptor::toAudioPort(
    355                                                     struct audio_port *port) const
    356 {
    357     ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle);
    358 
    359     AudioOutputDescriptor::toAudioPort(port);
    360 
    361     toAudioPortConfig(&port->active_config);
    362     port->ext.mix.handle = mIoHandle;
    363     port->ext.mix.latency_class =
    364             mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL;
    365 }
    366 
    367 bool SwAudioOutputDescriptor::setVolume(float volume,
    368                                         audio_stream_type_t stream,
    369                                         audio_devices_t device,
    370                                         uint32_t delayMs,
    371                                         bool force)
    372 {
    373     bool changed = AudioOutputDescriptor::setVolume(volume, stream, device, delayMs, force);
    374 
    375     if (changed) {
    376         // Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is
    377         // enabled
    378         float volume = Volume::DbToAmpl(mCurVolume[stream]);
    379         if (stream == AUDIO_STREAM_BLUETOOTH_SCO) {
    380             mClientInterface->setStreamVolume(
    381                     AUDIO_STREAM_VOICE_CALL, volume, mIoHandle, delayMs);
    382         }
    383         mClientInterface->setStreamVolume(stream, volume, mIoHandle, delayMs);
    384     }
    385     return changed;
    386 }
    387 
    388 status_t SwAudioOutputDescriptor::open(const audio_config_t *config,
    389                                        audio_devices_t device,
    390                                        const String8& address,
    391                                        audio_stream_type_t stream,
    392                                        audio_output_flags_t flags,
    393                                        audio_io_handle_t *output)
    394 {
    395     audio_config_t lConfig;
    396     if (config == nullptr) {
    397         lConfig = AUDIO_CONFIG_INITIALIZER;
    398         lConfig.sample_rate = mSamplingRate;
    399         lConfig.channel_mask = mChannelMask;
    400         lConfig.format = mFormat;
    401     } else {
    402         lConfig = *config;
    403     }
    404 
    405     mDevice = device;
    406     // if the selected profile is offloaded and no offload info was specified,
    407     // create a default one
    408     if ((mProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
    409             lConfig.offload_info.format == AUDIO_FORMAT_DEFAULT) {
    410         flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD);
    411         lConfig.offload_info = AUDIO_INFO_INITIALIZER;
    412         lConfig.offload_info.sample_rate = lConfig.sample_rate;
    413         lConfig.offload_info.channel_mask = lConfig.channel_mask;
    414         lConfig.offload_info.format = lConfig.format;
    415         lConfig.offload_info.stream_type = stream;
    416         lConfig.offload_info.duration_us = -1;
    417         lConfig.offload_info.has_video = true; // conservative
    418         lConfig.offload_info.is_streaming = true; // likely
    419     }
    420 
    421     mFlags = (audio_output_flags_t)(mFlags | flags);
    422 
    423     ALOGV("opening output for device %08x address %s profile %p name %s",
    424           mDevice, address.string(), mProfile.get(), mProfile->getName().string());
    425 
    426     status_t status = mClientInterface->openOutput(mProfile->getModuleHandle(),
    427                                                    output,
    428                                                    &lConfig,
    429                                                    &mDevice,
    430                                                    address,
    431                                                    &mLatency,
    432                                                    mFlags);
    433     LOG_ALWAYS_FATAL_IF(mDevice != device,
    434                         "%s openOutput returned device %08x when given device %08x",
    435                         __FUNCTION__, mDevice, device);
    436 
    437     if (status == NO_ERROR) {
    438         LOG_ALWAYS_FATAL_IF(*output == AUDIO_IO_HANDLE_NONE,
    439                             "%s openOutput returned output handle %d for device %08x",
    440                             __FUNCTION__, *output, device);
    441         mSamplingRate = lConfig.sample_rate;
    442         mChannelMask = lConfig.channel_mask;
    443         mFormat = lConfig.format;
    444         mId = AudioPort::getNextUniqueId();
    445         mIoHandle = *output;
    446         mProfile->curOpenCount++;
    447     }
    448 
    449     return status;
    450 }
    451 
    452 status_t SwAudioOutputDescriptor::start()
    453 {
    454     if (isDuplicated()) {
    455         status_t status = mOutput1->start();
    456         if (status != NO_ERROR) {
    457             return status;
    458         }
    459         status = mOutput2->start();
    460         if (status != NO_ERROR) {
    461             mOutput1->stop();
    462             return status;
    463         }
    464         return NO_ERROR;
    465     }
    466     if (!isActive()) {
    467         if (!mProfile->canStartNewIo()) {
    468             return INVALID_OPERATION;
    469         }
    470         mProfile->curActiveCount++;
    471     }
    472     return NO_ERROR;
    473 }
    474 
    475 void SwAudioOutputDescriptor::stop()
    476 {
    477     if (isDuplicated()) {
    478         mOutput1->stop();
    479         mOutput2->stop();
    480         return;
    481     }
    482 
    483     if (!isActive()) {
    484         LOG_ALWAYS_FATAL_IF(mProfile->curActiveCount < 1,
    485                             "%s invalid profile active count %u",
    486                             __func__, mProfile->curActiveCount);
    487         mProfile->curActiveCount--;
    488     }
    489 }
    490 
    491 void SwAudioOutputDescriptor::close()
    492 {
    493     if (mIoHandle != AUDIO_IO_HANDLE_NONE) {
    494         AudioParameter param;
    495         param.add(String8("closing"), String8("true"));
    496         mClientInterface->setParameters(mIoHandle, param.toString());
    497 
    498         mClientInterface->closeOutput(mIoHandle);
    499 
    500         LOG_ALWAYS_FATAL_IF(mProfile->curOpenCount < 1, "%s profile open count %u",
    501                             __FUNCTION__, mProfile->curOpenCount);
    502         // do not call stop() here as stop() is supposed to be called after changeRefCount(-1)
    503         // and we don't know how many streams are still active at this time
    504         if (isActive()) {
    505             mProfile->curActiveCount--;
    506         }
    507         mProfile->curOpenCount--;
    508         mIoHandle = AUDIO_IO_HANDLE_NONE;
    509     }
    510 }
    511 
    512 status_t SwAudioOutputDescriptor::openDuplicating(const sp<SwAudioOutputDescriptor>& output1,
    513                                                   const sp<SwAudioOutputDescriptor>& output2,
    514                                                   audio_io_handle_t *ioHandle)
    515 {
    516     // open a duplicating output thread for the new output and the primary output
    517     // Note: openDuplicateOutput() API expects the output handles in the reverse order from the
    518     // numbering in SwAudioOutputDescriptor mOutput1 and mOutput2
    519     *ioHandle = mClientInterface->openDuplicateOutput(output2->mIoHandle, output1->mIoHandle);
    520     if (*ioHandle == AUDIO_IO_HANDLE_NONE) {
    521         return INVALID_OPERATION;
    522     }
    523 
    524     mId = AudioPort::getNextUniqueId();
    525     mIoHandle = *ioHandle;
    526     mOutput1 = output1;
    527     mOutput2 = output2;
    528     mSamplingRate = output2->mSamplingRate;
    529     mFormat = output2->mFormat;
    530     mChannelMask = output2->mChannelMask;
    531     mLatency = output2->mLatency;
    532 
    533     return NO_ERROR;
    534 }
    535 
    536 // HwAudioOutputDescriptor implementation
    537 HwAudioOutputDescriptor::HwAudioOutputDescriptor(const sp<AudioSourceDescriptor>& source,
    538                                                  AudioPolicyClientInterface *clientInterface)
    539     : AudioOutputDescriptor(source->mDevice, clientInterface),
    540       mSource(source)
    541 {
    542 }
    543 
    544 status_t HwAudioOutputDescriptor::dump(int fd)
    545 {
    546     const size_t SIZE = 256;
    547     char buffer[SIZE];
    548     String8 result;
    549 
    550     AudioOutputDescriptor::dump(fd);
    551 
    552     snprintf(buffer, SIZE, "Source:\n");
    553     result.append(buffer);
    554     write(fd, result.string(), result.size());
    555     mSource->dump(fd);
    556 
    557     return NO_ERROR;
    558 }
    559 
    560 audio_devices_t HwAudioOutputDescriptor::supportedDevices()
    561 {
    562     return mDevice;
    563 }
    564 
    565 void HwAudioOutputDescriptor::toAudioPortConfig(
    566                                                  struct audio_port_config *dstConfig,
    567                                                  const struct audio_port_config *srcConfig) const
    568 {
    569     mSource->mDevice->toAudioPortConfig(dstConfig, srcConfig);
    570 }
    571 
    572 void HwAudioOutputDescriptor::toAudioPort(
    573                                                     struct audio_port *port) const
    574 {
    575     mSource->mDevice->toAudioPort(port);
    576 }
    577 
    578 
    579 bool HwAudioOutputDescriptor::setVolume(float volume,
    580                                         audio_stream_type_t stream,
    581                                         audio_devices_t device,
    582                                         uint32_t delayMs,
    583                                         bool force)
    584 {
    585     bool changed = AudioOutputDescriptor::setVolume(volume, stream, device, delayMs, force);
    586 
    587     if (changed) {
    588       // TODO: use gain controller on source device if any to adjust volume
    589     }
    590     return changed;
    591 }
    592 
    593 // SwAudioOutputCollection implementation
    594 bool SwAudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
    595 {
    596     nsecs_t sysTime = systemTime();
    597     for (size_t i = 0; i < this->size(); i++) {
    598         const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
    599         if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
    600             return true;
    601         }
    602     }
    603     return false;
    604 }
    605 
    606 bool SwAudioOutputCollection::isStreamActiveLocally(audio_stream_type_t stream, uint32_t inPastMs) const
    607 {
    608     nsecs_t sysTime = systemTime();
    609     for (size_t i = 0; i < this->size(); i++) {
    610         const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
    611         if (outputDesc->isStreamActive(stream, inPastMs, sysTime)
    612                 && ((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) == 0)) {
    613             return true;
    614         }
    615     }
    616     return false;
    617 }
    618 
    619 bool SwAudioOutputCollection::isStreamActiveRemotely(audio_stream_type_t stream,
    620                                                    uint32_t inPastMs) const
    621 {
    622     nsecs_t sysTime = systemTime();
    623     for (size_t i = 0; i < size(); i++) {
    624         const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
    625         if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
    626                 outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
    627             // do not consider re routing (when the output is going to a dynamic policy)
    628             // as "remote playback"
    629             if (outputDesc->mPolicyMix == NULL) {
    630                 return true;
    631             }
    632         }
    633     }
    634     return false;
    635 }
    636 
    637 audio_io_handle_t SwAudioOutputCollection::getA2dpOutput() const
    638 {
    639     for (size_t i = 0; i < size(); i++) {
    640         sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
    641         if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) {
    642             return this->keyAt(i);
    643         }
    644     }
    645     return 0;
    646 }
    647 
    648 bool SwAudioOutputCollection::isA2dpOffloadedOnPrimary() const
    649 {
    650     sp<SwAudioOutputDescriptor> primaryOutput = getPrimaryOutput();
    651 
    652     if ((primaryOutput != NULL) && (primaryOutput->mProfile != NULL)
    653         && (primaryOutput->mProfile->mModule != NULL)) {
    654         sp<HwModule> primaryHwModule = primaryOutput->mProfile->mModule;
    655         Vector <sp<IOProfile>> primaryHwModuleOutputProfiles =
    656                                    primaryHwModule->getOutputProfiles();
    657         for (size_t i = 0; i < primaryHwModuleOutputProfiles.size(); i++) {
    658             if (primaryHwModuleOutputProfiles[i]->supportDevice(AUDIO_DEVICE_OUT_ALL_A2DP)) {
    659                 return true;
    660             }
    661         }
    662     }
    663     return false;
    664 }
    665 
    666 bool SwAudioOutputCollection::isA2dpSupported() const
    667 {
    668     return (isA2dpOffloadedOnPrimary() || (getA2dpOutput() != 0));
    669 }
    670 
    671 sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getPrimaryOutput() const
    672 {
    673     for (size_t i = 0; i < size(); i++) {
    674         const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
    675         if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
    676             return outputDesc;
    677         }
    678     }
    679     return NULL;
    680 }
    681 
    682 sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getOutputFromId(audio_port_handle_t id) const
    683 {
    684     sp<SwAudioOutputDescriptor> outputDesc = NULL;
    685     for (size_t i = 0; i < size(); i++) {
    686         outputDesc = valueAt(i);
    687         if (outputDesc->getId() == id) {
    688             break;
    689         }
    690     }
    691     return outputDesc;
    692 }
    693 
    694 bool SwAudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const
    695 {
    696     for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) {
    697         if (s == (size_t) streamToIgnore) {
    698             continue;
    699         }
    700         for (size_t i = 0; i < size(); i++) {
    701             const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
    702             if (outputDesc->mRefCount[s] != 0) {
    703                 return true;
    704             }
    705         }
    706     }
    707     return false;
    708 }
    709 
    710 audio_devices_t SwAudioOutputCollection::getSupportedDevices(audio_io_handle_t handle) const
    711 {
    712     sp<SwAudioOutputDescriptor> outputDesc = valueFor(handle);
    713     audio_devices_t devices = outputDesc->mProfile->getSupportedDevicesType();
    714     return devices;
    715 }
    716 
    717 
    718 status_t SwAudioOutputCollection::dump(int fd) const
    719 {
    720     const size_t SIZE = 256;
    721     char buffer[SIZE];
    722 
    723     snprintf(buffer, SIZE, "\nOutputs dump:\n");
    724     write(fd, buffer, strlen(buffer));
    725     for (size_t i = 0; i < size(); i++) {
    726         snprintf(buffer, SIZE, "- Output %d dump:\n", keyAt(i));
    727         write(fd, buffer, strlen(buffer));
    728         valueAt(i)->dump(fd);
    729     }
    730 
    731     return NO_ERROR;
    732 }
    733 
    734 // HwAudioOutputCollection implementation
    735 bool HwAudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
    736 {
    737     nsecs_t sysTime = systemTime();
    738     for (size_t i = 0; i < this->size(); i++) {
    739         const sp<HwAudioOutputDescriptor> outputDesc = this->valueAt(i);
    740         if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
    741             return true;
    742         }
    743     }
    744     return false;
    745 }
    746 
    747 bool HwAudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const
    748 {
    749     for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) {
    750         if (s == (size_t) streamToIgnore) {
    751             continue;
    752         }
    753         for (size_t i = 0; i < size(); i++) {
    754             const sp<HwAudioOutputDescriptor> outputDesc = valueAt(i);
    755             if (outputDesc->mRefCount[s] != 0) {
    756                 return true;
    757             }
    758         }
    759     }
    760     return false;
    761 }
    762 
    763 status_t HwAudioOutputCollection::dump(int fd) const
    764 {
    765     const size_t SIZE = 256;
    766     char buffer[SIZE];
    767 
    768     snprintf(buffer, SIZE, "\nOutputs dump:\n");
    769     write(fd, buffer, strlen(buffer));
    770     for (size_t i = 0; i < size(); i++) {
    771         snprintf(buffer, SIZE, "- Output %d dump:\n", keyAt(i));
    772         write(fd, buffer, strlen(buffer));
    773         valueAt(i)->dump(fd);
    774     }
    775 
    776     return NO_ERROR;
    777 }
    778 
    779 }; //namespace android
    780