Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e30cb46 authored by Clark Scheff's avatar Clark Scheff Committed by Steve Kondik
Browse files

Themes: Enhanced theming capabilities [1/3]

This patch includes a new class, ThemeChangeRequest, which will be
used to facilitate theme changes.  This class includes a builder
that will be used to create a ThemeChangeRequest.

Change-Id: I60144f8a6505aefcc570feb15ccc50e77bcb1114
parent bc68fd68
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.ParceledListSlice;
import android.content.pm.ThemeUtils;
import android.content.res.IThemeService;
import android.content.res.ThemeChangeRequest;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -54,13 +55,14 @@ public class Tm extends BaseCommand {
        StringBuilder sb = new StringBuilder();
        sb.append("usage: tm [subcommand] [options]\n");
        sb.append("       tm list\n");
        sb.append("       tm apply <PACKAGE_NAME> [-c <COMPONENT> [-c <COMPONENT>] ...]\n");
        sb.append("       tm apply <PACKAGE_NAME> [-r] [-c <COMPONENT> [-c <COMPONENT>] ...]\n");
        sb.append("       tm rebuild\n");
        sb.append("       tm process <PACKAGE_NAME>\n");
        sb.append("\n");
        sb.append("tm list: return a list of theme packages.\n");
        sb.append("\n");
        sb.append("tm apply: applies the components for the theme specified by PACKAGE_NAME.\n");
        sb.append("       -r: remove per app themes\n");
        sb.append("       [-c <COMPONENT> [-c <COMPONENT>] ...]\n");
        sb.append("       if no components are specified all components will be applied.\n");
        sb.append("       Valid components are:\n");
@@ -143,22 +145,27 @@ public class Tm extends BaseCommand {
            }
        }

        Map<String, String> componentMap = new HashMap<String, String>();
        boolean removePerAppThemes = false;

        ThemeChangeRequest.Builder builder = new ThemeChangeRequest.Builder();
        String opt;
        while ((opt=nextOption()) != null) {
            if (opt.equals("-c")) {
                componentMap.put(nextArgRequired(), pkgName);
                builder.setComponent(nextArgRequired(), pkgName);
            } else if (opt.equals("-r")) {
                removePerAppThemes = true;
            }
        }

        // No components specified so let's just try and apply EVERYTHING!
        Map<String, String> componentMap = builder.build().getThemeComponentsMap();
        if (componentMap.size() == 0) {
            List<String> components = ThemeUtils.getAllComponents();
            for (String component : components) {
                componentMap.put(component, pkgName);
                builder.setComponent(component, pkgName);
            }
        }
        mTs.requestThemeChange(componentMap);
        mTs.requestThemeChange(builder.build(), removePerAppThemes);
    }

    private void runRebuildResourceCache() throws Exception {
+15 −0
Original line number Diff line number Diff line
@@ -107,6 +107,9 @@ public class ThemeUtils {

    public static final int SYSTEM_TARGET_API = 0;

    // Package name for any app which does not have a specific theme applied
    private static final String DEFAULT_PKG = "default";

    private static final String SETTINGS_DB =
            "/data/data/com.android.providers.settings/databases/settings.db";
    private static final String SETTINGS_SECURE_TABLE = "secure";
@@ -715,4 +718,16 @@ public class ThemeUtils {

        return config;
    }

    /**
     * Convenience method to determine if a theme component is a per app theme and not a standard
     * component.
     * @param component
     * @return
     */
    public static boolean isPerAppThemeComponent(String component) {
        return !(DEFAULT_PKG.equals(component)
                || ThemeConfig.SYSTEMUI_STATUS_BAR_PKG.equals(component)
                || ThemeConfig.SYSTEMUI_NAVBAR_PKG.equals(component));
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package android.content.res;

import android.content.res.IThemeChangeListener;
import android.content.res.IThemeProcessingListener;
import android.content.res.ThemeChangeRequest;
import android.graphics.Bitmap;

import java.util.Map;
@@ -26,7 +27,7 @@ interface IThemeService {
    void requestThemeChangeUpdates(in IThemeChangeListener listener);
    void removeUpdates(in IThemeChangeListener listener);

    void requestThemeChange(in Map componentMap);
    void requestThemeChange(in ThemeChangeRequest request, boolean removePerAppThemes);
    void applyDefaultTheme();
    boolean isThemeApplying();
    int getProgress();
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The CyanogenMod 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.content.res;

/** @hide */
parcelable ThemeChangeRequest;
+225 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The CyanogenMod 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.content.res;

import android.os.Parcel;
import android.os.Parcelable;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;


import static android.provider.ThemesContract.ThemesColumns.*;

/** @hide */
public final class ThemeChangeRequest implements Parcelable {
    private final Map<String, String> mThemeComponents = new HashMap<String, String>();
    private final Map<String, String> mPerAppOverlays = new HashMap<String, String>();

    public String getOverlayThemePackageName() {
        return getThemePackageNameForComponent(MODIFIES_OVERLAYS);
    }

    public String getStatusBarThemePackageName() {
        return getThemePackageNameForComponent(MODIFIES_STATUS_BAR);
    }

    public String getNavBarThemePackageName() {
        return getThemePackageNameForComponent(MODIFIES_NAVIGATION_BAR);
    }

    public String getFontThemePackageName() {
        return getThemePackageNameForComponent(MODIFIES_FONTS);
    }

    public String getIconsThemePackageName() {
        return getThemePackageNameForComponent(MODIFIES_ICONS);
    }

    public String getBootanimationThemePackageName() {
        return getThemePackageNameForComponent(MODIFIES_BOOT_ANIM);
    }

    public String getWallpaperThemePackageName() {
        return getThemePackageNameForComponent(MODIFIES_LAUNCHER);
    }

    public String getLockWallpaperThemePackageName() {
        return getThemePackageNameForComponent(MODIFIES_LOCKSCREEN);
    }

    public String getAlarmThemePackageName() {
        return getThemePackageNameForComponent(MODIFIES_ALARMS);
    }

    public String getNotificationThemePackageName() {
        return getThemePackageNameForComponent(MODIFIES_NOTIFICATIONS);
    }

    public String getRingtoneThemePackageName() {
        return getThemePackageNameForComponent(MODIFIES_RINGTONES);
    }

    public final Map<String, String> getThemeComponentsMap() {
        return Collections.unmodifiableMap(mThemeComponents);
    }

    /**
     * Get the mapping for per app themes
     * @return A mapping of apps and the theme to apply for each one. or null if none set.
     */
    public final Map<String, String> getPerAppOverlays() {
        return Collections.unmodifiableMap(mPerAppOverlays);
    }

    public int getNumChangesRequested() {
        return mThemeComponents.size() + mPerAppOverlays.size();
    }

    private String getThemePackageNameForComponent(String componentName) {
        return mThemeComponents.get(componentName);
    }

    private ThemeChangeRequest(Map<String, String> components, Map<String, String> perAppThemes) {
        if (components != null) {
            mThemeComponents.putAll(components);
        }
        if (perAppThemes != null) {
            mPerAppOverlays.putAll(perAppThemes);
        }
    }

    private ThemeChangeRequest(Parcel source) {
        int numComponents = source.readInt();
        for (int i = 0; i < numComponents; i++) {
            mThemeComponents.put(source.readString(), source.readString());
        }

        numComponents = source.readInt();
        for (int i = 0 ; i < numComponents; i++) {
            mPerAppOverlays.put(source.readString(), source.readString());
        }
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mThemeComponents.size());
        for (String component : mThemeComponents.keySet()) {
            dest.writeString(component);
            dest.writeString(mThemeComponents.get(component));
        }
        dest.writeInt((mPerAppOverlays.size()));
        for (String appPkgName : mPerAppOverlays.keySet()) {
            dest.writeString(appPkgName);
            dest.writeString(mPerAppOverlays.get(appPkgName));
        }
    }

    public static final Parcelable.Creator<ThemeChangeRequest> CREATOR =
            new Parcelable.Creator<ThemeChangeRequest>() {
                @Override
                public ThemeChangeRequest createFromParcel(Parcel source) {
                    return new ThemeChangeRequest(source);
                }

                @Override
                public ThemeChangeRequest[] newArray(int size) {
                    return new ThemeChangeRequest[size];
                }
            };

    public static class Builder {
        Map<String, String> mThemeComponents = new HashMap<String, String>();
        Map<String, String> mPerAppOverlays = new HashMap<String, String>();

        public Builder() {}

        public Builder setOverlay(String pkgName) {
            return setComponent(MODIFIES_OVERLAYS, pkgName);
        }

        public Builder setStatusBar(String pkgName) {
            return setComponent(MODIFIES_STATUS_BAR, pkgName);
        }

        public Builder setNavBar(String pkgName) {
            return setComponent(MODIFIES_NAVIGATION_BAR, pkgName);
        }

        public Builder setFont(String pkgName) {
            return setComponent(MODIFIES_FONTS, pkgName);
        }

        public Builder setIcons(String pkgName) {
            return setComponent(MODIFIES_ICONS, pkgName);
        }

        public Builder setBootanimation(String pkgName) {
            return setComponent(MODIFIES_BOOT_ANIM, pkgName);
        }

        public Builder setWallpaper(String pkgName) {
            return setComponent(MODIFIES_LAUNCHER, pkgName);
        }

        public Builder setLockWallpaper(String pkgName) {
            return setComponent(MODIFIES_LOCKSCREEN, pkgName);
        }

        public Builder setAlarm(String pkgName) {
            return setComponent(MODIFIES_ALARMS, pkgName);
        }

        public Builder setNotification(String pkgName) {
            return setComponent(MODIFIES_NOTIFICATIONS, pkgName);
        }

        public Builder setRingtone(String pkgName) {
            return setComponent(MODIFIES_RINGTONES, pkgName);
        }

        public Builder setComponent(String component, String pkgName) {
            if (pkgName != null) {
                mThemeComponents.put(component, pkgName);
            } else {
                mThemeComponents.remove(component);
            }
            return this;
        }

        public Builder setAppOverlay(String appPkgName, String themePkgName) {
            if (appPkgName != null) {
                if (themePkgName != null) {
                    mPerAppOverlays.put(appPkgName, themePkgName);
                } else {
                    mPerAppOverlays.remove(appPkgName);
                }
            }

            return this;
        }

        public ThemeChangeRequest build() {
            return new ThemeChangeRequest(mThemeComponents, mPerAppOverlays);
        }
    }
}
Loading