19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Copyright 2007, The Android Open Source Project 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** you may not use this file except in compliance with the License. 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** You may obtain a copy of the License at 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** See the License for the specific language governing permissions and 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** limitations under the License. 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server; 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 21de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackbornimport android.content.pm.ActivityInfo; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager; 23de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackbornimport android.content.res.Configuration; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray; 26bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackbornimport android.os.UserHandle; 27de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackbornimport android.util.SparseArray; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackbornimport java.util.HashMap; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.WeakHashMap; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn/** 33de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn * TODO: This should be better integrated into the system so it doesn't need 34de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn * special calls from the activity manager to clear it. 35de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn */ 36de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackbornpublic final class AttributeCache { 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static AttributeCache sInstance = null; 38bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Context mContext; 40bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn private final SparseArray<WeakHashMap<String, Package>> mPackages = 41bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn new SparseArray<WeakHashMap<String, Package>>(); 42de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn private final Configuration mConfiguration = new Configuration(); 43bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn 44de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn public final static class Package { 45de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn public final Context context; 46de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn private final SparseArray<HashMap<int[], Entry>> mMap 47de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn = new SparseArray<HashMap<int[], Entry>>(); 48bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn 49de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn public Package(Context c) { 50de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn context = c; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 53bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final static class Entry { 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final Context context; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final TypedArray array; 57bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Entry(Context c, TypedArray ta) { 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context = c; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project array = ta; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 63bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void init(Context context) { 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sInstance == null) { 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sInstance = new AttributeCache(context); 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 69bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static AttributeCache instance() { 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sInstance; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 73bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public AttributeCache(Context context) { 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 77bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn 78de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn public void removePackage(String packageName) { 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 80bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn for (int i=0; i<mPackages.size(); i++) { 81bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn mPackages.valueAt(i).remove(packageName); 82bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn } 83de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn } 84de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn } 85bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn 86de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn public void updateConfiguration(Configuration config) { 87de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn synchronized (this) { 88de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn int changes = mConfiguration.updateFrom(config); 89de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn if ((changes & ~(ActivityInfo.CONFIG_FONT_SCALE | 90de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn ActivityInfo.CONFIG_KEYBOARD_HIDDEN | 91de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn ActivityInfo.CONFIG_ORIENTATION)) != 0) { 92de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn // The configurations being masked out are ones that commonly 93de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn // change so we don't want flushing the cache... all others 94de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn // will flush the cache. 95de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn mPackages.clear(); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 97de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn } 98de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn } 99bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn 100bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn public void removeUser(int userId) { 101bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn synchronized (this) { 102bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn mPackages.remove(userId); 103bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn } 104bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn } 105bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn 106bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn public Entry get(int userId, String packageName, int resId, int[] styleable) { 107de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn synchronized (this) { 108bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn WeakHashMap<String, Package> packages = mPackages.get(userId); 109bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn if (packages == null) { 110bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn packages = new WeakHashMap<String, Package>(); 111bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn mPackages.put(userId, packages); 112bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn } 113bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn Package pkg = packages.get(packageName); 114de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn HashMap<int[], Entry> map = null; 115de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn Entry ent = null; 116de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn if (pkg != null) { 117de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn map = pkg.mMap.get(resId); 118de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn if (map != null) { 119de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn ent = map.get(styleable); 120de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn if (ent != null) { 121de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn return ent; 122de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn } 123de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn } 124de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn } else { 125de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn Context context; 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 127bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn context = mContext.createPackageContextAsUser(packageName, 0, 128bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn new UserHandle(userId)); 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (context == null) { 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (PackageManager.NameNotFoundException e) { 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 135de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn pkg = new Package(context); 136bb4ca5271a806c94a59d98c5c718db7b89728246Dianne Hackborn packages.put(packageName, pkg); 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 138de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn 139de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn if (map == null) { 140de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn map = new HashMap<int[], Entry>(); 141de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn pkg.mMap.put(resId, map); 142de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn } 143de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 145de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn ent = new Entry(pkg.context, 146de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn pkg.context.obtainStyledAttributes(resId, styleable)); 147de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn map.put(styleable, ent); 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Resources.NotFoundException e) { 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 151de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ent; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 157