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 #ifndef UTILITY_AAUDIO_UTILITIES_H 18 #define UTILITY_AAUDIO_UTILITIES_H 19 20 #include <algorithm> 21 #include <functional> 22 #include <stdint.h> 23 #include <sys/types.h> 24 25 #include <utils/Errors.h> 26 #include <system/audio.h> 27 28 #include "aaudio/AAudio.h" 29 30 /** 31 * Convert an AAudio result into the closest matching Android status. 32 */ 33 android::status_t AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result); 34 35 /** 36 * Convert an Android status into the closest matching AAudio result. 37 */ 38 aaudio_result_t AAudioConvert_androidToAAudioResult(android::status_t status); 39 40 /** 41 * Convert an aaudio_session_id_t to a value that is safe to pass to AudioFlinger. 42 * @param sessionId 43 * @return safe value 44 */ 45 audio_session_t AAudioConvert_aaudioToAndroidSessionId(aaudio_session_id_t sessionId); 46 47 /** 48 * Calculate the number of bytes and prevent numeric overflow. 49 * The *sizeInBytes will be set to zero if there is an error. 50 * 51 * @param numFrames frame count 52 * @param bytesPerFrame size of a frame in bytes 53 * @param sizeInBytes pointer to a variable to receive total size in bytes 54 * @return AAUDIO_OK or negative error, eg. AAUDIO_ERROR_OUT_OF_RANGE 55 */ 56 int32_t AAudioConvert_framesToBytes(int32_t numFrames, 57 int32_t bytesPerFrame, 58 int32_t *sizeInBytes); 59 60 audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudio_format); 61 62 aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t format); 63 64 65 /** 66 * Note that this function does not validate the passed in value. 67 * That is done somewhere else. 68 * @return internal value 69 */ 70 71 audio_usage_t AAudioConvert_usageToInternal(aaudio_usage_t usage); 72 73 /** 74 * Note that this function does not validate the passed in value. 75 * That is done somewhere else. 76 * @return internal value 77 */ 78 audio_content_type_t AAudioConvert_contentTypeToInternal(aaudio_content_type_t contentType); 79 80 /** 81 * Note that this function does not validate the passed in value. 82 * That is done somewhere else. 83 * @return internal audio source 84 */ 85 audio_source_t AAudioConvert_inputPresetToAudioSource(aaudio_input_preset_t preset); 86 87 /** 88 * Note that this function does not validate the passed in value. 89 * That is done somewhere else. 90 * @return internal audio flags mask 91 */ 92 audio_flags_mask_t AAudioConvert_allowCapturePolicyToAudioFlagsMask( 93 aaudio_allowed_capture_policy_t policy); 94 95 // Note that this code may be replaced by Settings or by some other system configuration tool. 96 97 #define AAUDIO_PROP_MMAP_POLICY "aaudio.mmap_policy" 98 99 /** 100 * Read system property. 101 * @return AAUDIO_UNSPECIFIED, AAUDIO_POLICY_NEVER or AAUDIO_POLICY_AUTO or AAUDIO_POLICY_ALWAYS 102 */ 103 int32_t AAudioProperty_getMMapPolicy(); 104 105 #define AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY "aaudio.mmap_exclusive_policy" 106 107 /** 108 * Read system property. 109 * @return AAUDIO_UNSPECIFIED, AAUDIO_POLICY_NEVER or AAUDIO_POLICY_AUTO or AAUDIO_POLICY_ALWAYS 110 */ 111 int32_t AAudioProperty_getMMapExclusivePolicy(); 112 113 #define AAUDIO_PROP_MIXER_BURSTS "aaudio.mixer_bursts" 114 115 /** 116 * Read system property. 117 * @return number of bursts per AAudio service mixer cycle 118 */ 119 int32_t AAudioProperty_getMixerBursts(); 120 121 #define AAUDIO_PROP_HW_BURST_MIN_USEC "aaudio.hw_burst_min_usec" 122 123 /** 124 * Read a system property that specifies the number of extra microseconds that a thread 125 * should sleep when waiting for another thread to service a FIFO. This is used 126 * to avoid the waking thread from being overly optimistic about the other threads 127 * wakeup timing. This value should be set high enough to cover typical scheduling jitter 128 * for a real-time thread. 129 * 130 * @return number of microseconds to delay the wakeup. 131 */ 132 int32_t AAudioProperty_getWakeupDelayMicros(); 133 134 #define AAUDIO_PROP_WAKEUP_DELAY_USEC "aaudio.wakeup_delay_usec" 135 136 /** 137 * Read a system property that specifies the minimum sleep time when polling the FIFO. 138 * 139 * @return minimum number of microseconds to sleep. 140 */ 141 int32_t AAudioProperty_getMinimumSleepMicros(); 142 143 #define AAUDIO_PROP_MINIMUM_SLEEP_USEC "aaudio.minimum_sleep_usec" 144 145 /** 146 * Read system property. 147 * This is handy in case the DMA is bursting too quickly for the CPU to keep up. 148 * For example, there may be a DMA burst every 100 usec but you only 149 * want to feed the MMAP buffer every 2000 usec. 150 * 151 * This will affect the framesPerBurst for an MMAP stream. 152 * 153 * @return minimum number of microseconds for a MMAP HW burst 154 */ 155 int32_t AAudioProperty_getHardwareBurstMinMicros(); 156 157 158 /** 159 * Is flush allowed for the given state? 160 * @param state 161 * @return AAUDIO_OK if allowed or an error 162 */ 163 aaudio_result_t AAudio_isFlushAllowed(aaudio_stream_state_t state); 164 165 /** 166 * Try a function f until it returns true. 167 * 168 * The function is always called at least once. 169 * 170 * @param f the function to evaluate, which returns a bool. 171 * @param times the number of times to evaluate f. 172 * @param sleepMs the sleep time per check of f, if greater than 0. 173 * @return true if f() eventually returns true. 174 */ 175 static inline bool AAudio_tryUntilTrue( 176 std::function<bool()> f, int times, int sleepMs) { 177 static const useconds_t US_PER_MS = 1000; 178 179 sleepMs = std::max(sleepMs, 0); 180 for (;;) { 181 if (f()) return true; 182 if (times <= 1) return false; 183 --times; 184 usleep(sleepMs * US_PER_MS); 185 } 186 } 187 188 189 /** 190 * Simple double buffer for a structure that can be written occasionally and read occasionally. 191 * This allows a SINGLE writer with multiple readers. 192 * 193 * It is OK if the FIFO overflows and we lose old values. 194 * It is also OK if we read an old value. 195 * Thread may return a non-atomic result if the other thread is rapidly writing 196 * new values on another core. 197 */ 198 template <class T> 199 class SimpleDoubleBuffer { 200 public: 201 SimpleDoubleBuffer() 202 : mValues() {} 203 204 __attribute__((no_sanitize("integer"))) 205 void write(T value) { 206 int index = mCounter.load() & 1; 207 mValues[index] = value; 208 mCounter++; // Increment AFTER updating storage, OK if it wraps. 209 } 210 211 /** 212 * This should only be called by the same thread that calls write() or when 213 * no other thread is calling write. 214 */ 215 void clear() { 216 mCounter.store(0); 217 } 218 219 T read() const { 220 T result; 221 int before; 222 int after; 223 int timeout = 3; 224 do { 225 // Check to see if a write occurred while were reading. 226 before = mCounter.load(); 227 int index = (before & 1) ^ 1; 228 result = mValues[index]; 229 after = mCounter.load(); 230 } while ((after != before) && (after > 0) && (--timeout > 0)); 231 return result; 232 } 233 234 /** 235 * @return true if at least one value has been written 236 */ 237 bool isValid() const { 238 return mCounter.load() > 0; 239 } 240 241 private: 242 T mValues[2]; 243 std::atomic<int> mCounter{0}; 244 }; 245 246 class Timestamp { 247 public: 248 Timestamp() 249 : mPosition(0) 250 , mNanoseconds(0) {} 251 Timestamp(int64_t position, int64_t nanoseconds) 252 : mPosition(position) 253 , mNanoseconds(nanoseconds) {} 254 255 int64_t getPosition() const { return mPosition; } 256 257 int64_t getNanoseconds() const { return mNanoseconds; } 258 259 private: 260 // These cannot be const because we need to implement the copy assignment operator. 261 int64_t mPosition; 262 int64_t mNanoseconds; 263 }; 264 265 266 /** 267 * Pass a request to another thread. 268 * This is used when one thread, A, wants another thread, B, to do something. 269 * A naive approach would be for A to set a flag and for B to clear it when done. 270 * But that creates a race condition. This technique avoids the race condition. 271 * 272 * Assumes only one requester and one acknowledger. 273 */ 274 class AtomicRequestor { 275 public: 276 277 __attribute__((no_sanitize("integer"))) 278 void request() { 279 mRequested++; 280 } 281 282 __attribute__((no_sanitize("integer"))) 283 bool isRequested() { 284 return (mRequested.load() - mAcknowledged.load()) > 0; 285 } 286 287 __attribute__((no_sanitize("integer"))) 288 void acknowledge() { 289 mAcknowledged++; 290 } 291 292 private: 293 std::atomic<int> mRequested{0}; 294 std::atomic<int> mAcknowledged{0}; 295 }; 296 #endif //UTILITY_AAUDIO_UTILITIES_H 297