diff options
4 files changed, 291 insertions, 6 deletions
diff --git a/packages/Vcn/service-b/Android.bp b/packages/Vcn/service-b/Android.bp index 1370b0678cc5..97574e6e35e3 100644 --- a/packages/Vcn/service-b/Android.bp +++ b/packages/Vcn/service-b/Android.bp @@ -39,9 +39,7 @@ java_library { name: "connectivity-utils-service-vcn-internal", sdk_version: "module_current", min_sdk_version: "30", - srcs: [ - ":framework-connectivity-shared-srcs", - ], + srcs: ["service-utils/**/*.java"], libs: [ "framework-annotations-lib", "unsupportedappusage", diff --git a/packages/Vcn/service-b/service-utils/android/util/LocalLog.java b/packages/Vcn/service-b/service-utils/android/util/LocalLog.java new file mode 100644 index 000000000000..5955d930aab1 --- /dev/null +++ b/packages/Vcn/service-b/service-utils/android/util/LocalLog.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2025 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 android.util; + +import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; +import android.os.SystemClock; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDateTime; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Iterator; + +/** + * @hide + */ +// Exported to Mainline modules; cannot use annotations +// @android.ravenwood.annotation.RavenwoodKeepWholeClass +// TODO: b/374174952 This is an exact copy of frameworks/base/core/java/android/util/LocalLog.java. +// This file is only used in "service-connectivity-b-platform" before the VCN modularization flag +// is fully ramped. When the flag is fully ramped and the development is finalized, this file can +// be removed. +public final class LocalLog { + + private final Deque<String> mLog; + private final int mMaxLines; + + /** + * {@code true} to use log timestamps expressed in local date/time, {@code false} to use log + * timestamped expressed with the elapsed realtime clock and UTC system clock. {@code false} is + * useful when logging behavior that modifies device time zone or system clock. + */ + private final boolean mUseLocalTimestamps; + + @UnsupportedAppUsage + public LocalLog(int maxLines) { + this(maxLines, true /* useLocalTimestamps */); + } + + public LocalLog(int maxLines, boolean useLocalTimestamps) { + mMaxLines = Math.max(0, maxLines); + mLog = new ArrayDeque<>(mMaxLines); + mUseLocalTimestamps = useLocalTimestamps; + } + + @UnsupportedAppUsage + public void log(String msg) { + if (mMaxLines <= 0) { + return; + } + final String logLine; + if (mUseLocalTimestamps) { + logLine = LocalDateTime.now() + " - " + msg; + } else { + logLine = Duration.ofMillis(SystemClock.elapsedRealtime()) + + " / " + Instant.now() + " - " + msg; + } + append(logLine); + } + + private synchronized void append(String logLine) { + while (mLog.size() >= mMaxLines) { + mLog.remove(); + } + mLog.add(logLine); + } + + @UnsupportedAppUsage + public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + dump(pw); + } + + public synchronized void dump(PrintWriter pw) { + dump("", pw); + } + + /** + * Dumps the content of local log to print writer with each log entry predeced with indent + * + * @param indent indent that precedes each log entry + * @param pw printer writer to write into + */ + public synchronized void dump(String indent, PrintWriter pw) { + Iterator<String> itr = mLog.iterator(); + while (itr.hasNext()) { + pw.printf("%s%s\n", indent, itr.next()); + } + } + + public synchronized void reverseDump(FileDescriptor fd, PrintWriter pw, String[] args) { + reverseDump(pw); + } + + public synchronized void reverseDump(PrintWriter pw) { + Iterator<String> itr = mLog.descendingIterator(); + while (itr.hasNext()) { + pw.println(itr.next()); + } + } + + // @VisibleForTesting(otherwise = VisibleForTesting.NONE) + public synchronized void clear() { + mLog.clear(); + } + + public static class ReadOnlyLocalLog { + private final LocalLog mLog; + ReadOnlyLocalLog(LocalLog log) { + mLog = log; + } + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + mLog.dump(pw); + } + public void dump(PrintWriter pw) { + mLog.dump(pw); + } + public void reverseDump(FileDescriptor fd, PrintWriter pw, String[] args) { + mLog.reverseDump(pw); + } + public void reverseDump(PrintWriter pw) { + mLog.reverseDump(pw); + } + } + + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public ReadOnlyLocalLog readOnlyLocalLog() { + return new ReadOnlyLocalLog(this); + } +}
\ No newline at end of file diff --git a/packages/Vcn/service-b/service-utils/com/android/internal/util/WakeupMessage.java b/packages/Vcn/service-b/service-utils/com/android/internal/util/WakeupMessage.java new file mode 100644 index 000000000000..7db62f8e9ffc --- /dev/null +++ b/packages/Vcn/service-b/service-utils/com/android/internal/util/WakeupMessage.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2025 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.internal.util; + +import android.app.AlarmManager; +import android.content.Context; +import android.os.Handler; +import android.os.Message; + +import com.android.internal.annotations.VisibleForTesting; + + /** + * An AlarmListener that sends the specified message to a Handler and keeps the system awake until + * the message is processed. + * + * This is useful when using the AlarmManager direct callback interface to wake up the system and + * request that an object whose API consists of messages (such as a StateMachine) perform some + * action. + * + * In this situation, using AlarmManager.onAlarmListener by itself will wake up the system to send + * the message, but does not guarantee that the system will be awake until the target object has + * processed it. This is because as soon as the onAlarmListener sends the message and returns, the + * AlarmManager releases its wakelock and the system is free to go to sleep again. + */ +// TODO: b/374174952 This is an exact copy of +// frameworks/base/core/java/com/android/internal/util/WakeupMessage.java. +// This file is only used in "service-connectivity-b-platform" before the VCN modularization flag +// is fully ramped. When the flag is fully ramped and the development is finalized, this file can +// be removed. +public class WakeupMessage implements AlarmManager.OnAlarmListener { + private final AlarmManager mAlarmManager; + + @VisibleForTesting + protected final Handler mHandler; + @VisibleForTesting + protected final String mCmdName; + @VisibleForTesting + protected final int mCmd, mArg1, mArg2; + @VisibleForTesting + protected final Object mObj; + private final Runnable mRunnable; + private boolean mScheduled; + + public WakeupMessage(Context context, Handler handler, + String cmdName, int cmd, int arg1, int arg2, Object obj) { + mAlarmManager = getAlarmManager(context); + mHandler = handler; + mCmdName = cmdName; + mCmd = cmd; + mArg1 = arg1; + mArg2 = arg2; + mObj = obj; + mRunnable = null; + } + + public WakeupMessage(Context context, Handler handler, String cmdName, int cmd, int arg1) { + this(context, handler, cmdName, cmd, arg1, 0, null); + } + + public WakeupMessage(Context context, Handler handler, + String cmdName, int cmd, int arg1, int arg2) { + this(context, handler, cmdName, cmd, arg1, arg2, null); + } + + public WakeupMessage(Context context, Handler handler, String cmdName, int cmd) { + this(context, handler, cmdName, cmd, 0, 0, null); + } + + public WakeupMessage(Context context, Handler handler, String cmdName, Runnable runnable) { + mAlarmManager = getAlarmManager(context); + mHandler = handler; + mCmdName = cmdName; + mCmd = 0; + mArg1 = 0; + mArg2 = 0; + mObj = null; + mRunnable = runnable; + } + + private static AlarmManager getAlarmManager(Context context) { + return (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + } + + /** + * Schedule the message to be delivered at the time in milliseconds of the + * {@link android.os.SystemClock#elapsedRealtime SystemClock.elapsedRealtime()} clock and wakeup + * the device when it goes off. If schedule is called multiple times without the message being + * dispatched then the alarm is rescheduled to the new time. + */ + public synchronized void schedule(long when) { + mAlarmManager.setExact( + AlarmManager.ELAPSED_REALTIME_WAKEUP, when, mCmdName, this, mHandler); + mScheduled = true; + } + + /** + * Cancel all pending messages. This includes alarms that may have been fired, but have not been + * run on the handler yet. + */ + public synchronized void cancel() { + if (mScheduled) { + mAlarmManager.cancel(this); + mScheduled = false; + } + } + + @Override + public void onAlarm() { + // Once this method is called the alarm has already been fired and removed from + // AlarmManager (it is still partially tracked, but only for statistics). The alarm can now + // be marked as unscheduled so that it can be rescheduled in the message handler. + final boolean stillScheduled; + synchronized (this) { + stillScheduled = mScheduled; + mScheduled = false; + } + if (stillScheduled) { + Message msg; + if (mRunnable == null) { + msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj); + } else { + msg = Message.obtain(mHandler, mRunnable); + } + mHandler.dispatchMessage(msg); + msg.recycle(); + } + } +}
\ No newline at end of file diff --git a/packages/Vcn/service-b/service-vcn-platform-jarjar-rules.txt b/packages/Vcn/service-b/service-vcn-platform-jarjar-rules.txt index 36307277b4b9..6ec39d953266 100644 --- a/packages/Vcn/service-b/service-vcn-platform-jarjar-rules.txt +++ b/packages/Vcn/service-b/service-vcn-platform-jarjar-rules.txt @@ -1,5 +1,2 @@ -rule android.util.IndentingPrintWriter android.net.vcn.module.repackaged.android.util.IndentingPrintWriter rule android.util.LocalLog android.net.vcn.module.repackaged.android.util.LocalLog -rule com.android.internal.util.IndentingPrintWriter android.net.vcn.module.repackaged.com.android.internal.util.IndentingPrintWriter -rule com.android.internal.util.MessageUtils android.net.vcn.module.repackaged.com.android.internal.util.MessageUtils rule com.android.internal.util.WakeupMessage android.net.vcn.module.repackaged.com.android.internal.util.WakeupMessage
\ No newline at end of file |