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 */
AAudio_tryUntilTrue(std::function<bool ()> f,int times,int sleepMs)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:
SimpleDoubleBuffer()201 SimpleDoubleBuffer()
202 : mValues() {}
203
204 __attribute__((no_sanitize("integer")))
write(T value)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 */
clear()215 void clear() {
216 mCounter.store(0);
217 }
218
read()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 */
isValid()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:
Timestamp()248 Timestamp()
249 : mPosition(0)
250 , mNanoseconds(0) {}
Timestamp(int64_t position,int64_t nanoseconds)251 Timestamp(int64_t position, int64_t nanoseconds)
252 : mPosition(position)
253 , mNanoseconds(nanoseconds) {}
254
getPosition()255 int64_t getPosition() const { return mPosition; }
256
getNanoseconds()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")))
request()278 void request() {
279 mRequested++;
280 }
281
282 __attribute__((no_sanitize("integer")))
isRequested()283 bool isRequested() {
284 return (mRequested.load() - mAcknowledged.load()) > 0;
285 }
286
287 __attribute__((no_sanitize("integer")))
acknowledge()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