Create the timerfd helper class

Create a helper class in Java to provide easy access to timerfd
JNI methods.

Bug: 366373064
Test: atest NetworkStaticLibTests
Change-Id: Iea09cd29e2a6ed837ece30c512393be2e27e8c2e
diff --git a/service/Android.bp b/service/Android.bp
index 567c079..fd3d4a3 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -90,7 +90,6 @@
     static_libs: [
         "libnet_utils_device_common_bpfjni",
         "libnet_utils_device_common_bpfutils",
-        "libnet_utils_device_common_timerfdjni",
     ],
     shared_libs: [
         "liblog",
@@ -126,6 +125,7 @@
         "libmodules-utils-build",
         "libnetjniutils",
         "libnet_utils_device_common_bpfjni",
+        "libnet_utils_device_common_timerfdjni",
         "netd_aidl_interface-lateststable-ndk",
     ],
     shared_libs: [
diff --git a/service/jni/onload.cpp b/service/jni/onload.cpp
index bb70d4f..8e01260 100644
--- a/service/jni/onload.cpp
+++ b/service/jni/onload.cpp
@@ -26,6 +26,8 @@
 int register_android_server_net_NetworkStatsFactory(JNIEnv* env);
 int register_android_server_net_NetworkStatsService(JNIEnv* env);
 int register_com_android_server_ServiceManagerWrapper(JNIEnv* env);
+int register_com_android_net_module_util_TimerFdUtils(JNIEnv *env,
+                                                      char const *class_name);
 
 extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
     JNIEnv *env;
@@ -56,6 +58,12 @@
         }
     }
 
+    if (register_com_android_net_module_util_TimerFdUtils(
+            env, "android/net/connectivity/com/android/net/module/util/"
+                 "TimerFdUtils") < 0) {
+      return JNI_ERR;
+    }
+
     return JNI_VERSION_1_6;
 }
 
diff --git a/staticlibs/Android.bp b/staticlibs/Android.bp
index a825b87..b5ee789 100644
--- a/staticlibs/Android.bp
+++ b/staticlibs/Android.bp
@@ -32,6 +32,8 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
+// This library shouldn't be used anymore (no class should be added), and per-user libraries like
+// net-utils-service-connectivity or net-utils-framework-wifi should be used instead.
 java_library {
     name: "net-utils-device-common",
     srcs: [
diff --git a/staticlibs/device/com/android/net/module/util/TimerFdUtils.java b/staticlibs/device/com/android/net/module/util/TimerFdUtils.java
new file mode 100644
index 0000000..310dbc9
--- /dev/null
+++ b/staticlibs/device/com/android/net/module/util/TimerFdUtils.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.net.module.util;
+
+import android.os.Process;
+import android.util.Log;
+
+import java.io.IOException;
+
+/**
+ * Contains mostly timerfd functionality.
+ */
+public class TimerFdUtils {
+    static {
+        if (Process.myUid() == Process.SYSTEM_UID) {
+            // This library is part of service-connectivity.jar when in the system server,
+            // so libservice-connectivity.so is the library to load.
+            System.loadLibrary("service-connectivity");
+        } else {
+            System.loadLibrary(JniUtil.getJniLibraryName(TimerFdUtils.class.getPackage()));
+        }
+    }
+
+    private static final String TAG = TimerFdUtils.class.getSimpleName();
+
+    /**
+     * Create a timerfd.
+     *
+     * @throws IOException if the timerfd creation is failed.
+     */
+    private static native int createTimerFd() throws IOException;
+
+    /**
+     * Set given time to the timerfd.
+     *
+     * @param timeMs target time
+     * @throws IOException if setting expiration time is failed.
+     */
+    private static native void setTime(int fd, long timeMs) throws IOException;
+
+    /**
+     * Create a timerfd
+     */
+    static int createTimerFileDescriptor() {
+        try {
+            return createTimerFd();
+        } catch (IOException e) {
+            Log.e(TAG, "createTimerFd failed", e);
+            return -1;
+        }
+    }
+
+    /**
+     * Set expiration time to timerfd
+     */
+    static boolean setExpirationTime(int id, long expirationTimeMs) {
+        try {
+            setTime(id, expirationTimeMs);
+        } catch (IOException e) {
+            Log.e(TAG, "setExpirationTime failed", e);
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/tests/unit/jni/android_net_frameworktests_util/onload.cpp b/tests/unit/jni/android_net_frameworktests_util/onload.cpp
index 06a3986..a0ce4f8 100644
--- a/tests/unit/jni/android_net_frameworktests_util/onload.cpp
+++ b/tests/unit/jni/android_net_frameworktests_util/onload.cpp
@@ -24,6 +24,8 @@
 
 int register_com_android_net_module_util_BpfMap(JNIEnv* env, char const* class_name);
 int register_com_android_net_module_util_TcUtils(JNIEnv* env, char const* class_name);
+int register_com_android_net_module_util_TimerFdUtils(JNIEnv *env,
+                                                      char const *class_name);
 
 extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
     JNIEnv *env;
@@ -38,6 +40,10 @@
     if (register_com_android_net_module_util_TcUtils(env,
             "android/net/frameworktests/util/TcUtils") < 0) return JNI_ERR;
 
+    if (register_com_android_net_module_util_TimerFdUtils(
+            env, "android/net/frameworktests/util/TimerFdUtils") < 0)
+      return JNI_ERR;
+
     return JNI_VERSION_1_6;
 }