Home | History | Annotate | Download | only in utility
      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  */
    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:
    201     SimpleDoubleBuffer()
    202             : mValues() {}
    203 
    204     __attribute__((no_sanitize("integer")))
    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      */
    215     void clear() {
    216         mCounter.store(0);
    217     }
    218 
    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      */
    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:
    248     Timestamp()
    249             : mPosition(0)
    250             , mNanoseconds(0) {}
    251     Timestamp(int64_t position, int64_t nanoseconds)
    252             : mPosition(position)
    253             , mNanoseconds(nanoseconds) {}
    254 
    255     int64_t getPosition() const { return mPosition; }
    256 
    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")))
    278     void request() {
    279         mRequested++;
    280     }
    281 
    282     __attribute__((no_sanitize("integer")))
    283     bool isRequested() {
    284         return (mRequested.load() - mAcknowledged.load()) > 0;
    285     }
    286 
    287     __attribute__((no_sanitize("integer")))
    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