| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 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 | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 19 |  | 
| jiabin | 4a34186 | 2022-09-20 17:58:37 +0000 | [diff] [blame] | 20 | #include <assert.h> | 
|  | 21 | #include <math.h> | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 22 | #include <stdint.h> | 
| jiabin | 4a34186 | 2022-09-20 17:58:37 +0000 | [diff] [blame] | 23 |  | 
|  | 24 | #include <aaudio/AAudioTesting.h> | 
|  | 25 | #include <android/media/audio/common/AudioMMapPolicy.h> | 
|  | 26 | #include <cutils/properties.h> | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 27 | #include <sys/types.h> | 
| jiabin | 4a34186 | 2022-09-20 17:58:37 +0000 | [diff] [blame] | 28 | #include <system/audio.h> | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 29 | #include <utils/Errors.h> | 
| jiabin | 4a34186 | 2022-09-20 17:58:37 +0000 | [diff] [blame] | 30 | #include <utils/Log.h> | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 31 |  | 
| Phil Burk | a4eb0d8 | 2017-04-12 15:44:06 -0700 | [diff] [blame] | 32 | #include "aaudio/AAudio.h" | 
| dimitry | 2d2f17c | 2019-07-17 13:55:16 +0200 | [diff] [blame] | 33 | #include "core/AudioGlobal.h" | 
| Phil Burk | d04aeea | 2017-05-23 13:56:41 -0700 | [diff] [blame] | 34 | #include "utility/AAudioUtilities.h" | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 35 |  | 
|  | 36 | using namespace android; | 
|  | 37 |  | 
| jiabin | 4a34186 | 2022-09-20 17:58:37 +0000 | [diff] [blame] | 38 | using android::media::audio::common::AudioMMapPolicy; | 
|  | 39 | using android::media::audio::common::AudioMMapPolicyInfo; | 
|  | 40 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 41 | status_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 Laurent | a2f296e | 2017-06-21 18:51:47 -0700 | [diff] [blame] | 49 | case AAUDIO_ERROR_NO_SERVICE: | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 50 | status = DEAD_OBJECT; | 
|  | 51 | break; | 
| Eric Laurent | a2f296e | 2017-06-21 18:51:47 -0700 | [diff] [blame] | 52 | case AAUDIO_ERROR_INVALID_HANDLE: | 
|  | 53 | status = BAD_TYPE; | 
|  | 54 | break; | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 55 | case AAUDIO_ERROR_INVALID_STATE: | 
|  | 56 | status = INVALID_OPERATION; | 
|  | 57 | break; | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 58 | case AAUDIO_ERROR_INVALID_RATE: | 
|  | 59 | case AAUDIO_ERROR_INVALID_FORMAT: | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 60 | case AAUDIO_ERROR_ILLEGAL_ARGUMENT: | 
| Phil Burk | 5204d31 | 2017-05-04 17:16:13 -0700 | [diff] [blame] | 61 | case AAUDIO_ERROR_OUT_OF_RANGE: | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 62 | status = BAD_VALUE; | 
|  | 63 | break; | 
|  | 64 | case AAUDIO_ERROR_WOULD_BLOCK: | 
|  | 65 | status = WOULD_BLOCK; | 
|  | 66 | break; | 
| Phil Burk | 5204d31 | 2017-05-04 17:16:13 -0700 | [diff] [blame] | 67 | case AAUDIO_ERROR_NULL: | 
|  | 68 | status = UNEXPECTED_NULL; | 
|  | 69 | break; | 
| Phil Burk | 940083c | 2017-07-17 17:00:02 -0700 | [diff] [blame] | 70 | case AAUDIO_ERROR_UNAVAILABLE: | 
|  | 71 | status = NOT_ENOUGH_DATA; | 
|  | 72 | break; | 
|  | 73 |  | 
| Phil Burk | 5204d31 | 2017-05-04 17:16:13 -0700 | [diff] [blame] | 74 | // TODO translate these result codes | 
| Phil Burk | 5204d31 | 2017-05-04 17:16:13 -0700 | [diff] [blame] | 75 | case AAUDIO_ERROR_INTERNAL: | 
| Phil Burk | 5204d31 | 2017-05-04 17:16:13 -0700 | [diff] [blame] | 76 | case AAUDIO_ERROR_UNIMPLEMENTED: | 
| Phil Burk | 5204d31 | 2017-05-04 17:16:13 -0700 | [diff] [blame] | 77 | case AAUDIO_ERROR_NO_FREE_HANDLES: | 
|  | 78 | case AAUDIO_ERROR_NO_MEMORY: | 
|  | 79 | case AAUDIO_ERROR_TIMEOUT: | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 80 | default: | 
|  | 81 | status = UNKNOWN_ERROR; | 
|  | 82 | break; | 
|  | 83 | } | 
|  | 84 | return status; | 
|  | 85 | } | 
|  | 86 |  | 
|  | 87 | aaudio_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 Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 98 | result = AAUDIO_ERROR_NO_SERVICE; | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 99 | break; | 
|  | 100 | case INVALID_OPERATION: | 
|  | 101 | result = AAUDIO_ERROR_INVALID_STATE; | 
|  | 102 | break; | 
| Eric Laurent | a2f296e | 2017-06-21 18:51:47 -0700 | [diff] [blame] | 103 | case UNEXPECTED_NULL: | 
|  | 104 | result = AAUDIO_ERROR_NULL; | 
|  | 105 | break; | 
|  | 106 | case BAD_VALUE: | 
|  | 107 | result = AAUDIO_ERROR_ILLEGAL_ARGUMENT; | 
|  | 108 | break; | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 109 | case WOULD_BLOCK: | 
|  | 110 | result = AAUDIO_ERROR_WOULD_BLOCK; | 
|  | 111 | break; | 
| Phil Burk | 940083c | 2017-07-17 17:00:02 -0700 | [diff] [blame] | 112 | case NOT_ENOUGH_DATA: | 
|  | 113 | result = AAUDIO_ERROR_UNAVAILABLE; | 
|  | 114 | break; | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 115 | default: | 
|  | 116 | result = AAUDIO_ERROR_INTERNAL; | 
|  | 117 | break; | 
|  | 118 | } | 
|  | 119 | return result; | 
|  | 120 | } | 
|  | 121 |  | 
| Phil Burk | 4e1af9f | 2018-01-03 15:54:35 -0800 | [diff] [blame] | 122 | audio_session_t AAudioConvert_aaudioToAndroidSessionId(aaudio_session_id_t sessionId) { | 
| Phil Burk | 67fdd89 | 2018-01-23 15:28:55 -0800 | [diff] [blame] | 123 | // 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 Burk | 4e1af9f | 2018-01-03 15:54:35 -0800 | [diff] [blame] | 125 | ? AUDIO_SESSION_ALLOCATE | 
|  | 126 | : (audio_session_t) sessionId; | 
|  | 127 | } | 
|  | 128 |  | 
| Phil Burk | 9dca982 | 2017-05-26 14:27:43 -0700 | [diff] [blame] | 129 | audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudioFormat) { | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 130 | audio_format_t androidFormat; | 
|  | 131 | switch (aaudioFormat) { | 
| Phil Burk | 0127c1b | 2018-03-29 13:48:06 -0700 | [diff] [blame] | 132 | case AAUDIO_FORMAT_UNSPECIFIED: | 
|  | 133 | androidFormat = AUDIO_FORMAT_DEFAULT; | 
|  | 134 | break; | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 135 | 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 Burk | 04e805b | 2018-03-27 09:13:53 -0700 | [diff] [blame] | 141 | 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; | 
| jiabin | ca6a3f4 | 2022-06-09 20:33:47 +0000 | [diff] [blame] | 147 | case AAUDIO_FORMAT_IEC61937: | 
|  | 148 | androidFormat = AUDIO_FORMAT_IEC61937; | 
|  | 149 | break; | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 150 | default: | 
| Phil Burk | 0127c1b | 2018-03-29 13:48:06 -0700 | [diff] [blame] | 151 | androidFormat = AUDIO_FORMAT_INVALID; | 
|  | 152 | ALOGE("%s() 0x%08X unrecognized", __func__, aaudioFormat); | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 153 | break; | 
|  | 154 | } | 
|  | 155 | return androidFormat; | 
|  | 156 | } | 
|  | 157 |  | 
| Phil Burk | 9dca982 | 2017-05-26 14:27:43 -0700 | [diff] [blame] | 158 | aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t androidFormat) { | 
| Phil Burk | 0127c1b | 2018-03-29 13:48:06 -0700 | [diff] [blame] | 159 | aaudio_format_t aaudioFormat; | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 160 | switch (androidFormat) { | 
| Phil Burk | 0127c1b | 2018-03-29 13:48:06 -0700 | [diff] [blame] | 161 | case AUDIO_FORMAT_DEFAULT: | 
|  | 162 | aaudioFormat = AAUDIO_FORMAT_UNSPECIFIED; | 
|  | 163 | break; | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 164 | 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 Burk | 04e805b | 2018-03-27 09:13:53 -0700 | [diff] [blame] | 170 | 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; | 
| jiabin | ca6a3f4 | 2022-06-09 20:33:47 +0000 | [diff] [blame] | 176 | case AUDIO_FORMAT_IEC61937: | 
|  | 177 | aaudioFormat = AAUDIO_FORMAT_IEC61937; | 
|  | 178 | break; | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 179 | default: | 
|  | 180 | aaudioFormat = AAUDIO_FORMAT_INVALID; | 
| Phil Burk | 0127c1b | 2018-03-29 13:48:06 -0700 | [diff] [blame] | 181 | ALOGE("%s() 0x%08X unrecognized", __func__, androidFormat); | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 182 | break; | 
|  | 183 | } | 
|  | 184 | return aaudioFormat; | 
|  | 185 | } | 
|  | 186 |  | 
| Robert Wu | 310037a | 2022-09-06 21:48:18 +0000 | [diff] [blame] | 187 | aaudio_format_t AAudioConvert_androidToNearestAAudioDataFormat(audio_format_t androidFormat) { | 
|  | 188 | // Special case AUDIO_FORMAT_PCM_8_24_BIT because this function should be used to find the | 
|  | 189 | // resolution of the data format. Setting AUDIO_FORMAT_PCM_8_24_BIT directly is not available | 
|  | 190 | // from AAudio but hardware may use AUDIO_FORMAT_PCM_8_24_BIT under the hood. | 
|  | 191 | if (androidFormat == AUDIO_FORMAT_PCM_8_24_BIT) { | 
|  | 192 | ALOGD("%s() converting 8.24 to 24 bit packed", __func__); | 
|  | 193 | return AAUDIO_FORMAT_PCM_I24_PACKED; | 
|  | 194 | } | 
|  | 195 | return AAudioConvert_androidToAAudioDataFormat(androidFormat); | 
|  | 196 | } | 
|  | 197 |  | 
| Phil Burk | d4ccc62 | 2017-12-20 15:32:44 -0800 | [diff] [blame] | 198 | // Make a message string from the condition. | 
|  | 199 | #define STATIC_ASSERT(condition) static_assert(condition, #condition) | 
|  | 200 |  | 
|  | 201 | audio_usage_t AAudioConvert_usageToInternal(aaudio_usage_t usage) { | 
|  | 202 | // The public aaudio_content_type_t constants are supposed to have the same | 
|  | 203 | // values as the internal audio_content_type_t values. | 
|  | 204 | STATIC_ASSERT(AAUDIO_USAGE_MEDIA == AUDIO_USAGE_MEDIA); | 
|  | 205 | STATIC_ASSERT(AAUDIO_USAGE_VOICE_COMMUNICATION == AUDIO_USAGE_VOICE_COMMUNICATION); | 
|  | 206 | STATIC_ASSERT(AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING | 
|  | 207 | == AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING); | 
|  | 208 | STATIC_ASSERT(AAUDIO_USAGE_ALARM == AUDIO_USAGE_ALARM); | 
|  | 209 | STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION == AUDIO_USAGE_NOTIFICATION); | 
|  | 210 | STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION_RINGTONE | 
|  | 211 | == AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE); | 
|  | 212 | STATIC_ASSERT(AAUDIO_USAGE_NOTIFICATION_EVENT == AUDIO_USAGE_NOTIFICATION_EVENT); | 
|  | 213 | STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY); | 
|  | 214 | STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE | 
|  | 215 | == AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE); | 
|  | 216 | STATIC_ASSERT(AAUDIO_USAGE_ASSISTANCE_SONIFICATION == AUDIO_USAGE_ASSISTANCE_SONIFICATION); | 
|  | 217 | STATIC_ASSERT(AAUDIO_USAGE_GAME == AUDIO_USAGE_GAME); | 
|  | 218 | STATIC_ASSERT(AAUDIO_USAGE_ASSISTANT == AUDIO_USAGE_ASSISTANT); | 
| Hayden Gomes | 3e8bbb9 | 2020-01-10 13:37:05 -0800 | [diff] [blame] | 219 | STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_EMERGENCY == AUDIO_USAGE_EMERGENCY); | 
|  | 220 | STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_SAFETY == AUDIO_USAGE_SAFETY); | 
|  | 221 | STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS == AUDIO_USAGE_VEHICLE_STATUS); | 
|  | 222 | STATIC_ASSERT(AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT == AUDIO_USAGE_ANNOUNCEMENT); | 
| Phil Burk | d4ccc62 | 2017-12-20 15:32:44 -0800 | [diff] [blame] | 223 | if (usage == AAUDIO_UNSPECIFIED) { | 
|  | 224 | usage = AAUDIO_USAGE_MEDIA; | 
|  | 225 | } | 
|  | 226 | return (audio_usage_t) usage; // same value | 
|  | 227 | } | 
|  | 228 |  | 
|  | 229 | audio_content_type_t AAudioConvert_contentTypeToInternal(aaudio_content_type_t contentType) { | 
|  | 230 | // The public aaudio_content_type_t constants are supposed to have the same | 
|  | 231 | // values as the internal audio_content_type_t values. | 
|  | 232 | STATIC_ASSERT(AAUDIO_CONTENT_TYPE_MUSIC == AUDIO_CONTENT_TYPE_MUSIC); | 
|  | 233 | STATIC_ASSERT(AAUDIO_CONTENT_TYPE_SPEECH == AUDIO_CONTENT_TYPE_SPEECH); | 
|  | 234 | STATIC_ASSERT(AAUDIO_CONTENT_TYPE_SONIFICATION == AUDIO_CONTENT_TYPE_SONIFICATION); | 
|  | 235 | STATIC_ASSERT(AAUDIO_CONTENT_TYPE_MOVIE == AUDIO_CONTENT_TYPE_MOVIE); | 
|  | 236 | if (contentType == AAUDIO_UNSPECIFIED) { | 
|  | 237 | contentType = AAUDIO_CONTENT_TYPE_MUSIC; | 
|  | 238 | } | 
|  | 239 | return (audio_content_type_t) contentType; // same value | 
|  | 240 | } | 
|  | 241 |  | 
|  | 242 | audio_source_t AAudioConvert_inputPresetToAudioSource(aaudio_input_preset_t preset) { | 
|  | 243 | // The public aaudio_input_preset_t constants are supposed to have the same | 
|  | 244 | // values as the internal audio_source_t values. | 
|  | 245 | STATIC_ASSERT(AAUDIO_UNSPECIFIED == AUDIO_SOURCE_DEFAULT); | 
|  | 246 | STATIC_ASSERT(AAUDIO_INPUT_PRESET_GENERIC == AUDIO_SOURCE_MIC); | 
|  | 247 | STATIC_ASSERT(AAUDIO_INPUT_PRESET_CAMCORDER == AUDIO_SOURCE_CAMCORDER); | 
|  | 248 | STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_RECOGNITION == AUDIO_SOURCE_VOICE_RECOGNITION); | 
|  | 249 | STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION == AUDIO_SOURCE_VOICE_COMMUNICATION); | 
|  | 250 | STATIC_ASSERT(AAUDIO_INPUT_PRESET_UNPROCESSED == AUDIO_SOURCE_UNPROCESSED); | 
| Eric Laurent | ae4b6ec | 2019-01-15 18:34:38 -0800 | [diff] [blame] | 251 | STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE == AUDIO_SOURCE_VOICE_PERFORMANCE); | 
| Phil Burk | d4ccc62 | 2017-12-20 15:32:44 -0800 | [diff] [blame] | 252 | if (preset == AAUDIO_UNSPECIFIED) { | 
| Phil Burk | eaef9b9 | 2018-01-18 09:09:42 -0800 | [diff] [blame] | 253 | preset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION; | 
| Phil Burk | d4ccc62 | 2017-12-20 15:32:44 -0800 | [diff] [blame] | 254 | } | 
|  | 255 | return (audio_source_t) preset; // same value | 
|  | 256 | } | 
|  | 257 |  | 
| Eric Laurent | fa7fe4d | 2023-04-21 15:58:59 +0200 | [diff] [blame] | 258 | audio_flags_mask_t AAudio_computeAudioFlagsMask( | 
| Jean-Michel Trivi | 656bfdc | 2021-09-20 18:42:37 -0700 | [diff] [blame] | 259 | aaudio_allowed_capture_policy_t policy, | 
|  | 260 | aaudio_spatialization_behavior_t spatializationBehavior, | 
| Eric Laurent | fa7fe4d | 2023-04-21 15:58:59 +0200 | [diff] [blame] | 261 | bool isContentSpatialized, | 
|  | 262 | audio_output_flags_t outputFlags) { | 
| Jean-Michel Trivi | 656bfdc | 2021-09-20 18:42:37 -0700 | [diff] [blame] | 263 | audio_flags_mask_t flagsMask = AUDIO_FLAG_NONE; | 
| Kevin Rocard | 68646ba | 2019-03-20 13:26:49 -0700 | [diff] [blame] | 264 | switch (policy) { | 
|  | 265 | case AAUDIO_UNSPECIFIED: | 
|  | 266 | case AAUDIO_ALLOW_CAPTURE_BY_ALL: | 
| Jean-Michel Trivi | 656bfdc | 2021-09-20 18:42:37 -0700 | [diff] [blame] | 267 | // flagsMask is not modified | 
|  | 268 | break; | 
| Kevin Rocard | 68646ba | 2019-03-20 13:26:49 -0700 | [diff] [blame] | 269 | case AAUDIO_ALLOW_CAPTURE_BY_SYSTEM: | 
| Jean-Michel Trivi | 656bfdc | 2021-09-20 18:42:37 -0700 | [diff] [blame] | 270 | flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_NO_MEDIA_PROJECTION); | 
|  | 271 | break; | 
| Kevin Rocard | 68646ba | 2019-03-20 13:26:49 -0700 | [diff] [blame] | 272 | case AAUDIO_ALLOW_CAPTURE_BY_NONE: | 
| Jean-Michel Trivi | 656bfdc | 2021-09-20 18:42:37 -0700 | [diff] [blame] | 273 | flagsMask = static_cast<audio_flags_mask_t>(flagsMask | | 
| Mikhail Naganov | 5577303 | 2020-10-01 15:08:13 -0700 | [diff] [blame] | 274 | AUDIO_FLAG_NO_MEDIA_PROJECTION | AUDIO_FLAG_NO_SYSTEM_CAPTURE); | 
| Jean-Michel Trivi | 656bfdc | 2021-09-20 18:42:37 -0700 | [diff] [blame] | 275 | break; | 
| Kevin Rocard | 68646ba | 2019-03-20 13:26:49 -0700 | [diff] [blame] | 276 | default: | 
| Jean-Michel Trivi | 656bfdc | 2021-09-20 18:42:37 -0700 | [diff] [blame] | 277 | ALOGE("%s() 0x%08X unrecognized capture policy", __func__, policy); | 
|  | 278 | // flagsMask is not modified | 
| Kevin Rocard | 68646ba | 2019-03-20 13:26:49 -0700 | [diff] [blame] | 279 | } | 
| Jean-Michel Trivi | 656bfdc | 2021-09-20 18:42:37 -0700 | [diff] [blame] | 280 |  | 
|  | 281 | switch (spatializationBehavior) { | 
|  | 282 | case AAUDIO_UNSPECIFIED: | 
|  | 283 | case AAUDIO_SPATIALIZATION_BEHAVIOR_AUTO: | 
|  | 284 | // flagsMask is not modified | 
|  | 285 | break; | 
|  | 286 | case AAUDIO_SPATIALIZATION_BEHAVIOR_NEVER: | 
|  | 287 | flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_NEVER_SPATIALIZE); | 
|  | 288 | break; | 
|  | 289 | default: | 
|  | 290 | ALOGE("%s() 0x%08X unrecognized spatialization behavior", | 
|  | 291 | __func__, spatializationBehavior); | 
|  | 292 | // flagsMask is not modified | 
|  | 293 | } | 
|  | 294 |  | 
|  | 295 | if (isContentSpatialized) { | 
|  | 296 | flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_CONTENT_SPATIALIZED); | 
|  | 297 | } | 
|  | 298 |  | 
| Eric Laurent | fa7fe4d | 2023-04-21 15:58:59 +0200 | [diff] [blame] | 299 | if ((outputFlags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) { | 
|  | 300 | flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_HW_AV_SYNC); | 
|  | 301 | } | 
|  | 302 | if ((outputFlags & AUDIO_OUTPUT_FLAG_FAST) != 0) { | 
|  | 303 | flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_LOW_LATENCY); | 
|  | 304 | } else if ((outputFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) { | 
|  | 305 | flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_DEEP_BUFFER); | 
|  | 306 | } | 
|  | 307 |  | 
| Jean-Michel Trivi | 656bfdc | 2021-09-20 18:42:37 -0700 | [diff] [blame] | 308 | return flagsMask; | 
| Kevin Rocard | 68646ba | 2019-03-20 13:26:49 -0700 | [diff] [blame] | 309 | } | 
|  | 310 |  | 
| Eric Laurent | d17c850 | 2019-10-24 15:58:35 -0700 | [diff] [blame] | 311 | audio_flags_mask_t AAudioConvert_privacySensitiveToAudioFlagsMask( | 
|  | 312 | bool privacySensitive) { | 
|  | 313 | return privacySensitive ? AUDIO_FLAG_CAPTURE_PRIVATE : AUDIO_FLAG_NONE; | 
|  | 314 | } | 
|  | 315 |  | 
| jiabin | a909409 | 2021-06-28 20:36:45 +0000 | [diff] [blame] | 316 | audio_channel_mask_t AAudioConvert_aaudioToAndroidChannelLayoutMask( | 
|  | 317 | aaudio_channel_mask_t channelMask, bool isInput) { | 
|  | 318 | if (isInput) { | 
|  | 319 | switch (channelMask) { | 
|  | 320 | case AAUDIO_CHANNEL_MONO: | 
|  | 321 | return AUDIO_CHANNEL_IN_MONO; | 
|  | 322 | case AAUDIO_CHANNEL_STEREO: | 
|  | 323 | return AUDIO_CHANNEL_IN_STEREO; | 
|  | 324 | case AAUDIO_CHANNEL_FRONT_BACK: | 
|  | 325 | return AUDIO_CHANNEL_IN_FRONT_BACK; | 
|  | 326 | case AAUDIO_CHANNEL_2POINT0POINT2: | 
|  | 327 | return AUDIO_CHANNEL_IN_2POINT0POINT2; | 
|  | 328 | case AAUDIO_CHANNEL_2POINT1POINT2: | 
|  | 329 | return AUDIO_CHANNEL_IN_2POINT1POINT2; | 
|  | 330 | case AAUDIO_CHANNEL_3POINT0POINT2: | 
|  | 331 | return AUDIO_CHANNEL_IN_3POINT0POINT2; | 
|  | 332 | case AAUDIO_CHANNEL_3POINT1POINT2: | 
|  | 333 | return AUDIO_CHANNEL_IN_3POINT1POINT2; | 
|  | 334 | case AAUDIO_CHANNEL_5POINT1: | 
|  | 335 | return AUDIO_CHANNEL_IN_5POINT1; | 
|  | 336 | default: | 
|  | 337 | ALOGE("%s() %#x unrecognized", __func__, channelMask); | 
|  | 338 | return AUDIO_CHANNEL_INVALID; | 
|  | 339 | } | 
|  | 340 | } else { | 
|  | 341 | switch (channelMask) { | 
|  | 342 | case AAUDIO_CHANNEL_MONO: | 
|  | 343 | return AUDIO_CHANNEL_OUT_MONO; | 
|  | 344 | case AAUDIO_CHANNEL_STEREO: | 
|  | 345 | return AUDIO_CHANNEL_OUT_STEREO; | 
|  | 346 | case AAUDIO_CHANNEL_2POINT1: | 
|  | 347 | return AUDIO_CHANNEL_OUT_2POINT1; | 
|  | 348 | case AAUDIO_CHANNEL_TRI: | 
|  | 349 | return AUDIO_CHANNEL_OUT_TRI; | 
|  | 350 | case AAUDIO_CHANNEL_TRI_BACK: | 
|  | 351 | return AUDIO_CHANNEL_OUT_TRI_BACK; | 
|  | 352 | case AAUDIO_CHANNEL_3POINT1: | 
|  | 353 | return AUDIO_CHANNEL_OUT_3POINT1; | 
|  | 354 | case AAUDIO_CHANNEL_2POINT0POINT2: | 
|  | 355 | return AUDIO_CHANNEL_OUT_2POINT0POINT2; | 
|  | 356 | case AAUDIO_CHANNEL_2POINT1POINT2: | 
|  | 357 | return AUDIO_CHANNEL_OUT_2POINT1POINT2; | 
|  | 358 | case AAUDIO_CHANNEL_3POINT0POINT2: | 
|  | 359 | return AUDIO_CHANNEL_OUT_3POINT0POINT2; | 
|  | 360 | case AAUDIO_CHANNEL_3POINT1POINT2: | 
|  | 361 | return AUDIO_CHANNEL_OUT_3POINT1POINT2; | 
|  | 362 | case AAUDIO_CHANNEL_QUAD: | 
|  | 363 | return AUDIO_CHANNEL_OUT_QUAD; | 
|  | 364 | case AAUDIO_CHANNEL_QUAD_SIDE: | 
|  | 365 | return AUDIO_CHANNEL_OUT_QUAD_SIDE; | 
|  | 366 | case AAUDIO_CHANNEL_SURROUND: | 
|  | 367 | return AUDIO_CHANNEL_OUT_SURROUND; | 
|  | 368 | case AAUDIO_CHANNEL_PENTA: | 
|  | 369 | return AUDIO_CHANNEL_OUT_PENTA; | 
|  | 370 | case AAUDIO_CHANNEL_5POINT1: | 
|  | 371 | return AUDIO_CHANNEL_OUT_5POINT1; | 
|  | 372 | case AAUDIO_CHANNEL_5POINT1_SIDE: | 
|  | 373 | return AUDIO_CHANNEL_OUT_5POINT1_SIDE; | 
|  | 374 | case AAUDIO_CHANNEL_5POINT1POINT2: | 
|  | 375 | return AUDIO_CHANNEL_OUT_5POINT1POINT2; | 
|  | 376 | case AAUDIO_CHANNEL_5POINT1POINT4: | 
|  | 377 | return AUDIO_CHANNEL_OUT_5POINT1POINT4; | 
|  | 378 | case AAUDIO_CHANNEL_6POINT1: | 
|  | 379 | return AUDIO_CHANNEL_OUT_6POINT1; | 
|  | 380 | case AAUDIO_CHANNEL_7POINT1: | 
|  | 381 | return AUDIO_CHANNEL_OUT_7POINT1; | 
|  | 382 | case AAUDIO_CHANNEL_7POINT1POINT2: | 
|  | 383 | return AUDIO_CHANNEL_OUT_7POINT1POINT2; | 
|  | 384 | case AAUDIO_CHANNEL_7POINT1POINT4: | 
|  | 385 | return AUDIO_CHANNEL_OUT_7POINT1POINT4; | 
|  | 386 | // TODO: add 9point1point4 and 9point1point6 when they are added in audio-hal-enums.h | 
|  | 387 | // case AAUDIO_CHANNEL_9POINT1POINT4: | 
|  | 388 | //     return AUDIO_CHANNEL_OUT_9POINT1POINT4; | 
|  | 389 | // case AAUDIO_CHANNEL_9POINT1POINT6: | 
|  | 390 | //     return AUDIO_CHANNEL_OUT_9POINT1POINT6; | 
|  | 391 | default: | 
|  | 392 | ALOGE("%s() %#x unrecognized", __func__, channelMask); | 
|  | 393 | return AUDIO_CHANNEL_INVALID; | 
|  | 394 | } | 
|  | 395 | } | 
|  | 396 | } | 
|  | 397 |  | 
|  | 398 | aaudio_channel_mask_t AAudioConvert_androidToAAudioChannelLayoutMask( | 
|  | 399 | audio_channel_mask_t channelMask, bool isInput) { | 
|  | 400 | if (isInput) { | 
|  | 401 | switch (channelMask) { | 
|  | 402 | case AUDIO_CHANNEL_IN_MONO: | 
|  | 403 | return AAUDIO_CHANNEL_MONO; | 
|  | 404 | case AUDIO_CHANNEL_IN_STEREO: | 
|  | 405 | return AAUDIO_CHANNEL_STEREO; | 
|  | 406 | case AUDIO_CHANNEL_IN_FRONT_BACK: | 
|  | 407 | return AAUDIO_CHANNEL_FRONT_BACK; | 
|  | 408 | case AUDIO_CHANNEL_IN_2POINT0POINT2: | 
|  | 409 | return AAUDIO_CHANNEL_2POINT0POINT2; | 
|  | 410 | case AUDIO_CHANNEL_IN_2POINT1POINT2: | 
|  | 411 | return AAUDIO_CHANNEL_2POINT1POINT2; | 
|  | 412 | case AUDIO_CHANNEL_IN_3POINT0POINT2: | 
|  | 413 | return AAUDIO_CHANNEL_3POINT0POINT2; | 
|  | 414 | case AUDIO_CHANNEL_IN_3POINT1POINT2: | 
|  | 415 | return AAUDIO_CHANNEL_3POINT1POINT2; | 
|  | 416 | case AUDIO_CHANNEL_IN_5POINT1: | 
|  | 417 | return AAUDIO_CHANNEL_5POINT1; | 
|  | 418 | default: | 
|  | 419 | ALOGE("%s() %#x unrecognized", __func__, channelMask); | 
|  | 420 | return AAUDIO_CHANNEL_INVALID; | 
|  | 421 | } | 
|  | 422 | } else { | 
|  | 423 | switch (channelMask) { | 
|  | 424 | case AUDIO_CHANNEL_OUT_MONO: | 
|  | 425 | return AAUDIO_CHANNEL_MONO; | 
|  | 426 | case AUDIO_CHANNEL_OUT_STEREO: | 
|  | 427 | return AAUDIO_CHANNEL_STEREO; | 
|  | 428 | case AUDIO_CHANNEL_OUT_2POINT1: | 
|  | 429 | return AAUDIO_CHANNEL_2POINT1; | 
|  | 430 | case AUDIO_CHANNEL_OUT_TRI: | 
|  | 431 | return AAUDIO_CHANNEL_TRI; | 
|  | 432 | case AUDIO_CHANNEL_OUT_TRI_BACK: | 
|  | 433 | return AAUDIO_CHANNEL_TRI_BACK; | 
|  | 434 | case AUDIO_CHANNEL_OUT_3POINT1: | 
|  | 435 | return AAUDIO_CHANNEL_3POINT1; | 
|  | 436 | case AUDIO_CHANNEL_OUT_2POINT0POINT2: | 
|  | 437 | return AAUDIO_CHANNEL_2POINT0POINT2; | 
|  | 438 | case AUDIO_CHANNEL_OUT_2POINT1POINT2: | 
|  | 439 | return AAUDIO_CHANNEL_2POINT1POINT2; | 
|  | 440 | case AUDIO_CHANNEL_OUT_3POINT0POINT2: | 
|  | 441 | return AAUDIO_CHANNEL_3POINT0POINT2; | 
|  | 442 | case AUDIO_CHANNEL_OUT_3POINT1POINT2: | 
|  | 443 | return AAUDIO_CHANNEL_3POINT1POINT2; | 
|  | 444 | case AUDIO_CHANNEL_OUT_QUAD: | 
|  | 445 | return AAUDIO_CHANNEL_QUAD; | 
|  | 446 | case AUDIO_CHANNEL_OUT_QUAD_SIDE: | 
|  | 447 | return AAUDIO_CHANNEL_QUAD_SIDE; | 
|  | 448 | case AUDIO_CHANNEL_OUT_SURROUND: | 
|  | 449 | return AAUDIO_CHANNEL_SURROUND; | 
|  | 450 | case AUDIO_CHANNEL_OUT_PENTA: | 
|  | 451 | return AAUDIO_CHANNEL_PENTA; | 
|  | 452 | case AUDIO_CHANNEL_OUT_5POINT1: | 
|  | 453 | return AAUDIO_CHANNEL_5POINT1; | 
|  | 454 | case AUDIO_CHANNEL_OUT_5POINT1_SIDE: | 
|  | 455 | return AAUDIO_CHANNEL_5POINT1_SIDE; | 
|  | 456 | case AUDIO_CHANNEL_OUT_5POINT1POINT2: | 
|  | 457 | return AAUDIO_CHANNEL_5POINT1POINT2; | 
|  | 458 | case AUDIO_CHANNEL_OUT_5POINT1POINT4: | 
|  | 459 | return AAUDIO_CHANNEL_5POINT1POINT4; | 
|  | 460 | case AUDIO_CHANNEL_OUT_6POINT1: | 
|  | 461 | return AAUDIO_CHANNEL_6POINT1; | 
|  | 462 | case AUDIO_CHANNEL_OUT_7POINT1: | 
|  | 463 | return AAUDIO_CHANNEL_7POINT1; | 
|  | 464 | case AUDIO_CHANNEL_OUT_7POINT1POINT2: | 
|  | 465 | return AAUDIO_CHANNEL_7POINT1POINT2; | 
|  | 466 | case AUDIO_CHANNEL_OUT_7POINT1POINT4: | 
|  | 467 | return AAUDIO_CHANNEL_7POINT1POINT4; | 
|  | 468 | // TODO: add 9point1point4 and 9point1point6 when they are added in audio-hal-enums.h | 
|  | 469 | // case AUDIO_CHANNEL_OUT_9POINT1POINT4: | 
|  | 470 | //     return AAUDIO_CHANNEL_9POINT1POINT4; | 
|  | 471 | // case AUDIO_CHANNEL_OUT_9POINT1POINT6: | 
|  | 472 | //     return AAUDIO_CHANNEL_9POINT1POINT6; | 
|  | 473 | default: | 
|  | 474 | ALOGE("%s() %#x unrecognized", __func__, channelMask); | 
|  | 475 | return AAUDIO_CHANNEL_INVALID; | 
|  | 476 | } | 
|  | 477 | } | 
|  | 478 | } | 
|  | 479 |  | 
|  | 480 | int32_t AAudioConvert_channelMaskToCount(aaudio_channel_mask_t channelMask) { | 
|  | 481 | return __builtin_popcount(channelMask & ~AAUDIO_CHANNEL_BIT_INDEX); | 
|  | 482 | } | 
|  | 483 |  | 
|  | 484 | aaudio_channel_mask_t AAudioConvert_channelCountToMask(int32_t channelCount) { | 
|  | 485 | if (channelCount < 0 || channelCount > AUDIO_CHANNEL_COUNT_MAX) { | 
|  | 486 | return AAUDIO_CHANNEL_INVALID; | 
|  | 487 | } | 
|  | 488 |  | 
|  | 489 | if (channelCount == 0) { | 
|  | 490 | return AAUDIO_UNSPECIFIED; | 
|  | 491 | } | 
|  | 492 |  | 
|  | 493 | // Return index mask if the channel count is greater than 2. | 
|  | 494 | return AAUDIO_CHANNEL_BIT_INDEX | ((1 << channelCount) - 1); | 
|  | 495 | } | 
|  | 496 |  | 
|  | 497 | aaudio_channel_mask_t AAudioConvert_androidToAAudioChannelIndexMask( | 
|  | 498 | audio_channel_mask_t channelMask) { | 
|  | 499 | if (audio_channel_mask_get_representation(channelMask) != AUDIO_CHANNEL_REPRESENTATION_INDEX) { | 
|  | 500 | ALOGE("%s() %#x not an index mask", __func__, channelMask); | 
|  | 501 | return AAUDIO_CHANNEL_INVALID; | 
|  | 502 | } | 
|  | 503 | return (channelMask & ~AUDIO_CHANNEL_INDEX_HDR) | AAUDIO_CHANNEL_BIT_INDEX; | 
|  | 504 | } | 
|  | 505 |  | 
|  | 506 | audio_channel_mask_t AAudioConvert_aaudioToAndroidChannelIndexMask( | 
|  | 507 | aaudio_channel_mask_t channelMask) { | 
|  | 508 | if (!AAudio_isChannelIndexMask(channelMask)) { | 
|  | 509 | ALOGE("%s() %#x not an index mask", __func__, channelMask); | 
|  | 510 | return AUDIO_CHANNEL_INVALID; | 
|  | 511 | } | 
|  | 512 | return audio_channel_mask_for_index_assignment_from_count( | 
|  | 513 | AAudioConvert_channelMaskToCount(channelMask)); | 
|  | 514 | } | 
|  | 515 |  | 
|  | 516 | aaudio_channel_mask_t AAudioConvert_androidToAAudioChannelMask( | 
|  | 517 | audio_channel_mask_t channelMask, bool isInput, bool indexMaskRequired) { | 
|  | 518 | if (audio_channel_mask_get_representation(channelMask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) { | 
|  | 519 | return AAudioConvert_androidToAAudioChannelIndexMask(channelMask); | 
|  | 520 | } | 
|  | 521 | if (indexMaskRequired) { | 
|  | 522 | // Require index mask, `channelMask` here is a position mask. | 
|  | 523 | const int channelCount = isInput ? audio_channel_count_from_in_mask(channelMask) | 
|  | 524 | : audio_channel_count_from_out_mask(channelMask); | 
|  | 525 | return AAudioConvert_channelCountToMask(channelCount); | 
|  | 526 | } | 
|  | 527 | return AAudioConvert_androidToAAudioChannelLayoutMask(channelMask, isInput); | 
|  | 528 | } | 
|  | 529 |  | 
|  | 530 | audio_channel_mask_t AAudioConvert_aaudioToAndroidChannelMask( | 
|  | 531 | aaudio_channel_mask_t channelMask, bool isInput) { | 
|  | 532 | return AAudio_isChannelIndexMask(channelMask) | 
|  | 533 | ? AAudioConvert_aaudioToAndroidChannelIndexMask(channelMask) | 
|  | 534 | : AAudioConvert_aaudioToAndroidChannelLayoutMask(channelMask, isInput); | 
|  | 535 | } | 
|  | 536 |  | 
|  | 537 | bool AAudio_isChannelIndexMask(aaudio_channel_mask_t channelMask) { | 
|  | 538 | return (channelMask & AAUDIO_CHANNEL_BIT_INDEX) == AAUDIO_CHANNEL_BIT_INDEX; | 
|  | 539 | } | 
|  | 540 |  | 
|  | 541 | audio_channel_mask_t AAudio_getChannelMaskForOpen( | 
|  | 542 | aaudio_channel_mask_t channelMask, int32_t samplesPerFrame, bool isInput) { | 
|  | 543 | if (channelMask != AAUDIO_UNSPECIFIED) { | 
|  | 544 | if (AAudio_isChannelIndexMask(channelMask) && samplesPerFrame <= 2) { | 
|  | 545 | // When it is index mask and the count is less than 3, use position mask | 
|  | 546 | // instead of index mask for opening a stream. This may need to be revisited | 
|  | 547 | // when making channel index mask public. | 
|  | 548 | return isInput ? audio_channel_in_mask_from_count(samplesPerFrame) | 
|  | 549 | : audio_channel_out_mask_from_count(samplesPerFrame); | 
|  | 550 | } | 
|  | 551 | return AAudioConvert_aaudioToAndroidChannelMask(channelMask, isInput); | 
|  | 552 | } | 
|  | 553 |  | 
|  | 554 | // Return stereo when unspecified. | 
|  | 555 | return isInput ? AUDIO_CHANNEL_IN_STEREO : AUDIO_CHANNEL_OUT_STEREO; | 
|  | 556 | } | 
|  | 557 |  | 
| Phil Burk | 3316d5e | 2017-02-15 11:23:01 -0800 | [diff] [blame] | 558 | int32_t AAudioConvert_framesToBytes(int32_t numFrames, | 
| Phil Burk | 7f68013 | 2018-03-12 14:48:06 -0700 | [diff] [blame] | 559 | int32_t bytesPerFrame, | 
|  | 560 | int32_t *sizeInBytes) { | 
|  | 561 | *sizeInBytes = 0; | 
|  | 562 |  | 
|  | 563 | if (numFrames < 0 || bytesPerFrame < 0) { | 
|  | 564 | ALOGE("negative size, numFrames = %d, frameSize = %d", numFrames, bytesPerFrame); | 
|  | 565 | return AAUDIO_ERROR_OUT_OF_RANGE; | 
|  | 566 | } | 
|  | 567 |  | 
|  | 568 | // Prevent numeric overflow. | 
|  | 569 | if (numFrames > (INT32_MAX / bytesPerFrame)) { | 
| Yi Kong | 0f414de | 2017-12-15 13:48:50 -0800 | [diff] [blame] | 570 | ALOGE("size overflow, numFrames = %d, frameSize = %d", numFrames, bytesPerFrame); | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 571 | return AAUDIO_ERROR_OUT_OF_RANGE; | 
|  | 572 | } | 
| Phil Burk | 7f68013 | 2018-03-12 14:48:06 -0700 | [diff] [blame] | 573 |  | 
| Phil Burk | 5ed503c | 2017-02-01 09:38:15 -0800 | [diff] [blame] | 574 | *sizeInBytes = numFrames * bytesPerFrame; | 
|  | 575 | return AAUDIO_OK; | 
|  | 576 | } | 
| Phil Burk | c8f69a0 | 2017-05-11 15:53:06 -0700 | [diff] [blame] | 577 |  | 
| Phil Burk | fd34a93 | 2017-07-19 07:03:52 -0700 | [diff] [blame] | 578 | int32_t AAudioProperty_getWakeupDelayMicros() { | 
|  | 579 | const int32_t minMicros = 0; // arbitrary | 
|  | 580 | const int32_t defaultMicros = 200; // arbitrary, based on some observed jitter | 
|  | 581 | const int32_t maxMicros = 5000; // arbitrary, probably don't want more than 500 | 
|  | 582 | int32_t prop = property_get_int32(AAUDIO_PROP_WAKEUP_DELAY_USEC, defaultMicros); | 
|  | 583 | if (prop < minMicros) { | 
|  | 584 | ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, minMicros); | 
|  | 585 | prop = minMicros; | 
|  | 586 | } else if (prop > maxMicros) { | 
|  | 587 | ALOGW("AAudioProperty_getWakeupDelayMicros: clipped %d to %d", prop, maxMicros); | 
|  | 588 | prop = maxMicros; | 
|  | 589 | } | 
|  | 590 | return prop; | 
|  | 591 | } | 
|  | 592 |  | 
|  | 593 | int32_t AAudioProperty_getMinimumSleepMicros() { | 
| Phil Burk | 4f578a2 | 2022-02-19 00:21:30 +0000 | [diff] [blame] | 594 | const int32_t minMicros = 1; // arbitrary | 
|  | 595 | // Higher values can increase latency for moderate workloads. | 
| Phil Burk | ec21f2b | 2022-04-19 18:52:03 +0000 | [diff] [blame] | 596 | // Short values can cause the CPU to short cycle if there is a bug in | 
|  | 597 | // calculating the wakeup times. | 
|  | 598 | const int32_t defaultMicros = 100; // arbitrary | 
| Phil Burk | 4f578a2 | 2022-02-19 00:21:30 +0000 | [diff] [blame] | 599 | const int32_t maxMicros = 200; // arbitrary | 
| Phil Burk | fd34a93 | 2017-07-19 07:03:52 -0700 | [diff] [blame] | 600 | int32_t prop = property_get_int32(AAUDIO_PROP_MINIMUM_SLEEP_USEC, defaultMicros); | 
|  | 601 | if (prop < minMicros) { | 
|  | 602 | ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, minMicros); | 
|  | 603 | prop = minMicros; | 
|  | 604 | } else if (prop > maxMicros) { | 
|  | 605 | ALOGW("AAudioProperty_getMinimumSleepMicros: clipped %d to %d", prop, maxMicros); | 
|  | 606 | prop = maxMicros; | 
|  | 607 | } | 
|  | 608 | return prop; | 
|  | 609 | } | 
|  | 610 |  | 
| Phil Burk | b31b66f | 2019-09-30 09:33:41 -0700 | [diff] [blame] | 611 | static int32_t AAudioProperty_getMMapOffsetMicros(const char *functionName, | 
|  | 612 | const char *propertyName) { | 
|  | 613 | const int32_t minMicros = -20000; // arbitrary | 
|  | 614 | const int32_t defaultMicros = 0;  // arbitrary | 
|  | 615 | const int32_t maxMicros =  20000; // arbitrary | 
|  | 616 | int32_t prop = property_get_int32(propertyName, defaultMicros); | 
|  | 617 | if (prop < minMicros) { | 
|  | 618 | ALOGW("%s: clipped %d to %d", functionName, prop, minMicros); | 
|  | 619 | prop = minMicros; | 
|  | 620 | } else if (prop > maxMicros) { | 
|  | 621 | ALOGW("%s: clipped %d to %d", functionName, prop, minMicros); | 
|  | 622 | prop = maxMicros; | 
|  | 623 | } | 
|  | 624 | return prop; | 
|  | 625 | } | 
|  | 626 |  | 
|  | 627 | int32_t AAudioProperty_getInputMMapOffsetMicros() { | 
|  | 628 | return AAudioProperty_getMMapOffsetMicros(__func__, AAUDIO_PROP_INPUT_MMAP_OFFSET_USEC); | 
|  | 629 | } | 
|  | 630 |  | 
|  | 631 | int32_t AAudioProperty_getOutputMMapOffsetMicros() { | 
|  | 632 | return AAudioProperty_getMMapOffsetMicros(__func__, AAUDIO_PROP_OUTPUT_MMAP_OFFSET_USEC); | 
|  | 633 | } | 
|  | 634 |  | 
| Phil Burk | ef34be5 | 2019-09-26 13:45:25 -0700 | [diff] [blame] | 635 | int32_t AAudioProperty_getLogMask() { | 
|  | 636 | return property_get_int32(AAUDIO_PROP_LOG_MASK, 0); | 
|  | 637 | } | 
|  | 638 |  | 
| Phil Burk | 5cc83c3 | 2017-11-28 15:43:18 -0800 | [diff] [blame] | 639 | aaudio_result_t AAudio_isFlushAllowed(aaudio_stream_state_t state) { | 
|  | 640 | aaudio_result_t result = AAUDIO_OK; | 
|  | 641 | switch (state) { | 
|  | 642 | // Proceed with flushing. | 
|  | 643 | case AAUDIO_STREAM_STATE_OPEN: | 
|  | 644 | case AAUDIO_STREAM_STATE_PAUSED: | 
|  | 645 | case AAUDIO_STREAM_STATE_STOPPED: | 
|  | 646 | case AAUDIO_STREAM_STATE_FLUSHED: | 
|  | 647 | break; | 
|  | 648 |  | 
|  | 649 | // Transition from one inactive state to another. | 
|  | 650 | case AAUDIO_STREAM_STATE_STARTING: | 
|  | 651 | case AAUDIO_STREAM_STATE_STARTED: | 
|  | 652 | case AAUDIO_STREAM_STATE_STOPPING: | 
|  | 653 | case AAUDIO_STREAM_STATE_PAUSING: | 
|  | 654 | case AAUDIO_STREAM_STATE_FLUSHING: | 
|  | 655 | case AAUDIO_STREAM_STATE_CLOSING: | 
|  | 656 | case AAUDIO_STREAM_STATE_CLOSED: | 
|  | 657 | case AAUDIO_STREAM_STATE_DISCONNECTED: | 
|  | 658 | default: | 
|  | 659 | ALOGE("can only flush stream when PAUSED, OPEN or STOPPED, state = %s", | 
| dimitry | 2d2f17c | 2019-07-17 13:55:16 +0200 | [diff] [blame] | 660 | aaudio::AudioGlobal_convertStreamStateToText(state)); | 
| Phil Burk | 5cc83c3 | 2017-11-28 15:43:18 -0800 | [diff] [blame] | 661 | result =  AAUDIO_ERROR_INVALID_STATE; | 
|  | 662 | break; | 
|  | 663 | } | 
|  | 664 | return result; | 
|  | 665 | } | 
| jiabin | 4a34186 | 2022-09-20 17:58:37 +0000 | [diff] [blame] | 666 |  | 
|  | 667 | namespace { | 
|  | 668 |  | 
|  | 669 | aaudio_policy_t aidl2legacy_aaudio_policy(AudioMMapPolicy aidl) { | 
|  | 670 | switch (aidl) { | 
|  | 671 | case AudioMMapPolicy::NEVER: | 
|  | 672 | return AAUDIO_POLICY_NEVER; | 
|  | 673 | case AudioMMapPolicy::AUTO: | 
|  | 674 | return AAUDIO_POLICY_AUTO; | 
|  | 675 | case AudioMMapPolicy::ALWAYS: | 
|  | 676 | return AAUDIO_POLICY_ALWAYS; | 
|  | 677 | case AudioMMapPolicy::UNSPECIFIED: | 
|  | 678 | default: | 
|  | 679 | return AAUDIO_UNSPECIFIED; | 
|  | 680 | } | 
|  | 681 | } | 
|  | 682 |  | 
|  | 683 | } // namespace | 
|  | 684 |  | 
|  | 685 | aaudio_policy_t AAudio_getAAudioPolicy(const std::vector<AudioMMapPolicyInfo>& policyInfos) { | 
|  | 686 | if (policyInfos.empty()) return AAUDIO_POLICY_AUTO; | 
|  | 687 | for (size_t i = 1; i < policyInfos.size(); ++i) { | 
|  | 688 | if (policyInfos.at(i).mmapPolicy != policyInfos.at(0).mmapPolicy) { | 
|  | 689 | return AAUDIO_POLICY_AUTO; | 
|  | 690 | } | 
|  | 691 | } | 
|  | 692 | return aidl2legacy_aaudio_policy(policyInfos.at(0).mmapPolicy); | 
|  | 693 | } |