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