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 Diff line number Diff line
@@ -66,7 +66,6 @@ import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -104,6 +103,7 @@ import java.util.IdentityHashMap;
import java.util.List;
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;

/**
@@ -114,13 +114,26 @@ public final class BridgeContext extends Context {
    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_REPLACE_VALUES = new HashMap<>(3);

    static {
        FRAMEWORK_PATCHED_VALUES.put("animateFirstView", new ResourceValue(
                ResourceType.BOOL, "animateFirstView", "false", false));
        FRAMEWORK_PATCHED_VALUES.put("animateLayoutChanges", new ResourceValue(
                ResourceType.BOOL, "animateFirstView", "false", false));
    };
        FRAMEWORK_PATCHED_VALUES.put("animateLayoutChanges",
                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. */
    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.
     * @return a parser or null.
     */
    public BridgeXmlBlockParser getCurrentParser() {
    private BridgeXmlBlockParser getCurrentParser() {
        return mParserStack.peek();
    }

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

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

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

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

        } else if (set instanceof BridgeLayoutParamsMapAttributes) {
@@ -935,16 +945,21 @@ public final class BridgeContext extends Context {
                        // exist, we should log a warning and omit it.
                        String val = defaultValue.getValue();
                        if (val != null && val.startsWith(SdkConstants.PREFIX_THEME_REF)) {
                            if (!attrName.equals(RTL_ATTRS.get(val)) ||
                                    getApplicationInfo().targetSdkVersion <
                                            VERSION_CODES.JELLY_BEAN_MR1) {
                            // 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.
                            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
                                // attributes, or the app targets old API.
                                Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR,
                                        String.format("Failed to find '%s' in current theme.", val),
                                        val);
                            }
                            defaultValue = null;
                        }
                    }

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

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

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

+14 −0
Original line number Diff line number Diff line
@@ -333,6 +333,20 @@ public class Main {
        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
    public void testTranslucentBars() throws ClassNotFoundException {
        LayoutLibTestCallback layoutLibCallback =