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