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