1 /*
2  * Copyright (C) 2024 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 #include <errno.h>
18 #include <jni.h>
19 #include <nativehelper/JNIHelp.h>
20 #include <nativehelper/scoped_utf_chars.h>
21 #include <stdint.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/epoll.h>
26 #include <sys/timerfd.h>
27 #include <time.h>
28 #include <unistd.h>
29 
30 #define MSEC_PER_SEC 1000
31 #define NSEC_PER_MSEC 1000000
32 
33 namespace android {
34 
35 static jint
com_android_net_module_util_TimerFdUtils_createTimerFd(JNIEnv * env,jclass clazz)36 com_android_net_module_util_TimerFdUtils_createTimerFd(JNIEnv *env,
37                                                        jclass clazz) {
38   int tfd;
39   tfd = timerfd_create(CLOCK_BOOTTIME, 0);
40   if (tfd == -1) {
41     jniThrowErrnoException(env, "createTimerFd", tfd);
42   }
43   return tfd;
44 }
45 
46 static void
com_android_net_module_util_TimerFdUtils_setTime(JNIEnv * env,jclass clazz,jint tfd,jlong milliseconds)47 com_android_net_module_util_TimerFdUtils_setTime(JNIEnv *env, jclass clazz,
48                                                  jint tfd, jlong milliseconds) {
49   struct itimerspec new_value;
50   new_value.it_value.tv_sec = milliseconds / MSEC_PER_SEC;
51   new_value.it_value.tv_nsec = (milliseconds % MSEC_PER_SEC) * NSEC_PER_MSEC;
52   // Set the interval time to 0 because it's designed for repeated timer expirations after the
53   // initial expiration, which doesn't fit the current usage.
54   new_value.it_interval.tv_sec = 0;
55   new_value.it_interval.tv_nsec = 0;
56 
57   int ret = timerfd_settime(tfd, 0, &new_value, NULL);
58   if (ret == -1) {
59     jniThrowErrnoException(env, "setTime", ret);
60   }
61 }
62 
63 /*
64  * JNI registration.
65  */
66 static const JNINativeMethod gMethods[] = {
67     /* name, signature, funcPtr */
68     {"createTimerFd", "()I",
69      (void *)com_android_net_module_util_TimerFdUtils_createTimerFd},
70     {"setTime", "(IJ)V",
71      (void *)com_android_net_module_util_TimerFdUtils_setTime},
72 };
73 
register_com_android_net_module_util_TimerFdUtils(JNIEnv * env,char const * class_name)74 int register_com_android_net_module_util_TimerFdUtils(JNIEnv *env,
75                                                       char const *class_name) {
76   return jniRegisterNativeMethods(env, class_name, gMethods, NELEM(gMethods));
77 }
78 
79 }; // namespace android
80