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 // Note that this code may be replaced by Settings or by some other system configuration tool.
97 
98 #define AAUDIO_PROP_MMAP_POLICY           "aaudio.mmap_policy"
99 
100 /**
101  * Read system property.
102  * @return AAUDIO_UNSPECIFIED, AAUDIO_POLICY_NEVER or AAUDIO_POLICY_AUTO or AAUDIO_POLICY_ALWAYS
103  */
104 int32_t AAudioProperty_getMMapPolicy();
105 
106 #define AAUDIO_PROP_MMAP_EXCLUSIVE_POLICY "aaudio.mmap_exclusive_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 
114 #define AAUDIO_PROP_MIXER_BURSTS           "aaudio.mixer_bursts"
115 
116 /**
117  * Read system property.
118  * @return number of bursts per AAudio service mixer cycle
119  */
120 int32_t AAudioProperty_getMixerBursts();
121 
122 #define AAUDIO_PROP_HW_BURST_MIN_USEC      "aaudio.hw_burst_min_usec"
123 
124 /**
125  * Read a system property that specifies the number of extra microseconds that a thread
126  * should sleep when waiting for another thread to service a FIFO. This is used
127  * to avoid the waking thread from being overly optimistic about the other threads
128  * wakeup timing. This value should be set high enough to cover typical scheduling jitter
129  * for a real-time thread.
130  *
131  * @return number of microseconds to delay the wakeup.
132  */
133 int32_t AAudioProperty_getWakeupDelayMicros();
134 
135 #define AAUDIO_PROP_WAKEUP_DELAY_USEC      "aaudio.wakeup_delay_usec"
136 
137 /**
138  * Read a system property that specifies the minimum sleep time when polling the FIFO.
139  *
140  * @return minimum number of microseconds to sleep.
141  */
142 int32_t AAudioProperty_getMinimumSleepMicros();
143 
144 #define AAUDIO_PROP_MINIMUM_SLEEP_USEC      "aaudio.minimum_sleep_usec"
145 
146 /**
147  * Read system property.
148  * This is handy in case the DMA is bursting too quickly for the CPU to keep up.
149  * For example, there may be a DMA burst every 100 usec but you only
150  * want to feed the MMAP buffer every 2000 usec.
151  *
152  * This will affect the framesPerBurst for an MMAP stream.
153  *
154  * @return minimum number of microseconds for a MMAP HW burst
155  */
156 int32_t AAudioProperty_getHardwareBurstMinMicros();
157 
158 
159 /**
160  * Is flush allowed for the given state?
161  * @param state
162  * @return AAUDIO_OK if allowed or an error
163  */
164 aaudio_result_t AAudio_isFlushAllowed(aaudio_stream_state_t state);
165 
166 /**
167  * Try a function f until it returns true.
168  *
169  * The function is always called at least once.
170  *
171  * @param f the function to evaluate, which returns a bool.
172  * @param times the number of times to evaluate f.
173  * @param sleepMs the sleep time per check of f, if greater than 0.
174  * @return true if f() eventually returns true.
175  */
AAudio_tryUntilTrue(std::function<bool ()> f,int times,int sleepMs)176 static inline bool AAudio_tryUntilTrue(
177         std::function<bool()> f, int times, int sleepMs) {
178     static const useconds_t US_PER_MS = 1000;
179 
180     sleepMs = std::max(sleepMs, 0);
181     for (;;) {
182         if (f()) return true;
183         if (times <= 1) return false;
184         --times;
185         usleep(sleepMs * US_PER_MS);
186     }
187 }
188 
189 
190 /**
191  * Simple double buffer for a structure that can be written occasionally and read occasionally.
192  * This allows a SINGLE writer with multiple readers.
193  *
194  * It is OK if the FIFO overflows and we lose old values.
195  * It is also OK if we read an old value.
196  * Thread may return a non-atomic result if the other thread is rapidly writing
197  * new values on another core.
198  */
199 template <class T>
200 class SimpleDoubleBuffer {
201 public:
SimpleDoubleBuffer()202     SimpleDoubleBuffer()
203             : mValues() {}
204 
205     __attribute__((no_sanitize("integer")))
write(T value)206     void write(T value) {
207         int index = mCounter.load() & 1;
208         mValues[index] = value;
209         mCounter++; // Increment AFTER updating storage, OK if it wraps.
210     }
211 
212     /**
213      * This should only be called by the same thread that calls write() or when
214      * no other thread is calling write.
215      */
clear()216     void clear() {
217         mCounter.store(0);
218     }
219 
read()220     T read() const {
221         T result;
222         int before;
223         int after;
224         int timeout = 3;
225         do {
226             // Check to see if a write occurred while were reading.
227             before = mCounter.load();
228             int index = (before & 1) ^ 1;
229             result = mValues[index];
230             after = mCounter.load();
231         } while ((after != before) && (after > 0) && (--timeout > 0));
232         return result;
233     }
234 
235     /**
236      * @return true if at least one value has been written
237      */
isValid()238     bool isValid() const {
239         return mCounter.load() > 0;
240     }
241 
242 private:
243     T                    mValues[2];
244     std::atomic<int>     mCounter{0};
245 };
246 
247 class Timestamp {
248 public:
Timestamp()249     Timestamp()
250             : mPosition(0)
251             , mNanoseconds(0) {}
Timestamp(int64_t position,int64_t nanoseconds)252     Timestamp(int64_t position, int64_t nanoseconds)
253             : mPosition(position)
254             , mNanoseconds(nanoseconds) {}
255 
getPosition()256     int64_t getPosition() const { return mPosition; }
257 
getNanoseconds()258     int64_t getNanoseconds() const { return mNanoseconds; }
259 
260 private:
261     // These cannot be const because we need to implement the copy assignment operator.
262     int64_t mPosition;
263     int64_t mNanoseconds;
264 };
265 
266 
267 /**
268  * Pass a request to another thread.
269  * This is used when one thread, A, wants another thread, B, to do something.
270  * A naive approach would be for A to set a flag and for B to clear it when done.
271  * But that creates a race condition. This technique avoids the race condition.
272  *
273  * Assumes only one requester and one acknowledger.
274  */
275 class AtomicRequestor {
276 public:
277 
278     __attribute__((no_sanitize("integer")))
request()279     void request() {
280         mRequested++;
281     }
282 
283     __attribute__((no_sanitize("integer")))
isRequested()284     bool isRequested() {
285         return (mRequested.load() - mAcknowledged.load()) > 0;
286     }
287 
288     __attribute__((no_sanitize("integer")))
acknowledge()289     void acknowledge() {
290         mAcknowledged++;
291     }
292 
293 private:
294     std::atomic<int> mRequested{0};
295     std::atomic<int> mAcknowledged{0};
296 };
297 #endif //UTILITY_AAUDIO_UTILITIES_H
298