blob: a197ced8e653bce1f4637d01449f7fd5bb1a8202 [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
19#include <utils/Log.h>
20
Phil Burkc8f69a02017-05-11 15:53:06 -070021#include <cutils/properties.h>
Phil Burk5ed503c2017-02-01 09:38:15 -080022#include <stdint.h>
23#include <sys/types.h>
24#include <utils/Errors.h>
25
Phil Burka4eb0d82017-04-12 15:44:06 -070026#include "aaudio/AAudio.h"
dimitry2d2f17c2019-07-17 13:55:16 +020027#include "core/AudioGlobal.h"
Phil Burkd04aeea2017-05-23 13:56:41 -070028#include <aaudio/AAudioTesting.h>
Phil Burkbba09002017-11-29 13:39:44 -080029#include <math.h>
Mikhail Naganovf33115d2020-09-25 23:03:05 +000030#include <system/audio.h>
Phil Burk41f19d82018-02-13 14:59:10 -080031#include <assert.h>
Phil Burkd04aeea2017-05-23 13:56:41 -070032
33#include "utility/AAudioUtilities.h"
Phil Burk5ed503c2017-02-01 09:38:15 -080034
35using namespace android;
36
Phil Burk5ed503c2017-02-01 09:38:15 -080037status_t AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result) {
38 // This covers the case for AAUDIO_OK and for positive results.
39 if (result >= 0) {
40 return result;
41 }
42 status_t status;
43 switch (result) {
44 case AAUDIO_ERROR_DISCONNECTED:
Eric Laurenta2f296e2017-06-21 18:51:47 -070045 case AAUDIO_ERROR_NO_SERVICE:
Phil Burk5ed503c2017-02-01 09:38:15 -080046 status = DEAD_OBJECT;
47 break;
Eric Laurenta2f296e2017-06-21 18:51:47 -070048 case AAUDIO_ERROR_INVALID_HANDLE:
49 status = BAD_TYPE;
50 break;
Phil Burk5ed503c2017-02-01 09:38:15 -080051 case AAUDIO_ERROR_INVALID_STATE:
52 status = INVALID_OPERATION;
53 break;
Phil Burk71f35bb2017-04-13 16:05:07 -070054 case AAUDIO_ERROR_INVALID_RATE:
55 case AAUDIO_ERROR_INVALID_FORMAT:
Phil Burk5ed503c2017-02-01 09:38:15 -080056 case AAUDIO_ERROR_ILLEGAL_ARGUMENT:
Phil Burk5204d312017-05-04 17:16:13 -070057 case AAUDIO_ERROR_OUT_OF_RANGE:
Phil Burk5ed503c2017-02-01 09:38:15 -080058 status = BAD_VALUE;
59 break;
60 case AAUDIO_ERROR_WOULD_BLOCK:
61 status = WOULD_BLOCK;
62 break;
Phil Burk5204d312017-05-04 17:16:13 -070063 case AAUDIO_ERROR_NULL:
64 status = UNEXPECTED_NULL;
65 break;
Phil Burk940083c2017-07-17 17:00:02 -070066 case AAUDIO_ERROR_UNAVAILABLE:
67 status = NOT_ENOUGH_DATA;
68 break;
69
Phil Burk5204d312017-05-04 17:16:13 -070070 // TODO translate these result codes
Phil Burk5204d312017-05-04 17:16:13 -070071 case AAUDIO_ERROR_INTERNAL:
Phil Burk5204d312017-05-04 17:16:13 -070072 case AAUDIO_ERROR_UNIMPLEMENTED:
Phil Burk5204d312017-05-04 17:16:13 -070073 case AAUDIO_ERROR_NO_FREE_HANDLES:
74 case AAUDIO_ERROR_NO_MEMORY:
75 case AAUDIO_ERROR_TIMEOUT:
Phil Burk5ed503c2017-02-01 09:38:15 -080076 default:
77 status = UNKNOWN_ERROR;
78 break;
79 }
80 return status;
81}
82
83aaudio_result_t AAudioConvert_androidToAAudioResult(status_t status) {
84 // This covers the case for OK and for positive result.
85 if (status >= 0) {
86 return status;
87 }
88 aaudio_result_t result;
89 switch (status) {
90 case BAD_TYPE:
91 result = AAUDIO_ERROR_INVALID_HANDLE;
92 break;
93 case DEAD_OBJECT:
Phil Burk71f35bb2017-04-13 16:05:07 -070094 result = AAUDIO_ERROR_NO_SERVICE;
Phil Burk5ed503c2017-02-01 09:38:15 -080095 break;
96 case INVALID_OPERATION:
97 result = AAUDIO_ERROR_INVALID_STATE;
98 break;
Eric Laurenta2f296e2017-06-21 18:51:47 -070099 case UNEXPECTED_NULL:
100 result = AAUDIO_ERROR_NULL;
101 break;
102 case BAD_VALUE:
103 result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
104 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800105 case WOULD_BLOCK:
106 result = AAUDIO_ERROR_WOULD_BLOCK;
107 break;
Phil Burk940083c2017-07-17 17:00:02 -0700108 case NOT_ENOUGH_DATA:
109 result = AAUDIO_ERROR_UNAVAILABLE;
110 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800111 default:
112 result = AAUDIO_ERROR_INTERNAL;
113 break;
114 }
115 return result;
116}
117
Phil Burk4e1af9f2018-01-03 15:54:35 -0800118audio_session_t AAudioConvert_aaudioToAndroidSessionId(aaudio_session_id_t sessionId) {
Phil Burk67fdd892018-01-23 15:28:55 -0800119 // If not a regular sessionId then convert to a safe value of AUDIO_SESSION_ALLOCATE.
120 return (sessionId == AAUDIO_SESSION_ID_ALLOCATE || sessionId == AAUDIO_SESSION_ID_NONE)
Phil Burk4e1af9f2018-01-03 15:54:35 -0800121 ? AUDIO_SESSION_ALLOCATE
122 : (audio_session_t) sessionId;
123}
124
Phil Burk9dca9822017-05-26 14:27:43 -0700125audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudioFormat) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800126 audio_format_t androidFormat;
127 switch (aaudioFormat) {
Phil Burk0127c1b2018-03-29 13:48:06 -0700128 case AAUDIO_FORMAT_UNSPECIFIED:
129 androidFormat = AUDIO_FORMAT_DEFAULT;
130 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800131 case AAUDIO_FORMAT_PCM_I16:
132 androidFormat = AUDIO_FORMAT_PCM_16_BIT;
133 break;
134 case AAUDIO_FORMAT_PCM_FLOAT:
135 androidFormat = AUDIO_FORMAT_PCM_FLOAT;
136 break;
Phil Burk04e805b2018-03-27 09:13:53 -0700137 case AAUDIO_FORMAT_PCM_I24_PACKED:
138 androidFormat = AUDIO_FORMAT_PCM_24_BIT_PACKED;
139 break;
140 case AAUDIO_FORMAT_PCM_I32:
141 androidFormat = AUDIO_FORMAT_PCM_32_BIT;
142 break;
jiabinca6a3f42022-06-09 20:33:47 +0000143 case AAUDIO_FORMAT_IEC61937:
144 androidFormat = AUDIO_FORMAT_IEC61937;
145 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800146 default:
Phil Burk0127c1b2018-03-29 13:48:06 -0700147 androidFormat = AUDIO_FORMAT_INVALID;
148 ALOGE("%s() 0x%08X unrecognized", __func__, aaudioFormat);
Phil Burk5ed503c2017-02-01 09:38:15 -0800149 break;
150 }
151 return androidFormat;
152}
153
Phil Burk9dca9822017-05-26 14:27:43 -0700154aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t androidFormat) {
Phil Burk0127c1b2018-03-29 13:48:06 -0700155 aaudio_format_t aaudioFormat;
Phil Burk5ed503c2017-02-01 09:38:15 -0800156 switch (androidFormat) {
Phil Burk0127c1b2018-03-29 13:48:06 -0700157 case AUDIO_FORMAT_DEFAULT:
158 aaudioFormat = AAUDIO_FORMAT_UNSPECIFIED;
159 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800160 case AUDIO_FORMAT_PCM_16_BIT:
161 aaudioFormat = AAUDIO_FORMAT_PCM_I16;
162 break;
163 case AUDIO_FORMAT_PCM_FLOAT:
164 aaudioFormat = AAUDIO_FORMAT_PCM_FLOAT;
165 break;
Phil Burk04e805b2018-03-27 09:13:53 -0700166 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
167 aaudioFormat = AAUDIO_FORMAT_PCM_I24_PACKED;
168 break;
169 case AUDIO_FORMAT_PCM_32_BIT:
170 aaudioFormat = AAUDIO_FORMAT_PCM_I32;
171 break;
jiabinca6a3f42022-06-09 20:33:47 +0000172 case AUDIO_FORMAT_IEC61937:
173 aaudioFormat = AAUDIO_FORMAT_IEC61937;
174 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800175 default:
176 aaudioFormat = AAUDIO_FORMAT_INVALID;
Phil Burk0127c1b2018-03-29 13:48:06 -0700177 ALOGE("%s() 0x%08X unrecognized", __func__, androidFormat);
Phil Burk5ed503c2017-02-01 09:38:15 -0800178 break;
179 }
180 return aaudioFormat;
181}
182
Phil Burkd4ccc622017-12-20 15:32:44 -0800183// Make a message string from the condition.
184#define STATIC_ASSERT(condition) static_assert(condition, #condition)
185
186audio_usage_t AAudioConvert_usageToInternal(aaudio_usage_t usage) {
187 // The public aaudio_content_type_t constants are supposed to have the same
188 // values as the internal audio_content_type_t values.
189 STATIC_ASSERT(AAUDIO_USAGE_MEDIA == AUDIO_USAGE_MEDIA);
190 STATIC_ASSERT(AAUDIO_USAGE_VOICE_COMMUNICATION == AUDIO_USAGE_VOICE_COMMUNICATION);
191 STATIC_ASSERT(AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING
192 == AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING);
193 STATIC_ASSERT(AAUDIO_USAGE_ALARM == AUDIO_USAGE_ALARM);
194 STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION == AUDIO_USAGE_NOTIFICATION);
195 STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION_RINGTONE
196 == AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE);
197 STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION_EVENT == AUDIO_USAGE_NOTIFICATION_EVENT);
198 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY);
199 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE
200 == AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE);
201 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_SONIFICATION == AUDIO_USAGE_ASSISTANCE_SONIFICATION);
202 STATIC_ASSERT(AAUDIO_USAGE_GAME == AUDIO_USAGE_GAME);
203 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANT == AUDIO_USAGE_ASSISTANT);
Hayden Gomes3e8bbb92020-01-10 13:37:05 -0800204 STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_EMERGENCY == AUDIO_USAGE_EMERGENCY);
205 STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_SAFETY == AUDIO_USAGE_SAFETY);
206 STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS == AUDIO_USAGE_VEHICLE_STATUS);
207 STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT == AUDIO_USAGE_ANNOUNCEMENT);
Phil Burkd4ccc622017-12-20 15:32:44 -0800208 if (usage == AAUDIO_UNSPECIFIED) {
209 usage = AAUDIO_USAGE_MEDIA;
210 }
211 return (audio_usage_t) usage; // same value
212}
213
214audio_content_type_t AAudioConvert_contentTypeToInternal(aaudio_content_type_t contentType) {
215 // The public aaudio_content_type_t constants are supposed to have the same
216 // values as the internal audio_content_type_t values.
217 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_MUSIC == AUDIO_CONTENT_TYPE_MUSIC);
218 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_SPEECH == AUDIO_CONTENT_TYPE_SPEECH);
219 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_SONIFICATION == AUDIO_CONTENT_TYPE_SONIFICATION);
220 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_MOVIE == AUDIO_CONTENT_TYPE_MOVIE);
221 if (contentType == AAUDIO_UNSPECIFIED) {
222 contentType = AAUDIO_CONTENT_TYPE_MUSIC;
223 }
224 return (audio_content_type_t) contentType; // same value
225}
226
227audio_source_t AAudioConvert_inputPresetToAudioSource(aaudio_input_preset_t preset) {
228 // The public aaudio_input_preset_t constants are supposed to have the same
229 // values as the internal audio_source_t values.
230 STATIC_ASSERT(AAUDIO_UNSPECIFIED == AUDIO_SOURCE_DEFAULT);
231 STATIC_ASSERT(AAUDIO_INPUT_PRESET_GENERIC == AUDIO_SOURCE_MIC);
232 STATIC_ASSERT(AAUDIO_INPUT_PRESET_CAMCORDER == AUDIO_SOURCE_CAMCORDER);
233 STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_RECOGNITION == AUDIO_SOURCE_VOICE_RECOGNITION);
234 STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION == AUDIO_SOURCE_VOICE_COMMUNICATION);
235 STATIC_ASSERT(AAUDIO_INPUT_PRESET_UNPROCESSED == AUDIO_SOURCE_UNPROCESSED);
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800236 STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE == AUDIO_SOURCE_VOICE_PERFORMANCE);
Phil Burkd4ccc622017-12-20 15:32:44 -0800237 if (preset == AAUDIO_UNSPECIFIED) {
Phil Burkeaef9b92018-01-18 09:09:42 -0800238 preset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
Phil Burkd4ccc622017-12-20 15:32:44 -0800239 }
240 return (audio_source_t) preset; // same value
241}
242
Kevin Rocard68646ba2019-03-20 13:26:49 -0700243audio_flags_mask_t AAudioConvert_allowCapturePolicyToAudioFlagsMask(
Jean-Michel Trivi656bfdc2021-09-20 18:42:37 -0700244 aaudio_allowed_capture_policy_t policy,
245 aaudio_spatialization_behavior_t spatializationBehavior,
246 bool isContentSpatialized) {
247 audio_flags_mask_t flagsMask = AUDIO_FLAG_NONE;
Kevin Rocard68646ba2019-03-20 13:26:49 -0700248 switch (policy) {
249 case AAUDIO_UNSPECIFIED:
250 case AAUDIO_ALLOW_CAPTURE_BY_ALL:
Jean-Michel Trivi656bfdc2021-09-20 18:42:37 -0700251 // flagsMask is not modified
252 break;
Kevin Rocard68646ba2019-03-20 13:26:49 -0700253 case AAUDIO_ALLOW_CAPTURE_BY_SYSTEM:
Jean-Michel Trivi656bfdc2021-09-20 18:42:37 -0700254 flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_NO_MEDIA_PROJECTION);
255 break;
Kevin Rocard68646ba2019-03-20 13:26:49 -0700256 case AAUDIO_ALLOW_CAPTURE_BY_NONE:
Jean-Michel Trivi656bfdc2021-09-20 18:42:37 -0700257 flagsMask = static_cast<audio_flags_mask_t>(flagsMask |
Mikhail Naganov55773032020-10-01 15:08:13 -0700258 AUDIO_FLAG_NO_MEDIA_PROJECTION | AUDIO_FLAG_NO_SYSTEM_CAPTURE);
Jean-Michel Trivi656bfdc2021-09-20 18:42:37 -0700259 break;
Kevin Rocard68646ba2019-03-20 13:26:49 -0700260 default:
Jean-Michel Trivi656bfdc2021-09-20 18:42:37 -0700261 ALOGE("%s() 0x%08X unrecognized capture policy", __func__, policy);
262 // flagsMask is not modified
Kevin Rocard68646ba2019-03-20 13:26:49 -0700263 }
Jean-Michel Trivi656bfdc2021-09-20 18:42:37 -0700264
265 switch (spatializationBehavior) {
266 case AAUDIO_UNSPECIFIED:
267 case AAUDIO_SPATIALIZATION_BEHAVIOR_AUTO:
268 // flagsMask is not modified
269 break;
270 case AAUDIO_SPATIALIZATION_BEHAVIOR_NEVER:
271 flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_NEVER_SPATIALIZE);
272 break;
273 default:
274 ALOGE("%s() 0x%08X unrecognized spatialization behavior",
275 __func__, spatializationBehavior);
276 // flagsMask is not modified
277 }
278
279 if (isContentSpatialized) {
280 flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_CONTENT_SPATIALIZED);
281 }
282
283 return flagsMask;
Kevin Rocard68646ba2019-03-20 13:26:49 -0700284}
285
Eric Laurentd17c8502019-10-24 15:58:35 -0700286audio_flags_mask_t AAudioConvert_privacySensitiveToAudioFlagsMask(
287 bool privacySensitive) {
288 return privacySensitive ? AUDIO_FLAG_CAPTURE_PRIVATE : AUDIO_FLAG_NONE;
289}
290
jiabina9094092021-06-28 20:36:45 +0000291audio_channel_mask_t AAudioConvert_aaudioToAndroidChannelLayoutMask(
292 aaudio_channel_mask_t channelMask, bool isInput) {
293 if (isInput) {
294 switch (channelMask) {
295 case AAUDIO_CHANNEL_MONO:
296 return AUDIO_CHANNEL_IN_MONO;
297 case AAUDIO_CHANNEL_STEREO:
298 return AUDIO_CHANNEL_IN_STEREO;
299 case AAUDIO_CHANNEL_FRONT_BACK:
300 return AUDIO_CHANNEL_IN_FRONT_BACK;
301 case AAUDIO_CHANNEL_2POINT0POINT2:
302 return AUDIO_CHANNEL_IN_2POINT0POINT2;
303 case AAUDIO_CHANNEL_2POINT1POINT2:
304 return AUDIO_CHANNEL_IN_2POINT1POINT2;
305 case AAUDIO_CHANNEL_3POINT0POINT2:
306 return AUDIO_CHANNEL_IN_3POINT0POINT2;
307 case AAUDIO_CHANNEL_3POINT1POINT2:
308 return AUDIO_CHANNEL_IN_3POINT1POINT2;
309 case AAUDIO_CHANNEL_5POINT1:
310 return AUDIO_CHANNEL_IN_5POINT1;
311 default:
312 ALOGE("%s() %#x unrecognized", __func__, channelMask);
313 return AUDIO_CHANNEL_INVALID;
314 }
315 } else {
316 switch (channelMask) {
317 case AAUDIO_CHANNEL_MONO:
318 return AUDIO_CHANNEL_OUT_MONO;
319 case AAUDIO_CHANNEL_STEREO:
320 return AUDIO_CHANNEL_OUT_STEREO;
321 case AAUDIO_CHANNEL_2POINT1:
322 return AUDIO_CHANNEL_OUT_2POINT1;
323 case AAUDIO_CHANNEL_TRI:
324 return AUDIO_CHANNEL_OUT_TRI;
325 case AAUDIO_CHANNEL_TRI_BACK:
326 return AUDIO_CHANNEL_OUT_TRI_BACK;
327 case AAUDIO_CHANNEL_3POINT1:
328 return AUDIO_CHANNEL_OUT_3POINT1;
329 case AAUDIO_CHANNEL_2POINT0POINT2:
330 return AUDIO_CHANNEL_OUT_2POINT0POINT2;
331 case AAUDIO_CHANNEL_2POINT1POINT2:
332 return AUDIO_CHANNEL_OUT_2POINT1POINT2;
333 case AAUDIO_CHANNEL_3POINT0POINT2:
334 return AUDIO_CHANNEL_OUT_3POINT0POINT2;
335 case AAUDIO_CHANNEL_3POINT1POINT2:
336 return AUDIO_CHANNEL_OUT_3POINT1POINT2;
337 case AAUDIO_CHANNEL_QUAD:
338 return AUDIO_CHANNEL_OUT_QUAD;
339 case AAUDIO_CHANNEL_QUAD_SIDE:
340 return AUDIO_CHANNEL_OUT_QUAD_SIDE;
341 case AAUDIO_CHANNEL_SURROUND:
342 return AUDIO_CHANNEL_OUT_SURROUND;
343 case AAUDIO_CHANNEL_PENTA:
344 return AUDIO_CHANNEL_OUT_PENTA;
345 case AAUDIO_CHANNEL_5POINT1:
346 return AUDIO_CHANNEL_OUT_5POINT1;
347 case AAUDIO_CHANNEL_5POINT1_SIDE:
348 return AUDIO_CHANNEL_OUT_5POINT1_SIDE;
349 case AAUDIO_CHANNEL_5POINT1POINT2:
350 return AUDIO_CHANNEL_OUT_5POINT1POINT2;
351 case AAUDIO_CHANNEL_5POINT1POINT4:
352 return AUDIO_CHANNEL_OUT_5POINT1POINT4;
353 case AAUDIO_CHANNEL_6POINT1:
354 return AUDIO_CHANNEL_OUT_6POINT1;
355 case AAUDIO_CHANNEL_7POINT1:
356 return AUDIO_CHANNEL_OUT_7POINT1;
357 case AAUDIO_CHANNEL_7POINT1POINT2:
358 return AUDIO_CHANNEL_OUT_7POINT1POINT2;
359 case AAUDIO_CHANNEL_7POINT1POINT4:
360 return AUDIO_CHANNEL_OUT_7POINT1POINT4;
361 // TODO: add 9point1point4 and 9point1point6 when they are added in audio-hal-enums.h
362 // case AAUDIO_CHANNEL_9POINT1POINT4:
363 // return AUDIO_CHANNEL_OUT_9POINT1POINT4;
364 // case AAUDIO_CHANNEL_9POINT1POINT6:
365 // return AUDIO_CHANNEL_OUT_9POINT1POINT6;
366 default:
367 ALOGE("%s() %#x unrecognized", __func__, channelMask);
368 return AUDIO_CHANNEL_INVALID;
369 }
370 }
371}
372
373aaudio_channel_mask_t AAudioConvert_androidToAAudioChannelLayoutMask(
374 audio_channel_mask_t channelMask, bool isInput) {
375 if (isInput) {
376 switch (channelMask) {
377 case AUDIO_CHANNEL_IN_MONO:
378 return AAUDIO_CHANNEL_MONO;
379 case AUDIO_CHANNEL_IN_STEREO:
380 return AAUDIO_CHANNEL_STEREO;
381 case AUDIO_CHANNEL_IN_FRONT_BACK:
382 return AAUDIO_CHANNEL_FRONT_BACK;
383 case AUDIO_CHANNEL_IN_2POINT0POINT2:
384 return AAUDIO_CHANNEL_2POINT0POINT2;
385 case AUDIO_CHANNEL_IN_2POINT1POINT2:
386 return AAUDIO_CHANNEL_2POINT1POINT2;
387 case AUDIO_CHANNEL_IN_3POINT0POINT2:
388 return AAUDIO_CHANNEL_3POINT0POINT2;
389 case AUDIO_CHANNEL_IN_3POINT1POINT2:
390 return AAUDIO_CHANNEL_3POINT1POINT2;
391 case AUDIO_CHANNEL_IN_5POINT1:
392 return AAUDIO_CHANNEL_5POINT1;
393 default:
394 ALOGE("%s() %#x unrecognized", __func__, channelMask);
395 return AAUDIO_CHANNEL_INVALID;
396 }
397 } else {
398 switch (channelMask) {
399 case AUDIO_CHANNEL_OUT_MONO:
400 return AAUDIO_CHANNEL_MONO;
401 case AUDIO_CHANNEL_OUT_STEREO:
402 return AAUDIO_CHANNEL_STEREO;
403 case AUDIO_CHANNEL_OUT_2POINT1:
404 return AAUDIO_CHANNEL_2POINT1;
405 case AUDIO_CHANNEL_OUT_TRI:
406 return AAUDIO_CHANNEL_TRI;
407 case AUDIO_CHANNEL_OUT_TRI_BACK:
408 return AAUDIO_CHANNEL_TRI_BACK;
409 case AUDIO_CHANNEL_OUT_3POINT1:
410 return AAUDIO_CHANNEL_3POINT1;
411 case AUDIO_CHANNEL_OUT_2POINT0POINT2:
412 return AAUDIO_CHANNEL_2POINT0POINT2;
413 case AUDIO_CHANNEL_OUT_2POINT1POINT2:
414 return AAUDIO_CHANNEL_2POINT1POINT2;
415 case AUDIO_CHANNEL_OUT_3POINT0POINT2:
416 return AAUDIO_CHANNEL_3POINT0POINT2;
417 case AUDIO_CHANNEL_OUT_3POINT1POINT2:
418 return AAUDIO_CHANNEL_3POINT1POINT2;
419 case AUDIO_CHANNEL_OUT_QUAD:
420 return AAUDIO_CHANNEL_QUAD;
421 case AUDIO_CHANNEL_OUT_QUAD_SIDE:
422 return AAUDIO_CHANNEL_QUAD_SIDE;
423 case AUDIO_CHANNEL_OUT_SURROUND:
424 return AAUDIO_CHANNEL_SURROUND;
425 case AUDIO_CHANNEL_OUT_PENTA:
426 return AAUDIO_CHANNEL_PENTA;
427 case AUDIO_CHANNEL_OUT_5POINT1:
428 return AAUDIO_CHANNEL_5POINT1;
429 case AUDIO_CHANNEL_OUT_5POINT1_SIDE:
430 return AAUDIO_CHANNEL_5POINT1_SIDE;
431 case AUDIO_CHANNEL_OUT_5POINT1POINT2:
432 return AAUDIO_CHANNEL_5POINT1POINT2;
433 case AUDIO_CHANNEL_OUT_5POINT1POINT4:
434 return AAUDIO_CHANNEL_5POINT1POINT4;
435 case AUDIO_CHANNEL_OUT_6POINT1:
436 return AAUDIO_CHANNEL_6POINT1;
437 case AUDIO_CHANNEL_OUT_7POINT1:
438 return AAUDIO_CHANNEL_7POINT1;
439 case AUDIO_CHANNEL_OUT_7POINT1POINT2:
440 return AAUDIO_CHANNEL_7POINT1POINT2;
441 case AUDIO_CHANNEL_OUT_7POINT1POINT4:
442 return AAUDIO_CHANNEL_7POINT1POINT4;
443 // TODO: add 9point1point4 and 9point1point6 when they are added in audio-hal-enums.h
444 // case AUDIO_CHANNEL_OUT_9POINT1POINT4:
445 // return AAUDIO_CHANNEL_9POINT1POINT4;
446 // case AUDIO_CHANNEL_OUT_9POINT1POINT6:
447 // return AAUDIO_CHANNEL_9POINT1POINT6;
448 default:
449 ALOGE("%s() %#x unrecognized", __func__, channelMask);
450 return AAUDIO_CHANNEL_INVALID;
451 }
452 }
453}
454
455int32_t AAudioConvert_channelMaskToCount(aaudio_channel_mask_t channelMask) {
456 return __builtin_popcount(channelMask & ~AAUDIO_CHANNEL_BIT_INDEX);
457}
458
459aaudio_channel_mask_t AAudioConvert_channelCountToMask(int32_t channelCount) {
460 if (channelCount < 0 || channelCount > AUDIO_CHANNEL_COUNT_MAX) {
461 return AAUDIO_CHANNEL_INVALID;
462 }
463
464 if (channelCount == 0) {
465 return AAUDIO_UNSPECIFIED;
466 }
467
468 // Return index mask if the channel count is greater than 2.
469 return AAUDIO_CHANNEL_BIT_INDEX | ((1 << channelCount) - 1);
470}
471
472aaudio_channel_mask_t AAudioConvert_androidToAAudioChannelIndexMask(
473 audio_channel_mask_t channelMask) {
474 if (audio_channel_mask_get_representation(channelMask) != AUDIO_CHANNEL_REPRESENTATION_INDEX) {
475 ALOGE("%s() %#x not an index mask", __func__, channelMask);
476 return AAUDIO_CHANNEL_INVALID;
477 }
478 return (channelMask & ~AUDIO_CHANNEL_INDEX_HDR) | AAUDIO_CHANNEL_BIT_INDEX;
479}
480
481audio_channel_mask_t AAudioConvert_aaudioToAndroidChannelIndexMask(
482 aaudio_channel_mask_t channelMask) {
483 if (!AAudio_isChannelIndexMask(channelMask)) {
484 ALOGE("%s() %#x not an index mask", __func__, channelMask);
485 return AUDIO_CHANNEL_INVALID;
486 }
487 return audio_channel_mask_for_index_assignment_from_count(
488 AAudioConvert_channelMaskToCount(channelMask));
489}
490
491aaudio_channel_mask_t AAudioConvert_androidToAAudioChannelMask(
492 audio_channel_mask_t channelMask, bool isInput, bool indexMaskRequired) {
493 if (audio_channel_mask_get_representation(channelMask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
494 return AAudioConvert_androidToAAudioChannelIndexMask(channelMask);
495 }
496 if (indexMaskRequired) {
497 // Require index mask, `channelMask` here is a position mask.
498 const int channelCount = isInput ? audio_channel_count_from_in_mask(channelMask)
499 : audio_channel_count_from_out_mask(channelMask);
500 return AAudioConvert_channelCountToMask(channelCount);
501 }
502 return AAudioConvert_androidToAAudioChannelLayoutMask(channelMask, isInput);
503}
504
505audio_channel_mask_t AAudioConvert_aaudioToAndroidChannelMask(
506 aaudio_channel_mask_t channelMask, bool isInput) {
507 return AAudio_isChannelIndexMask(channelMask)
508 ? AAudioConvert_aaudioToAndroidChannelIndexMask(channelMask)
509 : AAudioConvert_aaudioToAndroidChannelLayoutMask(channelMask, isInput);
510}
511
512bool AAudio_isChannelIndexMask(aaudio_channel_mask_t channelMask) {
513 return (channelMask & AAUDIO_CHANNEL_BIT_INDEX) == AAUDIO_CHANNEL_BIT_INDEX;
514}
515
516audio_channel_mask_t AAudio_getChannelMaskForOpen(
517 aaudio_channel_mask_t channelMask, int32_t samplesPerFrame, bool isInput) {
518 if (channelMask != AAUDIO_UNSPECIFIED) {
519 if (AAudio_isChannelIndexMask(channelMask) && samplesPerFrame <= 2) {
520 // When it is index mask and the count is less than 3, use position mask
521 // instead of index mask for opening a stream. This may need to be revisited
522 // when making channel index mask public.
523 return isInput ? audio_channel_in_mask_from_count(samplesPerFrame)
524 : audio_channel_out_mask_from_count(samplesPerFrame);
525 }
526 return AAudioConvert_aaudioToAndroidChannelMask(channelMask, isInput);
527 }
528
529 // Return stereo when unspecified.
530 return isInput ? AUDIO_CHANNEL_IN_STEREO : AUDIO_CHANNEL_OUT_STEREO;
531}
532
Phil Burk3316d5e2017-02-15 11:23:01 -0800533int32_t AAudioConvert_framesToBytes(int32_t numFrames,
Phil Burk7f680132018-03-12 14:48:06 -0700534 int32_t bytesPerFrame,
535 int32_t *sizeInBytes) {
536 *sizeInBytes = 0;
537
538 if (numFrames < 0 || bytesPerFrame < 0) {
539 ALOGE("negative size, numFrames = %d, frameSize = %d", numFrames, bytesPerFrame);
540 return AAUDIO_ERROR_OUT_OF_RANGE;
541 }
542
543 // Prevent numeric overflow.
544 if (numFrames > (INT32_MAX / bytesPerFrame)) {
Yi Kong0f414de2017-12-15 13:48:50 -0800545 ALOGE("size overflow, numFrames = %d, frameSize = %d", numFrames, bytesPerFrame);
Phil Burk5ed503c2017-02-01 09:38:15 -0800546 return AAUDIO_ERROR_OUT_OF_RANGE;
547 }
Phil Burk7f680132018-03-12 14:48:06 -0700548
Phil Burk5ed503c2017-02-01 09:38:15 -0800549 *sizeInBytes = numFrames * bytesPerFrame;
550 return AAUDIO_OK;
551}
Phil Burkc8f69a02017-05-11 15:53:06 -0700552
Phil Burkfd34a932017-07-19 07:03:52 -0700553int32_t AAudioProperty_getWakeupDelayMicros() {
554 const int32_t minMicros = 0; // arbitrary
555 const int32_t defaultMicros = 200; // arbitrary, based on some observed jitter
556 const int32_t maxMicros = 5000; // arbitrary, probably don't want more than 500
557 int32_t prop = property_get_int32(AAUDIO_PROP_WAKEUP_DELAY_USEC, defaultMicros);
558 if (prop < minMicros) {
559 ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, minMicros);
560 prop = minMicros;
561 } else if (prop > maxMicros) {
562 ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, maxMicros);
563 prop = maxMicros;
564 }
565 return prop;
566}
567
568int32_t AAudioProperty_getMinimumSleepMicros() {
Phil Burk4f578a22022-02-19 00:21:30 +0000569 const int32_t minMicros = 1; // arbitrary
570 // Higher values can increase latency for moderate workloads.
Phil Burkec21f2b2022-04-19 18:52:03 +0000571 // Short values can cause the CPU to short cycle if there is a bug in
572 // calculating the wakeup times.
573 const int32_t defaultMicros = 100; // arbitrary
Phil Burk4f578a22022-02-19 00:21:30 +0000574 const int32_t maxMicros = 200; // arbitrary
Phil Burkfd34a932017-07-19 07:03:52 -0700575 int32_t prop = property_get_int32(AAUDIO_PROP_MINIMUM_SLEEP_USEC, defaultMicros);
576 if (prop < minMicros) {
577 ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, minMicros);
578 prop = minMicros;
579 } else if (prop > maxMicros) {
580 ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, maxMicros);
581 prop = maxMicros;
582 }
583 return prop;
584}
585
Phil Burkb31b66f2019-09-30 09:33:41 -0700586static int32_t AAudioProperty_getMMapOffsetMicros(const char *functionName,
587 const char *propertyName) {
588 const int32_t minMicros = -20000; // arbitrary
589 const int32_t defaultMicros = 0; // arbitrary
590 const int32_t maxMicros = 20000; // arbitrary
591 int32_t prop = property_get_int32(propertyName, defaultMicros);
592 if (prop < minMicros) {
593 ALOGW("%s: clipped %d to %d", functionName, prop, minMicros);
594 prop = minMicros;
595 } else if (prop > maxMicros) {
596 ALOGW("%s: clipped %d to %d", functionName, prop, minMicros);
597 prop = maxMicros;
598 }
599 return prop;
600}
601
602int32_t AAudioProperty_getInputMMapOffsetMicros() {
603 return AAudioProperty_getMMapOffsetMicros(__func__, AAUDIO_PROP_INPUT_MMAP_OFFSET_USEC);
604}
605
606int32_t AAudioProperty_getOutputMMapOffsetMicros() {
607 return AAudioProperty_getMMapOffsetMicros(__func__, AAUDIO_PROP_OUTPUT_MMAP_OFFSET_USEC);
608}
609
Phil Burkef34be52019-09-26 13:45:25 -0700610int32_t AAudioProperty_getLogMask() {
611 return property_get_int32(AAUDIO_PROP_LOG_MASK, 0);
612}
613
Phil Burk5cc83c32017-11-28 15:43:18 -0800614aaudio_result_t AAudio_isFlushAllowed(aaudio_stream_state_t state) {
615 aaudio_result_t result = AAUDIO_OK;
616 switch (state) {
617// Proceed with flushing.
618 case AAUDIO_STREAM_STATE_OPEN:
619 case AAUDIO_STREAM_STATE_PAUSED:
620 case AAUDIO_STREAM_STATE_STOPPED:
621 case AAUDIO_STREAM_STATE_FLUSHED:
622 break;
623
624// Transition from one inactive state to another.
625 case AAUDIO_STREAM_STATE_STARTING:
626 case AAUDIO_STREAM_STATE_STARTED:
627 case AAUDIO_STREAM_STATE_STOPPING:
628 case AAUDIO_STREAM_STATE_PAUSING:
629 case AAUDIO_STREAM_STATE_FLUSHING:
630 case AAUDIO_STREAM_STATE_CLOSING:
631 case AAUDIO_STREAM_STATE_CLOSED:
632 case AAUDIO_STREAM_STATE_DISCONNECTED:
633 default:
634 ALOGE("can only flush stream when PAUSED, OPEN or STOPPED, state = %s",
dimitry2d2f17c2019-07-17 13:55:16 +0200635 aaudio::AudioGlobal_convertStreamStateToText(state));
Phil Burk5cc83c32017-11-28 15:43:18 -0800636 result = AAUDIO_ERROR_INVALID_STATE;
637 break;
638 }
639 return result;
640}