blob: d5d4ef476b080aa42fee57d61a6c69a501002d20 [file] [log] [blame]
Phil Burke1ce4912016-11-21 10:40:25 -08001/*
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
Phil Burkdec33ab2017-01-17 14:48:16 -080017#ifndef UTILITY_AUDIO_CLOCK_H
18#define UTILITY_AUDIO_CLOCK_H
Phil Burke1ce4912016-11-21 10:40:25 -080019
Dan Albert36967fb2017-10-11 12:43:41 -070020#include <errno.h>
Phil Burkd8bdcab2017-01-03 17:20:30 -080021#include <stdint.h>
Phil Burke1ce4912016-11-21 10:40:25 -080022#include <time.h>
Phil Burkd8bdcab2017-01-03 17:20:30 -080023
Phil Burka4eb0d82017-04-12 15:44:06 -070024#include <aaudio/AAudio.h>
Phil Burke1ce4912016-11-21 10:40:25 -080025
Phil Burk3316d5e2017-02-15 11:23:01 -080026// 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
Phil Burke1ce4912016-11-21 10:40:25 -080032class AudioClock {
33public:
Phil Burk3316d5e2017-02-15 11:23:01 -080034 static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC) {
Phil Burke1ce4912016-11-21 10:40:25 -080035 struct timespec time;
36 int result = clock_gettime(clockId, &time);
37 if (result < 0) {
38 return -errno;
39 }
Phil Burk5ed503c2017-02-01 09:38:15 -080040 return (time.tv_sec * AAUDIO_NANOS_PER_SECOND) + time.tv_nsec;
Phil Burke1ce4912016-11-21 10:40:25 -080041 }
42
43 /**
44 * Sleep until the specified absolute time.
Phil Burk5ed503c2017-02-01 09:38:15 -080045 * Return immediately with AAUDIO_ERROR_ILLEGAL_ARGUMENT if a negative
Phil Burke1ce4912016-11-21 10:40:25 -080046 * 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 */
Phil Burk3316d5e2017-02-15 11:23:01 -080052 static int sleepUntilNanoTime(int64_t nanoTime,
Phil Burke1ce4912016-11-21 10:40:25 -080053 clockid_t clockId = CLOCK_MONOTONIC) {
54 if (nanoTime > 0) {
55 struct timespec time;
Phil Burk5ed503c2017-02-01 09:38:15 -080056 time.tv_sec = nanoTime / AAUDIO_NANOS_PER_SECOND;
Phil Burke1ce4912016-11-21 10:40:25 -080057 // Calculate the fractional nanoseconds. Avoids expensive % operation.
Phil Burk5ed503c2017-02-01 09:38:15 -080058 time.tv_nsec = nanoTime - (time.tv_sec * AAUDIO_NANOS_PER_SECOND);
Phil Burke1ce4912016-11-21 10:40:25 -080059 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 {
Phil Burk5ed503c2017-02-01 09:38:15 -080070 return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
Phil Burke1ce4912016-11-21 10:40:25 -080071 }
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 */
Phil Burk3316d5e2017-02-15 11:23:01 -080082 static int sleepForNanos(int64_t nanoseconds, clockid_t clockId = CLOCK_MONOTONIC) {
Phil Burke1ce4912016-11-21 10:40:25 -080083 if (nanoseconds > 0) {
84 struct timespec time;
Phil Burk5ed503c2017-02-01 09:38:15 -080085 time.tv_sec = nanoseconds / AAUDIO_NANOS_PER_SECOND;
Phil Burke1ce4912016-11-21 10:40:25 -080086 // Calculate the fractional nanoseconds. Avoids expensive % operation.
Phil Burk5ed503c2017-02-01 09:38:15 -080087 time.tv_nsec = nanoseconds - (time.tv_sec * AAUDIO_NANOS_PER_SECOND);
Phil Burke1ce4912016-11-21 10:40:25 -080088 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
Phil Burkdec33ab2017-01-17 14:48:16 -0800105#endif // UTILITY_AUDIO_CLOCK_H