AudioPolicyMix.cpp revision 036e1e9126dcd496203434aa69e52115d8e730cc
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::AudioPolicyMix"
18//#define LOG_NDEBUG 0
19
20#include "AudioPolicyMix.h"
21#include "HwModule.h"
22#include "AudioPort.h"
23#include "IOProfile.h"
24#include "AudioGain.h"
25#include <AudioOutputDescriptor.h>
26
27namespace android {
28
29void AudioPolicyMix::setOutput(sp<AudioOutputDescriptor> &output)
30{
31    mOutput = output;
32}
33
34const sp<AudioOutputDescriptor> &AudioPolicyMix::getOutput() const
35{
36    return mOutput;
37}
38
39void AudioPolicyMix::clearOutput()
40{
41    mOutput.clear();
42}
43
44void AudioPolicyMix::setMix(AudioMix &mix)
45{
46    mMix = mix;
47}
48
49android::AudioMix &AudioPolicyMix::getMix()
50{
51    return mMix;
52}
53
54status_t AudioPolicyMixCollection::registerMix(String8 address, AudioMix mix)
55{
56    ssize_t index = indexOfKey(address);
57    if (index >= 0) {
58        ALOGE("registerPolicyMixes(): mix for address %s already registered", address.string());
59        return BAD_VALUE;
60    }
61    sp<AudioPolicyMix> policyMix = new AudioPolicyMix();
62    policyMix->setMix(mix);
63    add(address, policyMix);
64    return NO_ERROR;
65}
66
67status_t AudioPolicyMixCollection::unregisterMix(String8 address)
68{
69    ssize_t index = indexOfKey(address);
70    if (index < 0) {
71        ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string());
72        return BAD_VALUE;
73    }
74
75    removeItemsAt(index);
76    return NO_ERROR;
77}
78
79status_t AudioPolicyMixCollection::getAudioPolicyMix(String8 address,
80                                                     sp<AudioPolicyMix> &policyMix) const
81{
82    ssize_t index = indexOfKey(address);
83    if (index < 0) {
84        ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string());
85        return BAD_VALUE;
86    }
87    policyMix = valueAt(index);
88    return NO_ERROR;
89}
90
91void AudioPolicyMixCollection::closeOutput(sp<AudioOutputDescriptor> &desc)
92{
93    for (size_t i = 0; i < size(); i++) {
94        sp<AudioPolicyMix> policyMix = valueAt(i);
95        if (policyMix->getOutput() == desc) {
96            policyMix->clearOutput();
97        }
98    }
99}
100
101status_t AudioPolicyMixCollection::getOutputForAttr(audio_attributes_t attributes,
102                                                    sp<AudioOutputDescriptor> &desc)
103{
104    for (size_t i = 0; i < size(); i++) {
105        sp<AudioPolicyMix> policyMix = valueAt(i);
106        AudioMix mix = policyMix->getMix();
107
108        if (mix.mMixType == MIX_TYPE_PLAYERS) {
109            for (size_t j = 0; j < mix.mCriteria.size(); j++) {
110                if ((RULE_MATCH_ATTRIBUTE_USAGE == mix.mCriteria[j].mRule &&
111                     mix.mCriteria[j].mAttr.mUsage == attributes.usage) ||
112                        (RULE_EXCLUDE_ATTRIBUTE_USAGE == mix.mCriteria[j].mRule &&
113                         mix.mCriteria[j].mAttr.mUsage != attributes.usage)) {
114                    desc = policyMix->getOutput();
115                    break;
116                }
117                if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
118                        strncmp(attributes.tags + strlen("addr="),
119                                mix.mRegistrationId.string(),
120                                AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
121                    desc = policyMix->getOutput();
122                    break;
123                }
124            }
125        } else if (mix.mMixType == MIX_TYPE_RECORDERS) {
126            if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE &&
127                    strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
128                    strncmp(attributes.tags + strlen("addr="),
129                            mix.mRegistrationId.string(),
130                            AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
131                desc = policyMix->getOutput();
132            }
133        }
134        if (desc != 0) {
135            desc->mPolicyMix = &mix;
136            return NO_ERROR;
137        }
138    }
139    return BAD_VALUE;
140}
141
142audio_devices_t AudioPolicyMixCollection::getDeviceAndMixForInputSource(audio_source_t inputSource,
143                                                                        audio_devices_t availDevices,
144                                                                        AudioMix **policyMix)
145{
146    for (size_t i = 0; i < size(); i++) {
147        AudioMix mix = valueAt(i)->getMix();
148
149        if (mix.mMixType != MIX_TYPE_RECORDERS) {
150            continue;
151        }
152        for (size_t j = 0; j < mix.mCriteria.size(); j++) {
153            if ((RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET == mix.mCriteria[j].mRule &&
154                    mix.mCriteria[j].mAttr.mSource == inputSource) ||
155               (RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET == mix.mCriteria[j].mRule &&
156                    mix.mCriteria[j].mAttr.mSource != inputSource)) {
157                if (availDevices & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
158                    if (policyMix != NULL) {
159                        *policyMix = &mix;
160                    }
161                    return AUDIO_DEVICE_IN_REMOTE_SUBMIX;
162                }
163                break;
164            }
165        }
166    }
167    return AUDIO_DEVICE_NONE;
168}
169
170status_t AudioPolicyMixCollection::getInputMixForAttr(audio_attributes_t attr, AudioMix *&policyMix)
171{
172    if (strncmp(attr.tags, "addr=", strlen("addr=")) != 0) {
173        return BAD_VALUE;
174    }
175    String8 address(attr.tags + strlen("addr="));
176
177    ssize_t index = indexOfKey(address);
178    if (index < 0) {
179        ALOGW("getInputForAttr() no policy for address %s", address.string());
180        return BAD_VALUE;
181    }
182    sp<AudioPolicyMix> audioPolicyMix = valueAt(index);
183    AudioMix mix = audioPolicyMix->getMix();
184
185    if (mix.mMixType != MIX_TYPE_PLAYERS) {
186        ALOGW("getInputForAttr() bad policy mix type for address %s", address.string());
187        return BAD_VALUE;
188    }
189    policyMix = &mix;
190    return NO_ERROR;
191}
192
193}; //namespace android
194