blob: 0afa11b4c2f78a31ac11b4a173876033a0192cbc [file] [log] [blame]
Phil Burk5ed503c2017-02-01 09:38:15 -08001/*
2 * Copyright 2016 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 "AAudio"
18//#define LOG_NDEBUG 0
Phil Burk5ed503c2017-02-01 09:38:15 -080019
jiabin4a341862022-09-20 17:58:37 +000020#include <assert.h>
21#include <math.h>
Phil Burk5ed503c2017-02-01 09:38:15 -080022#include <stdint.h>
jiabin4a341862022-09-20 17:58:37 +000023
24#include <aaudio/AAudioTesting.h>
25#include <android/media/audio/common/AudioMMapPolicy.h>
26#include <cutils/properties.h>
Phil Burk5ed503c2017-02-01 09:38:15 -080027#include <sys/types.h>
jiabin4a341862022-09-20 17:58:37 +000028#include <system/audio.h>
Phil Burk5ed503c2017-02-01 09:38:15 -080029#include <utils/Errors.h>
jiabin4a341862022-09-20 17:58:37 +000030#include <utils/Log.h>
Phil Burk5ed503c2017-02-01 09:38:15 -080031
Phil Burka4eb0d82017-04-12 15:44:06 -070032#include "aaudio/AAudio.h"
dimitry2d2f17c2019-07-17 13:55:16 +020033#include "core/AudioGlobal.h"
Phil Burkd04aeea2017-05-23 13:56:41 -070034#include "utility/AAudioUtilities.h"
Phil Burk5ed503c2017-02-01 09:38:15 -080035
36using namespace android;
37
jiabin4a341862022-09-20 17:58:37 +000038using android::media::audio::common::AudioMMapPolicy;
39using android::media::audio::common::AudioMMapPolicyInfo;
40
Phil Burk5ed503c2017-02-01 09:38:15 -080041status_t AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result) {
42 // This covers the case for AAUDIO_OK and for positive results.
43 if (result >= 0) {
44 return result;
45 }
46 status_t status;
47 switch (result) {
48 case AAUDIO_ERROR_DISCONNECTED:
Eric Laurenta2f296e2017-06-21 18:51:47 -070049 case AAUDIO_ERROR_NO_SERVICE:
Phil Burk5ed503c2017-02-01 09:38:15 -080050 status = DEAD_OBJECT;
51 break;
Eric Laurenta2f296e2017-06-21 18:51:47 -070052 case AAUDIO_ERROR_INVALID_HANDLE:
53 status = BAD_TYPE;
54 break;
Phil Burk5ed503c2017-02-01 09:38:15 -080055 case AAUDIO_ERROR_INVALID_STATE:
56 status = INVALID_OPERATION;
57 break;
Phil Burk71f35bb2017-04-13 16:05:07 -070058 case AAUDIO_ERROR_INVALID_RATE:
59 case AAUDIO_ERROR_INVALID_FORMAT:
Phil Burk5ed503c2017-02-01 09:38:15 -080060 case AAUDIO_ERROR_ILLEGAL_ARGUMENT:
Phil Burk5204d312017-05-04 17:16:13 -070061 case AAUDIO_ERROR_OUT_OF_RANGE:
Phil Burk5ed503c2017-02-01 09:38:15 -080062 status = BAD_VALUE;
63 break;
64 case AAUDIO_ERROR_WOULD_BLOCK:
65 status = WOULD_BLOCK;
66 break;
Phil Burk5204d312017-05-04 17:16:13 -070067 case AAUDIO_ERROR_NULL:
68 status = UNEXPECTED_NULL;
69 break;
Phil Burk940083c2017-07-17 17:00:02 -070070 case AAUDIO_ERROR_UNAVAILABLE:
71 status = NOT_ENOUGH_DATA;
72 break;
73
Phil Burk5204d312017-05-04 17:16:13 -070074 // TODO translate these result codes
Phil Burk5204d312017-05-04 17:16:13 -070075 case AAUDIO_ERROR_INTERNAL:
Phil Burk5204d312017-05-04 17:16:13 -070076 case AAUDIO_ERROR_UNIMPLEMENTED:
Phil Burk5204d312017-05-04 17:16:13 -070077 case AAUDIO_ERROR_NO_FREE_HANDLES:
78 case AAUDIO_ERROR_NO_MEMORY:
79 case AAUDIO_ERROR_TIMEOUT:
Phil Burk5ed503c2017-02-01 09:38:15 -080080 default:
81 status = UNKNOWN_ERROR;
82 break;
83 }
84 return status;
85}
86
87aaudio_result_t AAudioConvert_androidToAAudioResult(status_t status) {
88 // This covers the case for OK and for positive result.
89 if (status >= 0) {
90 return status;
91 }
92 aaudio_result_t result;
93 switch (status) {
94 case BAD_TYPE:
95 result = AAUDIO_ERROR_INVALID_HANDLE;
96 break;
97 case DEAD_OBJECT:
Phil Burk71f35bb2017-04-13 16:05:07 -070098 result = AAUDIO_ERROR_NO_SERVICE;
Phil Burk5ed503c2017-02-01 09:38:15 -080099 break;
100 case INVALID_OPERATION:
101 result = AAUDIO_ERROR_INVALID_STATE;
102 break;
Eric Laurenta2f296e2017-06-21 18:51:47 -0700103 case UNEXPECTED_NULL:
104 result = AAUDIO_ERROR_NULL;
105 break;
106 case BAD_VALUE:
107 result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
108 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800109 case WOULD_BLOCK:
110 result = AAUDIO_ERROR_WOULD_BLOCK;
111 break;
Phil Burk940083c2017-07-17 17:00:02 -0700112 case NOT_ENOUGH_DATA:
113 result = AAUDIO_ERROR_UNAVAILABLE;
114 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800115 default:
116 result = AAUDIO_ERROR_INTERNAL;
117 break;
118 }
119 return result;
120}
121
Phil Burk4e1af9f2018-01-03 15:54:35 -0800122audio_session_t AAudioConvert_aaudioToAndroidSessionId(aaudio_session_id_t sessionId) {
Phil Burk67fdd892018-01-23 15:28:55 -0800123 // If not a regular sessionId then convert to a safe value of AUDIO_SESSION_ALLOCATE.
124 return (sessionId == AAUDIO_SESSION_ID_ALLOCATE || sessionId == AAUDIO_SESSION_ID_NONE)
Phil Burk4e1af9f2018-01-03 15:54:35 -0800125 ? AUDIO_SESSION_ALLOCATE
126 : (audio_session_t) sessionId;
127}
128
Phil Burk9dca9822017-05-26 14:27:43 -0700129audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudioFormat) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800130 audio_format_t androidFormat;
131 switch (aaudioFormat) {
Phil Burk0127c1b2018-03-29 13:48:06 -0700132 case AAUDIO_FORMAT_UNSPECIFIED:
133 androidFormat = AUDIO_FORMAT_DEFAULT;
134 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800135 case AAUDIO_FORMAT_PCM_I16:
136 androidFormat = AUDIO_FORMAT_PCM_16_BIT;
137 break;
138 case AAUDIO_FORMAT_PCM_FLOAT:
139 androidFormat = AUDIO_FORMAT_PCM_FLOAT;
140 break;
Phil Burk04e805b2018-03-27 09:13:53 -0700141 case AAUDIO_FORMAT_PCM_I24_PACKED:
142 androidFormat = AUDIO_FORMAT_PCM_24_BIT_PACKED;
143 break;
144 case AAUDIO_FORMAT_PCM_I32:
145 androidFormat = AUDIO_FORMAT_PCM_32_BIT;
146 break;
jiabinca6a3f42022-06-09 20:33:47 +0000147 case AAUDIO_FORMAT_IEC61937:
148 androidFormat = AUDIO_FORMAT_IEC61937;
149 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800150 default:
Phil Burk0127c1b2018-03-29 13:48:06 -0700151 androidFormat = AUDIO_FORMAT_INVALID;
152 ALOGE("%s() 0x%08X unrecognized", __func__, aaudioFormat);
Phil Burk5ed503c2017-02-01 09:38:15 -0800153 break;
154 }
155 return androidFormat;
156}
157
Phil Burk9dca9822017-05-26 14:27:43 -0700158aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t androidFormat) {
Phil Burk0127c1b2018-03-29 13:48:06 -0700159 aaudio_format_t aaudioFormat;
Phil Burk5ed503c2017-02-01 09:38:15 -0800160 switch (androidFormat) {
Phil Burk0127c1b2018-03-29 13:48:06 -0700161 case AUDIO_FORMAT_DEFAULT:
162 aaudioFormat = AAUDIO_FORMAT_UNSPECIFIED;
163 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800164 case AUDIO_FORMAT_PCM_16_BIT:
165 aaudioFormat = AAUDIO_FORMAT_PCM_I16;
166 break;
167 case AUDIO_FORMAT_PCM_FLOAT:
168 aaudioFormat = AAUDIO_FORMAT_PCM_FLOAT;
169 break;
Phil Burk04e805b2018-03-27 09:13:53 -0700170 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
171 aaudioFormat = AAUDIO_FORMAT_PCM_I24_PACKED;
172 break;
173 case AUDIO_FORMAT_PCM_32_BIT:
174 aaudioFormat = AAUDIO_FORMAT_PCM_I32;
175 break;
jiabinca6a3f42022-06-09 20:33:47 +0000176 case AUDIO_FORMAT_IEC61937:
177 aaudioFormat = AAUDIO_FORMAT_IEC61937;
178 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800179 default:
180 aaudioFormat = AAUDIO_FORMAT_INVALID;
Phil Burk0127c1b2018-03-29 13:48:06 -0700181 ALOGE("%s() 0x%08X unrecognized", __func__, androidFormat);
Phil Burk5ed503c2017-02-01 09:38:15 -0800182 break;
183 }
184 return aaudioFormat;
185}
186
Phil Burkd4ccc622017-12-20 15:32:44 -0800187// Make a message string from the condition.
188#define STATIC_ASSERT(condition) static_assert(condition, #condition)
189
190audio_usage_t AAudioConvert_usageToInternal(aaudio_usage_t usage) {
191 // The public aaudio_content_type_t constants are supposed to have the same
192 // values as the internal audio_content_type_t values.
193 STATIC_ASSERT(AAUDIO_USAGE_MEDIA == AUDIO_USAGE_MEDIA);
194 STATIC_ASSERT(AAUDIO_USAGE_VOICE_COMMUNICATION == AUDIO_USAGE_VOICE_COMMUNICATION);
195 STATIC_ASSERT(AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING
196 == AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING);
197 STATIC_ASSERT(AAUDIO_USAGE_ALARM == AUDIO_USAGE_ALARM);
198 STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION == AUDIO_USAGE_NOTIFICATION);
199 STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION_RINGTONE
200 == AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE);
201 STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION_EVENT == AUDIO_USAGE_NOTIFICATION_EVENT);
202 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY);
203 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE
204 == AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE);
205 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_SONIFICATION == AUDIO_USAGE_ASSISTANCE_SONIFICATION);
206 STATIC_ASSERT(AAUDIO_USAGE_GAME == AUDIO_USAGE_GAME);
207 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANT == AUDIO_USAGE_ASSISTANT);
Hayden Gomes3e8bbb92020-01-10 13:37:05 -0800208 STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_EMERGENCY == AUDIO_USAGE_EMERGENCY);
209 STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_SAFETY == AUDIO_USAGE_SAFETY);
210 STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS == AUDIO_USAGE_VEHICLE_STATUS);
211 STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT == AUDIO_USAGE_ANNOUNCEMENT);
Phil Burkd4ccc622017-12-20 15:32:44 -0800212 if (usage == AAUDIO_UNSPECIFIED) {
213 usage = AAUDIO_USAGE_MEDIA;
214 }
215 return (audio_usage_t) usage; // same value
216}
217
218audio_content_type_t AAudioConvert_contentTypeToInternal(aaudio_content_type_t contentType) {
219 // The public aaudio_content_type_t constants are supposed to have the same
220 // values as the internal audio_content_type_t values.
221 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_MUSIC == AUDIO_CONTENT_TYPE_MUSIC);
222 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_SPEECH == AUDIO_CONTENT_TYPE_SPEECH);
223 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_SONIFICATION == AUDIO_CONTENT_TYPE_SONIFICATION);
224 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_MOVIE == AUDIO_CONTENT_TYPE_MOVIE);
225 if (contentType == AAUDIO_UNSPECIFIED) {
226 contentType = AAUDIO_CONTENT_TYPE_MUSIC;
227 }
228 return (audio_content_type_t) contentType; // same value
229}
230
231audio_source_t AAudioConvert_inputPresetToAudioSource(aaudio_input_preset_t preset) {
232 // The public aaudio_input_preset_t constants are supposed to have the same
233 // values as the internal audio_source_t values.
234 STATIC_ASSERT(AAUDIO_UNSPECIFIED == AUDIO_SOURCE_DEFAULT);
235 STATIC_ASSERT(AAUDIO_INPUT_PRESET_GENERIC == AUDIO_SOURCE_MIC);
236 STATIC_ASSERT(AAUDIO_INPUT_PRESET_CAMCORDER == AUDIO_SOURCE_CAMCORDER);
237 STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_RECOGNITION == AUDIO_SOURCE_VOICE_RECOGNITION);
238 STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION == AUDIO_SOURCE_VOICE_COMMUNICATION);
239 STATIC_ASSERT(AAUDIO_INPUT_PRESET_UNPROCESSED == AUDIO_SOURCE_UNPROCESSED);
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800240 STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE == AUDIO_SOURCE_VOICE_PERFORMANCE);
Phil Burkd4ccc622017-12-20 15:32:44 -0800241 if (preset == AAUDIO_UNSPECIFIED) {
Phil Burkeaef9b92018-01-18 09:09:42 -0800242 preset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
Phil Burkd4ccc622017-12-20 15:32:44 -0800243 }
244 return (audio_source_t) preset; // same value
245}
246
Kevin Rocard68646ba2019-03-20 13:26:49 -0700247audio_flags_mask_t AAudioConvert_allowCapturePolicyToAudioFlagsMask(
Jean-Michel Trivi656bfdc2021-09-20 18:42:37 -0700248 aaudio_allowed_capture_policy_t policy,
249 aaudio_spatialization_behavior_t spatializationBehavior,
250 bool isContentSpatialized) {
251 audio_flags_mask_t flagsMask = AUDIO_FLAG_NONE;
Kevin Rocard68646ba2019-03-20 13:26:49 -0700252 switch (policy) {
253 case AAUDIO_UNSPECIFIED:
254 case AAUDIO_ALLOW_CAPTURE_BY_ALL:
Jean-Michel Trivi656bfdc2021-09-20 18:42:37 -0700255 // flagsMask is not modified
256 break;
Kevin Rocard68646ba2019-03-20 13:26:49 -0700257 case AAUDIO_ALLOW_CAPTURE_BY_SYSTEM:
Jean-Michel Trivi656bfdc2021-09-20 18:42:37 -0700258 flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_NO_MEDIA_PROJECTION);
259 break;
Kevin Rocard68646ba2019-03-20 13:26:49 -0700260 case AAUDIO_ALLOW_CAPTURE_BY_NONE:
Jean-Michel Trivi656bfdc2021-09-20 18:42:37 -0700261 flagsMask = static_cast<audio_flags_mask_t>(flagsMask |
Mikhail Naganov55773032020-10-01 15:08:13 -0700262 AUDIO_FLAG_NO_MEDIA_PROJECTION | AUDIO_FLAG_NO_SYSTEM_CAPTURE);
Jean-Michel Trivi656bfdc2021-09-20 18:42:37 -0700263 break;
Kevin Rocard68646ba2019-03-20 13:26:49 -0700264 default:
Jean-Michel Trivi656bfdc2021-09-20 18:42:37 -0700265 ALOGE("%s() 0x%08X unrecognized capture policy", __func__, policy);
266 // flagsMask is not modified
Kevin Rocard68646ba2019-03-20 13:26:49 -0700267 }
Jean-Michel Trivi656bfdc2021-09-20 18:42:37 -0700268
269 switch (spatializationBehavior) {
270 case AAUDIO_UNSPECIFIED:
271 case AAUDIO_SPATIALIZATION_BEHAVIOR_AUTO:
272 // flagsMask is not modified
273 break;
274 case AAUDIO_SPATIALIZATION_BEHAVIOR_NEVER:
275 flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_NEVER_SPATIALIZE);
276 break;
277 default:
278 ALOGE("%s() 0x%08X unrecognized spatialization behavior",
279 __func__, spatializationBehavior);
280 // flagsMask is not modified
281 }
282
283 if (isContentSpatialized) {
284 flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_CONTENT_SPATIALIZED);
285 }
286
287 return flagsMask;
Kevin Rocard68646ba2019-03-20 13:26:49 -0700288}
289
Eric Laurentd17c8502019-10-24 15:58:35 -0700290audio_flags_mask_t AAudioConvert_privacySensitiveToAudioFlagsMask(
291 bool privacySensitive) {
292 return privacySensitive ? AUDIO_FLAG_CAPTURE_PRIVATE : AUDIO_FLAG_NONE;
293}
294
jiabina9094092021-06-28 20:36:45 +0000295audio_channel_mask_t AAudioConvert_aaudioToAndroidChannelLayoutMask(
296 aaudio_channel_mask_t channelMask, bool isInput) {
297 if (isInput) {
298 switch (channelMask) {
299 case AAUDIO_CHANNEL_MONO:
300 return AUDIO_CHANNEL_IN_MONO;
301 case AAUDIO_CHANNEL_STEREO:
302 return AUDIO_CHANNEL_IN_STEREO;
303 case AAUDIO_CHANNEL_FRONT_BACK:
304 return AUDIO_CHANNEL_IN_FRONT_BACK;
305 case AAUDIO_CHANNEL_2POINT0POINT2:
306 return AUDIO_CHANNEL_IN_2POINT0POINT2;
307 case AAUDIO_CHANNEL_2POINT1POINT2:
308 return AUDIO_CHANNEL_IN_2POINT1POINT2;
309 case AAUDIO_CHANNEL_3POINT0POINT2:
310 return AUDIO_CHANNEL_IN_3POINT0POINT2;
311 case AAUDIO_CHANNEL_3POINT1POINT2:
312 return AUDIO_CHANNEL_IN_3POINT1POINT2;
313 case AAUDIO_CHANNEL_5POINT1:
314 return AUDIO_CHANNEL_IN_5POINT1;
315 default:
316 ALOGE("%s() %#x unrecognized", __func__, channelMask);
317 return AUDIO_CHANNEL_INVALID;
318 }
319 } else {
320 switch (channelMask) {
321 case AAUDIO_CHANNEL_MONO:
322 return AUDIO_CHANNEL_OUT_MONO;
323 case AAUDIO_CHANNEL_STEREO:
324 return AUDIO_CHANNEL_OUT_STEREO;
325 case AAUDIO_CHANNEL_2POINT1:
326 return AUDIO_CHANNEL_OUT_2POINT1;
327 case AAUDIO_CHANNEL_TRI:
328 return AUDIO_CHANNEL_OUT_TRI;
329 case AAUDIO_CHANNEL_TRI_BACK:
330 return AUDIO_CHANNEL_OUT_TRI_BACK;
331 case AAUDIO_CHANNEL_3POINT1:
332 return AUDIO_CHANNEL_OUT_3POINT1;
333 case AAUDIO_CHANNEL_2POINT0POINT2:
334 return AUDIO_CHANNEL_OUT_2POINT0POINT2;
335 case AAUDIO_CHANNEL_2POINT1POINT2:
336 return AUDIO_CHANNEL_OUT_2POINT1POINT2;
337 case AAUDIO_CHANNEL_3POINT0POINT2:
338 return AUDIO_CHANNEL_OUT_3POINT0POINT2;
339 case AAUDIO_CHANNEL_3POINT1POINT2:
340 return AUDIO_CHANNEL_OUT_3POINT1POINT2;
341 case AAUDIO_CHANNEL_QUAD:
342 return AUDIO_CHANNEL_OUT_QUAD;
343 case AAUDIO_CHANNEL_QUAD_SIDE:
344 return AUDIO_CHANNEL_OUT_QUAD_SIDE;
345 case AAUDIO_CHANNEL_SURROUND:
346 return AUDIO_CHANNEL_OUT_SURROUND;
347 case AAUDIO_CHANNEL_PENTA:
348 return AUDIO_CHANNEL_OUT_PENTA;
349 case AAUDIO_CHANNEL_5POINT1:
350 return AUDIO_CHANNEL_OUT_5POINT1;
351 case AAUDIO_CHANNEL_5POINT1_SIDE:
352 return AUDIO_CHANNEL_OUT_5POINT1_SIDE;
353 case AAUDIO_CHANNEL_5POINT1POINT2:
354 return AUDIO_CHANNEL_OUT_5POINT1POINT2;
355 case AAUDIO_CHANNEL_5POINT1POINT4:
356 return AUDIO_CHANNEL_OUT_5POINT1POINT4;
357 case AAUDIO_CHANNEL_6POINT1:
358 return AUDIO_CHANNEL_OUT_6POINT1;
359 case AAUDIO_CHANNEL_7POINT1:
360 return AUDIO_CHANNEL_OUT_7POINT1;
361 case AAUDIO_CHANNEL_7POINT1POINT2:
362 return AUDIO_CHANNEL_OUT_7POINT1POINT2;
363 case AAUDIO_CHANNEL_7POINT1POINT4:
364 return AUDIO_CHANNEL_OUT_7POINT1POINT4;
365 // TODO: add 9point1point4 and 9point1point6 when they are added in audio-hal-enums.h
366 // case AAUDIO_CHANNEL_9POINT1POINT4:
367 // return AUDIO_CHANNEL_OUT_9POINT1POINT4;
368 // case AAUDIO_CHANNEL_9POINT1POINT6:
369 // return AUDIO_CHANNEL_OUT_9POINT1POINT6;
370 default:
371 ALOGE("%s() %#x unrecognized", __func__, channelMask);
372 return AUDIO_CHANNEL_INVALID;
373 }
374 }
375}
376
377aaudio_channel_mask_t AAudioConvert_androidToAAudioChannelLayoutMask(
378 audio_channel_mask_t channelMask, bool isInput) {
379 if (isInput) {
380 switch (channelMask) {
381 case AUDIO_CHANNEL_IN_MONO:
382 return AAUDIO_CHANNEL_MONO;
383 case AUDIO_CHANNEL_IN_STEREO:
384 return AAUDIO_CHANNEL_STEREO;
385 case AUDIO_CHANNEL_IN_FRONT_BACK:
386 return AAUDIO_CHANNEL_FRONT_BACK;
387 case AUDIO_CHANNEL_IN_2POINT0POINT2:
388 return AAUDIO_CHANNEL_2POINT0POINT2;
389 case AUDIO_CHANNEL_IN_2POINT1POINT2:
390 return AAUDIO_CHANNEL_2POINT1POINT2;
391 case AUDIO_CHANNEL_IN_3POINT0POINT2:
392 return AAUDIO_CHANNEL_3POINT0POINT2;
393 case AUDIO_CHANNEL_IN_3POINT1POINT2:
394 return AAUDIO_CHANNEL_3POINT1POINT2;
395 case AUDIO_CHANNEL_IN_5POINT1:
396 return AAUDIO_CHANNEL_5POINT1;
397 default:
398 ALOGE("%s() %#x unrecognized", __func__, channelMask);
399 return AAUDIO_CHANNEL_INVALID;
400 }
401 } else {
402 switch (channelMask) {
403 case AUDIO_CHANNEL_OUT_MONO:
404 return AAUDIO_CHANNEL_MONO;
405 case AUDIO_CHANNEL_OUT_STEREO:
406 return AAUDIO_CHANNEL_STEREO;
407 case AUDIO_CHANNEL_OUT_2POINT1:
408 return AAUDIO_CHANNEL_2POINT1;
409 case AUDIO_CHANNEL_OUT_TRI:
410 return AAUDIO_CHANNEL_TRI;
411 case AUDIO_CHANNEL_OUT_TRI_BACK:
412 return AAUDIO_CHANNEL_TRI_BACK;
413 case AUDIO_CHANNEL_OUT_3POINT1:
414 return AAUDIO_CHANNEL_3POINT1;
415 case AUDIO_CHANNEL_OUT_2POINT0POINT2:
416 return AAUDIO_CHANNEL_2POINT0POINT2;
417 case AUDIO_CHANNEL_OUT_2POINT1POINT2:
418 return AAUDIO_CHANNEL_2POINT1POINT2;
419 case AUDIO_CHANNEL_OUT_3POINT0POINT2:
420 return AAUDIO_CHANNEL_3POINT0POINT2;
421 case AUDIO_CHANNEL_OUT_3POINT1POINT2:
422 return AAUDIO_CHANNEL_3POINT1POINT2;
423 case AUDIO_CHANNEL_OUT_QUAD:
424 return AAUDIO_CHANNEL_QUAD;
425 case AUDIO_CHANNEL_OUT_QUAD_SIDE:
426 return AAUDIO_CHANNEL_QUAD_SIDE;
427 case AUDIO_CHANNEL_OUT_SURROUND:
428 return AAUDIO_CHANNEL_SURROUND;
429 case AUDIO_CHANNEL_OUT_PENTA:
430 return AAUDIO_CHANNEL_PENTA;
431 case AUDIO_CHANNEL_OUT_5POINT1:
432 return AAUDIO_CHANNEL_5POINT1;
433 case AUDIO_CHANNEL_OUT_5POINT1_SIDE:
434 return AAUDIO_CHANNEL_5POINT1_SIDE;
435 case AUDIO_CHANNEL_OUT_5POINT1POINT2:
436 return AAUDIO_CHANNEL_5POINT1POINT2;
437 case AUDIO_CHANNEL_OUT_5POINT1POINT4:
438 return AAUDIO_CHANNEL_5POINT1POINT4;
439 case AUDIO_CHANNEL_OUT_6POINT1:
440 return AAUDIO_CHANNEL_6POINT1;
441 case AUDIO_CHANNEL_OUT_7POINT1:
442 return AAUDIO_CHANNEL_7POINT1;
443 case AUDIO_CHANNEL_OUT_7POINT1POINT2:
444 return AAUDIO_CHANNEL_7POINT1POINT2;
445 case AUDIO_CHANNEL_OUT_7POINT1POINT4:
446 return AAUDIO_CHANNEL_7POINT1POINT4;
447 // TODO: add 9point1point4 and 9point1point6 when they are added in audio-hal-enums.h
448 // case AUDIO_CHANNEL_OUT_9POINT1POINT4:
449 // return AAUDIO_CHANNEL_9POINT1POINT4;
450 // case AUDIO_CHANNEL_OUT_9POINT1POINT6:
451 // return AAUDIO_CHANNEL_9POINT1POINT6;
452 default:
453 ALOGE("%s() %#x unrecognized", __func__, channelMask);
454 return AAUDIO_CHANNEL_INVALID;
455 }
456 }
457}
458
459int32_t AAudioConvert_channelMaskToCount(aaudio_channel_mask_t channelMask) {
460 return __builtin_popcount(channelMask & ~AAUDIO_CHANNEL_BIT_INDEX);
461}
462
463aaudio_channel_mask_t AAudioConvert_channelCountToMask(int32_t channelCount) {
464 if (channelCount < 0 || channelCount > AUDIO_CHANNEL_COUNT_MAX) {
465 return AAUDIO_CHANNEL_INVALID;
466 }
467
468 if (channelCount == 0) {
469 return AAUDIO_UNSPECIFIED;
470 }
471
472 // Return index mask if the channel count is greater than 2.
473 return AAUDIO_CHANNEL_BIT_INDEX | ((1 << channelCount) - 1);
474}
475
476aaudio_channel_mask_t AAudioConvert_androidToAAudioChannelIndexMask(
477 audio_channel_mask_t channelMask) {
478 if (audio_channel_mask_get_representation(channelMask) != AUDIO_CHANNEL_REPRESENTATION_INDEX) {
479 ALOGE("%s() %#x not an index mask", __func__, channelMask);
480 return AAUDIO_CHANNEL_INVALID;
481 }
482 return (channelMask & ~AUDIO_CHANNEL_INDEX_HDR) | AAUDIO_CHANNEL_BIT_INDEX;
483}
484
485audio_channel_mask_t AAudioConvert_aaudioToAndroidChannelIndexMask(
486 aaudio_channel_mask_t channelMask) {
487 if (!AAudio_isChannelIndexMask(channelMask)) {
488 ALOGE("%s() %#x not an index mask", __func__, channelMask);
489 return AUDIO_CHANNEL_INVALID;
490 }
491 return audio_channel_mask_for_index_assignment_from_count(
492 AAudioConvert_channelMaskToCount(channelMask));
493}
494
495aaudio_channel_mask_t AAudioConvert_androidToAAudioChannelMask(
496 audio_channel_mask_t channelMask, bool isInput, bool indexMaskRequired) {
497 if (audio_channel_mask_get_representation(channelMask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
498 return AAudioConvert_androidToAAudioChannelIndexMask(channelMask);
499 }
500 if (indexMaskRequired) {
501 // Require index mask, `channelMask` here is a position mask.
502 const int channelCount = isInput ? audio_channel_count_from_in_mask(channelMask)
503 : audio_channel_count_from_out_mask(channelMask);
504 return AAudioConvert_channelCountToMask(channelCount);
505 }
506 return AAudioConvert_androidToAAudioChannelLayoutMask(channelMask, isInput);
507}
508
509audio_channel_mask_t AAudioConvert_aaudioToAndroidChannelMask(
510 aaudio_channel_mask_t channelMask, bool isInput) {
511 return AAudio_isChannelIndexMask(channelMask)
512 ? AAudioConvert_aaudioToAndroidChannelIndexMask(channelMask)
513 : AAudioConvert_aaudioToAndroidChannelLayoutMask(channelMask, isInput);
514}
515
516bool AAudio_isChannelIndexMask(aaudio_channel_mask_t channelMask) {
517 return (channelMask & AAUDIO_CHANNEL_BIT_INDEX) == AAUDIO_CHANNEL_BIT_INDEX;
518}
519
520audio_channel_mask_t AAudio_getChannelMaskForOpen(
521 aaudio_channel_mask_t channelMask, int32_t samplesPerFrame, bool isInput) {
522 if (channelMask != AAUDIO_UNSPECIFIED) {
523 if (AAudio_isChannelIndexMask(channelMask) && samplesPerFrame <= 2) {
524 // When it is index mask and the count is less than 3, use position mask
525 // instead of index mask for opening a stream. This may need to be revisited
526 // when making channel index mask public.
527 return isInput ? audio_channel_in_mask_from_count(samplesPerFrame)
528 : audio_channel_out_mask_from_count(samplesPerFrame);
529 }
530 return AAudioConvert_aaudioToAndroidChannelMask(channelMask, isInput);
531 }
532
533 // Return stereo when unspecified.
534 return isInput ? AUDIO_CHANNEL_IN_STEREO : AUDIO_CHANNEL_OUT_STEREO;
535}
536
Phil Burk3316d5e2017-02-15 11:23:01 -0800537int32_t AAudioConvert_framesToBytes(int32_t numFrames,
Phil Burk7f680132018-03-12 14:48:06 -0700538 int32_t bytesPerFrame,
539 int32_t *sizeInBytes) {
540 *sizeInBytes = 0;
541
542 if (numFrames < 0 || bytesPerFrame < 0) {
543 ALOGE("negative size, numFrames = %d, frameSize = %d", numFrames, bytesPerFrame);
544 return AAUDIO_ERROR_OUT_OF_RANGE;
545 }
546
547 // Prevent numeric overflow.
548 if (numFrames > (INT32_MAX / bytesPerFrame)) {
Yi Kong0f414de2017-12-15 13:48:50 -0800549 ALOGE("size overflow, numFrames = %d, frameSize = %d", numFrames, bytesPerFrame);
Phil Burk5ed503c2017-02-01 09:38:15 -0800550 return AAUDIO_ERROR_OUT_OF_RANGE;
551 }
Phil Burk7f680132018-03-12 14:48:06 -0700552
Phil Burk5ed503c2017-02-01 09:38:15 -0800553 *sizeInBytes = numFrames * bytesPerFrame;
554 return AAUDIO_OK;
555}
Phil Burkc8f69a02017-05-11 15:53:06 -0700556
Phil Burkfd34a932017-07-19 07:03:52 -0700557int32_t AAudioProperty_getWakeupDelayMicros() {
558 const int32_t minMicros = 0; // arbitrary
559 const int32_t defaultMicros = 200; // arbitrary, based on some observed jitter
560 const int32_t maxMicros = 5000; // arbitrary, probably don't want more than 500
561 int32_t prop = property_get_int32(AAUDIO_PROP_WAKEUP_DELAY_USEC, defaultMicros);
562 if (prop < minMicros) {
563 ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, minMicros);
564 prop = minMicros;
565 } else if (prop > maxMicros) {
566 ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, maxMicros);
567 prop = maxMicros;
568 }
569 return prop;
570}
571
572int32_t AAudioProperty_getMinimumSleepMicros() {
Phil Burk4f578a22022-02-19 00:21:30 +0000573 const int32_t minMicros = 1; // arbitrary
574 // Higher values can increase latency for moderate workloads.
Phil Burkec21f2b2022-04-19 18:52:03 +0000575 // Short values can cause the CPU to short cycle if there is a bug in
576 // calculating the wakeup times.
577 const int32_t defaultMicros = 100; // arbitrary
Phil Burk4f578a22022-02-19 00:21:30 +0000578 const int32_t maxMicros = 200; // arbitrary
Phil Burkfd34a932017-07-19 07:03:52 -0700579 int32_t prop = property_get_int32(AAUDIO_PROP_MINIMUM_SLEEP_USEC, defaultMicros);
580 if (prop < minMicros) {
581 ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, minMicros);
582 prop = minMicros;
583 } else if (prop > maxMicros) {
584 ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, maxMicros);
585 prop = maxMicros;
586 }
587 return prop;
588}
589
Phil Burkb31b66f2019-09-30 09:33:41 -0700590static int32_t AAudioProperty_getMMapOffsetMicros(const char *functionName,
591 const char *propertyName) {
592 const int32_t minMicros = -20000; // arbitrary
593 const int32_t defaultMicros = 0; // arbitrary
594 const int32_t maxMicros = 20000; // arbitrary
595 int32_t prop = property_get_int32(propertyName, defaultMicros);
596 if (prop < minMicros) {
597 ALOGW("%s: clipped %d to %d", functionName, prop, minMicros);
598 prop = minMicros;
599 } else if (prop > maxMicros) {
600 ALOGW("%s: clipped %d to %d", functionName, prop, minMicros);
601 prop = maxMicros;
602 }
603 return prop;
604}
605
606int32_t AAudioProperty_getInputMMapOffsetMicros() {
607 return AAudioProperty_getMMapOffsetMicros(__func__, AAUDIO_PROP_INPUT_MMAP_OFFSET_USEC);
608}
609
610int32_t AAudioProperty_getOutputMMapOffsetMicros() {
611 return AAudioProperty_getMMapOffsetMicros(__func__, AAUDIO_PROP_OUTPUT_MMAP_OFFSET_USEC);
612}
613
Phil Burkef34be52019-09-26 13:45:25 -0700614int32_t AAudioProperty_getLogMask() {
615 return property_get_int32(AAUDIO_PROP_LOG_MASK, 0);
616}
617
Phil Burk5cc83c32017-11-28 15:43:18 -0800618aaudio_result_t AAudio_isFlushAllowed(aaudio_stream_state_t state) {
619 aaudio_result_t result = AAUDIO_OK;
620 switch (state) {
621// Proceed with flushing.
622 case AAUDIO_STREAM_STATE_OPEN:
623 case AAUDIO_STREAM_STATE_PAUSED:
624 case AAUDIO_STREAM_STATE_STOPPED:
625 case AAUDIO_STREAM_STATE_FLUSHED:
626 break;
627
628// Transition from one inactive state to another.
629 case AAUDIO_STREAM_STATE_STARTING:
630 case AAUDIO_STREAM_STATE_STARTED:
631 case AAUDIO_STREAM_STATE_STOPPING:
632 case AAUDIO_STREAM_STATE_PAUSING:
633 case AAUDIO_STREAM_STATE_FLUSHING:
634 case AAUDIO_STREAM_STATE_CLOSING:
635 case AAUDIO_STREAM_STATE_CLOSED:
636 case AAUDIO_STREAM_STATE_DISCONNECTED:
637 default:
638 ALOGE("can only flush stream when PAUSED, OPEN or STOPPED, state = %s",
dimitry2d2f17c2019-07-17 13:55:16 +0200639 aaudio::AudioGlobal_convertStreamStateToText(state));
Phil Burk5cc83c32017-11-28 15:43:18 -0800640 result = AAUDIO_ERROR_INVALID_STATE;
641 break;
642 }
643 return result;
644}
jiabin4a341862022-09-20 17:58:37 +0000645
646namespace {
647
648aaudio_policy_t aidl2legacy_aaudio_policy(AudioMMapPolicy aidl) {
649 switch (aidl) {
650 case AudioMMapPolicy::NEVER:
651 return AAUDIO_POLICY_NEVER;
652 case AudioMMapPolicy::AUTO:
653 return AAUDIO_POLICY_AUTO;
654 case AudioMMapPolicy::ALWAYS:
655 return AAUDIO_POLICY_ALWAYS;
656 case AudioMMapPolicy::UNSPECIFIED:
657 default:
658 return AAUDIO_UNSPECIFIED;
659 }
660}
661
662} // namespace
663
664aaudio_policy_t AAudio_getAAudioPolicy(const std::vector<AudioMMapPolicyInfo>& policyInfos) {
665 if (policyInfos.empty()) return AAUDIO_POLICY_AUTO;
666 for (size_t i = 1; i < policyInfos.size(); ++i) {
667 if (policyInfos.at(i).mmapPolicy != policyInfos.at(0).mmapPolicy) {
668 return AAUDIO_POLICY_AUTO;
669 }
670 }
671 return aidl2legacy_aaudio_policy(policyInfos.at(0).mmapPolicy);
672}