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