DivestOS/Patches/LineageOS-20.0/android_frameworks_base/0015-System_Server_Extensions.patch
Tad 9475615e77
A13 QPR2 Churn
Signed-off-by: Tad <tad@spotco.us>
2023-03-19 20:52:48 -04:00

241 lines
8.5 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Sun, 31 Jul 2022 10:06:14 +0300
Subject: [PATCH] infrastructure for system_server extensions
---
.../server/ext/DelayedConditionalAction.java | 135 ++++++++++++++++++
.../android/server/ext/SystemServerExt.java | 58 ++++++++
.../java/com/android/server/SystemServer.java | 4 +-
3 files changed, 196 insertions(+), 1 deletion(-)
create mode 100644 services/core/java/com/android/server/ext/DelayedConditionalAction.java
create mode 100644 services/core/java/com/android/server/ext/SystemServerExt.java
diff --git a/services/core/java/com/android/server/ext/DelayedConditionalAction.java b/services/core/java/com/android/server/ext/DelayedConditionalAction.java
new file mode 100644
index 000000000000..d72f302e9d42
--- /dev/null
+++ b/services/core/java/com/android/server/ext/DelayedConditionalAction.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2022 GrapheneOS
+ *
+ * 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.server.ext;
+
+import android.app.AlarmManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.util.Slog;
+
+/**
+ * Infrastructure for actions that:
+ * - happen after a user-configurable device-wide (Settings.Global) delay
+ * - need to be taken even when the device is in deep sleep
+ * - need to be rescheduled based on some listenable event
+ */
+public abstract class DelayedConditionalAction {
+ private static final String TAG = "DelayedConditionalAction";
+
+ protected final SystemServerExt sse;
+ protected final Thread thread;
+ protected final Handler handler;
+
+ protected final ContentResolver contentResolver;
+ protected final AlarmManager alarmManager;
+ private final AlarmManager.OnAlarmListener alarmListener;
+
+ protected DelayedConditionalAction(SystemServerExt sse, Handler handler) {
+ this.sse = sse;
+
+ Looper looper = handler.getLooper();
+ thread = looper.getThread();
+ this.handler = handler;
+
+ if (Build.isDebuggable()) {
+ if (thread != Thread.currentThread()) {
+ throw new IllegalStateException("all calls should happen on the same thread");
+ }
+ }
+
+ Context ctx = sse.context;
+ contentResolver = ctx.getContentResolver();
+ alarmManager = ctx.getSystemService(AlarmManager.class);
+
+ alarmListener = () -> {
+ if (delayDurationMillis() == 0) {
+ return;
+ }
+
+ alarmTriggered();
+ };
+
+ registerStateListener();
+
+ Uri delaySettingUri = Settings.Global.getUriFor(getDelayGlobalSettingsKey());
+
+ ContentObserver delayChangeListener = new ContentObserver(handler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ update();
+ }
+ };
+
+ contentResolver.registerContentObserver(delaySettingUri, false, delayChangeListener);
+ }
+
+ private boolean alarmScheduled;
+
+ protected final void update() {
+ final Thread curThread = Thread.currentThread();
+ if (curThread != thread) {
+ String msg = "update() called on an unknown thread " + curThread;
+ if (Build.isDebuggable()) {
+ throw new IllegalStateException(msg);
+ } else {
+ Slog.e(TAG, msg, new Throwable());
+ return;
+ }
+ }
+
+ if (alarmScheduled) {
+ alarmManager.cancel(alarmListener);
+ alarmScheduled = false;
+ }
+
+ if (!shouldScheduleAlarm()) {
+ return;
+ }
+
+ long delayMillis = delayDurationMillis();
+
+ if (delayMillis == 0) {
+ return;
+ }
+
+ final long triggerAt = SystemClock.elapsedRealtime() + delayMillis;
+ alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAt,
+ getClass().getName(), alarmListener, handler);
+ alarmScheduled = true;
+ }
+
+ private long delayDurationMillis() {
+ return Settings.Global.getLong(contentResolver, getDelayGlobalSettingsKey(), 0);
+ }
+
+ // Make sure to use the same Handler that is used for all other callbacks;
+ // call update() to reschedule / cancel the alarm
+ protected abstract void registerStateListener();
+
+ protected abstract boolean shouldScheduleAlarm();
+ protected abstract void alarmTriggered();
+
+ // android.provider.Settings.Global key
+ protected abstract String getDelayGlobalSettingsKey();
+}
diff --git a/services/core/java/com/android/server/ext/SystemServerExt.java b/services/core/java/com/android/server/ext/SystemServerExt.java
new file mode 100644
index 000000000000..83d895650473
--- /dev/null
+++ b/services/core/java/com/android/server/ext/SystemServerExt.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2022 GrapheneOS
+ *
+ * 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.server.ext;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.IntentFilter;
+import android.os.Handler;
+
+import com.android.internal.os.BackgroundThread;
+import com.android.server.pm.PackageManagerService;
+
+public final class SystemServerExt {
+
+ public final Context context;
+ public final Handler bgHandler;
+ public final PackageManagerService packageManager;
+
+ private SystemServerExt(Context systemContext, PackageManagerService pm) {
+ context = systemContext;
+ bgHandler = BackgroundThread.getHandler();
+ packageManager = pm;
+ }
+
+ /*
+ Called after system server has completed its initialization,
+ but before any of the apps are started.
+
+ Call from com.android.server.SystemServer#startOtherServices(), at the end of lambda
+ that is passed into mActivityManagerService.systemReady()
+ */
+ public static void init(Context systemContext, PackageManagerService pm) {
+ SystemServerExt sse = new SystemServerExt(systemContext, pm);
+ sse.bgHandler.post(sse::initBgThread);
+ }
+
+ void initBgThread() {
+
+ }
+
+ public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter, Handler handler) {
+ context.registerReceiver(receiver, filter, null, handler);
+ }
+}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index aa6918451fc1..960d7ae2eba9 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -2223,7 +2223,7 @@ public final class SystemServer implements Dumpable {
Slog.e(TAG, "Failure starting HardwarePropertiesManagerService", e);
}
t.traceEnd();
-
+
if (!isWatch) {
t.traceBegin("StartTwilightService");
mSystemServiceManager.startService(TwilightService.class);
@@ -3062,6 +3062,8 @@ public final class SystemServer implements Dumpable {
reportWtf("Triggering OdsignStatsLogger", e);
}
t.traceEnd();
+
+ com.android.server.ext.SystemServerExt.init(mSystemContext, mPackageManagerService);
}, t);
t.traceBegin("StartSystemUI");