blob: 96ed56a28400079b7a2bdcf5016dc8116496ba97 [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"
Phil Burkd04aeea2017-05-23 13:56:41 -070027#include <aaudio/AAudioTesting.h>
Phil Burkbba09002017-11-29 13:39:44 -080028#include <math.h>
Phil Burkd4ccc622017-12-20 15:32:44 -080029#include <system/audio-base.h>
Phil Burk41f19d82018-02-13 14:59:10 -080030#include <assert.h>
Phil Burkd04aeea2017-05-23 13:56:41 -070031
32#include "utility/AAudioUtilities.h"
Phil Burk5ed503c2017-02-01 09:38:15 -080033
34using namespace android;
35
Phil Burk5ed503c2017-02-01 09:38:15 -080036status_t AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result) {
37 // This covers the case for AAUDIO_OK and for positive results.
38 if (result >= 0) {
39 return result;
40 }
41 status_t status;
42 switch (result) {
43 case AAUDIO_ERROR_DISCONNECTED:
Eric Laurenta2f296e2017-06-21 18:51:47 -070044 case AAUDIO_ERROR_NO_SERVICE:
Phil Burk5ed503c2017-02-01 09:38:15 -080045 status = DEAD_OBJECT;
46 break;
Eric Laurenta2f296e2017-06-21 18:51:47 -070047 case AAUDIO_ERROR_INVALID_HANDLE:
48 status = BAD_TYPE;
49 break;
Phil Burk5ed503c2017-02-01 09:38:15 -080050 case AAUDIO_ERROR_INVALID_STATE:
51 status = INVALID_OPERATION;
52 break;
Phil Burk71f35bb2017-04-13 16:05:07 -070053 case AAUDIO_ERROR_INVALID_RATE:
54 case AAUDIO_ERROR_INVALID_FORMAT:
Phil Burk5ed503c2017-02-01 09:38:15 -080055 case AAUDIO_ERROR_ILLEGAL_ARGUMENT:
Phil Burk5204d312017-05-04 17:16:13 -070056 case AAUDIO_ERROR_OUT_OF_RANGE:
Phil Burk5ed503c2017-02-01 09:38:15 -080057 status = BAD_VALUE;
58 break;
59 case AAUDIO_ERROR_WOULD_BLOCK:
60 status = WOULD_BLOCK;
61 break;
Phil Burk5204d312017-05-04 17:16:13 -070062 case AAUDIO_ERROR_NULL:
63 status = UNEXPECTED_NULL;
64 break;
Phil Burk940083c2017-07-17 17:00:02 -070065 case AAUDIO_ERROR_UNAVAILABLE:
66 status = NOT_ENOUGH_DATA;
67 break;
68
Phil Burk5204d312017-05-04 17:16:13 -070069 // TODO translate these result codes
Phil Burk5204d312017-05-04 17:16:13 -070070 case AAUDIO_ERROR_INTERNAL:
Phil Burk5204d312017-05-04 17:16:13 -070071 case AAUDIO_ERROR_UNIMPLEMENTED:
Phil Burk5204d312017-05-04 17:16:13 -070072 case AAUDIO_ERROR_NO_FREE_HANDLES:
73 case AAUDIO_ERROR_NO_MEMORY:
74 case AAUDIO_ERROR_TIMEOUT:
Phil Burk5ed503c2017-02-01 09:38:15 -080075 default:
76 status = UNKNOWN_ERROR;
77 break;
78 }
79 return status;
80}
81
82aaudio_result_t AAudioConvert_androidToAAudioResult(status_t status) {
83 // This covers the case for OK and for positive result.
84 if (status >= 0) {
85 return status;
86 }
87 aaudio_result_t result;
88 switch (status) {
89 case BAD_TYPE:
90 result = AAUDIO_ERROR_INVALID_HANDLE;
91 break;
92 case DEAD_OBJECT:
Phil Burk71f35bb2017-04-13 16:05:07 -070093 result = AAUDIO_ERROR_NO_SERVICE;
Phil Burk5ed503c2017-02-01 09:38:15 -080094 break;
95 case INVALID_OPERATION:
96 result = AAUDIO_ERROR_INVALID_STATE;
97 break;
Eric Laurenta2f296e2017-06-21 18:51:47 -070098 case UNEXPECTED_NULL:
99 result = AAUDIO_ERROR_NULL;
100 break;
101 case BAD_VALUE:
102 result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
103 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800104 case WOULD_BLOCK:
105 result = AAUDIO_ERROR_WOULD_BLOCK;
106 break;
Phil Burk940083c2017-07-17 17:00:02 -0700107 case NOT_ENOUGH_DATA:
108 result = AAUDIO_ERROR_UNAVAILABLE;
109 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800110 default:
111 result = AAUDIO_ERROR_INTERNAL;
112 break;
113 }
114 return result;
115}
116
Phil Burk4e1af9f2018-01-03 15:54:35 -0800117audio_session_t AAudioConvert_aaudioToAndroidSessionId(aaudio_session_id_t sessionId) {
Phil Burk67fdd892018-01-23 15:28:55 -0800118 // If not a regular sessionId then convert to a safe value of AUDIO_SESSION_ALLOCATE.
119 return (sessionId == AAUDIO_SESSION_ID_ALLOCATE || sessionId == AAUDIO_SESSION_ID_NONE)
Phil Burk4e1af9f2018-01-03 15:54:35 -0800120 ? AUDIO_SESSION_ALLOCATE
121 : (audio_session_t) sessionId;
122}
123
Phil Burk9dca9822017-05-26 14:27:43 -0700124audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudioFormat) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800125 audio_format_t androidFormat;
126 switch (aaudioFormat) {
Phil Burk0127c1b2018-03-29 13:48:06 -0700127 case AAUDIO_FORMAT_UNSPECIFIED:
128 androidFormat = AUDIO_FORMAT_DEFAULT;
129 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800130 case AAUDIO_FORMAT_PCM_I16:
131 androidFormat = AUDIO_FORMAT_PCM_16_BIT;
132 break;
133 case AAUDIO_FORMAT_PCM_FLOAT:
134 androidFormat = AUDIO_FORMAT_PCM_FLOAT;
135 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800136 default:
Phil Burk0127c1b2018-03-29 13:48:06 -0700137 androidFormat = AUDIO_FORMAT_INVALID;
138 ALOGE("%s() 0x%08X unrecognized", __func__, aaudioFormat);
Phil Burk5ed503c2017-02-01 09:38:15 -0800139 break;
140 }
141 return androidFormat;
142}
143
Phil Burk9dca9822017-05-26 14:27:43 -0700144aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t androidFormat) {
Phil Burk0127c1b2018-03-29 13:48:06 -0700145 aaudio_format_t aaudioFormat;
Phil Burk5ed503c2017-02-01 09:38:15 -0800146 switch (androidFormat) {
Phil Burk0127c1b2018-03-29 13:48:06 -0700147 case AUDIO_FORMAT_DEFAULT:
148 aaudioFormat = AAUDIO_FORMAT_UNSPECIFIED;
149 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800150 case AUDIO_FORMAT_PCM_16_BIT:
151 aaudioFormat = AAUDIO_FORMAT_PCM_I16;
152 break;
153 case AUDIO_FORMAT_PCM_FLOAT:
154 aaudioFormat = AAUDIO_FORMAT_PCM_FLOAT;
155 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800156 default:
157 aaudioFormat = AAUDIO_FORMAT_INVALID;
Phil Burk0127c1b2018-03-29 13:48:06 -0700158 ALOGE("%s() 0x%08X unrecognized", __func__, androidFormat);
Phil Burk5ed503c2017-02-01 09:38:15 -0800159 break;
160 }
161 return aaudioFormat;
162}
163
Phil Burkd4ccc622017-12-20 15:32:44 -0800164// Make a message string from the condition.
165#define STATIC_ASSERT(condition) static_assert(condition, #condition)
166
167audio_usage_t AAudioConvert_usageToInternal(aaudio_usage_t usage) {
168 // The public aaudio_content_type_t constants are supposed to have the same
169 // values as the internal audio_content_type_t values.
170 STATIC_ASSERT(AAUDIO_USAGE_MEDIA == AUDIO_USAGE_MEDIA);
171 STATIC_ASSERT(AAUDIO_USAGE_VOICE_COMMUNICATION == AUDIO_USAGE_VOICE_COMMUNICATION);
172 STATIC_ASSERT(AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING
173 == AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING);
174 STATIC_ASSERT(AAUDIO_USAGE_ALARM == AUDIO_USAGE_ALARM);
175 STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION == AUDIO_USAGE_NOTIFICATION);
176 STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION_RINGTONE
177 == AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE);
178 STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION_EVENT == AUDIO_USAGE_NOTIFICATION_EVENT);
179 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY);
180 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE
181 == AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE);
182 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_SONIFICATION == AUDIO_USAGE_ASSISTANCE_SONIFICATION);
183 STATIC_ASSERT(AAUDIO_USAGE_GAME == AUDIO_USAGE_GAME);
184 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANT == AUDIO_USAGE_ASSISTANT);
185 if (usage == AAUDIO_UNSPECIFIED) {
186 usage = AAUDIO_USAGE_MEDIA;
187 }
188 return (audio_usage_t) usage; // same value
189}
190
191audio_content_type_t AAudioConvert_contentTypeToInternal(aaudio_content_type_t contentType) {
192 // The public aaudio_content_type_t constants are supposed to have the same
193 // values as the internal audio_content_type_t values.
194 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_MUSIC == AUDIO_CONTENT_TYPE_MUSIC);
195 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_SPEECH == AUDIO_CONTENT_TYPE_SPEECH);
196 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_SONIFICATION == AUDIO_CONTENT_TYPE_SONIFICATION);
197 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_MOVIE == AUDIO_CONTENT_TYPE_MOVIE);
198 if (contentType == AAUDIO_UNSPECIFIED) {
199 contentType = AAUDIO_CONTENT_TYPE_MUSIC;
200 }
201 return (audio_content_type_t) contentType; // same value
202}
203
204audio_source_t AAudioConvert_inputPresetToAudioSource(aaudio_input_preset_t preset) {
205 // The public aaudio_input_preset_t constants are supposed to have the same
206 // values as the internal audio_source_t values.
207 STATIC_ASSERT(AAUDIO_UNSPECIFIED == AUDIO_SOURCE_DEFAULT);
208 STATIC_ASSERT(AAUDIO_INPUT_PRESET_GENERIC == AUDIO_SOURCE_MIC);
209 STATIC_ASSERT(AAUDIO_INPUT_PRESET_CAMCORDER == AUDIO_SOURCE_CAMCORDER);
210 STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_RECOGNITION == AUDIO_SOURCE_VOICE_RECOGNITION);
211 STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION == AUDIO_SOURCE_VOICE_COMMUNICATION);
212 STATIC_ASSERT(AAUDIO_INPUT_PRESET_UNPROCESSED == AUDIO_SOURCE_UNPROCESSED);
Eric Laurentae4b6ec2019-01-15 18:34:38 -0800213 STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE == AUDIO_SOURCE_VOICE_PERFORMANCE);
Phil Burkd4ccc622017-12-20 15:32:44 -0800214 if (preset == AAUDIO_UNSPECIFIED) {
Phil Burkeaef9b92018-01-18 09:09:42 -0800215 preset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
Phil Burkd4ccc622017-12-20 15:32:44 -0800216 }
217 return (audio_source_t) preset; // same value
218}
219
Kevin Rocard68646ba2019-03-20 13:26:49 -0700220audio_flags_mask_t AAudioConvert_allowCapturePolicyToAudioFlagsMask(
221 aaudio_allowed_capture_policy_t policy) {
222 switch (policy) {
223 case AAUDIO_UNSPECIFIED:
224 case AAUDIO_ALLOW_CAPTURE_BY_ALL:
225 return AUDIO_FLAG_NONE;
226 case AAUDIO_ALLOW_CAPTURE_BY_SYSTEM:
227 return AUDIO_FLAG_NO_MEDIA_PROJECTION;
228 case AAUDIO_ALLOW_CAPTURE_BY_NONE:
229 return AUDIO_FLAG_NO_MEDIA_PROJECTION | AUDIO_FLAG_NO_SYSTEM_CAPTURE;
230 default:
231 ALOGE("%s() 0x%08X unrecognized", __func__, policy);
232 return AUDIO_FLAG_NONE; //
233 }
234}
235
Phil Burk3316d5e2017-02-15 11:23:01 -0800236int32_t AAudioConvert_framesToBytes(int32_t numFrames,
Phil Burk7f680132018-03-12 14:48:06 -0700237 int32_t bytesPerFrame,
238 int32_t *sizeInBytes) {
239 *sizeInBytes = 0;
240
241 if (numFrames < 0 || bytesPerFrame < 0) {
242 ALOGE("negative size, numFrames = %d, frameSize = %d", numFrames, bytesPerFrame);
243 return AAUDIO_ERROR_OUT_OF_RANGE;
244 }
245
246 // Prevent numeric overflow.
247 if (numFrames > (INT32_MAX / bytesPerFrame)) {
Yi Kong0f414de2017-12-15 13:48:50 -0800248 ALOGE("size overflow, numFrames = %d, frameSize = %d", numFrames, bytesPerFrame);
Phil Burk5ed503c2017-02-01 09:38:15 -0800249 return AAUDIO_ERROR_OUT_OF_RANGE;
250 }
Phil Burk7f680132018-03-12 14:48:06 -0700251
Phil Burk5ed503c2017-02-01 09:38:15 -0800252 *sizeInBytes = numFrames * bytesPerFrame;
253 return AAUDIO_OK;
254}
Phil Burkc8f69a02017-05-11 15:53:06 -0700255
256static int32_t AAudioProperty_getMMapProperty(const char *propName,
257 int32_t defaultValue,
258 const char * caller) {
Phil Burk87c9f642017-05-17 07:22:39 -0700259 int32_t prop = property_get_int32(propName, defaultValue);
Phil Burkc8f69a02017-05-11 15:53:06 -0700260 switch (prop) {
Phil Burkd04aeea2017-05-23 13:56:41 -0700261 case AAUDIO_UNSPECIFIED:
262 case AAUDIO_POLICY_NEVER:
263 case AAUDIO_POLICY_ALWAYS:
264 case AAUDIO_POLICY_AUTO:
Phil Burkc8f69a02017-05-11 15:53:06 -0700265 break;
266 default:
267 ALOGE("%s: invalid = %d", caller, prop);
268 prop = defaultValue;
269 break;
270 }
271 return prop;
272}
273
Phil Burkd04aeea2017-05-23 13:56:41 -0700274int32_t AAudioProperty_getMMapPolicy() {
275 return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_POLICY,
276 AAUDIO_UNSPECIFIED, __func__);
Phil Burkc8f69a02017-05-11 15:53:06 -0700277}
278
Phil Burkd04aeea2017-05-23 13:56:41 -0700279int32_t AAudioProperty_getMMapExclusivePolicy() {
280 return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY,
281 AAUDIO_UNSPECIFIED, __func__);
Phil Burkc8f69a02017-05-11 15:53:06 -0700282}
283
284int32_t AAudioProperty_getMixerBursts() {
Phil Burk87c9f642017-05-17 07:22:39 -0700285 const int32_t defaultBursts = 2; // arbitrary, use 2 for double buffered
Phil Burkc8f69a02017-05-11 15:53:06 -0700286 const int32_t maxBursts = 1024; // arbitrary
Phil Burk87c9f642017-05-17 07:22:39 -0700287 int32_t prop = property_get_int32(AAUDIO_PROP_MIXER_BURSTS, defaultBursts);
Phil Burkc8f69a02017-05-11 15:53:06 -0700288 if (prop < 1 || prop > maxBursts) {
289 ALOGE("AAudioProperty_getMixerBursts: invalid = %d", prop);
290 prop = defaultBursts;
291 }
292 return prop;
293}
294
Phil Burkfd34a932017-07-19 07:03:52 -0700295int32_t AAudioProperty_getWakeupDelayMicros() {
296 const int32_t minMicros = 0; // arbitrary
297 const int32_t defaultMicros = 200; // arbitrary, based on some observed jitter
298 const int32_t maxMicros = 5000; // arbitrary, probably don't want more than 500
299 int32_t prop = property_get_int32(AAUDIO_PROP_WAKEUP_DELAY_USEC, defaultMicros);
300 if (prop < minMicros) {
301 ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, minMicros);
302 prop = minMicros;
303 } else if (prop > maxMicros) {
304 ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, maxMicros);
305 prop = maxMicros;
306 }
307 return prop;
308}
309
310int32_t AAudioProperty_getMinimumSleepMicros() {
311 const int32_t minMicros = 20; // arbitrary
312 const int32_t defaultMicros = 200; // arbitrary
313 const int32_t maxMicros = 2000; // arbitrary
314 int32_t prop = property_get_int32(AAUDIO_PROP_MINIMUM_SLEEP_USEC, defaultMicros);
315 if (prop < minMicros) {
316 ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, minMicros);
317 prop = minMicros;
318 } else if (prop > maxMicros) {
319 ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, maxMicros);
320 prop = maxMicros;
321 }
322 return prop;
323}
324
Phil Burkc8f69a02017-05-11 15:53:06 -0700325int32_t AAudioProperty_getHardwareBurstMinMicros() {
326 const int32_t defaultMicros = 1000; // arbitrary
327 const int32_t maxMicros = 1000 * 1000; // arbitrary
328 int32_t prop = property_get_int32(AAUDIO_PROP_HW_BURST_MIN_USEC, defaultMicros);
329 if (prop < 1 || prop > maxMicros) {
Phil Burkfd34a932017-07-19 07:03:52 -0700330 ALOGE("AAudioProperty_getHardwareBurstMinMicros: invalid = %d, use %d",
331 prop, defaultMicros);
Phil Burkc8f69a02017-05-11 15:53:06 -0700332 prop = defaultMicros;
333 }
334 return prop;
335}
Phil Burk5cc83c32017-11-28 15:43:18 -0800336
337aaudio_result_t AAudio_isFlushAllowed(aaudio_stream_state_t state) {
338 aaudio_result_t result = AAUDIO_OK;
339 switch (state) {
340// Proceed with flushing.
341 case AAUDIO_STREAM_STATE_OPEN:
342 case AAUDIO_STREAM_STATE_PAUSED:
343 case AAUDIO_STREAM_STATE_STOPPED:
344 case AAUDIO_STREAM_STATE_FLUSHED:
345 break;
346
347// Transition from one inactive state to another.
348 case AAUDIO_STREAM_STATE_STARTING:
349 case AAUDIO_STREAM_STATE_STARTED:
350 case AAUDIO_STREAM_STATE_STOPPING:
351 case AAUDIO_STREAM_STATE_PAUSING:
352 case AAUDIO_STREAM_STATE_FLUSHING:
353 case AAUDIO_STREAM_STATE_CLOSING:
354 case AAUDIO_STREAM_STATE_CLOSED:
355 case AAUDIO_STREAM_STATE_DISCONNECTED:
356 default:
357 ALOGE("can only flush stream when PAUSED, OPEN or STOPPED, state = %s",
358 AAudio_convertStreamStateToText(state));
359 result = AAUDIO_ERROR_INVALID_STATE;
360 break;
361 }
362 return result;
363}