blob: adc4904d57336fbbdfd138b833171072415c93bc [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 Burkd04aeea2017-05-23 13:56:41 -070030
31#include "utility/AAudioUtilities.h"
Phil Burk5ed503c2017-02-01 09:38:15 -080032
33using namespace android;
34
Phil Burke572f462017-04-20 13:03:19 -070035// This is 3 dB, (10^(3/20)), to match the maximum headroom in AudioTrack for float data.
36// It is designed to allow occasional transient peaks.
37#define MAX_HEADROOM (1.41253754f)
38#define MIN_HEADROOM (0 - MAX_HEADROOM)
39
Phil Burk9dca9822017-05-26 14:27:43 -070040int32_t AAudioConvert_formatToSizeInBytes(aaudio_format_t format) {
Phil Burk3316d5e2017-02-15 11:23:01 -080041 int32_t size = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
Phil Burk5ed503c2017-02-01 09:38:15 -080042 switch (format) {
43 case AAUDIO_FORMAT_PCM_I16:
44 size = sizeof(int16_t);
45 break;
Phil Burk5ed503c2017-02-01 09:38:15 -080046 case AAUDIO_FORMAT_PCM_FLOAT:
47 size = sizeof(float);
48 break;
49 default:
50 break;
51 }
52 return size;
53}
54
Phil Burk5204d312017-05-04 17:16:13 -070055// TODO expose and call clamp16_from_float function in primitives.h
Phil Burke572f462017-04-20 13:03:19 -070056static inline int16_t clamp16_from_float(float f) {
Phil Burkbba09002017-11-29 13:39:44 -080057 static const float scale = 1 << 15;
58 return (int16_t) roundf(fmaxf(fminf(f * scale, scale - 1.f), -scale));
Phil Burke572f462017-04-20 13:03:19 -070059}
60
61static float clipAndClampFloatToPcm16(float sample, float scaler) {
62 // Clip to valid range of a float sample to prevent excessive volume.
63 if (sample > MAX_HEADROOM) sample = MAX_HEADROOM;
64 else if (sample < MIN_HEADROOM) sample = MIN_HEADROOM;
65
66 // Scale and convert to a short.
67 float fval = sample * scaler;
68 return clamp16_from_float(fval);
69}
70
71void AAudioConvert_floatToPcm16(const float *source,
72 int16_t *destination,
73 int32_t numSamples,
74 float amplitude) {
75 float scaler = amplitude;
Phil Burk5ed503c2017-02-01 09:38:15 -080076 for (int i = 0; i < numSamples; i++) {
Phil Burke572f462017-04-20 13:03:19 -070077 float sample = *source++;
78 *destination++ = clipAndClampFloatToPcm16(sample, scaler);
Phil Burk5ed503c2017-02-01 09:38:15 -080079 }
80}
81
Phil Burke572f462017-04-20 13:03:19 -070082void AAudioConvert_floatToPcm16(const float *source,
83 int16_t *destination,
84 int32_t numFrames,
85 int32_t samplesPerFrame,
86 float amplitude1,
87 float amplitude2) {
88 float scaler = amplitude1;
89 // divide by numFrames so that we almost reach amplitude2
90 float delta = (amplitude2 - amplitude1) / numFrames;
91 for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
92 for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) {
93 float sample = *source++;
94 *destination++ = clipAndClampFloatToPcm16(sample, scaler);
95 }
96 scaler += delta;
97 }
98}
99
100#define SHORT_SCALE 32768
101
102void AAudioConvert_pcm16ToFloat(const int16_t *source,
103 float *destination,
104 int32_t numSamples,
105 float amplitude) {
106 float scaler = amplitude / SHORT_SCALE;
Phil Burk5ed503c2017-02-01 09:38:15 -0800107 for (int i = 0; i < numSamples; i++) {
Phil Burke572f462017-04-20 13:03:19 -0700108 destination[i] = source[i] * scaler;
109 }
110}
111
112// This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0
113void AAudioConvert_pcm16ToFloat(const int16_t *source,
114 float *destination,
115 int32_t numFrames,
116 int32_t samplesPerFrame,
117 float amplitude1,
118 float amplitude2) {
119 float scaler = amplitude1 / SHORT_SCALE;
120 float delta = (amplitude2 - amplitude1) / (SHORT_SCALE * (float) numFrames);
121 for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
122 for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) {
123 *destination++ = *source++ * scaler;
124 }
125 scaler += delta;
126 }
127}
128
129// This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0
130void AAudio_linearRamp(const float *source,
131 float *destination,
132 int32_t numFrames,
133 int32_t samplesPerFrame,
134 float amplitude1,
135 float amplitude2) {
136 float scaler = amplitude1;
137 float delta = (amplitude2 - amplitude1) / numFrames;
138 for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
139 for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) {
140 float sample = *source++;
141
142 // Clip to valid range of a float sample to prevent excessive volume.
143 if (sample > MAX_HEADROOM) sample = MAX_HEADROOM;
144 else if (sample < MIN_HEADROOM) sample = MIN_HEADROOM;
145
146 *destination++ = sample * scaler;
147 }
148 scaler += delta;
149 }
150}
151
152// This code assumes amplitude1 and amplitude2 are between 0.0 and 1.0
153void AAudio_linearRamp(const int16_t *source,
154 int16_t *destination,
155 int32_t numFrames,
156 int32_t samplesPerFrame,
157 float amplitude1,
158 float amplitude2) {
Phil Burkbba09002017-11-29 13:39:44 -0800159 // Because we are converting from int16 to 1nt16, we do not have to scale by 1/32768.
160 float scaler = amplitude1;
161 float delta = (amplitude2 - amplitude1) / numFrames;
Phil Burke572f462017-04-20 13:03:19 -0700162 for (int frameIndex = 0; frameIndex < numFrames; frameIndex++) {
163 for (int sampleIndex = 0; sampleIndex < samplesPerFrame; sampleIndex++) {
164 // No need to clip because int16_t range is inherently limited.
165 float sample = *source++ * scaler;
Phil Burkbba09002017-11-29 13:39:44 -0800166 *destination++ = (int16_t) roundf(sample);
Phil Burke572f462017-04-20 13:03:19 -0700167 }
168 scaler += delta;
Phil Burk5ed503c2017-02-01 09:38:15 -0800169 }
170}
171
172status_t AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result) {
173 // This covers the case for AAUDIO_OK and for positive results.
174 if (result >= 0) {
175 return result;
176 }
177 status_t status;
178 switch (result) {
179 case AAUDIO_ERROR_DISCONNECTED:
Eric Laurenta2f296e2017-06-21 18:51:47 -0700180 case AAUDIO_ERROR_NO_SERVICE:
Phil Burk5ed503c2017-02-01 09:38:15 -0800181 status = DEAD_OBJECT;
182 break;
Eric Laurenta2f296e2017-06-21 18:51:47 -0700183 case AAUDIO_ERROR_INVALID_HANDLE:
184 status = BAD_TYPE;
185 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800186 case AAUDIO_ERROR_INVALID_STATE:
187 status = INVALID_OPERATION;
188 break;
Phil Burk71f35bb2017-04-13 16:05:07 -0700189 case AAUDIO_ERROR_INVALID_RATE:
190 case AAUDIO_ERROR_INVALID_FORMAT:
Phil Burk5ed503c2017-02-01 09:38:15 -0800191 case AAUDIO_ERROR_ILLEGAL_ARGUMENT:
Phil Burk5204d312017-05-04 17:16:13 -0700192 case AAUDIO_ERROR_OUT_OF_RANGE:
Phil Burk5ed503c2017-02-01 09:38:15 -0800193 status = BAD_VALUE;
194 break;
195 case AAUDIO_ERROR_WOULD_BLOCK:
196 status = WOULD_BLOCK;
197 break;
Phil Burk5204d312017-05-04 17:16:13 -0700198 case AAUDIO_ERROR_NULL:
199 status = UNEXPECTED_NULL;
200 break;
Phil Burk940083c2017-07-17 17:00:02 -0700201 case AAUDIO_ERROR_UNAVAILABLE:
202 status = NOT_ENOUGH_DATA;
203 break;
204
Phil Burk5204d312017-05-04 17:16:13 -0700205 // TODO translate these result codes
Phil Burk5204d312017-05-04 17:16:13 -0700206 case AAUDIO_ERROR_INTERNAL:
Phil Burk5204d312017-05-04 17:16:13 -0700207 case AAUDIO_ERROR_UNIMPLEMENTED:
Phil Burk5204d312017-05-04 17:16:13 -0700208 case AAUDIO_ERROR_NO_FREE_HANDLES:
209 case AAUDIO_ERROR_NO_MEMORY:
210 case AAUDIO_ERROR_TIMEOUT:
Phil Burk5ed503c2017-02-01 09:38:15 -0800211 default:
212 status = UNKNOWN_ERROR;
213 break;
214 }
215 return status;
216}
217
218aaudio_result_t AAudioConvert_androidToAAudioResult(status_t status) {
219 // This covers the case for OK and for positive result.
220 if (status >= 0) {
221 return status;
222 }
223 aaudio_result_t result;
224 switch (status) {
225 case BAD_TYPE:
226 result = AAUDIO_ERROR_INVALID_HANDLE;
227 break;
228 case DEAD_OBJECT:
Phil Burk71f35bb2017-04-13 16:05:07 -0700229 result = AAUDIO_ERROR_NO_SERVICE;
Phil Burk5ed503c2017-02-01 09:38:15 -0800230 break;
231 case INVALID_OPERATION:
232 result = AAUDIO_ERROR_INVALID_STATE;
233 break;
Eric Laurenta2f296e2017-06-21 18:51:47 -0700234 case UNEXPECTED_NULL:
235 result = AAUDIO_ERROR_NULL;
236 break;
237 case BAD_VALUE:
238 result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
239 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800240 case WOULD_BLOCK:
241 result = AAUDIO_ERROR_WOULD_BLOCK;
242 break;
Phil Burk940083c2017-07-17 17:00:02 -0700243 case NOT_ENOUGH_DATA:
244 result = AAUDIO_ERROR_UNAVAILABLE;
245 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800246 default:
247 result = AAUDIO_ERROR_INTERNAL;
248 break;
249 }
250 return result;
251}
252
Phil Burk4e1af9f2018-01-03 15:54:35 -0800253audio_session_t AAudioConvert_aaudioToAndroidSessionId(aaudio_session_id_t sessionId) {
254 // If not a valid sessionId then convert to a safe value of AUDIO_SESSION_ALLOCATE.
255 return (sessionId < AAUDIO_SESSION_ID_MIN)
256 ? AUDIO_SESSION_ALLOCATE
257 : (audio_session_t) sessionId;
258}
259
Phil Burk9dca9822017-05-26 14:27:43 -0700260audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudioFormat) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800261 audio_format_t androidFormat;
262 switch (aaudioFormat) {
263 case AAUDIO_FORMAT_PCM_I16:
264 androidFormat = AUDIO_FORMAT_PCM_16_BIT;
265 break;
266 case AAUDIO_FORMAT_PCM_FLOAT:
267 androidFormat = AUDIO_FORMAT_PCM_FLOAT;
268 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800269 default:
270 androidFormat = AUDIO_FORMAT_DEFAULT;
271 ALOGE("AAudioConvert_aaudioToAndroidDataFormat 0x%08X unrecognized", aaudioFormat);
272 break;
273 }
274 return androidFormat;
275}
276
Phil Burk9dca9822017-05-26 14:27:43 -0700277aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t androidFormat) {
278 aaudio_format_t aaudioFormat = AAUDIO_FORMAT_INVALID;
Phil Burk5ed503c2017-02-01 09:38:15 -0800279 switch (androidFormat) {
280 case AUDIO_FORMAT_PCM_16_BIT:
281 aaudioFormat = AAUDIO_FORMAT_PCM_I16;
282 break;
283 case AUDIO_FORMAT_PCM_FLOAT:
284 aaudioFormat = AAUDIO_FORMAT_PCM_FLOAT;
285 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800286 default:
287 aaudioFormat = AAUDIO_FORMAT_INVALID;
288 ALOGE("AAudioConvert_androidToAAudioDataFormat 0x%08X unrecognized", androidFormat);
289 break;
290 }
291 return aaudioFormat;
292}
293
Phil Burkd4ccc622017-12-20 15:32:44 -0800294// Make a message string from the condition.
295#define STATIC_ASSERT(condition) static_assert(condition, #condition)
296
297audio_usage_t AAudioConvert_usageToInternal(aaudio_usage_t usage) {
298 // The public aaudio_content_type_t constants are supposed to have the same
299 // values as the internal audio_content_type_t values.
300 STATIC_ASSERT(AAUDIO_USAGE_MEDIA == AUDIO_USAGE_MEDIA);
301 STATIC_ASSERT(AAUDIO_USAGE_VOICE_COMMUNICATION == AUDIO_USAGE_VOICE_COMMUNICATION);
302 STATIC_ASSERT(AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING
303 == AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING);
304 STATIC_ASSERT(AAUDIO_USAGE_ALARM == AUDIO_USAGE_ALARM);
305 STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION == AUDIO_USAGE_NOTIFICATION);
306 STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION_RINGTONE
307 == AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE);
308 STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION_EVENT == AUDIO_USAGE_NOTIFICATION_EVENT);
309 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY);
310 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE
311 == AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE);
312 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_SONIFICATION == AUDIO_USAGE_ASSISTANCE_SONIFICATION);
313 STATIC_ASSERT(AAUDIO_USAGE_GAME == AUDIO_USAGE_GAME);
314 STATIC_ASSERT(AAUDIO_USAGE_ASSISTANT == AUDIO_USAGE_ASSISTANT);
315 if (usage == AAUDIO_UNSPECIFIED) {
316 usage = AAUDIO_USAGE_MEDIA;
317 }
318 return (audio_usage_t) usage; // same value
319}
320
321audio_content_type_t AAudioConvert_contentTypeToInternal(aaudio_content_type_t contentType) {
322 // The public aaudio_content_type_t constants are supposed to have the same
323 // values as the internal audio_content_type_t values.
324 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_MUSIC == AUDIO_CONTENT_TYPE_MUSIC);
325 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_SPEECH == AUDIO_CONTENT_TYPE_SPEECH);
326 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_SONIFICATION == AUDIO_CONTENT_TYPE_SONIFICATION);
327 STATIC_ASSERT(AAUDIO_CONTENT_TYPE_MOVIE == AUDIO_CONTENT_TYPE_MOVIE);
328 if (contentType == AAUDIO_UNSPECIFIED) {
329 contentType = AAUDIO_CONTENT_TYPE_MUSIC;
330 }
331 return (audio_content_type_t) contentType; // same value
332}
333
334audio_source_t AAudioConvert_inputPresetToAudioSource(aaudio_input_preset_t preset) {
335 // The public aaudio_input_preset_t constants are supposed to have the same
336 // values as the internal audio_source_t values.
337 STATIC_ASSERT(AAUDIO_UNSPECIFIED == AUDIO_SOURCE_DEFAULT);
338 STATIC_ASSERT(AAUDIO_INPUT_PRESET_GENERIC == AUDIO_SOURCE_MIC);
339 STATIC_ASSERT(AAUDIO_INPUT_PRESET_CAMCORDER == AUDIO_SOURCE_CAMCORDER);
340 STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_RECOGNITION == AUDIO_SOURCE_VOICE_RECOGNITION);
341 STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION == AUDIO_SOURCE_VOICE_COMMUNICATION);
342 STATIC_ASSERT(AAUDIO_INPUT_PRESET_UNPROCESSED == AUDIO_SOURCE_UNPROCESSED);
343 if (preset == AAUDIO_UNSPECIFIED) {
Phil Burkeaef9b92018-01-18 09:09:42 -0800344 preset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
Phil Burkd4ccc622017-12-20 15:32:44 -0800345 }
346 return (audio_source_t) preset; // same value
347}
348
Phil Burk3316d5e2017-02-15 11:23:01 -0800349int32_t AAudioConvert_framesToBytes(int32_t numFrames,
350 int32_t bytesPerFrame,
351 int32_t *sizeInBytes) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800352 // TODO implement more elegantly
353 const int32_t maxChannels = 256; // ridiculously large
Phil Burk3316d5e2017-02-15 11:23:01 -0800354 const int32_t maxBytesPerFrame = maxChannels * sizeof(float);
Phil Burk5ed503c2017-02-01 09:38:15 -0800355 // Prevent overflow by limiting multiplicands.
356 if (bytesPerFrame > maxBytesPerFrame || numFrames > (0x3FFFFFFF / maxBytesPerFrame)) {
Yi Kong0f414de2017-12-15 13:48:50 -0800357 ALOGE("size overflow, numFrames = %d, frameSize = %d", numFrames, bytesPerFrame);
Phil Burk5ed503c2017-02-01 09:38:15 -0800358 return AAUDIO_ERROR_OUT_OF_RANGE;
359 }
360 *sizeInBytes = numFrames * bytesPerFrame;
361 return AAUDIO_OK;
362}
Phil Burkc8f69a02017-05-11 15:53:06 -0700363
364static int32_t AAudioProperty_getMMapProperty(const char *propName,
365 int32_t defaultValue,
366 const char * caller) {
Phil Burk87c9f642017-05-17 07:22:39 -0700367 int32_t prop = property_get_int32(propName, defaultValue);
Phil Burkc8f69a02017-05-11 15:53:06 -0700368 switch (prop) {
Phil Burkd04aeea2017-05-23 13:56:41 -0700369 case AAUDIO_UNSPECIFIED:
370 case AAUDIO_POLICY_NEVER:
371 case AAUDIO_POLICY_ALWAYS:
372 case AAUDIO_POLICY_AUTO:
Phil Burkc8f69a02017-05-11 15:53:06 -0700373 break;
374 default:
375 ALOGE("%s: invalid = %d", caller, prop);
376 prop = defaultValue;
377 break;
378 }
379 return prop;
380}
381
Phil Burkd04aeea2017-05-23 13:56:41 -0700382int32_t AAudioProperty_getMMapPolicy() {
383 return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_POLICY,
384 AAUDIO_UNSPECIFIED, __func__);
Phil Burkc8f69a02017-05-11 15:53:06 -0700385}
386
Phil Burkd04aeea2017-05-23 13:56:41 -0700387int32_t AAudioProperty_getMMapExclusivePolicy() {
388 return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY,
389 AAUDIO_UNSPECIFIED, __func__);
Phil Burkc8f69a02017-05-11 15:53:06 -0700390}
391
392int32_t AAudioProperty_getMixerBursts() {
Phil Burk87c9f642017-05-17 07:22:39 -0700393 const int32_t defaultBursts = 2; // arbitrary, use 2 for double buffered
Phil Burkc8f69a02017-05-11 15:53:06 -0700394 const int32_t maxBursts = 1024; // arbitrary
Phil Burk87c9f642017-05-17 07:22:39 -0700395 int32_t prop = property_get_int32(AAUDIO_PROP_MIXER_BURSTS, defaultBursts);
Phil Burkc8f69a02017-05-11 15:53:06 -0700396 if (prop < 1 || prop > maxBursts) {
397 ALOGE("AAudioProperty_getMixerBursts: invalid = %d", prop);
398 prop = defaultBursts;
399 }
400 return prop;
401}
402
Phil Burkfd34a932017-07-19 07:03:52 -0700403int32_t AAudioProperty_getWakeupDelayMicros() {
404 const int32_t minMicros = 0; // arbitrary
405 const int32_t defaultMicros = 200; // arbitrary, based on some observed jitter
406 const int32_t maxMicros = 5000; // arbitrary, probably don't want more than 500
407 int32_t prop = property_get_int32(AAUDIO_PROP_WAKEUP_DELAY_USEC, defaultMicros);
408 if (prop < minMicros) {
409 ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, minMicros);
410 prop = minMicros;
411 } else if (prop > maxMicros) {
412 ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, maxMicros);
413 prop = maxMicros;
414 }
415 return prop;
416}
417
418int32_t AAudioProperty_getMinimumSleepMicros() {
419 const int32_t minMicros = 20; // arbitrary
420 const int32_t defaultMicros = 200; // arbitrary
421 const int32_t maxMicros = 2000; // arbitrary
422 int32_t prop = property_get_int32(AAUDIO_PROP_MINIMUM_SLEEP_USEC, defaultMicros);
423 if (prop < minMicros) {
424 ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, minMicros);
425 prop = minMicros;
426 } else if (prop > maxMicros) {
427 ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, maxMicros);
428 prop = maxMicros;
429 }
430 return prop;
431}
432
Phil Burkc8f69a02017-05-11 15:53:06 -0700433int32_t AAudioProperty_getHardwareBurstMinMicros() {
434 const int32_t defaultMicros = 1000; // arbitrary
435 const int32_t maxMicros = 1000 * 1000; // arbitrary
436 int32_t prop = property_get_int32(AAUDIO_PROP_HW_BURST_MIN_USEC, defaultMicros);
437 if (prop < 1 || prop > maxMicros) {
Phil Burkfd34a932017-07-19 07:03:52 -0700438 ALOGE("AAudioProperty_getHardwareBurstMinMicros: invalid = %d, use %d",
439 prop, defaultMicros);
Phil Burkc8f69a02017-05-11 15:53:06 -0700440 prop = defaultMicros;
441 }
442 return prop;
443}
Phil Burk5cc83c32017-11-28 15:43:18 -0800444
445aaudio_result_t AAudio_isFlushAllowed(aaudio_stream_state_t state) {
446 aaudio_result_t result = AAUDIO_OK;
447 switch (state) {
448// Proceed with flushing.
449 case AAUDIO_STREAM_STATE_OPEN:
450 case AAUDIO_STREAM_STATE_PAUSED:
451 case AAUDIO_STREAM_STATE_STOPPED:
452 case AAUDIO_STREAM_STATE_FLUSHED:
453 break;
454
455// Transition from one inactive state to another.
456 case AAUDIO_STREAM_STATE_STARTING:
457 case AAUDIO_STREAM_STATE_STARTED:
458 case AAUDIO_STREAM_STATE_STOPPING:
459 case AAUDIO_STREAM_STATE_PAUSING:
460 case AAUDIO_STREAM_STATE_FLUSHING:
461 case AAUDIO_STREAM_STATE_CLOSING:
462 case AAUDIO_STREAM_STATE_CLOSED:
463 case AAUDIO_STREAM_STATE_DISCONNECTED:
464 default:
465 ALOGE("can only flush stream when PAUSED, OPEN or STOPPED, state = %s",
466 AAudio_convertStreamStateToText(state));
467 result = AAUDIO_ERROR_INVALID_STATE;
468 break;
469 }
470 return result;
471}