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

Commit 0c864fde authored by Diego Perez's avatar Diego Perez
Browse files

Add missing attributes to old themes

Because we always use the latest framework code, some resources might
fail to resolve when using old themes (they haven't been backported).
Since this is an artifact caused by us using always the latest code, we
check for some of those values and replace them here.

Bug: http://b.android.com/225105
Test: Included new testActivityOnOldTheme
Change-Id: Ia7a8a27fb81fe0b4a1e0c9610a2033a87720864d
parent 37f9ddb1
Loading
Loading
Loading
Loading
+33 −26
Original line number Original line Diff line number Diff line
@@ -66,7 +66,6 @@ import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.net.Uri;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder;
@@ -104,6 +103,7 @@ import java.util.IdentityHashMap;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Map;


import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_APPLICATION_PACKAGE;
import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_APPLICATION_PACKAGE;


/**
/**
@@ -114,13 +114,26 @@ public final class BridgeContext extends Context {
    private static final String PREFIX_THEME_APPCOMPAT = "Theme.AppCompat";
    private static final String PREFIX_THEME_APPCOMPAT = "Theme.AppCompat";


    private static final Map<String, ResourceValue> FRAMEWORK_PATCHED_VALUES = new HashMap<>(2);
    private static final Map<String, ResourceValue> FRAMEWORK_PATCHED_VALUES = new HashMap<>(2);
    private static final Map<String, ResourceValue> FRAMEWORK_REPLACE_VALUES = new HashMap<>(3);


    static {
    static {
        FRAMEWORK_PATCHED_VALUES.put("animateFirstView", new ResourceValue(
        FRAMEWORK_PATCHED_VALUES.put("animateFirstView", new ResourceValue(
                ResourceType.BOOL, "animateFirstView", "false", false));
                ResourceType.BOOL, "animateFirstView", "false", false));
        FRAMEWORK_PATCHED_VALUES.put("animateLayoutChanges", new ResourceValue(
        FRAMEWORK_PATCHED_VALUES.put("animateLayoutChanges",
                ResourceType.BOOL, "animateFirstView", "false", false));
                new ResourceValue(ResourceType.BOOL, "animateLayoutChanges", "false", false));
    };


        FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionItemLayout",
                new ResourceValue(ResourceType.LAYOUT, "textEditSuggestionItemLayout",
                        "text_edit_suggestion_item", true));
        FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionContainerLayout",
                new ResourceValue(ResourceType.LAYOUT, "textEditSuggestionContainerLayout",
                        "text_edit_suggestion_container", true));
        FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionHighlightStyle",
                new ResourceValue(ResourceType.STYLE, "textEditSuggestionHighlightStyle",
                        "TextAppearance.Holo.SuggestionHighlight", true));

    }


    /** The map adds cookies to each view so that IDE can link xml tags to views. */
    /** The map adds cookies to each view so that IDE can link xml tags to views. */
    private final HashMap<View, Object> mViewKeyMap = new HashMap<>();
    private final HashMap<View, Object> mViewKeyMap = new HashMap<>();
@@ -321,7 +334,7 @@ public final class BridgeContext extends Context {
     * Returns the current parser at the top the of the stack.
     * Returns the current parser at the top the of the stack.
     * @return a parser or null.
     * @return a parser or null.
     */
     */
    public BridgeXmlBlockParser getCurrentParser() {
    private BridgeXmlBlockParser getCurrentParser() {
        return mParserStack.peek();
        return mParserStack.peek();
    }
    }


@@ -415,7 +428,8 @@ public final class BridgeContext extends Context {
    }
    }


    public Pair<View, Boolean> inflateView(ResourceReference resource, ViewGroup parent,
    public Pair<View, Boolean> inflateView(ResourceReference resource, ViewGroup parent,
            boolean attachToRoot, boolean skipCallbackParser) {
            @SuppressWarnings("SameParameterValue") boolean attachToRoot,
            boolean skipCallbackParser) {
        boolean isPlatformLayout = resource.isFramework();
        boolean isPlatformLayout = resource.isFramework();


        if (!isPlatformLayout && !skipCallbackParser) {
        if (!isPlatformLayout && !skipCallbackParser) {
@@ -720,11 +734,7 @@ public final class BridgeContext extends Context {


            Object key = parser.getViewCookie();
            Object key = parser.getViewCookie();
            if (key != null) {
            if (key != null) {
                defaultPropMap = mDefaultPropMaps.get(key);
                defaultPropMap = mDefaultPropMaps.computeIfAbsent(key, k -> new PropertiesMap());
                if (defaultPropMap == null) {
                    defaultPropMap = new PropertiesMap();
                    mDefaultPropMaps.put(key, defaultPropMap);
                }
            }
            }


        } else if (set instanceof BridgeLayoutParamsMapAttributes) {
        } else if (set instanceof BridgeLayoutParamsMapAttributes) {
@@ -935,16 +945,21 @@ public final class BridgeContext extends Context {
                        // exist, we should log a warning and omit it.
                        // exist, we should log a warning and omit it.
                        String val = defaultValue.getValue();
                        String val = defaultValue.getValue();
                        if (val != null && val.startsWith(SdkConstants.PREFIX_THEME_REF)) {
                        if (val != null && val.startsWith(SdkConstants.PREFIX_THEME_REF)) {
                            if (!attrName.equals(RTL_ATTRS.get(val)) ||
                            // Because we always use the latest framework code, some resources might
                                    getApplicationInfo().targetSdkVersion <
                            // fail to resolve when using old themes (they haven't been backported).
                                            VERSION_CODES.JELLY_BEAN_MR1) {
                            // Since this is an artifact caused by us using always the latest
                            // code, we check for some of those values and replace them here.
                            defaultValue = FRAMEWORK_REPLACE_VALUES.get(attrName);

                            if (defaultValue == null &&
                                    (getApplicationInfo().targetSdkVersion < JELLY_BEAN_MR1 ||
                                    !attrName.equals(RTL_ATTRS.get(val)))) {
                                // Only log a warning if the referenced value isn't one of the RTL
                                // Only log a warning if the referenced value isn't one of the RTL
                                // attributes, or the app targets old API.
                                // attributes, or the app targets old API.
                                Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR,
                                Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR,
                                        String.format("Failed to find '%s' in current theme.", val),
                                        String.format("Failed to find '%s' in current theme.", val),
                                        val);
                                        val);
                            }
                            }
                            defaultValue = null;
                        }
                        }
                    }
                    }


@@ -1963,7 +1978,7 @@ public final class BridgeContext extends Context {
                Map<List<StyleResourceValue>,
                Map<List<StyleResourceValue>,
                        Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>> mCache;
                        Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>> mCache;


        public TypedArrayCache() {
        private TypedArrayCache() {
            mCache = new IdentityHashMap<>();
            mCache = new IdentityHashMap<>();
        }
        }


@@ -1984,17 +1999,9 @@ public final class BridgeContext extends Context {
        public void put(int[] attrs, List<StyleResourceValue> themes, int resId,
        public void put(int[] attrs, List<StyleResourceValue> themes, int resId,
                Pair<BridgeTypedArray, PropertiesMap> value) {
                Pair<BridgeTypedArray, PropertiesMap> value) {
            Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>
            Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>
                    cacheFromThemes = mCache.get(attrs);
                    cacheFromThemes = mCache.computeIfAbsent(attrs, k -> new HashMap<>());
            if (cacheFromThemes == null) {
                cacheFromThemes = new HashMap<>();
                mCache.put(attrs, cacheFromThemes);
            }
            Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId =
            Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId =
                    cacheFromThemes.get(themes);
                    cacheFromThemes.computeIfAbsent(themes, k -> new HashMap<>());
            if (cacheFromResId == null) {
                cacheFromResId = new HashMap<>();
                cacheFromThemes.put(themes, cacheFromResId);
            }
            cacheFromResId.put(resId, value);
            cacheFromResId.put(resId, value);
        }
        }


+14 −0
Original line number Original line Diff line number Diff line
@@ -333,6 +333,20 @@ public class Main {
        renderAndVerify("activity.xml", "activity.png");
        renderAndVerify("activity.xml", "activity.png");
    }
    }


    @Test
    public void testActivityOnOldTheme() throws ClassNotFoundException {
        LayoutLibTestCallback layoutLibCallback =
                new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
        layoutLibCallback.initResources();

        LayoutPullParser parser = createLayoutPullParser("simple_activity.xml");
        SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
                layoutLibCallback, "Theme.NoTitleBar", false,
                RenderingMode.NORMAL, 22);

        renderAndVerify(params, "simple_activity-old-theme.png");
    }

    @Test
    @Test
    public void testTranslucentBars() throws ClassNotFoundException {
    public void testTranslucentBars() throws ClassNotFoundException {
        LayoutLibTestCallback layoutLibCallback =
        LayoutLibTestCallback layoutLibCallback =