1 /*
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 
21 #include <cutils/properties.h>
22 #include <stdint.h>
23 #include <sys/types.h>
24 #include <utils/Errors.h>
25 
26 #include "aaudio/AAudio.h"
27 #include "core/AudioGlobal.h"
28 #include <aaudio/AAudioTesting.h>
29 #include <math.h>
30 #include <system/audio-base.h>
31 #include <assert.h>
32 
33 #include "utility/AAudioUtilities.h"
34 
35 using namespace android;
36 
AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result)37 status_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:
45     case AAUDIO_ERROR_NO_SERVICE:
46         status = DEAD_OBJECT;
47         break;
48     case AAUDIO_ERROR_INVALID_HANDLE:
49         status = BAD_TYPE;
50         break;
51     case AAUDIO_ERROR_INVALID_STATE:
52         status = INVALID_OPERATION;
53         break;
54     case AAUDIO_ERROR_INVALID_RATE:
55     case AAUDIO_ERROR_INVALID_FORMAT:
56     case AAUDIO_ERROR_ILLEGAL_ARGUMENT:
57     case AAUDIO_ERROR_OUT_OF_RANGE:
58         status = BAD_VALUE;
59         break;
60     case AAUDIO_ERROR_WOULD_BLOCK:
61         status = WOULD_BLOCK;
62         break;
63     case AAUDIO_ERROR_NULL:
64         status = UNEXPECTED_NULL;
65         break;
66     case AAUDIO_ERROR_UNAVAILABLE:
67         status = NOT_ENOUGH_DATA;
68         break;
69 
70     // TODO translate these result codes
71     case AAUDIO_ERROR_INTERNAL:
72     case AAUDIO_ERROR_UNIMPLEMENTED:
73     case AAUDIO_ERROR_NO_FREE_HANDLES:
74     case AAUDIO_ERROR_NO_MEMORY:
75     case AAUDIO_ERROR_TIMEOUT:
76     default:
77         status = UNKNOWN_ERROR;
78         break;
79     }
80     return status;
81 }
82 
AAudioConvert_androidToAAudioResult(status_t status)83 aaudio_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:
94         result = AAUDIO_ERROR_NO_SERVICE;
95         break;
96     case INVALID_OPERATION:
97         result = AAUDIO_ERROR_INVALID_STATE;
98         break;
99     case UNEXPECTED_NULL:
100         result = AAUDIO_ERROR_NULL;
101         break;
102     case BAD_VALUE:
103         result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
104         break;
105     case WOULD_BLOCK:
106         result = AAUDIO_ERROR_WOULD_BLOCK;
107         break;
108     case NOT_ENOUGH_DATA:
109         result = AAUDIO_ERROR_UNAVAILABLE;
110         break;
111     default:
112         result = AAUDIO_ERROR_INTERNAL;
113         break;
114     }
115     return result;
116 }
117 
AAudioConvert_aaudioToAndroidSessionId(aaudio_session_id_t sessionId)118 audio_session_t AAudioConvert_aaudioToAndroidSessionId(aaudio_session_id_t sessionId) {
119     // 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)
121            ? AUDIO_SESSION_ALLOCATE
122            : (audio_session_t) sessionId;
123 }
124 
AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudioFormat)125 audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudioFormat) {
126     audio_format_t androidFormat;
127     switch (aaudioFormat) {
128     case AAUDIO_FORMAT_UNSPECIFIED:
129         androidFormat = AUDIO_FORMAT_DEFAULT;
130         break;
131     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;
137     default:
138         androidFormat = AUDIO_FORMAT_INVALID;
139         ALOGE("%s() 0x%08X unrecognized", __func__, aaudioFormat);
140         break;
141     }
142     return androidFormat;
143 }
144 
AAudioConvert_androidToAAudioDataFormat(audio_format_t androidFormat)145 aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t androidFormat) {
146     aaudio_format_t aaudioFormat;
147     switch (androidFormat) {
148     case AUDIO_FORMAT_DEFAULT:
149         aaudioFormat = AAUDIO_FORMAT_UNSPECIFIED;
150         break;
151     case AUDIO_FORMAT_PCM_16_BIT:
152         aaudioFormat = AAUDIO_FORMAT_PCM_I16;
153         break;
154     case AUDIO_FORMAT_PCM_FLOAT:
155         aaudioFormat = AAUDIO_FORMAT_PCM_FLOAT;
156         break;
157     default:
158         aaudioFormat = AAUDIO_FORMAT_INVALID;
159         ALOGE("%s() 0x%08X unrecognized", __func__, androidFormat);
160         break;
161     }
162     return aaudioFormat;
163 }
164 
165 // Make a message string from the condition.
166 #define STATIC_ASSERT(condition) static_assert(condition, #condition)
167 
AAudioConvert_usageToInternal(aaudio_usage_t usage)168 audio_usage_t AAudioConvert_usageToInternal(aaudio_usage_t usage) {
169     // The public aaudio_content_type_t constants are supposed to have the same
170     // values as the internal audio_content_type_t values.
171     STATIC_ASSERT(AAUDIO_USAGE_MEDIA == AUDIO_USAGE_MEDIA);
172     STATIC_ASSERT(AAUDIO_USAGE_VOICE_COMMUNICATION == AUDIO_USAGE_VOICE_COMMUNICATION);
173     STATIC_ASSERT(AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING
174                   == AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING);
175     STATIC_ASSERT(AAUDIO_USAGE_ALARM == AUDIO_USAGE_ALARM);
176     STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION == AUDIO_USAGE_NOTIFICATION);
177     STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION_RINGTONE
178                   == AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE);
179     STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION_EVENT == AUDIO_USAGE_NOTIFICATION_EVENT);
180     STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY);
181     STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE
182                   == AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE);
183     STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_SONIFICATION == AUDIO_USAGE_ASSISTANCE_SONIFICATION);
184     STATIC_ASSERT(AAUDIO_USAGE_GAME == AUDIO_USAGE_GAME);
185     STATIC_ASSERT(AAUDIO_USAGE_ASSISTANT == AUDIO_USAGE_ASSISTANT);
186     STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_EMERGENCY == AUDIO_USAGE_EMERGENCY);
187     STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_SAFETY == AUDIO_USAGE_SAFETY);
188     STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS == AUDIO_USAGE_VEHICLE_STATUS);
189     STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT == AUDIO_USAGE_ANNOUNCEMENT);
190     if (usage == AAUDIO_UNSPECIFIED) {
191         usage = AAUDIO_USAGE_MEDIA;
192     }
193     return (audio_usage_t) usage; // same value
194 }
195 
AAudioConvert_contentTypeToInternal(aaudio_content_type_t contentType)196 audio_content_type_t AAudioConvert_contentTypeToInternal(aaudio_content_type_t contentType) {
197     // The public aaudio_content_type_t constants are supposed to have the same
198     // values as the internal audio_content_type_t values.
199     STATIC_ASSERT(AAUDIO_CONTENT_TYPE_MUSIC == AUDIO_CONTENT_TYPE_MUSIC);
200     STATIC_ASSERT(AAUDIO_CONTENT_TYPE_SPEECH == AUDIO_CONTENT_TYPE_SPEECH);
201     STATIC_ASSERT(AAUDIO_CONTENT_TYPE_SONIFICATION == AUDIO_CONTENT_TYPE_SONIFICATION);
202     STATIC_ASSERT(AAUDIO_CONTENT_TYPE_MOVIE == AUDIO_CONTENT_TYPE_MOVIE);
203     if (contentType == AAUDIO_UNSPECIFIED) {
204         contentType = AAUDIO_CONTENT_TYPE_MUSIC;
205     }
206     return (audio_content_type_t) contentType; // same value
207 }
208 
AAudioConvert_inputPresetToAudioSource(aaudio_input_preset_t preset)209 audio_source_t AAudioConvert_inputPresetToAudioSource(aaudio_input_preset_t preset) {
210     // The public aaudio_input_preset_t constants are supposed to have the same
211     // values as the internal audio_source_t values.
212     STATIC_ASSERT(AAUDIO_UNSPECIFIED == AUDIO_SOURCE_DEFAULT);
213     STATIC_ASSERT(AAUDIO_INPUT_PRESET_GENERIC == AUDIO_SOURCE_MIC);
214     STATIC_ASSERT(AAUDIO_INPUT_PRESET_CAMCORDER == AUDIO_SOURCE_CAMCORDER);
215     STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_RECOGNITION == AUDIO_SOURCE_VOICE_RECOGNITION);
216     STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION == AUDIO_SOURCE_VOICE_COMMUNICATION);
217     STATIC_ASSERT(AAUDIO_INPUT_PRESET_UNPROCESSED == AUDIO_SOURCE_UNPROCESSED);
218     STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE == AUDIO_SOURCE_VOICE_PERFORMANCE);
219     if (preset == AAUDIO_UNSPECIFIED) {
220         preset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
221     }
222     return (audio_source_t) preset; // same value
223 }
224 
AAudioConvert_allowCapturePolicyToAudioFlagsMask(aaudio_allowed_capture_policy_t policy)225 audio_flags_mask_t AAudioConvert_allowCapturePolicyToAudioFlagsMask(
226         aaudio_allowed_capture_policy_t policy) {
227     switch (policy) {
228         case AAUDIO_UNSPECIFIED:
229         case AAUDIO_ALLOW_CAPTURE_BY_ALL:
230             return AUDIO_FLAG_NONE;
231         case AAUDIO_ALLOW_CAPTURE_BY_SYSTEM:
232             return AUDIO_FLAG_NO_MEDIA_PROJECTION;
233         case AAUDIO_ALLOW_CAPTURE_BY_NONE:
234             return AUDIO_FLAG_NO_MEDIA_PROJECTION | AUDIO_FLAG_NO_SYSTEM_CAPTURE;
235         default:
236             ALOGE("%s() 0x%08X unrecognized", __func__, policy);
237             return AUDIO_FLAG_NONE; //
238     }
239 }
240 
AAudioConvert_privacySensitiveToAudioFlagsMask(bool privacySensitive)241 audio_flags_mask_t AAudioConvert_privacySensitiveToAudioFlagsMask(
242         bool privacySensitive) {
243     return privacySensitive ? AUDIO_FLAG_CAPTURE_PRIVATE : AUDIO_FLAG_NONE;
244 }
245 
AAudioConvert_framesToBytes(int32_t numFrames,int32_t bytesPerFrame,int32_t * sizeInBytes)246 int32_t AAudioConvert_framesToBytes(int32_t numFrames,
247                                     int32_t bytesPerFrame,
248                                     int32_t *sizeInBytes) {
249     *sizeInBytes = 0;
250 
251     if (numFrames < 0 || bytesPerFrame < 0) {
252         ALOGE("negative size, numFrames = %d, frameSize = %d", numFrames, bytesPerFrame);
253         return AAUDIO_ERROR_OUT_OF_RANGE;
254     }
255 
256     // Prevent numeric overflow.
257     if (numFrames > (INT32_MAX / bytesPerFrame)) {
258         ALOGE("size overflow, numFrames = %d, frameSize = %d", numFrames, bytesPerFrame);
259         return AAUDIO_ERROR_OUT_OF_RANGE;
260     }
261 
262     *sizeInBytes = numFrames * bytesPerFrame;
263     return AAUDIO_OK;
264 }
265 
AAudioProperty_getMMapProperty(const char * propName,int32_t defaultValue,const char * caller)266 static int32_t AAudioProperty_getMMapProperty(const char *propName,
267                                               int32_t defaultValue,
268                                               const char * caller) {
269     int32_t prop = property_get_int32(propName, defaultValue);
270     switch (prop) {
271         case AAUDIO_UNSPECIFIED:
272         case AAUDIO_POLICY_NEVER:
273         case AAUDIO_POLICY_ALWAYS:
274         case AAUDIO_POLICY_AUTO:
275             break;
276         default:
277             ALOGE("%s: invalid = %d", caller, prop);
278             prop = defaultValue;
279             break;
280     }
281     return prop;
282 }
283 
AAudioProperty_getMMapPolicy()284 int32_t AAudioProperty_getMMapPolicy() {
285     return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_POLICY,
286                                           AAUDIO_UNSPECIFIED, __func__);
287 }
288 
AAudioProperty_getMMapExclusivePolicy()289 int32_t AAudioProperty_getMMapExclusivePolicy() {
290     return AAudioProperty_getMMapProperty(AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY,
291                                           AAUDIO_UNSPECIFIED, __func__);
292 }
293 
AAudioProperty_getMixerBursts()294 int32_t AAudioProperty_getMixerBursts() {
295     const int32_t defaultBursts = 2; // arbitrary, use 2 for double buffered
296     const int32_t maxBursts = 1024; // arbitrary
297     int32_t prop = property_get_int32(AAUDIO_PROP_MIXER_BURSTS, defaultBursts);
298     if (prop < 1 || prop > maxBursts) {
299         ALOGE("AAudioProperty_getMixerBursts: invalid = %d", prop);
300         prop = defaultBursts;
301     }
302     return prop;
303 }
304 
AAudioProperty_getWakeupDelayMicros()305 int32_t AAudioProperty_getWakeupDelayMicros() {
306     const int32_t minMicros = 0; // arbitrary
307     const int32_t defaultMicros = 200; // arbitrary, based on some observed jitter
308     const int32_t maxMicros = 5000; // arbitrary, probably don't want more than 500
309     int32_t prop = property_get_int32(AAUDIO_PROP_WAKEUP_DELAY_USEC, defaultMicros);
310     if (prop < minMicros) {
311         ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, minMicros);
312         prop = minMicros;
313     } else if (prop > maxMicros) {
314         ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, maxMicros);
315         prop = maxMicros;
316     }
317     return prop;
318 }
319 
AAudioProperty_getMinimumSleepMicros()320 int32_t AAudioProperty_getMinimumSleepMicros() {
321     const int32_t minMicros = 20; // arbitrary
322     const int32_t defaultMicros = 200; // arbitrary
323     const int32_t maxMicros = 2000; // arbitrary
324     int32_t prop = property_get_int32(AAUDIO_PROP_MINIMUM_SLEEP_USEC, defaultMicros);
325     if (prop < minMicros) {
326         ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, minMicros);
327         prop = minMicros;
328     } else if (prop > maxMicros) {
329         ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, maxMicros);
330         prop = maxMicros;
331     }
332     return prop;
333 }
334 
AAudioProperty_getHardwareBurstMinMicros()335 int32_t AAudioProperty_getHardwareBurstMinMicros() {
336     const int32_t defaultMicros = 1000; // arbitrary
337     const int32_t maxMicros = 1000 * 1000; // arbitrary
338     int32_t prop = property_get_int32(AAUDIO_PROP_HW_BURST_MIN_USEC, defaultMicros);
339     if (prop < 1 || prop > maxMicros) {
340         ALOGE("AAudioProperty_getHardwareBurstMinMicros: invalid = %d, use %d",
341               prop, defaultMicros);
342         prop = defaultMicros;
343     }
344     return prop;
345 }
346 
AAudioProperty_getMMapOffsetMicros(const char * functionName,const char * propertyName)347 static int32_t AAudioProperty_getMMapOffsetMicros(const char *functionName,
348         const char *propertyName) {
349     const int32_t minMicros = -20000; // arbitrary
350     const int32_t defaultMicros = 0;  // arbitrary
351     const int32_t maxMicros =  20000; // arbitrary
352     int32_t prop = property_get_int32(propertyName, defaultMicros);
353     if (prop < minMicros) {
354         ALOGW("%s: clipped %d to %d", functionName, prop, minMicros);
355         prop = minMicros;
356     } else if (prop > maxMicros) {
357         ALOGW("%s: clipped %d to %d", functionName, prop, minMicros);
358         prop = maxMicros;
359     }
360     return prop;
361 }
362 
AAudioProperty_getInputMMapOffsetMicros()363 int32_t AAudioProperty_getInputMMapOffsetMicros() {
364     return AAudioProperty_getMMapOffsetMicros(__func__, AAUDIO_PROP_INPUT_MMAP_OFFSET_USEC);
365 }
366 
AAudioProperty_getOutputMMapOffsetMicros()367 int32_t AAudioProperty_getOutputMMapOffsetMicros() {
368     return AAudioProperty_getMMapOffsetMicros(__func__, AAUDIO_PROP_OUTPUT_MMAP_OFFSET_USEC);
369 }
370 
AAudioProperty_getLogMask()371 int32_t AAudioProperty_getLogMask() {
372     return property_get_int32(AAUDIO_PROP_LOG_MASK, 0);
373 }
374 
AAudio_isFlushAllowed(aaudio_stream_state_t state)375 aaudio_result_t AAudio_isFlushAllowed(aaudio_stream_state_t state) {
376     aaudio_result_t result = AAUDIO_OK;
377     switch (state) {
378 // Proceed with flushing.
379         case AAUDIO_STREAM_STATE_OPEN:
380         case AAUDIO_STREAM_STATE_PAUSED:
381         case AAUDIO_STREAM_STATE_STOPPED:
382         case AAUDIO_STREAM_STATE_FLUSHED:
383             break;
384 
385 // Transition from one inactive state to another.
386         case AAUDIO_STREAM_STATE_STARTING:
387         case AAUDIO_STREAM_STATE_STARTED:
388         case AAUDIO_STREAM_STATE_STOPPING:
389         case AAUDIO_STREAM_STATE_PAUSING:
390         case AAUDIO_STREAM_STATE_FLUSHING:
391         case AAUDIO_STREAM_STATE_CLOSING:
392         case AAUDIO_STREAM_STATE_CLOSED:
393         case AAUDIO_STREAM_STATE_DISCONNECTED:
394         default:
395             ALOGE("can only flush stream when PAUSED, OPEN or STOPPED, state = %s",
396                   aaudio::AudioGlobal_convertStreamStateToText(state));
397             result =  AAUDIO_ERROR_INVALID_STATE;
398             break;
399     }
400     return result;
401 }
402