From 56ec4ffcbae8aeac6c5245fc7b825d02e2e6cefd Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Fri, 23 Jan 2015 16:45:18 -0800 Subject: Refactor AudioPolicyManager AudioPolicyManager implementation is now split into the following files: files managerdefault/Gains.* class AudioGain class VolumeCurvePoint class StreamDescriptor files managerdefault/Devices.* class DeviceDescriptor class DeviceVector files managerdefault/Ports.* class AudioPort class AudioPortConfig class AudioPatch files managerdefault/IOProfile.* class IOProfile files managerdefault/HwModule.* class HwModule files managerdefault/AudioInputDescriptor.* class AudioInputDescriptor files managerdefault/AudioOutputDescriptor.* class AudioOutputDescriptor All files for libaudiopolicyservice are moved under service/ All files for libaudiopolicymanager are moved under manager/ Change-Id: I43758be1894e37d34db194b51a19ae24461e066e --- .../managerdefault/AudioOutputDescriptor.cpp | 221 +++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 services/audiopolicy/managerdefault/AudioOutputDescriptor.cpp (limited to 'services/audiopolicy/managerdefault/AudioOutputDescriptor.cpp') diff --git a/services/audiopolicy/managerdefault/AudioOutputDescriptor.cpp b/services/audiopolicy/managerdefault/AudioOutputDescriptor.cpp new file mode 100644 index 0000000..4b85972 --- /dev/null +++ b/services/audiopolicy/managerdefault/AudioOutputDescriptor.cpp @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "APM::AudioOutputDescriptor" +//#define LOG_NDEBUG 0 + +#include "AudioPolicyManager.h" + +namespace android { + +AudioOutputDescriptor::AudioOutputDescriptor( + const sp& profile) + : mId(0), mIoHandle(0), mLatency(0), + mFlags((audio_output_flags_t)0), mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL), + mPatchHandle(0), + mOutput1(0), mOutput2(0), mProfile(profile), mDirectOpenCount(0) +{ + // clear usage count for all stream types + for (int i = 0; i < AUDIO_STREAM_CNT; i++) { + mRefCount[i] = 0; + mCurVolume[i] = -1.0; + mMuteCount[i] = 0; + mStopTime[i] = 0; + } + for (int i = 0; i < NUM_STRATEGIES; i++) { + mStrategyMutedByDevice[i] = false; + } + if (profile != NULL) { + mFlags = (audio_output_flags_t)profile->mFlags; + mSamplingRate = profile->pickSamplingRate(); + mFormat = profile->pickFormat(); + mChannelMask = profile->pickChannelMask(); + if (profile->mGains.size() > 0) { + profile->mGains[0]->getDefaultConfig(&mGain); + } + } +} + +audio_devices_t AudioOutputDescriptor::device() const +{ + if (isDuplicated()) { + return (audio_devices_t)(mOutput1->mDevice | mOutput2->mDevice); + } else { + return mDevice; + } +} + +uint32_t AudioOutputDescriptor::latency() +{ + if (isDuplicated()) { + return (mOutput1->mLatency > mOutput2->mLatency) ? mOutput1->mLatency : mOutput2->mLatency; + } else { + return mLatency; + } +} + +bool AudioOutputDescriptor::sharesHwModuleWith( + const sp outputDesc) +{ + if (isDuplicated()) { + return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc); + } else if (outputDesc->isDuplicated()){ + return sharesHwModuleWith(outputDesc->mOutput1) || sharesHwModuleWith(outputDesc->mOutput2); + } else { + return (mProfile->mModule == outputDesc->mProfile->mModule); + } +} + +void AudioOutputDescriptor::changeRefCount(audio_stream_type_t stream, + int delta) +{ + // forward usage count change to attached outputs + if (isDuplicated()) { + mOutput1->changeRefCount(stream, delta); + mOutput2->changeRefCount(stream, delta); + } + if ((delta + (int)mRefCount[stream]) < 0) { + ALOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", + delta, stream, mRefCount[stream]); + mRefCount[stream] = 0; + return; + } + mRefCount[stream] += delta; + ALOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]); +} + +audio_devices_t AudioOutputDescriptor::supportedDevices() +{ + if (isDuplicated()) { + return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices()); + } else { + return mProfile->mSupportedDevices.types() ; + } +} + +bool AudioOutputDescriptor::isActive(uint32_t inPastMs) const +{ + return isStrategyActive(NUM_STRATEGIES, inPastMs); +} + +bool AudioOutputDescriptor::isStrategyActive(routing_strategy strategy, + uint32_t inPastMs, + nsecs_t sysTime) const +{ + if ((sysTime == 0) && (inPastMs != 0)) { + sysTime = systemTime(); + } + for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) { + if (i == AUDIO_STREAM_PATCH) { + continue; + } + if (((AudioPolicyManager::getStrategy((audio_stream_type_t)i) == strategy) || + (NUM_STRATEGIES == strategy)) && + isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) { + return true; + } + } + return false; +} + +bool AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream, + uint32_t inPastMs, + nsecs_t sysTime) const +{ + if (mRefCount[stream] != 0) { + return true; + } + if (inPastMs == 0) { + return false; + } + if (sysTime == 0) { + sysTime = systemTime(); + } + if (ns2ms(sysTime - mStopTime[stream]) < inPastMs) { + return true; + } + return false; +} + +void AudioOutputDescriptor::toAudioPortConfig( + struct audio_port_config *dstConfig, + const struct audio_port_config *srcConfig) const +{ + ALOG_ASSERT(!isDuplicated(), "toAudioPortConfig() called on duplicated output %d", mIoHandle); + + dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK| + AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN; + if (srcConfig != NULL) { + dstConfig->config_mask |= srcConfig->config_mask; + } + AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig); + + dstConfig->id = mId; + dstConfig->role = AUDIO_PORT_ROLE_SOURCE; + dstConfig->type = AUDIO_PORT_TYPE_MIX; + dstConfig->ext.mix.hw_module = mProfile->mModule->mHandle; + dstConfig->ext.mix.handle = mIoHandle; + dstConfig->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT; +} + +void AudioOutputDescriptor::toAudioPort( + struct audio_port *port) const +{ + ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle); + mProfile->toAudioPort(port); + port->id = mId; + toAudioPortConfig(&port->active_config); + port->ext.mix.hw_module = mProfile->mModule->mHandle; + port->ext.mix.handle = mIoHandle; + port->ext.mix.latency_class = + mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL; +} + +status_t AudioOutputDescriptor::dump(int fd) +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + + snprintf(buffer, SIZE, " ID: %d\n", mId); + result.append(buffer); + snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate); + result.append(buffer); + snprintf(buffer, SIZE, " Format: %08x\n", mFormat); + result.append(buffer); + snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask); + result.append(buffer); + snprintf(buffer, SIZE, " Latency: %d\n", mLatency); + result.append(buffer); + snprintf(buffer, SIZE, " Flags %08x\n", mFlags); + result.append(buffer); + snprintf(buffer, SIZE, " Devices %08x\n", device()); + result.append(buffer); + snprintf(buffer, SIZE, " Stream volume refCount muteCount\n"); + result.append(buffer); + for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) { + snprintf(buffer, SIZE, " %02d %.03f %02d %02d\n", + i, mCurVolume[i], mRefCount[i], mMuteCount[i]); + result.append(buffer); + } + write(fd, result.string(), result.size()); + + return NO_ERROR; +} + + + +}; //namespace android -- cgit v1.1