1036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie/*
2036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie * Copyright (C) 2015 The Android Open Source Project
3036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie *
4036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie * Licensed under the Apache License, Version 2.0 (the "License");
5036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie * you may not use this file except in compliance with the License.
6036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie * You may obtain a copy of the License at
7036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie *
8036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie *      http://www.apache.org/licenses/LICENSE-2.0
9036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie *
10036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie * Unless required by applicable law or agreed to in writing, software
11036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie * distributed under the License is distributed on an "AS IS" BASIS,
12036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie * See the License for the specific language governing permissions and
14036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie * limitations under the License.
15036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie */
16036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
175ac8cd425e1a0c4287c0bb84f922fef4fa106411Jean-Michel Trivi#define LOG_TAG "APM_AudioPolicyMix"
18036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie//#define LOG_NDEBUG 0
19036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
20036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie#include "AudioPolicyMix.h"
2144344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov#include "TypeConverter.h"
22036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie#include "HwModule.h"
23036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie#include "AudioPort.h"
24036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie#include "IOProfile.h"
25036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie#include "AudioGain.h"
26036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie#include <AudioOutputDescriptor.h>
27036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
28036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffienamespace android {
29036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
30c75307b73d324d590d0dbc05b44bce9aa89b7145Eric Laurentvoid AudioPolicyMix::setOutput(sp<SwAudioOutputDescriptor> &output)
31036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie{
32036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    mOutput = output;
33036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie}
34036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
35c75307b73d324d590d0dbc05b44bce9aa89b7145Eric Laurentconst sp<SwAudioOutputDescriptor> &AudioPolicyMix::getOutput() const
36036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie{
37036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    return mOutput;
38036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie}
39036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
40036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffievoid AudioPolicyMix::clearOutput()
41036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie{
42036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    mOutput.clear();
43036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie}
44036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
45036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffievoid AudioPolicyMix::setMix(AudioMix &mix)
46036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie{
47036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    mMix = mix;
48036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie}
49036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
50dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Triviandroid::AudioMix *AudioPolicyMix::getMix()
51036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie{
52dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Trivi    return &mMix;
53036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie}
54036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
5544344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganovstatus_t AudioPolicyMix::dump(int fd, int spaces, int index) const
5644344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov{
5744344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    const size_t SIZE = 256;
5844344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    char buffer[SIZE];
5944344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    String8 result;
6044344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov
6144344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    snprintf(buffer, SIZE, "%*sAudio Policy Mix %d:\n", spaces, "", index+1);
6244344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    result.append(buffer);
6344344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    std::string mixTypeLiteral;
6444344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    if (!MixTypeConverter::toString(mMix.mMixType, mixTypeLiteral)) {
6544344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        ALOGE("%s: failed to convert mix type %d", __FUNCTION__, mMix.mMixType);
6644344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        return BAD_VALUE;
6744344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    }
6844344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    snprintf(buffer, SIZE, "%*s- mix type: %s\n", spaces, "", mixTypeLiteral.c_str());
6944344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    result.append(buffer);
7044344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    std::string routeFlagLiteral;
7144344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    RouteFlagTypeConverter::maskToString(mMix.mRouteFlags, routeFlagLiteral);
7244344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    snprintf(buffer, SIZE, "%*s- Route Flags: %s\n", spaces, "", routeFlagLiteral.c_str());
7344344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    result.append(buffer);
7444344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    std::string deviceLiteral;
7544344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    deviceToString(mMix.mDeviceType, deviceLiteral);
7644344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    snprintf(buffer, SIZE, "%*s- device type: %s\n", spaces, "", deviceLiteral.c_str());
7744344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    result.append(buffer);
7844344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    snprintf(buffer, SIZE, "%*s- device address: %s\n", spaces, "", mMix.mDeviceAddress.string());
7944344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    result.append(buffer);
8044344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov
8144344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    int indexCriterion = 0;
8244344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    for (const auto &criterion : mMix.mCriteria) {
8344344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        snprintf(buffer, SIZE, "%*s- Criterion %d:\n", spaces + 2, "", indexCriterion++);
8444344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        result.append(buffer);
8544344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        std::string usageLiteral;
8644344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        if (!UsageTypeConverter::toString(criterion.mValue.mUsage, usageLiteral)) {
8744344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov            ALOGE("%s: failed to convert usage %d", __FUNCTION__, criterion.mValue.mUsage);
8844344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov            return BAD_VALUE;
8944344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        }
9044344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        snprintf(buffer, SIZE, "%*s- Usage:%s\n", spaces + 4, "", usageLiteral.c_str());
9144344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        result.append(buffer);
9244344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        if (mMix.mMixType == MIX_TYPE_RECORDERS) {
9344344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov            std::string sourceLiteral;
9444344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov            if (!SourceTypeConverter::toString(criterion.mValue.mSource, sourceLiteral)) {
9544344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov                ALOGE("%s: failed to convert source %d", __FUNCTION__, criterion.mValue.mSource);
9644344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov                return BAD_VALUE;
9744344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov            }
9844344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov            snprintf(buffer, SIZE, "%*s- Source:%s\n", spaces + 4, "", sourceLiteral.c_str());
9944344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov            result.append(buffer);
10044344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        }
10144344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        snprintf(buffer, SIZE, "%*s- Uid:%d\n", spaces + 4, "", criterion.mValue.mUid);
10244344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        result.append(buffer);
10344344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        std::string ruleLiteral;
10444344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        if (!RuleTypeConverter::toString(criterion.mRule, ruleLiteral)) {
10544344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov            ALOGE("%s: failed to convert source %d", __FUNCTION__,criterion.mRule);
10644344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov            return BAD_VALUE;
10744344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        }
10844344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        snprintf(buffer, SIZE, "%*s- Rule:%s\n", spaces + 4, "", ruleLiteral.c_str());
10944344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        result.append(buffer);
11044344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    }
11144344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    write(fd, result.string(), result.size());
11244344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    return NO_ERROR;
11344344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov}
11444344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov
115e964d4e421e2d1ca937227a580c0c837091a11e3Chih-Hung Hsiehstatus_t AudioPolicyMixCollection::registerMix(const String8& address, AudioMix mix,
1167638ca29e8400a19524adb982e9d22c02786de82Jean-Michel Trivi                                               sp<SwAudioOutputDescriptor> desc)
117036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie{
118036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    ssize_t index = indexOfKey(address);
119036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    if (index >= 0) {
120036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        ALOGE("registerPolicyMixes(): mix for address %s already registered", address.string());
121036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        return BAD_VALUE;
122036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    }
123036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    sp<AudioPolicyMix> policyMix = new AudioPolicyMix();
124036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    policyMix->setMix(mix);
125036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    add(address, policyMix);
1267638ca29e8400a19524adb982e9d22c02786de82Jean-Michel Trivi
1277638ca29e8400a19524adb982e9d22c02786de82Jean-Michel Trivi    if (desc != 0) {
1287638ca29e8400a19524adb982e9d22c02786de82Jean-Michel Trivi        desc->mPolicyMix = policyMix->getMix();
1297638ca29e8400a19524adb982e9d22c02786de82Jean-Michel Trivi        policyMix->setOutput(desc);
1307638ca29e8400a19524adb982e9d22c02786de82Jean-Michel Trivi    }
131036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    return NO_ERROR;
132036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie}
133036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
134e964d4e421e2d1ca937227a580c0c837091a11e3Chih-Hung Hsiehstatus_t AudioPolicyMixCollection::unregisterMix(const String8& address)
135036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie{
136036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    ssize_t index = indexOfKey(address);
137036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    if (index < 0) {
138036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string());
139036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        return BAD_VALUE;
140036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    }
141036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
142036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    removeItemsAt(index);
143036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    return NO_ERROR;
144036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie}
145036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
146e964d4e421e2d1ca937227a580c0c837091a11e3Chih-Hung Hsiehstatus_t AudioPolicyMixCollection::getAudioPolicyMix(const String8& address,
147036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                                                     sp<AudioPolicyMix> &policyMix) const
148036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie{
149036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    ssize_t index = indexOfKey(address);
150036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    if (index < 0) {
151036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string());
152036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        return BAD_VALUE;
153036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    }
154036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    policyMix = valueAt(index);
155036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    return NO_ERROR;
156036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie}
157036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
158c75307b73d324d590d0dbc05b44bce9aa89b7145Eric Laurentvoid AudioPolicyMixCollection::closeOutput(sp<SwAudioOutputDescriptor> &desc)
159036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie{
160036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    for (size_t i = 0; i < size(); i++) {
161036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        sp<AudioPolicyMix> policyMix = valueAt(i);
162036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        if (policyMix->getOutput() == desc) {
163036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie            policyMix->clearOutput();
164036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        }
165036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    }
166036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie}
167036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
168e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivistatus_t AudioPolicyMixCollection::getOutputForAttr(audio_attributes_t attributes, uid_t uid,
169c75307b73d324d590d0dbc05b44bce9aa89b7145Eric Laurent                                                    sp<SwAudioOutputDescriptor> &desc)
170036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie{
1715ac8cd425e1a0c4287c0bb84f922fef4fa106411Jean-Michel Trivi    ALOGV("getOutputForAttr() querying %zu mixes:", size());
172e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi    desc = 0;
173036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    for (size_t i = 0; i < size(); i++) {
174036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        sp<AudioPolicyMix> policyMix = valueAt(i);
175dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Trivi        AudioMix *mix = policyMix->getMix();
176dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Trivi
177dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Trivi        if (mix->mMixType == MIX_TYPE_PLAYERS) {
178e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi            // TODO if adding more player rules (currently only 2), make rule handling "generic"
179e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi            //      as there is no difference in the treatment of usage- or uid-based rules
180e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi            bool hasUsageMatchRules = false;
181e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi            bool hasUsageExcludeRules = false;
182e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi            bool usageMatchFound = false;
183e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi            bool usageExclusionFound = false;
184e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi
185e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi            bool hasUidMatchRules = false;
186e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi            bool hasUidExcludeRules = false;
187e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi            bool uidMatchFound = false;
188e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi            bool uidExclusionFound = false;
189e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi
190e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi            bool hasAddrMatch = false;
191e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi
192e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi            // iterate over all mix criteria to list what rules this mix contains
193dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Trivi            for (size_t j = 0; j < mix->mCriteria.size(); j++) {
1945ac8cd425e1a0c4287c0bb84f922fef4fa106411Jean-Michel Trivi                ALOGV(" getOutputForAttr: mix %zu: inspecting mix criteria %zu of %zu",
1955ac8cd425e1a0c4287c0bb84f922fef4fa106411Jean-Michel Trivi                        i, j, mix->mCriteria.size());
196e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi
197e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                // if there is an address match, prioritize that match
198036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
199036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                        strncmp(attributes.tags + strlen("addr="),
2007638ca29e8400a19524adb982e9d22c02786de82Jean-Michel Trivi                                mix->mDeviceAddress.string(),
201036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                                AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
202e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    hasAddrMatch = true;
203036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                    break;
204036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                }
205e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi
206e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                switch (mix->mCriteria[j].mRule) {
207e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                case RULE_MATCH_ATTRIBUTE_USAGE:
208e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    ALOGV("\tmix has RULE_MATCH_ATTRIBUTE_USAGE for usage %d",
209e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                                                mix->mCriteria[j].mValue.mUsage);
210e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    hasUsageMatchRules = true;
211e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    if (mix->mCriteria[j].mValue.mUsage == attributes.usage) {
212e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                        // found one match against all allowed usages
213e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                        usageMatchFound = true;
214e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    }
215e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    break;
216e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                case RULE_EXCLUDE_ATTRIBUTE_USAGE:
217e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    ALOGV("\tmix has RULE_EXCLUDE_ATTRIBUTE_USAGE for usage %d",
218e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                            mix->mCriteria[j].mValue.mUsage);
219e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    hasUsageExcludeRules = true;
220e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    if (mix->mCriteria[j].mValue.mUsage == attributes.usage) {
221e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                        // found this usage is to be excluded
222e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                        usageExclusionFound = true;
223e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    }
224e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    break;
225e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                case RULE_MATCH_UID:
226e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    ALOGV("\tmix has RULE_MATCH_UID for uid %d", mix->mCriteria[j].mValue.mUid);
227e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    hasUidMatchRules = true;
228e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    if (mix->mCriteria[j].mValue.mUid == uid) {
229e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                        // found one UID match against all allowed UIDs
230e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                        uidMatchFound = true;
231e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    }
232e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    break;
233e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                case RULE_EXCLUDE_UID:
234e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    ALOGV("\tmix has RULE_EXCLUDE_UID for uid %d", mix->mCriteria[j].mValue.mUid);
235e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    hasUidExcludeRules = true;
236e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    if (mix->mCriteria[j].mValue.mUid == uid) {
237e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                        // found this UID is to be excluded
238e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                        uidExclusionFound = true;
239e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    }
240e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    break;
241e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                default:
242e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    break;
243e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                }
244e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi
245e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                // consistency checks: for each "dimension" of rules (usage, uid...), we can
246e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                // only have MATCH rules, or EXCLUDE rules in each dimension, not a combination
247e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                if (hasUsageMatchRules && hasUsageExcludeRules) {
248e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    ALOGE("getOutputForAttr: invalid combination of RULE_MATCH_ATTRIBUTE_USAGE"
249e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                            " and RULE_EXCLUDE_ATTRIBUTE_USAGE in mix %zu", i);
250e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    return BAD_VALUE;
251e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                }
252e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                if (hasUidMatchRules && hasUidExcludeRules) {
253e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    ALOGE("getOutputForAttr: invalid combination of RULE_MATCH_UID"
254e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                            " and RULE_EXCLUDE_UID in mix %zu", i);
255e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    return BAD_VALUE;
256e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                }
257e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi
258e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                if ((hasUsageExcludeRules && usageExclusionFound)
259e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                        || (hasUidExcludeRules && uidExclusionFound)) {
260e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    break; // stop iterating on criteria because an exclusion was found (will fail)
261e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                }
262e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi
263e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi            }//iterate on mix criteria
264e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi
265e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi            // determine if exiting on success (or implicit failure as desc is 0)
266e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi            if (hasAddrMatch ||
267e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    !((hasUsageExcludeRules && usageExclusionFound) ||
268e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                      (hasUsageMatchRules && !usageMatchFound)  ||
269e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                      (hasUidExcludeRules && uidExclusionFound) ||
270e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                      (hasUidMatchRules && !uidMatchFound))) {
271e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                ALOGV("\tgetOutputForAttr will use mix %zu", i);
272e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                desc = policyMix->getOutput();
273036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie            }
274e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi
275dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Trivi        } else if (mix->mMixType == MIX_TYPE_RECORDERS) {
276036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie            if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE &&
277036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                    strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
278036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                    strncmp(attributes.tags + strlen("addr="),
2797638ca29e8400a19524adb982e9d22c02786de82Jean-Michel Trivi                            mix->mDeviceAddress.string(),
280036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                            AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
281036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                desc = policyMix->getOutput();
282036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie            }
283036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        }
284036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        if (desc != 0) {
285dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Trivi            desc->mPolicyMix = mix;
286036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie            return NO_ERROR;
287036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        }
288036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    }
289036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    return BAD_VALUE;
290036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie}
291036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
292036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffieaudio_devices_t AudioPolicyMixCollection::getDeviceAndMixForInputSource(audio_source_t inputSource,
293036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                                                                        audio_devices_t availDevices,
294036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                                                                        AudioMix **policyMix)
295036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie{
296036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    for (size_t i = 0; i < size(); i++) {
297dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Trivi        AudioMix *mix = valueAt(i)->getMix();
298036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
299dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Trivi        if (mix->mMixType != MIX_TYPE_RECORDERS) {
300036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie            continue;
301036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        }
302dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Trivi        for (size_t j = 0; j < mix->mCriteria.size(); j++) {
303dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Trivi            if ((RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET == mix->mCriteria[j].mRule &&
304e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    mix->mCriteria[j].mValue.mSource == inputSource) ||
305dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Trivi               (RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET == mix->mCriteria[j].mRule &&
306e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi                    mix->mCriteria[j].mValue.mSource != inputSource)) {
307036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                if (availDevices & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
308036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                    if (policyMix != NULL) {
309dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Trivi                        *policyMix = mix;
310036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                    }
311036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                    return AUDIO_DEVICE_IN_REMOTE_SUBMIX;
312036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                }
313036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie                break;
314036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie            }
315036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        }
316036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    }
317036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    return AUDIO_DEVICE_NONE;
318036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie}
319036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
320dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Trivistatus_t AudioPolicyMixCollection::getInputMixForAttr(audio_attributes_t attr, AudioMix **policyMix)
321036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie{
322036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    if (strncmp(attr.tags, "addr=", strlen("addr=")) != 0) {
323036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        return BAD_VALUE;
324036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    }
325036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    String8 address(attr.tags + strlen("addr="));
326036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
327e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi#ifdef LOG_NDEBUG
328e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi    ALOGV("getInputMixForAttr looking for address %s\n  mixes available:", address.string());
329e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi    for (size_t i = 0; i < size(); i++) {
330e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi            sp<AudioPolicyMix> policyMix = valueAt(i);
331e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi            AudioMix *mix = policyMix->getMix();
3327638ca29e8400a19524adb982e9d22c02786de82Jean-Michel Trivi            ALOGV("\tmix %zu address=%s", i, mix->mDeviceAddress.string());
333e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi    }
334e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi#endif
335e8decedb429ed76dfa84cdb3e80ab3b969e77298Jean-Michel Trivi
336036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    ssize_t index = indexOfKey(address);
337036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    if (index < 0) {
3388c7e6dac6f5eb38cef627dab92eac8b38513450cEric Laurent        ALOGW("getInputMixForAttr() no policy for address %s", address.string());
339036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        return BAD_VALUE;
340036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    }
341036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    sp<AudioPolicyMix> audioPolicyMix = valueAt(index);
342dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Trivi    AudioMix *mix = audioPolicyMix->getMix();
343036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
344dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Trivi    if (mix->mMixType != MIX_TYPE_PLAYERS) {
3458c7e6dac6f5eb38cef627dab92eac8b38513450cEric Laurent        ALOGW("getInputMixForAttr() bad policy mix type for address %s", address.string());
346036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie        return BAD_VALUE;
347036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    }
348dacc06f5e8d00ace9d16a149fc41ff65323ffbb3Jean-Michel Trivi    *policyMix = mix;
349036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie    return NO_ERROR;
350036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie}
351036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie
35244344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganovstatus_t AudioPolicyMixCollection::dump(int fd) const
35344344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov{
35444344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    std::string log("\nAudio Policy Mix:\n");
35544344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    write(fd, log.c_str(), log.size());
35644344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    for (size_t i = 0; i < size(); i++) {
35744344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov        valueAt(i)->dump(fd, 2, i);
35844344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    }
35944344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov    return NO_ERROR;
36044344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov}
36144344b05261cb9ad46a43e635f637b89aecc7afeMikhail Naganov
362036e1e9126dcd496203434aa69e52115d8e730ccFrançois Gaffie}; //namespace android
363