1/* 2** 3** Copyright 2007, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18package com.android.server; 19 20import android.content.Context; 21import android.content.pm.ActivityInfo; 22import android.content.pm.PackageManager; 23import android.content.res.Configuration; 24import android.content.res.Resources; 25import android.content.res.TypedArray; 26import android.util.SparseArray; 27 28import java.util.HashMap; 29import java.util.WeakHashMap; 30 31/** 32 * TODO: This should be better integrated into the system so it doesn't need 33 * special calls from the activity manager to clear it. 34 */ 35public final class AttributeCache { 36 private static AttributeCache sInstance = null; 37 38 private final Context mContext; 39 private final WeakHashMap<String, Package> mPackages = 40 new WeakHashMap<String, Package>(); 41 private final Configuration mConfiguration = new Configuration(); 42 43 public final static class Package { 44 public final Context context; 45 private final SparseArray<HashMap<int[], Entry>> mMap 46 = new SparseArray<HashMap<int[], Entry>>(); 47 48 public Package(Context c) { 49 context = c; 50 } 51 } 52 53 public final static class Entry { 54 public final Context context; 55 public final TypedArray array; 56 57 public Entry(Context c, TypedArray ta) { 58 context = c; 59 array = ta; 60 } 61 } 62 63 public static void init(Context context) { 64 if (sInstance == null) { 65 sInstance = new AttributeCache(context); 66 } 67 } 68 69 public static AttributeCache instance() { 70 return sInstance; 71 } 72 73 public AttributeCache(Context context) { 74 mContext = context; 75 } 76 77 public void removePackage(String packageName) { 78 synchronized (this) { 79 mPackages.remove(packageName); 80 } 81 } 82 83 public void updateConfiguration(Configuration config) { 84 synchronized (this) { 85 int changes = mConfiguration.updateFrom(config); 86 if ((changes & ~(ActivityInfo.CONFIG_FONT_SCALE | 87 ActivityInfo.CONFIG_KEYBOARD_HIDDEN | 88 ActivityInfo.CONFIG_ORIENTATION)) != 0) { 89 // The configurations being masked out are ones that commonly 90 // change so we don't want flushing the cache... all others 91 // will flush the cache. 92 mPackages.clear(); 93 } 94 } 95 } 96 97 public Entry get(String packageName, int resId, int[] styleable) { 98 synchronized (this) { 99 Package pkg = mPackages.get(packageName); 100 HashMap<int[], Entry> map = null; 101 Entry ent = null; 102 if (pkg != null) { 103 map = pkg.mMap.get(resId); 104 if (map != null) { 105 ent = map.get(styleable); 106 if (ent != null) { 107 return ent; 108 } 109 } 110 } else { 111 Context context; 112 try { 113 context = mContext.createPackageContext(packageName, 0); 114 if (context == null) { 115 return null; 116 } 117 } catch (PackageManager.NameNotFoundException e) { 118 return null; 119 } 120 pkg = new Package(context); 121 mPackages.put(packageName, pkg); 122 } 123 124 if (map == null) { 125 map = new HashMap<int[], Entry>(); 126 pkg.mMap.put(resId, map); 127 } 128 129 try { 130 ent = new Entry(pkg.context, 131 pkg.context.obtainStyledAttributes(resId, styleable)); 132 map.put(styleable, ent); 133 } catch (Resources.NotFoundException e) { 134 return null; 135 } 136 137 return ent; 138 } 139 } 140} 141 142