/* ** ** Copyright 2007, 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 com.android.server; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.util.SparseArray; import java.util.HashMap; import java.util.WeakHashMap; /** * TODO: This should be better integrated into the system so it doesn't need * special calls from the activity manager to clear it. */ public final class AttributeCache { private static AttributeCache sInstance = null; private final Context mContext; private final WeakHashMap mPackages = new WeakHashMap(); private final Configuration mConfiguration = new Configuration(); public final static class Package { public final Context context; private final SparseArray> mMap = new SparseArray>(); public Package(Context c) { context = c; } } public final static class Entry { public final Context context; public final TypedArray array; public Entry(Context c, TypedArray ta) { context = c; array = ta; } } public static void init(Context context) { if (sInstance == null) { sInstance = new AttributeCache(context); } } public static AttributeCache instance() { return sInstance; } public AttributeCache(Context context) { mContext = context; } public void removePackage(String packageName) { synchronized (this) { mPackages.remove(packageName); } } public void updateConfiguration(Configuration config) { synchronized (this) { int changes = mConfiguration.updateFrom(config); if ((changes & ~(ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_KEYBOARD_HIDDEN | ActivityInfo.CONFIG_ORIENTATION)) != 0) { // The configurations being masked out are ones that commonly // change so we don't want flushing the cache... all others // will flush the cache. mPackages.clear(); } } } public Entry get(String packageName, int resId, int[] styleable) { synchronized (this) { Package pkg = mPackages.get(packageName); HashMap map = null; Entry ent = null; if (pkg != null) { map = pkg.mMap.get(resId); if (map != null) { ent = map.get(styleable); if (ent != null) { return ent; } } } else { Context context; try { context = mContext.createPackageContext(packageName, 0); if (context == null) { return null; } } catch (PackageManager.NameNotFoundException e) { return null; } pkg = new Package(context); mPackages.put(packageName, pkg); } if (map == null) { map = new HashMap(); pkg.mMap.put(resId, map); } try { ent = new Entry(pkg.context, pkg.context.obtainStyledAttributes(resId, styleable)); map.put(styleable, ent); } catch (Resources.NotFoundException e) { return null; } return ent; } } }