• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
18 package com.android.server;
19 
20 import android.content.Context;
21 import android.content.pm.ActivityInfo;
22 import android.content.pm.PackageManager;
23 import android.content.res.Configuration;
24 import android.content.res.Resources;
25 import android.content.res.TypedArray;
26 import android.os.UserHandle;
27 import android.util.SparseArray;
28 
29 import java.util.HashMap;
30 import java.util.WeakHashMap;
31 
32 /**
33  * TODO: This should be better integrated into the system so it doesn't need
34  * special calls from the activity manager to clear it.
35  */
36 public final class AttributeCache {
37     private static AttributeCache sInstance = null;
38 
39     private final Context mContext;
40     private final SparseArray<WeakHashMap<String, Package>> mPackages =
41             new SparseArray<WeakHashMap<String, Package>>();
42     private final Configuration mConfiguration = new Configuration();
43 
44     public final static class Package {
45         public final Context context;
46         private final SparseArray<HashMap<int[], Entry>> mMap
47                 = new SparseArray<HashMap<int[], Entry>>();
48 
Package(Context c)49         public Package(Context c) {
50             context = c;
51         }
52     }
53 
54     public final static class Entry {
55         public final Context context;
56         public final TypedArray array;
57 
Entry(Context c, TypedArray ta)58         public Entry(Context c, TypedArray ta) {
59             context = c;
60             array = ta;
61         }
62     }
63 
init(Context context)64     public static void init(Context context) {
65         if (sInstance == null) {
66             sInstance = new AttributeCache(context);
67         }
68     }
69 
instance()70     public static AttributeCache instance() {
71         return sInstance;
72     }
73 
AttributeCache(Context context)74     public AttributeCache(Context context) {
75         mContext = context;
76     }
77 
removePackage(String packageName)78     public void removePackage(String packageName) {
79         synchronized (this) {
80             for (int i=0; i<mPackages.size(); i++) {
81                 mPackages.valueAt(i).remove(packageName);
82             }
83         }
84     }
85 
updateConfiguration(Configuration config)86     public void updateConfiguration(Configuration config) {
87         synchronized (this) {
88             int changes = mConfiguration.updateFrom(config);
89             if ((changes & ~(ActivityInfo.CONFIG_FONT_SCALE |
90                     ActivityInfo.CONFIG_KEYBOARD_HIDDEN |
91                     ActivityInfo.CONFIG_ORIENTATION)) != 0) {
92                 // The configurations being masked out are ones that commonly
93                 // change so we don't want flushing the cache... all others
94                 // will flush the cache.
95                 mPackages.clear();
96             }
97         }
98     }
99 
removeUser(int userId)100     public void removeUser(int userId) {
101         synchronized (this) {
102             mPackages.remove(userId);
103         }
104     }
105 
get(int userId, String packageName, int resId, int[] styleable)106     public Entry get(int userId, String packageName, int resId, int[] styleable) {
107         synchronized (this) {
108             WeakHashMap<String, Package> packages = mPackages.get(userId);
109             if (packages == null) {
110                 packages = new WeakHashMap<String, Package>();
111                 mPackages.put(userId, packages);
112             }
113             Package pkg = packages.get(packageName);
114             HashMap<int[], Entry> map = null;
115             Entry ent = null;
116             if (pkg != null) {
117                 map = pkg.mMap.get(resId);
118                 if (map != null) {
119                     ent = map.get(styleable);
120                     if (ent != null) {
121                         return ent;
122                     }
123                 }
124             } else {
125                 Context context;
126                 try {
127                     context = mContext.createPackageContextAsUser(packageName, 0,
128                             new UserHandle(userId));
129                     if (context == null) {
130                         return null;
131                     }
132                 } catch (PackageManager.NameNotFoundException e) {
133                     return null;
134                 }
135                 pkg = new Package(context);
136                 packages.put(packageName, pkg);
137             }
138 
139             if (map == null) {
140                 map = new HashMap<int[], Entry>();
141                 pkg.mMap.put(resId, map);
142             }
143 
144             try {
145                 ent = new Entry(pkg.context,
146                         pkg.context.obtainStyledAttributes(resId, styleable));
147                 map.put(styleable, ent);
148             } catch (Resources.NotFoundException e) {
149                 return null;
150             }
151 
152             return ent;
153         }
154     }
155 }
156 
157