diff --git a/res/values/evolution_attrs.xml b/res/values/evolution_attrs.xml
index 5018c28..9adbe71 100644
--- a/res/values/evolution_attrs.xml
+++ b/res/values/evolution_attrs.xml
@@ -22,4 +22,10 @@
+
+
+
+
+
+
diff --git a/src/org/evolution/settings/preferences/OverlaySwitchPreference.java b/src/org/evolution/settings/preferences/OverlaySwitchPreference.java
new file mode 100644
index 0000000..9a7856e
--- /dev/null
+++ b/src/org/evolution/settings/preferences/OverlaySwitchPreference.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2022 Yet Another AOSP 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 org.evolution.settings.preferences;
+
+import static android.os.UserHandle.CURRENT;
+import static android.os.UserHandle.USER_CURRENT;
+
+import android.content.Context;
+import android.content.om.OverlayManager;
+import android.content.om.OverlayManagerTransaction;
+import android.content.om.OverlayIdentifier;
+import android.content.om.OverlayInfo;
+import android.content.res.Configuration;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.util.AttributeSet;
+import android.util.Log;
+
+import java.lang.SecurityException;
+import java.util.List;
+
+import lineageos.preference.SelfRemovingSwitchPreference;
+
+public class OverlaySwitchPreference extends SelfRemovingSwitchPreference {
+
+ private final static String TAG = "OverlaySwitchPreference";
+ private final static String SETTINGSNS = "http://schemas.android.com/apk/res-auto";
+ private static final String DKEY = "dkey";
+ private static final String DKEY_NIGHT_ONLY = "dkeyNightOnly";
+
+ private final String mDisableKey;
+ private final boolean mDKeyNightOnly;
+ private final OverlayManager mOverlayManager;
+
+ public OverlaySwitchPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ mDisableKey = attrs.getAttributeValue(SETTINGSNS, DKEY);
+ mDKeyNightOnly = attrs.getAttributeBooleanValue(SETTINGSNS, DKEY_NIGHT_ONLY, false);
+ mOverlayManager = context.getSystemService(OverlayManager.class);
+ }
+
+ public OverlaySwitchPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mDisableKey = attrs.getAttributeValue(SETTINGSNS, DKEY);
+ mDKeyNightOnly = attrs.getAttributeBooleanValue(SETTINGSNS, DKEY_NIGHT_ONLY, false);
+ mOverlayManager = context.getSystemService(OverlayManager.class);
+ }
+
+ public OverlaySwitchPreference(Context context) {
+ this(context, null);
+ }
+
+ @Override
+ protected boolean isPersisted() {
+ return true;
+ }
+
+ @Override
+ protected boolean getBoolean(String key, boolean defaultValue) {
+ if (mOverlayManager == null) return false;
+ OverlayInfo info = null;
+ info = mOverlayManager.getOverlayInfo(getOverlayID(getKey()), CURRENT);
+ if (info != null) return info.isEnabled();
+ return false;
+ }
+
+ @Override
+ protected void putBoolean(String key, boolean value) {
+ if (mOverlayManager == null) return;
+ OverlayManagerTransaction.Builder transaction = new OverlayManagerTransaction.Builder();
+ transaction.setEnabled(getOverlayID(getKey()), value, USER_CURRENT);
+ if (mDisableKey != null && !mDisableKey.isEmpty()) {
+ if (mDKeyNightOnly) {
+ final boolean isNight = (getContext().getResources().getConfiguration().uiMode
+ & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
+ if (isNight)
+ transaction.setEnabled(getOverlayID(mDisableKey), !value, USER_CURRENT);
+ else // always enabled in day
+ transaction.setEnabled(getOverlayID(mDisableKey), true, USER_CURRENT);
+ } else {
+ transaction.setEnabled(getOverlayID(mDisableKey), !value, USER_CURRENT);
+ }
+ }
+ try {
+ mOverlayManager.commit(transaction.build());
+ } catch (SecurityException | IllegalStateException e) {
+ Log.e(TAG, "Failed setting overlay(s), future logs will point the reason");
+ e.printStackTrace();
+ return;
+ }
+ }
+
+ private OverlayIdentifier getOverlayID(String name) throws IllegalStateException {
+ if (mOverlayManager == null) return null;
+ if (name.contains(":")) {
+ // specific overlay name in a package
+ final String[] value = name.split(":");
+ final String pkgName = value[0];
+ final String overlayName = value[1];
+ final List infos =
+ mOverlayManager.getOverlayInfosForTarget(pkgName, CURRENT);
+ for (OverlayInfo info : infos) {
+ if (overlayName.equals(info.getOverlayName()))
+ return info.getOverlayIdentifier();
+ }
+ throw new IllegalStateException("No overlay found for " + name);
+ }
+ // package with only one overlay
+ return mOverlayManager.getOverlayInfo(name, CURRENT).getOverlayIdentifier();
+ }
+}