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