1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "APM::PolicyAudioPort"
18 //#define LOG_NDEBUG 0
19 #include "TypeConverter.h"
20 #include "PolicyAudioPort.h"
21 #include "HwModule.h"
22 #include <policy.h>
23
24 #ifndef ARRAY_SIZE
25 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
26 #endif
27
28 namespace android {
29
30 // --- PolicyAudioPort class implementation
attach(const sp<HwModule> & module)31 void PolicyAudioPort::attach(const sp<HwModule>& module)
32 {
33 mModule = module;
34 ALOGV("%s: attaching module %s to port %s",
35 __FUNCTION__, getModuleName(), asAudioPort()->getName().c_str());
36 }
37
detach()38 void PolicyAudioPort::detach()
39 {
40 mModule = nullptr;
41 }
42
43 // Note that is a different namespace than AudioFlinger unique IDs
getNextUniqueId()44 audio_port_handle_t PolicyAudioPort::getNextUniqueId()
45 {
46 return getNextHandle();
47 }
48
getModuleHandle() const49 audio_module_handle_t PolicyAudioPort::getModuleHandle() const
50 {
51 return mModule != 0 ? mModule->getHandle() : AUDIO_MODULE_HANDLE_NONE;
52 }
53
getModuleVersionMajor() const54 uint32_t PolicyAudioPort::getModuleVersionMajor() const
55 {
56 return mModule != 0 ? mModule->getHalVersionMajor() : 0;
57 }
58
getModuleName() const59 const char *PolicyAudioPort::getModuleName() const
60 {
61 return mModule != 0 ? mModule->getName() : "invalid module";
62 }
63
checkExactAudioProfile(const struct audio_port_config * config) const64 status_t PolicyAudioPort::checkExactAudioProfile(const struct audio_port_config *config) const
65 {
66 return checkAudioProfile(config, checkExactProfile);
67 }
68
checkIdenticalAudioProfile(const struct audio_port_config * config) const69 status_t PolicyAudioPort::checkIdenticalAudioProfile(const struct audio_port_config *config) const {
70 return checkAudioProfile(config, checkIdenticalProfile);
71 }
72
pickSamplingRate(uint32_t & pickedRate,const SampleRateSet & samplingRates) const73 void PolicyAudioPort::pickSamplingRate(uint32_t &pickedRate,
74 const SampleRateSet &samplingRates) const
75 {
76 pickedRate = 0;
77 // For direct outputs, pick minimum sampling rate: this helps ensuring that the
78 // channel count / sampling rate combination chosen will be supported by the connected
79 // sink
80 if (asAudioPort()->isDirectOutput()) {
81 uint32_t samplingRate = UINT_MAX;
82 for (const auto rate : samplingRates) {
83 if ((rate < samplingRate) && (rate > 0)) {
84 samplingRate = rate;
85 }
86 }
87 pickedRate = (samplingRate == UINT_MAX) ? 0 : samplingRate;
88 } else {
89 uint32_t maxRate = SAMPLE_RATE_HZ_MAX;
90
91 // For mixed output and inputs, use max mixer sampling rates. Do not
92 // limit sampling rate otherwise
93 // For inputs, also see checkCompatibleSamplingRate().
94 if (asAudioPort()->getType() == AUDIO_PORT_TYPE_MIX) {
95 maxRate = UINT_MAX;
96 }
97 // TODO: should mSamplingRates[] be ordered in terms of our preference
98 // and we return the first (and hence most preferred) match? This is of concern if
99 // we want to choose 96kHz over 192kHz for USB driver stability or resource constraints.
100 for (const auto rate : samplingRates) {
101 if ((rate > pickedRate) && (rate <= maxRate)) {
102 pickedRate = rate;
103 }
104 }
105 }
106 }
107
pickChannelMask(audio_channel_mask_t & pickedChannelMask,const ChannelMaskSet & channelMasks) const108 void PolicyAudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask,
109 const ChannelMaskSet &channelMasks) const
110 {
111 pickedChannelMask = AUDIO_CHANNEL_NONE;
112 // For direct outputs, pick minimum channel count: this helps ensuring that the
113 // channel count / sampling rate combination chosen will be supported by the connected
114 // sink
115 if (asAudioPort()->isDirectOutput()) {
116 uint32_t channelCount = UINT_MAX;
117 for (const auto channelMask : channelMasks) {
118 uint32_t cnlCount;
119 if (asAudioPort()->useInputChannelMask()) {
120 cnlCount = audio_channel_count_from_in_mask(channelMask);
121 } else {
122 cnlCount = audio_channel_count_from_out_mask(channelMask);
123 }
124 if ((cnlCount < channelCount) && (cnlCount > 0)) {
125 pickedChannelMask = channelMask;
126 channelCount = cnlCount;
127 }
128 }
129 } else {
130 uint32_t channelCount = 0;
131 uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT;
132
133 // For mixed output and inputs, use max mixer channel count. Do not
134 // limit channel count otherwise
135 if (asAudioPort()->getType() != AUDIO_PORT_TYPE_MIX) {
136 maxCount = UINT_MAX;
137 }
138 for (const auto channelMask : channelMasks) {
139 uint32_t cnlCount;
140 if (asAudioPort()->useInputChannelMask()) {
141 cnlCount = audio_channel_count_from_in_mask(channelMask);
142 } else {
143 cnlCount = audio_channel_count_from_out_mask(channelMask);
144 }
145 if ((cnlCount > channelCount) && (cnlCount <= maxCount)) {
146 pickedChannelMask = channelMask;
147 channelCount = cnlCount;
148 }
149 }
150 }
151 }
152
153 /* format in order of increasing preference */
154 const audio_format_t PolicyAudioPort::sPcmFormatCompareTable[] = {
155 AUDIO_FORMAT_DEFAULT,
156 AUDIO_FORMAT_PCM_16_BIT,
157 AUDIO_FORMAT_PCM_8_24_BIT,
158 AUDIO_FORMAT_PCM_24_BIT_PACKED,
159 AUDIO_FORMAT_PCM_32_BIT,
160 AUDIO_FORMAT_PCM_FLOAT,
161 };
162
compareFormats(audio_format_t format1,audio_format_t format2)163 int PolicyAudioPort::compareFormats(audio_format_t format1, audio_format_t format2)
164 {
165 // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any
166 // compressed format and better than any PCM format. This is by design of pickFormat()
167 if (!audio_is_linear_pcm(format1)) {
168 if (!audio_is_linear_pcm(format2)) {
169 return 0;
170 }
171 return 1;
172 }
173 if (!audio_is_linear_pcm(format2)) {
174 return -1;
175 }
176
177 int index1 = -1, index2 = -1;
178 for (size_t i = 0;
179 (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1));
180 i ++) {
181 if (sPcmFormatCompareTable[i] == format1) {
182 index1 = i;
183 }
184 if (sPcmFormatCompareTable[i] == format2) {
185 index2 = i;
186 }
187 }
188 // format1 not found => index1 < 0 => format2 > format1
189 // format2 not found => index2 < 0 => format2 < format1
190 return index1 - index2;
191 }
192
formatDistance(audio_format_t format1,audio_format_t format2)193 uint32_t PolicyAudioPort::formatDistance(audio_format_t format1, audio_format_t format2)
194 {
195 if (format1 == format2) {
196 return 0;
197 }
198 if (format1 == AUDIO_FORMAT_INVALID || format2 == AUDIO_FORMAT_INVALID) {
199 return kFormatDistanceMax;
200 }
201 int diffBytes = (int)audio_bytes_per_sample(format1) -
202 audio_bytes_per_sample(format2);
203
204 return abs(diffBytes);
205 }
206
isBetterFormatMatch(audio_format_t newFormat,audio_format_t currentFormat,audio_format_t targetFormat)207 bool PolicyAudioPort::isBetterFormatMatch(audio_format_t newFormat,
208 audio_format_t currentFormat,
209 audio_format_t targetFormat)
210 {
211 return formatDistance(newFormat, targetFormat) < formatDistance(currentFormat, targetFormat);
212 }
213
pickAudioProfile(uint32_t & samplingRate,audio_channel_mask_t & channelMask,audio_format_t & format) const214 void PolicyAudioPort::pickAudioProfile(uint32_t &samplingRate,
215 audio_channel_mask_t &channelMask,
216 audio_format_t &format) const
217 {
218 format = AUDIO_FORMAT_DEFAULT;
219 samplingRate = 0;
220 channelMask = AUDIO_CHANNEL_NONE;
221
222 // special case for uninitialized dynamic profile
223 if (!asAudioPort()->hasValidAudioProfile()) {
224 return;
225 }
226 audio_format_t bestFormat = sPcmFormatCompareTable[ARRAY_SIZE(sPcmFormatCompareTable) - 1];
227 // For mixed output and inputs, use best mixer output format.
228 // Do not limit format otherwise
229 if ((asAudioPort()->getType() != AUDIO_PORT_TYPE_MIX) || asAudioPort()->isDirectOutput()) {
230 bestFormat = AUDIO_FORMAT_INVALID;
231 }
232
233 const AudioProfileVector& audioProfiles = asAudioPort()->getAudioProfiles();
234 for (size_t i = 0; i < audioProfiles.size(); i ++) {
235 if (!audioProfiles[i]->isValid()) {
236 continue;
237 }
238 audio_format_t formatToCompare = audioProfiles[i]->getFormat();
239 if ((compareFormats(formatToCompare, format) > 0) &&
240 (compareFormats(formatToCompare, bestFormat) <= 0)) {
241 uint32_t pickedSamplingRate = 0;
242 audio_channel_mask_t pickedChannelMask = AUDIO_CHANNEL_NONE;
243 pickChannelMask(pickedChannelMask, audioProfiles[i]->getChannels());
244 pickSamplingRate(pickedSamplingRate, audioProfiles[i]->getSampleRates());
245
246 if (formatToCompare != AUDIO_FORMAT_DEFAULT && pickedChannelMask != AUDIO_CHANNEL_NONE
247 && pickedSamplingRate != 0) {
248 format = formatToCompare;
249 channelMask = pickedChannelMask;
250 samplingRate = pickedSamplingRate;
251 // TODO: shall we return on the first one or still trying to pick a better Profile?
252 }
253 }
254 }
255 ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__,
256 asAudioPort()->getName().c_str(), samplingRate, channelMask, format);
257 }
258
checkAudioProfile(const struct audio_port_config * config,std::function<status_t (const AudioProfileVector &,const uint32_t,audio_channel_mask_t,audio_format_t)> checkProfile) const259 status_t PolicyAudioPort::checkAudioProfile(
260 const struct audio_port_config *config,
261 std::function<status_t(const AudioProfileVector &,
262 const uint32_t,
263 audio_channel_mask_t,
264 audio_format_t)> checkProfile) const {
265 status_t status = NO_ERROR;
266 auto config_mask = config->config_mask;
267 if (config_mask & AUDIO_PORT_CONFIG_GAIN) {
268 config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
269 status = asAudioPort()->checkGain(&config->gain, config->gain.index);
270 if (status != NO_ERROR) {
271 return status;
272 }
273 }
274 if (config_mask != 0) {
275 // TODO should we check sample_rate / channel_mask / format separately?
276 status = checkProfile(asAudioPort()->getAudioProfiles(), config->sample_rate,
277 config->channel_mask, config->format);
278 }
279 return status;
280
281 }
282
283 } // namespace android
284