[1/2] OmniGears: add omni theme selector
Change-Id: I14b6d31f35db391450b2e2f6dc60ff593e8a6afb
diff --git a/res/values/custom_strings.xml b/res/values/custom_strings.xml
index f981518..96a1052 100644
--- a/res/values/custom_strings.xml
+++ b/res/values/custom_strings.xml
@@ -441,8 +441,6 @@
<!-- OMS -->
<string name="theming_title">Theming</string>
- <string name="oms_app_title">Substratum theme engine</string>
- <string name="oms_app_summary">Start Substratum experience</string>
<string name="status_bar_ime_notification_title">Show IME notification</string>
<string name="status_bar_ime_notification_summary">If navigation bar is not available</string>
@@ -608,8 +606,6 @@
<string name="logcat_app_title">MatLog</string>
<string name="logcat_app_summary">Start app to collect logs</string>
- <string name="omni_theme_title">Omni Light/Dark theme</string>
- <string name="omni_theme_summary">Substratum based theme</string>
<string name="show_dashboard_columns_title">Use columns layout</string>
<string name="show_dashboard_columns_summary">In settings main page</string>
@@ -637,4 +633,7 @@
<string name="screen_off_animation_crt">CRT</string>
<string name="screen_off_animation_scale">Scale</string>
<string name="screen_off_animation_title">Screen off animation</string>
+
+ <string name="omni_theme_select_title">Omni themes</string>
+ <string name="omni_theme_select_none">Disabled</string>
</resources>
diff --git a/res/xml/style_settings.xml b/res/xml/style_settings.xml
index 06b8cd7..94971eb 100644
--- a/res/xml/style_settings.xml
+++ b/res/xml/style_settings.xml
@@ -38,6 +38,11 @@
android:entries="@array/systemui_theme_style_entries"
android:entryValues="@array/systemui_theme_style_values" />
+ <ListPreference
+ android:key="omni_theme_select"
+ android:title="@string/omni_theme_select_title"
+ android:summary="@string/summary_placeholder" />
+
</PreferenceCategory>
<PreferenceCategory
diff --git a/src/org/omnirom/omnigears/interfacesettings/OmniThemePreferenceController.java b/src/org/omnirom/omnigears/interfacesettings/OmniThemePreferenceController.java
new file mode 100644
index 0000000..346e286
--- /dev/null
+++ b/src/org/omnirom/omnigears/interfacesettings/OmniThemePreferenceController.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2017 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 org.omnirom.omnigears.interfacesettings;
+
+import android.content.Context;
+import android.content.om.IOverlayManager;
+import android.content.om.OverlayInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.Preference;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.core.instrumentation.MetricsFeatureProvider;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import libcore.util.Objects;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_THEME;
+
+public class OmniThemePreferenceController extends AbstractPreferenceController implements
+ PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
+
+ private static final String KEY_THEME = "omni_theme_select";
+ private static final String KEY_THEMES_DISABLED = "default";
+ private static final String OMNI_THEME_PREFIX = "org.omnirom.";
+
+ private final MetricsFeatureProvider mMetricsFeatureProvider;
+ private final OverlayManager mOverlayService;
+ private final PackageManager mPackageManager;
+
+ public OmniThemePreferenceController(Context context) {
+ this(context, ServiceManager.getService(Context.OVERLAY_SERVICE) != null
+ ? new OverlayManager() : null);
+ }
+
+ @VisibleForTesting
+ OmniThemePreferenceController(Context context, OverlayManager overlayManager) {
+ super(context);
+ mOverlayService = overlayManager;
+ mPackageManager = context.getPackageManager();
+ mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_THEME;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (KEY_THEME.equals(preference.getKey())) {
+ mMetricsFeatureProvider.action(mContext, ACTION_THEME);
+ }
+ return false;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ ListPreference pref = (ListPreference) preference;
+ List<String> pkgs = new ArrayList<>(Arrays.asList(getAvailableThemes()));
+ List<CharSequence> labels = new ArrayList<>(pkgs.size());
+ for (String pkg : pkgs) {
+ CharSequence label = null;
+ try {
+ label = mPackageManager.getApplicationInfo(pkg, 0).loadLabel(mPackageManager);
+ } catch (NameNotFoundException e) {
+ label = pkg;
+ }
+ labels.add(label);
+ }
+ labels.add(mContext.getString(R.string.omni_theme_select_none));
+ pkgs.add(KEY_THEMES_DISABLED);
+
+ pref.setEntries(labels.toArray(new CharSequence[labels.size()]));
+ pref.setEntryValues(pkgs.toArray(new String[pkgs.size()]));
+ String theme = getCurrentTheme();
+ CharSequence themeLabel = null;
+
+ if (theme != null) {
+ int i = 0;
+ for (String pkg : pkgs) {
+ if (TextUtils.equals(pkg, theme)) {
+ themeLabel = labels.get(i);
+ break;
+ }
+ i++;
+ }
+ }
+
+ if (TextUtils.isEmpty(themeLabel)) {
+ themeLabel = mContext.getString(R.string.omni_theme_select_none);
+ theme = KEY_THEMES_DISABLED;
+ }
+
+ pref.setSummary(themeLabel);
+ pref.setValue(theme);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String current = getTheme();
+ if (Objects.equal(newValue, current)) {
+ return true;
+ }
+ try {
+ if (newValue.equals(KEY_THEMES_DISABLED)) {
+ disableTheme();
+ } else {
+ mOverlayService.setEnabledExclusive((String) newValue, true, UserHandle.myUserId());
+ }
+ } catch (RemoteException e) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isChangeableOverlay(String packageName) {
+ try {
+ PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0);
+ return pi != null && !pi.isStaticOverlay;
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ private String getTheme() {
+ try {
+ List<OverlayInfo> infos = mOverlayService.getOverlayInfosForTarget("android",
+ UserHandle.myUserId());
+ for (int i = 0, size = infos.size(); i < size; i++) {
+ if (infos.get(i).isEnabled() &&
+ isChangeableOverlay(infos.get(i).packageName)) {
+ return infos.get(i).packageName;
+ }
+ }
+ } catch (RemoteException e) {
+ }
+ return null;
+ }
+
+ private void disableTheme() {
+ try {
+ List<OverlayInfo> infos = mOverlayService.getOverlayInfosForTarget("android",
+ UserHandle.myUserId());
+ for (int i = 0, size = infos.size(); i < size; i++) {
+ if (infos.get(i).isEnabled() &&
+ infos.get(i).packageName.startsWith(OMNI_THEME_PREFIX) &&
+ isChangeableOverlay(infos.get(i).packageName)) {
+ mOverlayService.setEnabled(infos.get(i).packageName, false, UserHandle.myUserId());
+ }
+ }
+ } catch (RemoteException e) {
+ }
+ }
+
+ @Override
+ public boolean isAvailable() {
+ if (mOverlayService == null) return false;
+ String[] themes = getAvailableThemes();
+ return themes != null && themes.length >= 1;
+ }
+
+
+ @VisibleForTesting
+ String getCurrentTheme() {
+ return getTheme();
+ }
+
+ @VisibleForTesting
+ String[] getAvailableThemes() {
+ try {
+ List<OverlayInfo> infos = mOverlayService.getOverlayInfosForTarget("android",
+ UserHandle.myUserId());
+ List<String> pkgs = new ArrayList(infos.size());
+ for (int i = 0, size = infos.size(); i < size; i++) {
+ if (infos.get(i).packageName.startsWith(OMNI_THEME_PREFIX) &&
+ isChangeableOverlay(infos.get(i).packageName)) {
+ pkgs.add(infos.get(i).packageName);
+ }
+ }
+ return pkgs.toArray(new String[pkgs.size()]);
+ } catch (RemoteException e) {
+ }
+ return new String[0];
+ }
+
+ public static class OverlayManager {
+ private final IOverlayManager mService;
+
+ public OverlayManager() {
+ mService = IOverlayManager.Stub.asInterface(
+ ServiceManager.getService(Context.OVERLAY_SERVICE));
+ }
+
+ public void setEnabledExclusive(String pkg, boolean enabled, int userId)
+ throws RemoteException {
+ mService.setEnabledExclusive(pkg, enabled, userId);
+ }
+
+ public void setEnabled(String pkg, boolean enabled, int userId)
+ throws RemoteException {
+ mService.setEnabled(pkg, enabled, userId);
+ }
+
+ public List<OverlayInfo> getOverlayInfosForTarget(String target, int userId)
+ throws RemoteException {
+ return mService.getOverlayInfosForTarget(target, userId);
+ }
+ }
+}
diff --git a/src/org/omnirom/omnigears/interfacesettings/StyleSettings.java b/src/org/omnirom/omnigears/interfacesettings/StyleSettings.java
index d1ceb1a..4f0a670 100644
--- a/src/org/omnirom/omnigears/interfacesettings/StyleSettings.java
+++ b/src/org/omnirom/omnigears/interfacesettings/StyleSettings.java
@@ -35,12 +35,13 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.omni.PackageUtils;
-import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.R;
import com.android.settings.Utils;
+import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
+import com.android.settingslib.core.AbstractPreferenceController;
import org.omnirom.omnigears.preference.SystemSettingSwitchPreference;
import org.omnirom.omnigears.preference.SeekBarPreference;
@@ -51,7 +52,7 @@
import java.util.List;
import java.util.Map;
-public class StyleSettings extends SettingsPreferenceFragment implements
+public class StyleSettings extends DashboardFragment implements
Preference.OnPreferenceChangeListener, Indexable {
private static final String TAG = "StyleSettings";
private static final String CUSTOM_WALL_BROWSE = "custom_wall_browse";
@@ -84,9 +85,19 @@
}
@Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.style_settings;
+ }
+
+ @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- addPreferencesFromResource(R.xml.style_settings);
+ //addPreferencesFromResource(R.xml.style_settings);
mWallBrowse = findPreference(CUSTOM_WALL_BROWSE);
mWallBrowse.setEnabled(isBrowseWallsAvailable());
@@ -266,6 +277,13 @@
}
}
+ @Override
+ protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
+ final List<AbstractPreferenceController> controllers = new ArrayList<>();
+ controllers.add(new OmniThemePreferenceController(context));
+ return controllers;
+ }
+
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override