1112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie/*
2112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * Copyright (C) 2015 The Android Open Source Project
3112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie *
4112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * Licensed under the Apache License, Version 2.0 (the "License");
5112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * you may not use this file except in compliance with the License.
6112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * You may obtain a copy of the License at
7112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie *
8112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie *      http://www.apache.org/licenses/LICENSE-2.0
9112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie *
10112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * Unless required by applicable law or agreed to in writing, software
11112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * distributed under the License is distributed on an "AS IS" BASIS,
12112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * See the License for the specific language governing permissions and
14112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * limitations under the License.
15112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie */
16112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
17112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#define LOG_TAG "APM::AudioProfile"
18112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie//#define LOG_NDEBUG 0
19112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
20112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#include "AudioProfile.h"
21112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#include "AudioPort.h"
22112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#include "HwModule.h"
23112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#include "AudioGain.h"
24112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#include <utils/SortedVector.h>
25112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#include "TypeConverter.h"
26112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#include <media/AudioResamplerPublic.h>
27112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#include <algorithm>
28112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
29112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffienamespace android {
30112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
31112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffiestatus_t AudioProfile::checkExact(uint32_t samplingRate, audio_channel_mask_t channelMask,
32112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                  audio_format_t format) const
33112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{
34e693002b0fb25099540588245892ed98103749baEric Laurent    if (audio_formats_match(format, mFormat) &&
352cc2a03319144bcebac5a9693319776afc471307Phil Burk            supportsChannels(channelMask) &&
362cc2a03319144bcebac5a9693319776afc471307Phil Burk            supportsRate(samplingRate)) {
37112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        return NO_ERROR;
38112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    }
39112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    return BAD_VALUE;
40112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie}
41112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
42112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffietemplate <typename T>
43112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffiebool operator == (const SortedVector<T> &left, const SortedVector<T> &right)
44112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{
45112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (left.size() != right.size()) {
46112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        return false;
47112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    }
48112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    for(size_t index = 0; index < right.size(); index++) {
49112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        if (left[index] != right[index]) {
50112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            return false;
51112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        }
52112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    }
53112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    return true;
54112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie}
55112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
56112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffiebool operator == (const AudioProfile &left, const AudioProfile &compareTo)
57112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{
58112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    return (left.getFormat() == compareTo.getFormat()) &&
59112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            (left.getChannels() == compareTo.getChannels()) &&
60112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            (left.getSampleRates() == compareTo.getSampleRates());
61112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie}
62112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
63112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffiestatus_t AudioProfile::checkCompatibleSamplingRate(uint32_t samplingRate,
64112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                                   uint32_t &updatedSamplingRate) const
65112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{
6605ddca504ce8e0e61b41e5c1aebea72086eea57bGlenn Kasten    ALOG_ASSERT(samplingRate > 0);
6705ddca504ce8e0e61b41e5c1aebea72086eea57bGlenn Kasten
68112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (mSamplingRates.isEmpty()) {
69112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        updatedSamplingRate = samplingRate;
70112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        return NO_ERROR;
71112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    }
7205ddca504ce8e0e61b41e5c1aebea72086eea57bGlenn Kasten
73112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    // Search for the closest supported sampling rate that is above (preferred)
74112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    // or below (acceptable) the desired sampling rate, within a permitted ratio.
75112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    // The sampling rates are sorted in ascending order.
76112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    size_t orderOfDesiredRate = mSamplingRates.orderOf(samplingRate);
77112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
78112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum.
79112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (orderOfDesiredRate < mSamplingRates.size()) {
80112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        uint32_t candidate = mSamplingRates[orderOfDesiredRate];
81112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        if (candidate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) {
82112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            updatedSamplingRate = candidate;
83112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            return NO_ERROR;
84112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        }
85112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    }
86112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    // But if we have to up-sample from a lower sampling rate, that's OK.
87112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (orderOfDesiredRate != 0) {
88112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        uint32_t candidate = mSamplingRates[orderOfDesiredRate - 1];
89112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) {
90112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            updatedSamplingRate = candidate;
91112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            return NO_ERROR;
92112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        }
93112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    }
94112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    // leave updatedSamplingRate unmodified
95112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    return BAD_VALUE;
96112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie}
97112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
98112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffiestatus_t AudioProfile::checkCompatibleChannelMask(audio_channel_mask_t channelMask,
99112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                                  audio_channel_mask_t &updatedChannelMask,
100112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                                  audio_port_type_t portType,
101112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                                  audio_port_role_t portRole) const
102112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{
103112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (mChannelMasks.isEmpty()) {
104112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        updatedChannelMask = channelMask;
105112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        return NO_ERROR;
106112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    }
107112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    const bool isRecordThread = portType == AUDIO_PORT_TYPE_MIX && portRole == AUDIO_PORT_ROLE_SINK;
108112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    const bool isIndex = audio_channel_mask_get_representation(channelMask)
109112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            == AUDIO_CHANNEL_REPRESENTATION_INDEX;
110112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    int bestMatch = 0;
111112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    for (size_t i = 0; i < mChannelMasks.size(); i ++) {
112112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        audio_channel_mask_t supported = mChannelMasks[i];
113112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        if (supported == channelMask) {
114112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // Exact matches always taken.
115112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            updatedChannelMask = channelMask;
116112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            return NO_ERROR;
117112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        }
118112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
119112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        // AUDIO_CHANNEL_NONE (value: 0) is used for dynamic channel support
120112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        if (isRecordThread && supported != AUDIO_CHANNEL_NONE) {
121112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // Approximate (best) match:
122112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // The match score measures how well the supported channel mask matches the
123112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // desired mask, where increasing-is-better.
124112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            //
125112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // TODO: Some tweaks may be needed.
126112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // Should be a static function of the data processing library.
127112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            //
128112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // In priority:
129112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // match score = 1000 if legacy channel conversion equivalent (always prefer this)
130112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // OR
131112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // match score += 100 if the channel mask representations match
132112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // match score += number of channels matched.
133112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            //
134112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // If there are no matched channels, the mask may still be accepted
135112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // but the playback or record will be silent.
136112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            const bool isSupportedIndex = (audio_channel_mask_get_representation(supported)
137112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                    == AUDIO_CHANNEL_REPRESENTATION_INDEX);
138112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            int match;
139112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            if (isIndex && isSupportedIndex) {
140112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                // index equivalence
141112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                match = 100 + __builtin_popcount(
142112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                        audio_channel_mask_get_bits(channelMask)
143112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                            & audio_channel_mask_get_bits(supported));
144112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            } else if (isIndex && !isSupportedIndex) {
145112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                const uint32_t equivalentBits =
146112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                        (1 << audio_channel_count_from_in_mask(supported)) - 1 ;
147112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                match = __builtin_popcount(
148112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                        audio_channel_mask_get_bits(channelMask) & equivalentBits);
149112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            } else if (!isIndex && isSupportedIndex) {
150112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                const uint32_t equivalentBits =
151112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                        (1 << audio_channel_count_from_in_mask(channelMask)) - 1;
152112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                match = __builtin_popcount(
153112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                        equivalentBits & audio_channel_mask_get_bits(supported));
154112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            } else {
155112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                // positional equivalence
156112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                match = 100 + __builtin_popcount(
157112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                        audio_channel_mask_get_bits(channelMask)
158112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                            & audio_channel_mask_get_bits(supported));
159112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                switch (supported) {
160112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                case AUDIO_CHANNEL_IN_FRONT_BACK:
161112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                case AUDIO_CHANNEL_IN_STEREO:
162112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                    if (channelMask == AUDIO_CHANNEL_IN_MONO) {
163112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                        match = 1000;
164112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                    }
165112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                    break;
166112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                case AUDIO_CHANNEL_IN_MONO:
167112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                    if (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK
168112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                            || channelMask == AUDIO_CHANNEL_IN_STEREO) {
169112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                        match = 1000;
170112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                    }
171112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                    break;
172112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                default:
173112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                    break;
174112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                }
175112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            }
176112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            if (match > bestMatch) {
177112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                bestMatch = match;
178112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                updatedChannelMask = supported;
179112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            }
180112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        }
181112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    }
182112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    return bestMatch > 0 ? NO_ERROR : BAD_VALUE;
183112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie}
184112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
185112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffievoid AudioProfile::dump(int fd, int spaces) const
186112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{
187112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    const size_t SIZE = 256;
188112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    char buffer[SIZE];
189112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    String8 result;
190112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
191112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    snprintf(buffer, SIZE, "%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "",
192112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie             mIsDynamicChannels ? "[dynamic channels]" : "",
193112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie             mIsDynamicRate ? "[dynamic rates]" : "");
194112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    result.append(buffer);
195112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (mName.length() != 0) {
196112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string());
197112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        result.append(buffer);
198112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    }
199112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    std::string formatLiteral;
200112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (FormatConverter::toString(mFormat, formatLiteral)) {
201112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        snprintf(buffer, SIZE, "%*s- format: %s\n", spaces, "", formatLiteral.c_str());
202112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        result.append(buffer);
203112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    }
204112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (!mSamplingRates.isEmpty()) {
205112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        snprintf(buffer, SIZE, "%*s- sampling rates:", spaces, "");
206112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        result.append(buffer);
207112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        for (size_t i = 0; i < mSamplingRates.size(); i++) {
208112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            snprintf(buffer, SIZE, "%d", mSamplingRates[i]);
209112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            result.append(buffer);
210112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            result.append(i == (mSamplingRates.size() - 1) ? "" : ", ");
211112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        }
212112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        result.append("\n");
213112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    }
214112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
215112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (!mChannelMasks.isEmpty()) {
216112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        snprintf(buffer, SIZE, "%*s- channel masks:", spaces, "");
217112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        result.append(buffer);
218112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        for (size_t i = 0; i < mChannelMasks.size(); i++) {
219112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]);
220112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            result.append(buffer);
221112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            result.append(i == (mChannelMasks.size() - 1) ? "" : ", ");
222112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        }
223112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        result.append("\n");
224112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    }
225112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    write(fd, result.string(), result.size());
226112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie}
227112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
228112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffiestatus_t AudioProfileVector::checkExactProfile(uint32_t samplingRate,
229112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                               audio_channel_mask_t channelMask,
230112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                               audio_format_t format) const
231112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{
232112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (isEmpty()) {
233112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        return NO_ERROR;
234112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    }
235112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
236112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    for (size_t i = 0; i < size(); i++) {
237112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        const sp<AudioProfile> profile = itemAt(i);
238112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        if (profile->checkExact(samplingRate, channelMask, format) == NO_ERROR) {
239112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            return NO_ERROR;
240112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        }
241112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    }
242112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    return BAD_VALUE;
243112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie}
244112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
245112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffiestatus_t AudioProfileVector::checkCompatibleProfile(uint32_t &samplingRate,
246112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                                    audio_channel_mask_t &channelMask,
247112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                                    audio_format_t &format,
248112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                                    audio_port_type_t portType,
249112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                                    audio_port_role_t portRole) const
250112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{
251112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (isEmpty()) {
252112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        return NO_ERROR;
253112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    }
254112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
255112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    const bool checkInexact = // when port is input and format is linear pcm
256112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            portType == AUDIO_PORT_TYPE_MIX && portRole == AUDIO_PORT_ROLE_SINK
257112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            && audio_is_linear_pcm(format);
258112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
259112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    // iterate from best format to worst format (reverse order)
260112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    for (ssize_t i = size() - 1; i >= 0 ; --i) {
261112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        const sp<AudioProfile> profile = itemAt(i);
262112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        audio_format_t formatToCompare = profile->getFormat();
263112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        if (formatToCompare == format ||
264112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                (checkInexact
265112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                        && formatToCompare != AUDIO_FORMAT_DEFAULT
266112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                        && audio_is_linear_pcm(formatToCompare))) {
267112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // Compatible profile has been found, checks if this profile has compatible
268112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            // rate and channels as well
269112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            audio_channel_mask_t updatedChannels;
270112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            uint32_t updatedRate;
271112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            if (profile->checkCompatibleChannelMask(channelMask, updatedChannels,
272112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                                    portType, portRole) == NO_ERROR &&
273112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                    profile->checkCompatibleSamplingRate(samplingRate, updatedRate) == NO_ERROR) {
274112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                // for inexact checks we take the first linear pcm format due to sorting.
275112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                format = formatToCompare;
276112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                channelMask = updatedChannels;
277112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                samplingRate = updatedRate;
278112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                return NO_ERROR;
279112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            }
280112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        }
281112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    }
282112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    return BAD_VALUE;
283112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie}
284112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
285112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffieint AudioProfileVector::compareFormats(const sp<AudioProfile> *profile1,
286112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                       const sp<AudioProfile> *profile2)
287112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie{
288112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    return AudioPort::compareFormats((*profile1)->getFormat(), (*profile2)->getFormat());
289112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie}
290112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie
291112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie}; // namespace android
292