• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <vector>
23 #include <stdint.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 
27 #include <android/media/audio/common/AudioMMapPolicyInfo.h>
28 #include <utils/Errors.h>
29 #include <system/audio.h>
30 
31 #include "aaudio/AAudio.h"
32 #include "aaudio/AAudioTesting.h"
33 
34 /**
35  * Convert an AAudio result into the closest matching Android status.
36  */
37 android::status_t AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result);
38 
39 /**
40  * Convert an Android status into the closest matching AAudio result.
41  */
42 aaudio_result_t AAudioConvert_androidToAAudioResult(android::status_t status);
43 
44 /**
45  * Convert an aaudio_session_id_t to a value that is safe to pass to AudioFlinger.
46  * @param sessionId
47  * @return safe value
48  */
49 audio_session_t AAudioConvert_aaudioToAndroidSessionId(aaudio_session_id_t sessionId);
50 
51 /**
52  * Calculate the number of bytes and prevent numeric overflow.
53  * The *sizeInBytes will be set to zero if there is an error.
54  *
55  * @param numFrames frame count
56  * @param bytesPerFrame size of a frame in bytes
57  * @param sizeInBytes pointer to a variable to receive total size in bytes
58  * @return AAUDIO_OK or negative error, eg. AAUDIO_ERROR_OUT_OF_RANGE
59  */
60 int32_t AAudioConvert_framesToBytes(int32_t numFrames,
61                                     int32_t bytesPerFrame,
62                                     int32_t *sizeInBytes);
63 
64 audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudio_format);
65 
66 aaudio_format_t AAudioConvert_androidToAAudioDataFormat(audio_format_t format);
67 
68 aaudio_format_t AAudioConvert_androidToNearestAAudioDataFormat(audio_format_t format);
69 
70 /**
71  * Note that this function does not validate the passed in value.
72  * That is done somewhere else.
73  * @return internal value
74  */
75 
76 audio_usage_t AAudioConvert_usageToInternal(aaudio_usage_t usage);
77 
78 /**
79  * Note that this function does not validate the passed in value.
80  * That is done somewhere else.
81  * @return internal value
82  */
83 audio_content_type_t AAudioConvert_contentTypeToInternal(aaudio_content_type_t contentType);
84 
85 /**
86  * Note that this function does not validate the passed in value.
87  * That is done somewhere else.
88  * @return internal audio source
89  */
90 audio_source_t AAudioConvert_inputPresetToAudioSource(aaudio_input_preset_t preset);
91 
92 /**
93  * Note that this function does not validate the passed in value.
94  * That is done somewhere else.
95  * @return internal audio flags mask
96  */
97 audio_flags_mask_t AAudio_computeAudioFlagsMask(
98         aaudio_allowed_capture_policy_t policy,
99         aaudio_spatialization_behavior_t spatializationBehavior,
100         bool isContentSpatialized,
101         audio_output_flags_t outputFlags);
102 
103 audio_flags_mask_t AAudioConvert_privacySensitiveToAudioFlagsMask(
104         bool privacySensitive);
105 
106 audio_channel_mask_t AAudioConvert_aaudioToAndroidChannelLayoutMask(
107         aaudio_channel_mask_t channelMask, bool isInput);
108 
109 aaudio_channel_mask_t AAudioConvert_androidToAAudioChannelLayoutMask(
110         audio_channel_mask_t channelMask, bool isInput);
111 
112 aaudio_channel_mask_t AAudioConvert_androidToAAudioChannelIndexMask(
113         audio_channel_mask_t channelMask);
114 
115 audio_channel_mask_t AAudioConvert_aaudioToAndroidChannelIndexMask(
116         aaudio_channel_mask_t channelMask);
117 
118 aaudio_channel_mask_t AAudioConvert_androidToAAudioChannelMask(
119         audio_channel_mask_t channelMask, bool isInput, bool indexMaskRequired);
120 
121 audio_channel_mask_t AAudioConvert_aaudioToAndroidChannelMask(
122         aaudio_channel_mask_t channelMask, bool isInput);
123 
124 bool AAudio_isChannelIndexMask(aaudio_channel_mask_t channelMask);
125 
126 int32_t AAudioConvert_channelMaskToCount(aaudio_channel_mask_t channelMask);
127 
128 aaudio_channel_mask_t AAudioConvert_channelCountToMask(int32_t channelCount);
129 
130 audio_channel_mask_t AAudio_getChannelMaskForOpen(
131         aaudio_channel_mask_t channelMask, int32_t samplesPerFrame, bool isInput);
132 
133 // Note that this code may be replaced by Settings or by some other system configuration tool.
134 
135 /**
136  * Read a system property that specifies the number of extra microseconds that a thread
137  * should sleep when waiting for another thread to service a FIFO. This is used
138  * to avoid the waking thread from being overly optimistic about the other threads
139  * wakeup timing. This value should be set high enough to cover typical scheduling jitter
140  * for a real-time thread.
141  *
142  * @return number of microseconds to delay the wakeup.
143  */
144 int32_t AAudioProperty_getWakeupDelayMicros();
145 #define AAUDIO_PROP_WAKEUP_DELAY_USEC      "aaudio.wakeup_delay_usec"
146 
147 /**
148  * Read a system property that specifies the minimum sleep time when polling the FIFO.
149  *
150  * @return minimum number of microseconds to sleep.
151  */
152 int32_t AAudioProperty_getMinimumSleepMicros();
153 #define AAUDIO_PROP_MINIMUM_SLEEP_USEC      "aaudio.minimum_sleep_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(const std::function<bool ()> & f,int times,int sleepMs)200 static inline bool AAudio_tryUntilTrue(
201         const 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:
273     Timestamp() = default;
Timestamp(int64_t position,int64_t nanoseconds)274     Timestamp(int64_t position, int64_t nanoseconds)
275             : mPosition(position)
276             , mNanoseconds(nanoseconds) {}
277 
getPosition()278     int64_t getPosition() const { return mPosition; }
279 
getNanoseconds()280     int64_t getNanoseconds() const { return mNanoseconds; }
281 
282 private:
283     // These cannot be const because we need to implement the copy assignment operator.
284     int64_t mPosition{0};
285     int64_t mNanoseconds{0};
286 };
287 
288 
289 /**
290  * Pass a request to another thread.
291  * This is used when one thread, A, wants another thread, B, to do something.
292  * A naive approach would be for A to set a flag and for B to clear it when done.
293  * But that creates a race condition. This technique avoids the race condition.
294  *
295  * Assumes only one requester and one acknowledger.
296  */
297 class AtomicRequestor {
298 public:
299 
300     __attribute__((no_sanitize("integer")))
request()301     void request() {
302         mRequested++;
303     }
304 
305     __attribute__((no_sanitize("integer")))
isRequested()306     bool isRequested() {
307         return (mRequested.load() - mAcknowledged.load()) > 0;
308     }
309 
310     __attribute__((no_sanitize("integer")))
acknowledge()311     void acknowledge() {
312         mAcknowledged++;
313     }
314 
315 private:
316     std::atomic<int> mRequested{0};
317     std::atomic<int> mAcknowledged{0};
318 };
319 
320 enum {
321     /**
322      * Audio channel index mask, only used internally.
323      */
324     AAUDIO_CHANNEL_BIT_INDEX = 0x80000000,
325     AAUDIO_CHANNEL_INDEX_MASK_1 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 1) - 1,
326     AAUDIO_CHANNEL_INDEX_MASK_2 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 2) - 1,
327     AAUDIO_CHANNEL_INDEX_MASK_3 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 3) - 1,
328     AAUDIO_CHANNEL_INDEX_MASK_4 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 4) - 1,
329     AAUDIO_CHANNEL_INDEX_MASK_5 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 5) - 1,
330     AAUDIO_CHANNEL_INDEX_MASK_6 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 6) - 1,
331     AAUDIO_CHANNEL_INDEX_MASK_7 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 7) - 1,
332     AAUDIO_CHANNEL_INDEX_MASK_8 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 8) - 1,
333     AAUDIO_CHANNEL_INDEX_MASK_9 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 9) - 1,
334     AAUDIO_CHANNEL_INDEX_MASK_10 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 10) - 1,
335     AAUDIO_CHANNEL_INDEX_MASK_11 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 11) - 1,
336     AAUDIO_CHANNEL_INDEX_MASK_12 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 12) - 1,
337     AAUDIO_CHANNEL_INDEX_MASK_13 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 13) - 1,
338     AAUDIO_CHANNEL_INDEX_MASK_14 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 14) - 1,
339     AAUDIO_CHANNEL_INDEX_MASK_15 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 15) - 1,
340     AAUDIO_CHANNEL_INDEX_MASK_16 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 16) - 1,
341     AAUDIO_CHANNEL_INDEX_MASK_17 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 17) - 1,
342     AAUDIO_CHANNEL_INDEX_MASK_18 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 18) - 1,
343     AAUDIO_CHANNEL_INDEX_MASK_19 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 19) - 1,
344     AAUDIO_CHANNEL_INDEX_MASK_20 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 20) - 1,
345     AAUDIO_CHANNEL_INDEX_MASK_21 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 21) - 1,
346     AAUDIO_CHANNEL_INDEX_MASK_22 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 22) - 1,
347     AAUDIO_CHANNEL_INDEX_MASK_23 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 23) - 1,
348     AAUDIO_CHANNEL_INDEX_MASK_24 = AAUDIO_CHANNEL_BIT_INDEX | (1 << 24) - 1,
349 };
350 
351 /**
352  * Returns the aaudio mmap policy based on the vector of mmap policy info. The rule as
353  * 1. Returns AUTO if any of the policy is AUTO or ALWAYS
354  * 2. Returns NEVER if all of the policies are NEVER or UNSPECIFIED
355  * 3. Returns default policy if all of the policies are UNSPECIFIED
356  *
357  * @param policyInfos
358  * @param defaultPolicy
359  * @return
360  */
361 aaudio_policy_t AAudio_getAAudioPolicy(
362         const std::vector<android::media::audio::common::AudioMMapPolicyInfo>& policyInfos,
363         android::media::audio::common::AudioMMapPolicy defaultPolicy =
364                 android::media::audio::common::AudioMMapPolicy::NEVER);
365 
366 #endif //UTILITY_AAUDIO_UTILITIES_H
367