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
27 namespace android {
28
setOutput(sp<SwAudioOutputDescriptor> & output)29 void AudioPolicyMix::setOutput(sp<SwAudioOutputDescriptor> &output)
30 {
31 mOutput = output;
32 }
33
getOutput() const34 const sp<SwAudioOutputDescriptor> &AudioPolicyMix::getOutput() const
35 {
36 return mOutput;
37 }
38
clearOutput()39 void AudioPolicyMix::clearOutput()
40 {
41 mOutput.clear();
42 }
43
setMix(AudioMix & mix)44 void AudioPolicyMix::setMix(AudioMix &mix)
45 {
46 mMix = mix;
47 }
48
getMix()49 android::AudioMix *AudioPolicyMix::getMix()
50 {
51 return &mMix;
52 }
53
registerMix(String8 address,AudioMix mix)54 status_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
unregisterMix(String8 address)67 status_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
getAudioPolicyMix(String8 address,sp<AudioPolicyMix> & policyMix) const79 status_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
closeOutput(sp<SwAudioOutputDescriptor> & desc)91 void AudioPolicyMixCollection::closeOutput(sp<SwAudioOutputDescriptor> &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
getOutputForAttr(audio_attributes_t attributes,sp<SwAudioOutputDescriptor> & desc)101 status_t AudioPolicyMixCollection::getOutputForAttr(audio_attributes_t attributes,
102 sp<SwAudioOutputDescriptor> &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
getDeviceAndMixForInputSource(audio_source_t inputSource,audio_devices_t availDevices,AudioMix ** policyMix)142 audio_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
getInputMixForAttr(audio_attributes_t attr,AudioMix ** policyMix)170 status_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("getInputMixForAttr() 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("getInputMixForAttr() 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