1/* 2 * Copyright (C) 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_AUDIO_CLOCK_H 18#define UTILITY_AUDIO_CLOCK_H 19 20#include <stdint.h> 21#include <time.h> 22 23#include <aaudio/AAudio.h> 24 25// Time conversion constants. 26#define AAUDIO_NANOS_PER_MICROSECOND ((int64_t)1000) 27#define AAUDIO_NANOS_PER_MILLISECOND (AAUDIO_NANOS_PER_MICROSECOND * 1000) 28#define AAUDIO_MILLIS_PER_SECOND 1000 29#define AAUDIO_NANOS_PER_SECOND (AAUDIO_NANOS_PER_MILLISECOND * AAUDIO_MILLIS_PER_SECOND) 30 31class AudioClock { 32public: 33 static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC) { 34 struct timespec time; 35 int result = clock_gettime(clockId, &time); 36 if (result < 0) { 37 return -errno; 38 } 39 return (time.tv_sec * AAUDIO_NANOS_PER_SECOND) + time.tv_nsec; 40 } 41 42 /** 43 * Sleep until the specified absolute time. 44 * Return immediately with AAUDIO_ERROR_ILLEGAL_ARGUMENT if a negative 45 * nanoTime is specified. 46 * 47 * @param nanoTime time to wake up 48 * @param clockId CLOCK_MONOTONIC is default 49 * @return 0, a negative error, or 1 if the call is interrupted by a signal handler (EINTR) 50 */ 51 static int sleepUntilNanoTime(int64_t nanoTime, 52 clockid_t clockId = CLOCK_MONOTONIC) { 53 if (nanoTime > 0) { 54 struct timespec time; 55 time.tv_sec = nanoTime / AAUDIO_NANOS_PER_SECOND; 56 // Calculate the fractional nanoseconds. Avoids expensive % operation. 57 time.tv_nsec = nanoTime - (time.tv_sec * AAUDIO_NANOS_PER_SECOND); 58 int err = clock_nanosleep(clockId, TIMER_ABSTIME, &time, nullptr); 59 switch (err) { 60 case EINTR: 61 return 1; 62 case 0: 63 return 0; 64 default: 65 // Subtract because clock_nanosleep() returns a positive error number! 66 return 0 - err; 67 } 68 } else { 69 return AAUDIO_ERROR_ILLEGAL_ARGUMENT; 70 } 71 } 72 73 /** 74 * Sleep for the specified number of relative nanoseconds in real-time. 75 * Return immediately with 0 if a negative nanoseconds is specified. 76 * 77 * @param nanoseconds time to sleep 78 * @param clockId CLOCK_MONOTONIC is default 79 * @return 0, a negative error, or 1 if the call is interrupted by a signal handler (EINTR) 80 */ 81 static int sleepForNanos(int64_t nanoseconds, clockid_t clockId = CLOCK_MONOTONIC) { 82 if (nanoseconds > 0) { 83 struct timespec time; 84 time.tv_sec = nanoseconds / AAUDIO_NANOS_PER_SECOND; 85 // Calculate the fractional nanoseconds. Avoids expensive % operation. 86 time.tv_nsec = nanoseconds - (time.tv_sec * AAUDIO_NANOS_PER_SECOND); 87 const int flags = 0; // documented as relative sleep 88 int err = clock_nanosleep(clockId, flags, &time, nullptr); 89 switch (err) { 90 case EINTR: 91 return 1; 92 case 0: 93 return 0; 94 default: 95 // Subtract because clock_nanosleep() returns a positive error number! 96 return 0 - err; 97 } 98 } 99 return 0; 100 } 101}; 102 103 104#endif // UTILITY_AUDIO_CLOCK_H 105