Add switchable theme to tuner
Allows option in tuner to switch between system theme overlays
if multiple exist. Requires a restart to take effect.
Test: Settings -> Tuner -> Other -> Theme
Change-Id: Iea43b9cbb67fd91c6008be594ad4cfd19c3f57ec
diff --git a/core/java/android/app/IUiModeManager.aidl b/core/java/android/app/IUiModeManager.aidl
index cae54b6..848464c 100644
--- a/core/java/android/app/IUiModeManager.aidl
+++ b/core/java/android/app/IUiModeManager.aidl
@@ -53,6 +53,16 @@
int getNightMode();
/**
+ * Sets whith theme overlays to use within /vendor/overlay.
+ */
+ void setTheme(String theme);
+
+ /**
+ * Gets whith theme overlays to use within /vendor/overlay.
+ */
+ String getTheme();
+
+ /**
* Tells if UI mode is locked or not.
*/
boolean isUiModeLocked();
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 0046b0e..2e21729 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -241,6 +241,35 @@
}
/**
+ * Sets the vendor theme overlay property, then triggers a reboot.
+ * @hide
+ */
+ public void setTheme(String theme) {
+ if (mService != null) {
+ try {
+ mService.setTheme(theme);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Gets the vendor theme overlay property.
+ * @hide
+ */
+ public String getTheme() {
+ if (mService != null) {
+ try {
+ return mService.getTheme();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ return null;
+ }
+
+ /**
* Returns the currently configured night mode.
* <p>
* May be one of:
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3dea051..0f7b5a5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3130,6 +3130,12 @@
<permission android:name="android.permission.MANAGE_AUTO_FILL"
android:protectionLevel="signature" />
+ <!-- Allows an app to set the theme overlay in /vendor/overlay
+ being used.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.MODIFY_THEME_OVERLAY"
+ android:protectionLevel="signature" />
+
<application android:process="system"
android:persistent="true"
android:hasCode="false"
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index e07d865..0b5383a 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -171,6 +171,8 @@
<!-- shortcut manager -->
<uses-permission android:name="android.permission.RESET_SHORTCUT_MANAGER_THROTTLING" />
+ <uses-permission android:name="android.permission.MODIFY_THEME_OVERLAY" />
+
<application
android:name=".SystemUIApplication"
android:persistent="true"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index b1d81ca..331d09e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1722,4 +1722,11 @@
not appear on production builds ever. -->
<string name="pip_allow_minimize_summary" translatable="false">Allow PIP to minimize slightly offscreen</string>
+ <!-- Tuner string -->
+ <string name="change_theme_reboot" translatable="false">Changing the theme requires a restart.</string>
+ <!-- Tuner string -->
+ <string name="theme" translatable="false">Theme</string>
+ <!-- Tuner string -->
+ <string name="default_theme" translatable="false">Default</string>
+
</resources>
diff --git a/packages/SystemUI/res/xml/other_settings.xml b/packages/SystemUI/res/xml/other_settings.xml
index ce636cd..18cb930 100644
--- a/packages/SystemUI/res/xml/other_settings.xml
+++ b/packages/SystemUI/res/xml/other_settings.xml
@@ -23,5 +23,10 @@
android:key="power_notification_controls"
android:title="@string/tuner_full_importance_settings"
android:fragment="com.android.systemui.tuner.PowerNotificationControlsFragment"/>
+e
+ <com.android.systemui.tuner.ThemePreference
+ android:key="theme"
+ android:title="@string/theme"
+ android:summary="%s" />
-</PreferenceScreen>
\ No newline at end of file
+</PreferenceScreen>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 99e7876..8292f85 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -32,6 +32,7 @@
import com.android.systemui.keyboard.KeyboardUI;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.media.RingtonePlayer;
+import com.android.systemui.pip.PipUI;
import com.android.systemui.plugins.OverlayPlugin;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.PluginManager;
@@ -42,7 +43,6 @@
import com.android.systemui.statusbar.SystemBars;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.tuner.TunerService;
-import com.android.systemui.pip.PipUI;
import com.android.systemui.usb.StorageNotification;
import com.android.systemui.volume.VolumeUI;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ThemePreference.java b/packages/SystemUI/src/com/android/systemui/tuner/ThemePreference.java
new file mode 100644
index 0000000..e5bb3d5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ThemePreference.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 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.systemui.tuner;
+
+import android.app.AlertDialog;
+import android.app.UiModeManager;
+import android.content.Context;
+import android.os.SystemProperties;
+import android.support.v7.preference.ListPreference;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+
+import com.android.systemui.R;
+
+import libcore.util.Objects;
+
+import com.google.android.collect.Lists;
+
+import java.io.File;
+import java.util.ArrayList;
+
+public class ThemePreference extends ListPreference {
+
+ public ThemePreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public void onAttached() {
+ super.onAttached();
+ File file = new File("/vendor/overlay");
+ ArrayList<String> options = Lists.newArrayList(file.list());
+ String def = SystemProperties.get("ro.boot.vendor.overlay.theme");
+ if (TextUtils.isEmpty(def)) {
+ def = getContext().getString(R.string.default_theme);
+ }
+ if (!options.contains(def)) {
+ options.add(0, def);
+ }
+ String[] list = options.toArray(new String[options.size()]);
+ setVisible(options.size() > 1);
+ setEntries(list);
+ setEntryValues(list);
+ updateValue();
+ }
+
+ private void updateValue() {
+ setValue(getContext().getSystemService(UiModeManager.class).getTheme());
+ }
+
+ @Override
+ protected void notifyChanged() {
+ super.notifyChanged();
+ if (!Objects.equal(getValue(),
+ getContext().getSystemService(UiModeManager.class).getTheme())) {
+ new AlertDialog.Builder(getContext())
+ .setTitle(R.string.change_theme_reboot)
+ .setPositiveButton(com.android.internal.R.string.global_action_restart, (d, i)
+ -> getContext().getSystemService(UiModeManager.class)
+ .setTheme(getValue()))
+ .setNegativeButton(android.R.string.cancel, (d, i) -> updateValue())
+ .show();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 2825cf9..6268697 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -39,19 +39,24 @@
import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.dreams.Sandman;
import android.util.Slog;
+import android.view.WindowManagerInternal;
+import android.view.WindowManagerPolicy;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import com.android.internal.R;
import com.android.internal.app.DisableCarModeActivity;
+import com.android.server.power.ShutdownThread;
import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
+import com.android.server.wm.WindowManagerService;
final class UiModeManagerService extends SystemService {
private static final String TAG = UiModeManager.class.getSimpleName();
@@ -297,6 +302,30 @@
}
@Override
+ public void setTheme(String theme) {
+ if (getContext().checkCallingOrSelfPermission(
+ android.Manifest.permission.MODIFY_THEME_OVERLAY)
+ != PackageManager.PERMISSION_GRANTED) {
+ Slog.e(TAG, "setTheme requires MODIFY_THEME_OVERLAY permission");
+ return;
+ }
+ SystemProperties.set("persist.vendor.overlay.theme", theme);
+ mHandler.post(() -> ShutdownThread.reboot(getContext(),
+ PowerManager.SHUTDOWN_USER_REQUESTED, false));
+ }
+
+ @Override
+ public String getTheme() {
+ if (getContext().checkCallingOrSelfPermission(
+ android.Manifest.permission.MODIFY_THEME_OVERLAY)
+ != PackageManager.PERMISSION_GRANTED) {
+ Slog.e(TAG, "setTheme requires MODIFY_THEME_OVERLAY permission");
+ return null;
+ }
+ return SystemProperties.get("persist.vendor.overlay.theme");
+ }
+
+ @Override
public int getNightMode() {
synchronized (mLock) {
return mNightMode;