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

Commit fce264d5 authored by Josh Guilfoyle's avatar Josh Guilfoyle Committed by Josh Guilfoyle
Browse files

Introduced an asset redirection system to the theme engine.

Previously, the theme engine required careful redirection of only the
highest-level "theme" style element, relying then on the theme attribute
lookups to satisfy the demands of all themeable apps.  This approach
created significant challenges which required, in some cases, heavy
modification for existing applications to support the engine.  Custom
widgets and themed components required special theme support in order to
be reachable by the style engine alone.  Similarly, a number of clumsy
hacks were required around the framework to support certain components
such as menus and tab widgets.

The asset redirection system allows the theme to specify a redirection
table which is consulted for nearly all final resource resolutions.
This essentially means that once the theme is applied, any original
resource being redirected would no longer be accessible by the
AssetManager, instead being redirected to the matching resource in the
theme itself.

In order for this to function efficiently it is necessary to create
cache files mapping resource integers from one package to another, even
if those integers will change across releases.  For this, one-time name
to integer conversions occur, with the results written in a data
format suitable for efficient reads for each AssetManager created.
Currently this format must be parsed and cannot be directly mmaped
though this will be addressed in future commits.

Change-Id: Ie36e74314c600a72e03e568675a38801b7acd1ee
parent 238a60da
Loading
Loading
Loading
Loading
+19 −9
Original line number Diff line number Diff line
@@ -226,6 +226,8 @@ public final class ActivityThread {
        if (assets.addAssetPath(resDir) == 0) {
            return null;
        }

        /* Attach theme information to the resulting AssetManager when appropriate. */
        Configuration config = getConfiguration();
        if (isThemable && config != null) {
            if (config.customTheme == null) {
@@ -233,14 +235,8 @@ public final class ActivityThread {
            }

            if (!TextUtils.isEmpty(config.customTheme.getThemePackageName())) {
                PackageInfo pi = getPackageInfo(config.customTheme.getThemePackageName(), 0);
                if (pi != null) {
                    String themeResDir = pi.getResDir();
                    if (assets.addAssetPath(themeResDir) != 0) {
                        assets.setThemePackageName(config.customTheme.getThemePackageName());
                    } else {
                        Log.e(TAG, "Unable to add theme resdir=" + themeResDir);
                    }
                if (!attachThemeAssets(assets, resDir, config.customTheme)) {
                    Log.e(TAG, "Failed to attach theme " + config.customTheme + " to resource '" + resDir + "'");
                }
            }
        }
@@ -270,6 +266,20 @@ public final class ActivityThread {
        }
    }

    private boolean attachThemeAssets(AssetManager assets, String resDir, CustomTheme theme) {
        PackageInfo pi = getPackageInfo(theme.getThemePackageName(), 0);
        if (pi != null) {
            String themeResDir = pi.getResDir();
            if (assets.addAssetPath(themeResDir) != 0) {
                assets.setThemePackageName(theme.getThemePackageName());
                return true;
            } else {
                Log.e(TAG, "Unable to add theme resdir=" + themeResDir);
            }
        }
        return false;
    }

    /**
     * Creates the top level resources for the given package.
     *
+2 −40
Original line number Diff line number Diff line
@@ -291,53 +291,15 @@ class ContextImpl extends Context {
        mThemeResource = resid;
    }

    private int determineDefaultThemeResource() {
        if (getResources() != Resources.getSystem() && mPackageInfo.mApplicationInfo.isThemeable) {
            try {
                Configuration config = ActivityManagerNative.getDefault().getConfiguration();
                if (config.customTheme != null) {
                    int themeId = CustomTheme.getStyleId(this,
                                config.customTheme.getThemePackageName(),
                                config.customTheme.getThemeId());
                    if (themeId == -1) {
                        CustomTheme defaultTheme = CustomTheme.getDefault();
                        if (config.customTheme.equals(defaultTheme)) {
                            return com.android.internal.R.style.Theme;
                        } else {
                            themeId = CustomTheme.getStyleId(this,
                                    defaultTheme.getThemePackageName(),
                                    defaultTheme.getThemeId());
                            if (themeId == -1) {
                                return com.android.internal.R.style.Theme;
                            } else {
                                return themeId;
                            }
                        }
                    } else {
                        return themeId;
                    }
                }
            } catch (RemoteException e) {
                Log.e(TAG, "Unable to access configuration, reverting to original system default theme", e);
            }
        }

        /* Fallback... */
        return com.android.internal.R.style.Theme;
    }
    
    @Override
    public Resources.Theme getTheme() {
        if (mTheme == null) {
            int themeId;
            if (mThemeResource == 0) {
                themeId = determineDefaultThemeResource();
            } else {
                themeId = mThemeResource;
                mThemeResource = com.android.internal.R.style.Theme;
            }

            mTheme = mResources.newTheme();
            mTheme.applyStyle(themeId, true);
            mTheme.applyStyle(mThemeResource, true);
        }
        return mTheme;
    }
+0 −63
Original line number Diff line number Diff line
@@ -307,48 +307,6 @@ public class ActivityInfo extends ComponentInfo
     */
    public int softInputMode;

    /**
     * isThemeable flag is not explicitly set - use isThemeable value from ApllicationInfo.
     */
    private static final int ISTHEMEABLE_INHERITED = 0;

    /**
     * isThemeable flag is explicitly set to false.
     */
    private static final int ISTHEMEABLE_FALSE = 1;

    /**
     * isThemeable flag is explicitly set to true.
     */
    private static final int ISTHEMEABLE_TRUE = 2;

    /**
     * Is given activity theme agnostic, i.e. behaves properly when default theme is changed.
     * 
     * @deprecated Not fully supported; do not use.
     * @hide
     */
    private int isThemeable = ISTHEMEABLE_INHERITED;

    /**
     * @deprecated Not fully supported; do not use.
     * @hide
     */
    public boolean getIsThemeable() {
        if (isThemeable == ISTHEMEABLE_INHERITED) {
            return applicationInfo != null && applicationInfo.isThemeable;
        }
        return isThemeable != ISTHEMEABLE_FALSE;
    }

    /**
     * @deprecated Not fully supported; do not use.
     * @hide
     */
    public void setIsThemeable(boolean value) {
        isThemeable = value? ISTHEMEABLE_TRUE : ISTHEMEABLE_FALSE;
    }

    public ActivityInfo() {
    }

@@ -363,7 +321,6 @@ public class ActivityInfo extends ComponentInfo
        screenOrientation = orig.screenOrientation;
        configChanges = orig.configChanges;
        softInputMode = orig.softInputMode;
        isThemeable = orig.isThemeable;
    }
    
    /**
@@ -377,23 +334,6 @@ public class ActivityInfo extends ComponentInfo
        return theme != 0 ? theme : applicationInfo.theme;
    }

    /**
     * @deprecated Not fully supported; do not use.
     * @hide
     */
    public final boolean isThemeable() {
        switch (isThemeable) {
            case ISTHEMEABLE_TRUE:
                return true;

            case ISTHEMEABLE_INHERITED:
                return applicationInfo.isThemeable;

            default:
                return false;
        }
    }

    public void dump(Printer pw, String prefix) {
        super.dumpFront(pw, prefix);
        if (permission != null) {
@@ -412,7 +352,6 @@ public class ActivityInfo extends ComponentInfo
                    + " configChanges=0x" + Integer.toHexString(configChanges)
                    + " softInputMode=0x" + Integer.toHexString(softInputMode));
        }
        pw.println(prefix + "isThemeable=" + isThemeable);
        super.dumpBack(pw, prefix);
    }
    
