• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::AudioPort"
18 //#define LOG_NDEBUG 0
19 #include "TypeConverter.h"
20 #include "AudioPort.h"
21 #include "HwModule.h"
22 #include "AudioGain.h"
23 #include <policy.h>
24 #include <cutils/atomic.h>
25 
26 #ifndef ARRAY_SIZE
27 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
28 #endif
29 
30 namespace android {
31 
32 int32_t volatile AudioPort::mNextUniqueId = 1;
33 
34 // --- AudioPort class implementation
attach(const sp<HwModule> & module)35 void AudioPort::attach(const sp<HwModule>& module)
36 {
37     mModule = module;
38 }
39 
40 // Note that is a different namespace than AudioFlinger unique IDs
getNextUniqueId()41 audio_port_handle_t AudioPort::getNextUniqueId()
42 {
43     return static_cast<audio_port_handle_t>(android_atomic_inc(&mNextUniqueId));
44 }
45 
getModuleHandle() const46 audio_module_handle_t AudioPort::getModuleHandle() const
47 {
48     if (mModule == 0) {
49         return AUDIO_MODULE_HANDLE_NONE;
50     }
51     return mModule->mHandle;
52 }
53 
getModuleVersionMajor() const54 uint32_t AudioPort::getModuleVersionMajor() const
55 {
56     if (mModule == 0) {
57         return 0;
58     }
59     return mModule->getHalVersionMajor();
60 }
61 
getModuleName() const62 const char *AudioPort::getModuleName() const
63 {
64     if (mModule == 0) {
65         return "invalid module";
66     }
67     return mModule->getName();
68 }
69 
toAudioPort(struct audio_port * port) const70 void AudioPort::toAudioPort(struct audio_port *port) const
71 {
72     // TODO: update this function once audio_port structure reflects the new profile definition.
73     // For compatibility reason: flatening the AudioProfile into audio_port structure.
74     SortedVector<audio_format_t> flatenedFormats;
75     SampleRateVector flatenedRates;
76     ChannelsVector flatenedChannels;
77     for (size_t profileIndex = 0; profileIndex < mProfiles.size(); profileIndex++) {
78         if (mProfiles[profileIndex]->isValid()) {
79             audio_format_t formatToExport = mProfiles[profileIndex]->getFormat();
80             const SampleRateVector &ratesToExport = mProfiles[profileIndex]->getSampleRates();
81             const ChannelsVector &channelsToExport = mProfiles[profileIndex]->getChannels();
82 
83             if (flatenedFormats.indexOf(formatToExport) < 0) {
84                 flatenedFormats.add(formatToExport);
85             }
86             for (size_t rateIndex = 0; rateIndex < ratesToExport.size(); rateIndex++) {
87                 uint32_t rate = ratesToExport[rateIndex];
88                 if (flatenedRates.indexOf(rate) < 0) {
89                     flatenedRates.add(rate);
90                 }
91             }
92             for (size_t chanIndex = 0; chanIndex < channelsToExport.size(); chanIndex++) {
93                 audio_channel_mask_t channels = channelsToExport[chanIndex];
94                 if (flatenedChannels.indexOf(channels) < 0) {
95                     flatenedChannels.add(channels);
96                 }
97             }
98             if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES ||
99                     flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS ||
100                     flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) {
101                 ALOGE("%s: bailing out: cannot export profiles to port config", __FUNCTION__);
102                 return;
103             }
104         }
105     }
106     port->role = mRole;
107     port->type = mType;
108     strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN);
109     port->num_sample_rates = flatenedRates.size();
110     port->num_channel_masks = flatenedChannels.size();
111     port->num_formats = flatenedFormats.size();
112     for (size_t i = 0; i < flatenedRates.size(); i++) {
113         port->sample_rates[i] = flatenedRates[i];
114     }
115     for (size_t i = 0; i < flatenedChannels.size(); i++) {
116         port->channel_masks[i] = flatenedChannels[i];
117     }
118     for (size_t i = 0; i < flatenedFormats.size(); i++) {
119         port->formats[i] = flatenedFormats[i];
120     }
121 
122     ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());
123 
124     uint32_t i;
125     for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) {
126         port->gains[i] = mGains[i]->getGain();
127     }
128     port->num_gains = i;
129 }
130 
importAudioPort(const sp<AudioPort> & port,bool force __unused)131 void AudioPort::importAudioPort(const sp<AudioPort>& port, bool force __unused)
132 {
133     size_t indexToImport;
134     for (indexToImport = 0; indexToImport < port->mProfiles.size(); indexToImport++) {
135         const sp<AudioProfile> &profileToImport = port->mProfiles[indexToImport];
136         if (profileToImport->isValid()) {
137             // Import only valid port, i.e. valid format, non empty rates and channels masks
138             bool hasSameProfile = false;
139             for (size_t profileIndex = 0; profileIndex < mProfiles.size(); profileIndex++) {
140                 if (*mProfiles[profileIndex] == *profileToImport) {
141                     // never import a profile twice
142                     hasSameProfile = true;
143                     break;
144                 }
145             }
146             if (hasSameProfile) { // never import a same profile twice
147                 continue;
148             }
149             addAudioProfile(profileToImport);
150         }
151     }
152 }
153 
pickSamplingRate(uint32_t & pickedRate,const SampleRateVector & samplingRates) const154 void AudioPort::pickSamplingRate(uint32_t &pickedRate,const SampleRateVector &samplingRates) const
155 {
156     pickedRate = 0;
157     // For direct outputs, pick minimum sampling rate: this helps ensuring that the
158     // channel count / sampling rate combination chosen will be supported by the connected
159     // sink
160     if (isDirectOutput()) {
161         uint32_t samplingRate = UINT_MAX;
162         for (size_t i = 0; i < samplingRates.size(); i ++) {
163             if ((samplingRates[i] < samplingRate) && (samplingRates[i] > 0)) {
164                 samplingRate = samplingRates[i];
165             }
166         }
167         pickedRate = (samplingRate == UINT_MAX) ? 0 : samplingRate;
168     } else {
169         uint32_t maxRate = SAMPLE_RATE_HZ_MAX;
170 
171         // For mixed output and inputs, use max mixer sampling rates. Do not
172         // limit sampling rate otherwise
173         // For inputs, also see checkCompatibleSamplingRate().
174         if (mType != AUDIO_PORT_TYPE_MIX) {
175             maxRate = UINT_MAX;
176         }
177         // TODO: should mSamplingRates[] be ordered in terms of our preference
178         // and we return the first (and hence most preferred) match?  This is of concern if
179         // we want to choose 96kHz over 192kHz for USB driver stability or resource constraints.
180         for (size_t i = 0; i < samplingRates.size(); i ++) {
181             if ((samplingRates[i] > pickedRate) && (samplingRates[i] <= maxRate)) {
182                 pickedRate = samplingRates[i];
183             }
184         }
185     }
186 }
187 
pickChannelMask(audio_channel_mask_t & pickedChannelMask,const ChannelsVector & channelMasks) const188 void AudioPort::pickChannelMask(audio_channel_mask_t &pickedChannelMask,
189                                 const ChannelsVector &channelMasks) const
190 {
191     pickedChannelMask = AUDIO_CHANNEL_NONE;
192     // For direct outputs, pick minimum channel count: this helps ensuring that the
193     // channel count / sampling rate combination chosen will be supported by the connected
194     // sink
195     if (isDirectOutput()) {
196         uint32_t channelCount = UINT_MAX;
197         for (size_t i = 0; i < channelMasks.size(); i ++) {
198             uint32_t cnlCount;
199             if (useInputChannelMask()) {
200                 cnlCount = audio_channel_count_from_in_mask(channelMasks[i]);
201             } else {
202                 cnlCount = audio_channel_count_from_out_mask(channelMasks[i]);
203             }
204             if ((cnlCount < channelCount) && (cnlCount > 0)) {
205                 pickedChannelMask = channelMasks[i];
206                 channelCount = cnlCount;
207             }
208         }
209     } else {
210         uint32_t channelCount = 0;
211         uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT;
212 
213         // For mixed output and inputs, use max mixer channel count. Do not
214         // limit channel count otherwise
215         if (mType != AUDIO_PORT_TYPE_MIX) {
216             maxCount = UINT_MAX;
217         }
218         for (size_t i = 0; i < channelMasks.size(); i ++) {
219             uint32_t cnlCount;
220             if (useInputChannelMask()) {
221                 cnlCount = audio_channel_count_from_in_mask(channelMasks[i]);
222             } else {
223                 cnlCount = audio_channel_count_from_out_mask(channelMasks[i]);
224             }
225             if ((cnlCount > channelCount) && (cnlCount <= maxCount)) {
226                 pickedChannelMask = channelMasks[i];
227                 channelCount = cnlCount;
228             }
229         }
230     }
231 }
232 
233 /* format in order of increasing preference */
234 const audio_format_t AudioPort::sPcmFormatCompareTable[] = {
235         AUDIO_FORMAT_DEFAULT,
236         AUDIO_FORMAT_PCM_16_BIT,
237         AUDIO_FORMAT_PCM_8_24_BIT,
238         AUDIO_FORMAT_PCM_24_BIT_PACKED,
239         AUDIO_FORMAT_PCM_32_BIT,
240         AUDIO_FORMAT_PCM_FLOAT,
241 };
242 
compareFormats(audio_format_t format1,audio_format_t format2)243 int AudioPort::compareFormats(audio_format_t format1, audio_format_t format2)
244 {
245     // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any
246     // compressed format and better than any PCM format. This is by design of pickFormat()
247     if (!audio_is_linear_pcm(format1)) {
248         if (!audio_is_linear_pcm(format2)) {
249             return 0;
250         }
251         return 1;
252     }
253     if (!audio_is_linear_pcm(format2)) {
254         return -1;
255     }
256 
257     int index1 = -1, index2 = -1;
258     for (size_t i = 0;
259             (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1));
260             i ++) {
261         if (sPcmFormatCompareTable[i] == format1) {
262             index1 = i;
263         }
264         if (sPcmFormatCompareTable[i] == format2) {
265             index2 = i;
266         }
267     }
268     // format1 not found => index1 < 0 => format2 > format1
269     // format2 not found => index2 < 0 => format2 < format1
270     return index1 - index2;
271 }
272 
isBetterFormatMatch(audio_format_t newFormat,audio_format_t currentFormat,audio_format_t targetFormat)273 bool AudioPort::isBetterFormatMatch(audio_format_t newFormat,
274                                     audio_format_t currentFormat,
275                                     audio_format_t targetFormat)
276 {
277     if (newFormat == currentFormat) {
278         return false;
279     }
280     if (currentFormat == AUDIO_FORMAT_INVALID) {
281         return true;
282     }
283     if (newFormat == targetFormat) {
284         return true;
285     }
286     int currentDiffBytes = (int)audio_bytes_per_sample(targetFormat) -
287             audio_bytes_per_sample(currentFormat);
288     int newDiffBytes = (int)audio_bytes_per_sample(targetFormat) -
289             audio_bytes_per_sample(newFormat);
290 
291     if (abs(newDiffBytes) < abs(currentDiffBytes)) {
292         return true;
293     } else if (abs(newDiffBytes) == abs(currentDiffBytes)) {
294         return (newDiffBytes >= 0);
295     }
296     return false;
297 }
298 
pickAudioProfile(uint32_t & samplingRate,audio_channel_mask_t & channelMask,audio_format_t & format) const299 void AudioPort::pickAudioProfile(uint32_t &samplingRate,
300                                  audio_channel_mask_t &channelMask,
301                                  audio_format_t &format) const
302 {
303     format = AUDIO_FORMAT_DEFAULT;
304     samplingRate = 0;
305     channelMask = AUDIO_CHANNEL_NONE;
306 
307     // special case for uninitialized dynamic profile
308     if (!mProfiles.hasValidProfile()) {
309         return;
310     }
311     audio_format_t bestFormat = sPcmFormatCompareTable[ARRAY_SIZE(sPcmFormatCompareTable) - 1];
312     // For mixed output and inputs, use best mixer output format.
313     // Do not limit format otherwise
314     if ((mType != AUDIO_PORT_TYPE_MIX) || isDirectOutput()) {
315         bestFormat = AUDIO_FORMAT_INVALID;
316     }
317 
318     for (size_t i = 0; i < mProfiles.size(); i ++) {
319         if (!mProfiles[i]->isValid()) {
320             continue;
321         }
322         audio_format_t formatToCompare = mProfiles[i]->getFormat();
323         if ((compareFormats(formatToCompare, format) > 0) &&
324                 (compareFormats(formatToCompare, bestFormat) <= 0)) {
325             uint32_t pickedSamplingRate = 0;
326             audio_channel_mask_t pickedChannelMask = AUDIO_CHANNEL_NONE;
327             pickChannelMask(pickedChannelMask, mProfiles[i]->getChannels());
328             pickSamplingRate(pickedSamplingRate, mProfiles[i]->getSampleRates());
329 
330             if (formatToCompare != AUDIO_FORMAT_DEFAULT && pickedChannelMask != AUDIO_CHANNEL_NONE
331                     && pickedSamplingRate != 0) {
332                 format = formatToCompare;
333                 channelMask = pickedChannelMask;
334                 samplingRate = pickedSamplingRate;
335                 // TODO: shall we return on the first one or still trying to pick a better Profile?
336             }
337         }
338     }
339     ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__, mName.string(),
340           samplingRate, channelMask, format);
341 }
342 
checkGain(const struct audio_gain_config * gainConfig,int index) const343 status_t AudioPort::checkGain(const struct audio_gain_config *gainConfig, int index) const
344 {
345     if (index < 0 || (size_t)index >= mGains.size()) {
346         return BAD_VALUE;
347     }
348     return mGains[index]->checkConfig(gainConfig);
349 }
350 
dump(int fd,int spaces,bool verbose) const351 void AudioPort::dump(int fd, int spaces, bool verbose) const
352 {
353     const size_t SIZE = 256;
354     char buffer[SIZE];
355     String8 result;
356 
357     if (!mName.isEmpty()) {
358         snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string());
359         result.append(buffer);
360         write(fd, result.string(), result.size());
361     }
362     if (verbose) {
363         mProfiles.dump(fd, spaces);
364 
365         if (mGains.size() != 0) {
366             snprintf(buffer, SIZE, "%*s- gains:\n", spaces, "");
367             result = buffer;
368             write(fd, result.string(), result.size());
369             for (size_t i = 0; i < mGains.size(); i++) {
370                 mGains[i]->dump(fd, spaces + 2, i);
371             }
372         }
373     }
374 }
375 
log(const char * indent) const376 void AudioPort::log(const char* indent) const
377 {
378     ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.string(), mType, mRole);
379 }
380 
381 // --- AudioPortConfig class implementation
382 
AudioPortConfig()383 AudioPortConfig::AudioPortConfig()
384 {
385     mSamplingRate = 0;
386     mChannelMask = AUDIO_CHANNEL_NONE;
387     mFormat = AUDIO_FORMAT_INVALID;
388     memset(&mGain, 0, sizeof(struct audio_gain_config));
389     mGain.index = -1;
390 }
391 
applyAudioPortConfig(const struct audio_port_config * config,struct audio_port_config * backupConfig)392 status_t AudioPortConfig::applyAudioPortConfig(const struct audio_port_config *config,
393                                                struct audio_port_config *backupConfig)
394 {
395     struct audio_port_config localBackupConfig;
396     status_t status = NO_ERROR;
397 
398     localBackupConfig.config_mask = config->config_mask;
399     toAudioPortConfig(&localBackupConfig);
400 
401     sp<AudioPort> audioport = getAudioPort();
402     if (audioport == 0) {
403         status = NO_INIT;
404         goto exit;
405     }
406     status = audioport->checkExactAudioProfile(config->sample_rate,
407                                                config->channel_mask,
408                                                config->format);
409     if (status != NO_ERROR) {
410         goto exit;
411     }
412     if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
413         mSamplingRate = config->sample_rate;
414     }
415     if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
416         mChannelMask = config->channel_mask;
417     }
418     if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
419         mFormat = config->format;
420     }
421     if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) {
422         status = audioport->checkGain(&config->gain, config->gain.index);
423         if (status != NO_ERROR) {
424             goto exit;
425         }
426         mGain = config->gain;
427     }
428 
429 exit:
430     if (status != NO_ERROR) {
431         applyAudioPortConfig(&localBackupConfig);
432     }
433     if (backupConfig != NULL) {
434         *backupConfig = localBackupConfig;
435     }
436     return status;
437 }
438 
toAudioPortConfig(struct audio_port_config * dstConfig,const struct audio_port_config * srcConfig) const439 void AudioPortConfig::toAudioPortConfig(struct audio_port_config *dstConfig,
440                                         const struct audio_port_config *srcConfig) const
441 {
442     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
443         dstConfig->sample_rate = mSamplingRate;
444         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE)) {
445             dstConfig->sample_rate = srcConfig->sample_rate;
446         }
447     } else {
448         dstConfig->sample_rate = 0;
449     }
450     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
451         dstConfig->channel_mask = mChannelMask;
452         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK)) {
453             dstConfig->channel_mask = srcConfig->channel_mask;
454         }
455     } else {
456         dstConfig->channel_mask = AUDIO_CHANNEL_NONE;
457     }
458     if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
459         dstConfig->format = mFormat;
460         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT)) {
461             dstConfig->format = srcConfig->format;
462         }
463     } else {
464         dstConfig->format = AUDIO_FORMAT_INVALID;
465     }
466     sp<AudioPort> audioport = getAudioPort();
467     if ((dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) && audioport != NULL) {
468         dstConfig->gain = mGain;
469         if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)
470                 && audioport->checkGain(&srcConfig->gain, srcConfig->gain.index) == OK) {
471             dstConfig->gain = srcConfig->gain;
472         }
473     } else {
474         dstConfig->gain.index = -1;
475     }
476     if (dstConfig->gain.index != -1) {
477         dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN;
478     } else {
479         dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
480     }
481 }
482 
483 }; // namespace android
484