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

Commit 74f50acf authored by Diego Perez's avatar Diego Perez Committed by Android (Google) Code Review
Browse files

Merge changes Ia7a8a27f,I0646aab6,Ia324f18d,I38c6c6df,Ic9214929, ...

* changes:
  Add missing attributes to old themes
  Fix plurals support in layoutlib
  Do not log errors while loading string arrays
  Hack to deal with android:pointerIcon in layoutlib
  Force animateFirstValue to false
  Avoid passing antialias when measuring scaled text
  Catch all exceptions in NativeAllocationRegistry free
parents e92b15ca 0c864fde
Loading
Loading
Loading
Loading
+44 −3
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import com.android.ide.common.rendering.api.ArrayResourceValue;
import com.android.ide.common.rendering.api.DensityBasedResourceValue;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.LayoutlibCallback;
import com.android.ide.common.rendering.api.PluralsResourceValue;
import com.android.ide.common.rendering.api.RenderResources;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.layoutlib.bridge.Bridge;
@@ -43,6 +44,7 @@ import android.annotation.Nullable;
import android.content.res.Resources.NotFoundException;
import android.content.res.Resources.Theme;
import android.graphics.drawable.Drawable;
import android.icu.text.PluralRules;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.LruCache;
@@ -405,9 +407,6 @@ public class Resources_Delegate {
            rv = resources.mContext.getRenderResources().resolveResValue(rv);
            if (rv != null) {
                return rv.getValue();
            } else {
                Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE,
                        "Unable to resolve resource " + ref, null);
            }
        }
        // Not a reference.
@@ -737,6 +736,48 @@ public class Resources_Delegate {
        return null;
    }

    @LayoutlibDelegate
    static String getQuantityString(Resources resources, int id, int quantity) throws
            NotFoundException {
        Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);

        if (value != null) {
            if (value.getSecond() instanceof PluralsResourceValue) {
                PluralsResourceValue pluralsResourceValue = (PluralsResourceValue) value.getSecond();
                PluralRules pluralRules = PluralRules.forLocale(resources.getConfiguration().getLocales()
                        .get(0));
                String strValue = pluralsResourceValue.getValue(pluralRules.select(quantity));
                if (strValue == null) {
                    strValue = pluralsResourceValue.getValue(PluralRules.KEYWORD_OTHER);
                }

                return strValue;
            }
            else {
                return value.getSecond().getValue();
            }
        }

        // id was not found or not resolved. Throw a NotFoundException.
        throwException(resources, id);

        // this is not used since the method above always throws
        return null;
    }

    @LayoutlibDelegate
    static String getQuantityString(Resources resources, int id, int quantity, Object... formatArgs)
            throws NotFoundException {
        String raw = getQuantityString(resources, id, quantity);
        return String.format(resources.getConfiguration().getLocales().get(0), raw, formatArgs);
    }

    @LayoutlibDelegate
    static CharSequence getQuantityText(Resources resources, int id, int quantity) throws
            NotFoundException {
        return getQuantityString(resources, id, quantity);
    }

    @LayoutlibDelegate
    static void getValue(Resources resources, int id, TypedValue outValue, boolean resolveRefs)
            throws NotFoundException {
+10 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.LinkedList;
@@ -41,6 +42,7 @@ import java.util.List;
 */
@SuppressWarnings("deprecation")
public class BidiRenderer {
    private static String JAVA_VENDOR = System.getProperty("java.vendor");

    private static class ScriptRun {
        int start;
@@ -221,9 +223,16 @@ public class BidiRenderer {
            frc = mGraphics.getFontRenderContext();
        } else {
            frc = Toolkit.getDefaultToolkit().getFontMetrics(font).getFontRenderContext();

            // Metrics obtained this way don't have anti-aliasing set. So,
            // we create a new FontRenderContext with anti-aliasing set.
            frc = new FontRenderContext(font.getTransform(), mPaint.isAntiAliased(), frc.usesFractionalMetrics());
            AffineTransform transform = font.getTransform();
            if (mPaint.isAntiAliased() &&
                    // Workaround for http://b.android.com/211659
                    (transform.getScaleX() <= 9.9 ||
                    !"JetBrains s.r.o".equals(JAVA_VENDOR))) {
                frc = new FontRenderContext(transform, true, frc.usesFractionalMetrics());
            }
        }
        GlyphVector gv = font.layoutGlyphVector(frc, mText, start, limit, flag);
        int ng = gv.getNumGlyphs();
+33 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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 android.view;

import com.android.tools.layoutlib.annotations.LayoutlibDelegate;

import android.content.Context;
import android.content.res.Resources;

public class PointerIcon_Delegate {

    @LayoutlibDelegate
    /*package*/ static void loadResource(PointerIcon icon, Context context, Resources resources,
            int resourceId) {
        // HACK: This bypasses the problem of having an enum resolved as a resourceId.
        // PointerIcon would not be displayed by layoutlib anyway, so we always return the null
        // icon.
    }
}
+49 −23
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;

/**
@@ -113,6 +113,28 @@ import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_AP
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, "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<>();
    /**
@@ -312,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();
    }

@@ -406,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) {
@@ -711,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) {
@@ -909,6 +928,16 @@ public final class BridgeContext extends Context {
                // if there's no direct value for this attribute in the XML, we look for default
                // values in the widget defStyle, and then in the theme.
                if (value == null) {
                    if (frameworkAttr) {
                        // For some framework values, layoutlib patches the actual value in the
                        // theme when it helps to improve the final preview. In most cases
                        // we just disable animations.
                        ResourceValue patchedValue = FRAMEWORK_PATCHED_VALUES.get(attrName);
                        if (patchedValue != null) {
                            defaultValue = patchedValue;
                        }
                    }

                    // if we found a value, we make sure this doesn't reference another value.
                    // So we resolve it.
                    if (defaultValue != null) {
@@ -916,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;
                        }
                    }

@@ -1944,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<>();
        }

@@ -1965,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);
        }

+9 −3
Original line number Diff line number Diff line
@@ -52,10 +52,16 @@ public class NativeAllocationRegistry_Delegate {

    @LayoutlibDelegate
    /*package*/ static void applyFreeFunction(long freeFunction, long nativePtr) {
        // This method MIGHT run in the context of the finalizer thread. If the delegate method
        // crashes, it could bring down the VM. That's why we catch all the exceptions and ignore
        // them.
        try {
            NativeAllocationRegistry_Delegate delegate = sManager.getDelegate(freeFunction);
            if (delegate != null) {
                delegate.mFinalizer.free(nativePtr);
            }
        } catch (Throwable ignore) {
        }
    }

    public interface FreeFunction {
Loading