@@ -437,7 +376,6 @@ public class ActivityInfo extends ComponentInfo
        dest.writeInt(screenOrientation);
        dest.writeInt(configChanges);
        dest.writeInt(softInputMode);
        dest.writeInt(isThemeable);
    }

    public static final Parcelable.Creator<ActivityInfo> CREATOR
@@ -461,6 +399,5 @@ public class ActivityInfo extends ComponentInfo
        screenOrientation = source.readInt();
        configChanges = source.readInt();
        softInputMode = source.readInt();
        isThemeable = source.readInt();
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -353,7 +353,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
     * Is given application theme agnostic, i.e. behaves properly when default theme is changed.
     *  {@hide}
     */
    public boolean isThemeable = false;
    public boolean isThemeable = true;

    private static final String PLUTO_SCHEMA = "http://www.w3.org/2001/pluto.html";

+1 −3
Original line number Diff line number Diff line
@@ -1472,9 +1472,7 @@ public class PackageParser {
                continue;
            }
            String attrName = attrs.getAttributeName(i);
            if (attrName.equalsIgnoreCase(ApplicationInfo.PLUTO_ISTHEMEABLE_ATTRIBUTE_NAME)) {
                ai.setIsThemeable(attrs.getAttributeBooleanValue(i, false));
            } else if (attrName.equalsIgnoreCase(ApplicationInfo.PLUTO_HANDLE_THEME_CONFIG_CHANGES_ATTRIBUTE_NAME)) {
            if (attrName.equalsIgnoreCase(ApplicationInfo.PLUTO_HANDLE_THEME_CONFIG_CHANGES_ATTRIBUTE_NAME)) {
                ai.configChanges |= ActivityInfo.CONFIG_THEME_RESOURCE;
            }
        }
Loading