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

Commit 6a8c79bb authored by Alan Viverette's avatar Alan Viverette Committed by Android (Google) Code Review
Browse files

Merge "Improve keying for theme caches, rebase system theme on config change" into mnc-dev

parents 6fc03e65 e54d245b
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ public class AnimatorInflater {
            float pathErrorScale) throws NotFoundException {
        final ConfigurationBoundResourceCache<Animator> animatorCache = resources
                .getAnimatorCache();
        Animator animator = animatorCache.get(id, theme);
        Animator animator = animatorCache.getInstance(id, theme);
        if (animator != null) {
            if (DBG_ANIMATOR_INFLATER) {
                Log.d(TAG, "loaded animator from cache, " + resources.getResourceName(id));
@@ -157,7 +157,7 @@ public class AnimatorInflater {
        final ConfigurationBoundResourceCache<StateListAnimator> cache = resources
                .getStateListAnimatorCache();
        final Theme theme = context.getTheme();
        StateListAnimator animator = cache.get(id, theme);
        StateListAnimator animator = cache.getInstance(id, theme);
        if (animator != null) {
            return animator;
        }
+8 −2
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import android.content.res.AssetManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDebug;
import android.database.sqlite.SQLiteDebug.DbStats;
@@ -4186,9 +4187,14 @@ public final class ActivityThread {
            if (!mConfiguration.isOtherSeqNewer(config) && compat == null) {
                return;
            }
            configDiff = mConfiguration.diff(config);
            mConfiguration.updateFrom(config);

            configDiff = mConfiguration.updateFrom(config);
            config = applyCompatConfiguration(mCurDefaultDisplayDpi);

            final Theme systemTheme = getSystemContext().getTheme();
            if ((systemTheme.getChangingConfigurations() & configDiff) != 0) {
                systemTheme.rebase();
            }
        }

        ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
+1 −0
Original line number Diff line number Diff line
@@ -785,6 +785,7 @@ public final class AssetManager implements AutoCloseable {
    private native final void deleteTheme(long theme);
    /*package*/ native static final void applyThemeStyle(long theme, int styleRes, boolean force);
    /*package*/ native static final void copyTheme(long dest, long source);
    /*package*/ native static final void clearTheme(long theme);
    /*package*/ native static final int loadThemeAttributeValue(long theme, int ident,
                                                                TypedValue outValue,
                                                                boolean resolve);
+33 −113
Original line number Diff line number Diff line
@@ -13,126 +13,46 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.content.res;

import android.util.ArrayMap;
import android.util.LongSparseArray;
import java.lang.ref.WeakReference;
package android.content.res;

/**
 * A Cache class which can be used to cache resource objects that are easy to clone but more
 * expensive to inflate.
 * @hide
 *
 * @hide For internal use only.
 */
public class ConfigurationBoundResourceCache<T> {

    private final ArrayMap<String, LongSparseArray<WeakReference<ConstantState<T>>>> mCache =
            new ArrayMap<String, LongSparseArray<WeakReference<ConstantState<T>>>>();

    final Resources mResources;
public class ConfigurationBoundResourceCache<T> extends ThemedResourceCache<ConstantState<T>> {
    private final Resources mResources;

    /**
     * Creates a Resource cache for the given Resources instance.
     * Creates a cache for the given Resources instance.
     *
     * @param resources The Resource which can be used when creating new instances.
     * @param resources the resources to use when creating new instances
     */
    public ConfigurationBoundResourceCache(Resources resources) {
        mResources = resources;
    }

    /**
     * Adds a new item to the cache.
     *
     * @param key A custom key that uniquely identifies the resource.
     * @param theme The Theme instance where this resource was loaded.
     * @param constantState The constant state that can create new instances of the resource.
     * If the resource is cached, creates and returns a new instance of it.
     *
     * @param key a key that uniquely identifies the drawable resource
     * @param theme the theme where the resource will be used
     * @return a new instance of the resource, or {@code null} if not in
     *         the cache
     */
    public void put(long key, Resources.Theme theme, ConstantState<T> constantState) {
        if (constantState == null) {
            return;
        }
        final String themeKey = theme == null ? "" : theme.getKey();
        LongSparseArray<WeakReference<ConstantState<T>>> themedCache;
        synchronized (this) {
            themedCache = mCache.get(themeKey);
            if (themedCache == null) {
                themedCache = new LongSparseArray<WeakReference<ConstantState<T>>>(1);
                mCache.put(themeKey, themedCache);
            }
            themedCache.put(key, new WeakReference<ConstantState<T>>(constantState));
        }
    }

    /**
     * If the resource is cached, creates a new instance of it and returns.
     *
     * @param key The long key which can be used to uniquely identify the resource.
     * @param theme The The Theme instance where we want to load this resource.
     *
     * @return If this resources was loaded before, returns a new instance of it. Otherwise, returns
     *         null.
     */
    public T get(long key, Resources.Theme theme) {
        final String themeKey = theme != null ? theme.getKey() : "";
        final LongSparseArray<WeakReference<ConstantState<T>>> themedCache;
        final WeakReference<ConstantState<T>> wr;
        synchronized (this) {
            themedCache = mCache.get(themeKey);
            if (themedCache == null) {
                return null;
            }
            wr = themedCache.get(key);
        }
        if (wr == null) {
            return null;
        }
        final ConstantState entry = wr.get();
    public T getInstance(long key, Resources.Theme theme) {
        final ConstantState<T> entry = get(key, theme);
        if (entry != null) {
            return  (T) entry.newInstance(mResources, theme);
        } else {  // our entry has been purged
            synchronized (this) {
                // there is a potential race condition here where this entry may be put in
                // another thread. But we prefer it to minimize lock duration
                themedCache.delete(key);
            }
        }
        return null;
            return entry.newInstance(mResources, theme);
        }

    /**
     * Users of ConfigurationBoundResourceCache must call this method whenever a configuration
     * change happens. On this callback, the cache invalidates all resources that are not valid
     * anymore.
     *
     * @param configChanges The configuration changes
     */
    public void onConfigurationChange(final int configChanges) {
        synchronized (this) {
            final int size = mCache.size();
            for (int i = size - 1; i >= 0; i--) {
                final LongSparseArray<WeakReference<ConstantState<T>>>
                        themeCache = mCache.valueAt(i);
                onConfigurationChangeInt(themeCache, configChanges);
                if (themeCache.size() == 0) {
                    mCache.removeAt(i);
                }
            }
        }
        return null;
    }

    private void onConfigurationChangeInt(
            final LongSparseArray<WeakReference<ConstantState<T>>> themeCache,
            final int configChanges) {
        final int size = themeCache.size();
        for (int i = size - 1; i >= 0; i--) {
            final WeakReference<ConstantState<T>> wr = themeCache.valueAt(i);
            final ConstantState<T> constantState = wr.get();
            if (constantState == null || Configuration.needNewResources(
                    configChanges, constantState.getChangingConfigurations())) {
                themeCache.removeAt(i);
            }
    @Override
    public boolean shouldInvalidateEntry(ConstantState<T> entry, int configChanges) {
        return Configuration.needNewResources(configChanges, entry.getChangingConfigurations());
    }
}

}
+57 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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.content.res;

import android.graphics.drawable.Drawable;

/**
 * Class which can be used to cache Drawable resources against a theme.
 */
class DrawableCache extends ThemedResourceCache<Drawable.ConstantState> {
    private final Resources mResources;

    /**
     * Creates a cache for the given Resources instance.
     *
     * @param resources the resources to use when creating new instances
     */
    public DrawableCache(Resources resources) {
        mResources = resources;
    }

    /**
     * If the resource is cached, creates and returns a new instance of it.
     *
     * @param key a key that uniquely identifies the drawable resource
     * @param theme the theme where the resource will be used
     * @return a new instance of the resource, or {@code null} if not in
     *         the cache
     */
    public Drawable getInstance(long key, Resources.Theme theme) {
        final Drawable.ConstantState entry = get(key, theme);
        if (entry != null) {
            return entry.newDrawable(mResources, theme);
        }

        return null;
    }

    @Override
    public boolean shouldInvalidateEntry(Drawable.ConstantState entry, int configChanges) {
        return false;
    }
}
Loading