Add base async io interfaces for wear tethering
Bug: 245971639
Change-Id: I31ccd7193409c82a0902e4ae318cc096f93f32da
diff --git a/staticlibs/device/com/android/net/module/util/async/AsyncFile.java b/staticlibs/device/com/android/net/module/util/async/AsyncFile.java
new file mode 100644
index 0000000..2a3231b
--- /dev/null
+++ b/staticlibs/device/com/android/net/module/util/async/AsyncFile.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2022 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.async;
+
+import java.io.IOException;
+
+/**
+ * Represents an EventManager-managed file with Async IO semantics.
+ *
+ * Implements level-based Asyn IO semantics. This means that:
+ * - onReadReady() callback would keep happening as long as there's any remaining
+ * data to read, or the user calls enableReadEvents(false)
+ * - onWriteReady() callback would keep happening as long as there's remaining space
+ * to write to, or the user calls enableWriteEvents(false)
+ *
+ * All operations except close() must be called on the EventManager thread.
+ *
+ * @hide
+ */
+public interface AsyncFile {
+ /**
+ * Receives notifications when file readability or writeability changes.
+ * @hide
+ */
+ public interface Listener {
+ /** Invoked after the underlying file has been closed. */
+ void onClosed(AsyncFile file);
+
+ /** Invoked while the file has readable data and read notifications are enabled. */
+ void onReadReady(AsyncFile file);
+
+ /** Invoked while the file has writeable space and write notifications are enabled. */
+ void onWriteReady(AsyncFile file);
+ }
+
+ /** Requests this file to be closed. */
+ void close();
+
+ /** Enables or disables onReadReady() events. */
+ void enableReadEvents(boolean enable);
+
+ /** Enables or disables onWriteReady() events. */
+ void enableWriteEvents(boolean enable);
+
+ /** Returns true if the input stream has reached its end, or has been closed. */
+ boolean reachedEndOfFile();
+
+ /**
+ * Reads available data from the given non-blocking file descriptor.
+ *
+ * Returns zero if there's no data to read at this moment.
+ * Returns -1 if the file has reached its end or the input stream has been closed.
+ * Otherwise returns the number of bytes read.
+ */
+ int read(byte[] buffer, int pos, int len) throws IOException;
+
+ /**
+ * Writes data into the given non-blocking file descriptor.
+ *
+ * Returns zero if there's no buffer space to write to at this moment.
+ * Otherwise returns the number of bytes written.
+ */
+ int write(byte[] buffer, int pos, int len) throws IOException;
+}
diff --git a/staticlibs/device/com/android/net/module/util/async/EventManager.java b/staticlibs/device/com/android/net/module/util/async/EventManager.java
new file mode 100644
index 0000000..4ed4a70
--- /dev/null
+++ b/staticlibs/device/com/android/net/module/util/async/EventManager.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022 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.async;
+
+import java.io.IOException;
+import java.util.concurrent.Executor;
+
+/**
+ * Manages Async IO files and scheduled alarms, and executes all related callbacks
+ * in its own thread.
+ *
+ * All callbacks of AsyncFile, Alarm and EventManager will execute on EventManager's thread.
+ *
+ * Methods of this interface can be called from any thread.
+ *
+ * @hide
+ */
+public interface EventManager extends Executor {
+ /**
+ * Represents a scheduled alarm, allowing caller to attempt to cancel that alarm
+ * before it executes.
+ *
+ * @hide
+ */
+ public interface Alarm {
+ /** @hide */
+ public interface Listener {
+ void onAlarm(Alarm alarm, long elapsedTimeMs);
+ void onAlarmCancelled(Alarm alarm);
+ }
+
+ /**
+ * Attempts to cancel this alarm. Note that this request is inherently
+ * racy if executed close to the alarm's expiration time.
+ */
+ void cancel();
+ }
+
+ /**
+ * Requests EventManager to manage the given file.
+ *
+ * The file descriptors are not cloned, and EventManager takes ownership of all files passed.
+ *
+ * No event callbacks are enabled by this method.
+ */
+ AsyncFile registerFile(FileHandle fileHandle, AsyncFile.Listener listener) throws IOException;
+
+ /**
+ * Schedules Alarm with the given timeout.
+ *
+ * Timeout of zero can be used for immediate execution.
+ */
+ Alarm scheduleAlarm(long timeout, Alarm.Listener callback);
+
+ /** Schedules Runnable for immediate execution. */
+ @Override
+ void execute(Runnable callback);
+
+ /** Throws a runtime exception if the caller is not executing on this EventManager's thread. */
+ void assertInThread();
+}
diff --git a/staticlibs/device/com/android/net/module/util/async/FileHandle.java b/staticlibs/device/com/android/net/module/util/async/FileHandle.java
new file mode 100644
index 0000000..9f7942d
--- /dev/null
+++ b/staticlibs/device/com/android/net/module/util/async/FileHandle.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2022 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.async;
+
+import android.os.ParcelFileDescriptor;
+
+import java.io.Closeable;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Represents an file descriptor or another way to access a file.
+ *
+ * @hide
+ */
+public final class FileHandle {
+ private final ParcelFileDescriptor mFd;
+ private final Closeable mCloseable;
+ private final InputStream mInputStream;
+ private final OutputStream mOutputStream;
+
+ public static FileHandle fromFileDescriptor(ParcelFileDescriptor fd) {
+ if (fd == null) {
+ throw new NullPointerException();
+ }
+ return new FileHandle(fd, null, null, null);
+ }
+
+ public static FileHandle fromBlockingStream(
+ Closeable closeable, InputStream is, OutputStream os) {
+ if (closeable == null || is == null || os == null) {
+ throw new NullPointerException();
+ }
+ return new FileHandle(null, closeable, is, os);
+ }
+
+ private FileHandle(ParcelFileDescriptor fd, Closeable closeable,
+ InputStream is, OutputStream os) {
+ mFd = fd;
+ mCloseable = closeable;
+ mInputStream = is;
+ mOutputStream = os;
+ }
+
+ ParcelFileDescriptor getFileDescriptor() {
+ return mFd;
+ }
+
+ Closeable getCloseable() {
+ return mCloseable;
+ }
+
+ InputStream getInputStream() {
+ return mInputStream;
+ }
+
+ OutputStream getOutputStream() {
+ return mOutputStream;
+ }
+}