blob: 58ec836547a7dec9d16205c0bcd1cb4e219bfdfe [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.content.Context;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070021import android.content.pm.ActivityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.content.pm.PackageManager;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070023import android.content.res.Configuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.res.Resources;
25import android.content.res.TypedArray;
Amith Yamasani4befbec2013-07-10 16:18:01 -070026import android.os.UserHandle;
Jeff Sharkey98bf12f2016-05-26 11:56:57 -060027import android.util.ArrayMap;
Adam Lesinski6aec4522016-06-27 12:30:02 -070028import android.util.LruCache;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070029import android.util.SparseArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030
Jeff Sharkey98bf12f2016-05-26 11:56:57 -060031import com.android.internal.annotations.GuardedBy;
32
Dianne Hackbornde7faf62009-06-30 13:27:30 -070033/**
34 * TODO: This should be better integrated into the system so it doesn't need
35 * special calls from the activity manager to clear it.
36 */
37public final class AttributeCache {
Adam Lesinski6aec4522016-06-27 12:30:02 -070038 private static final int CACHE_SIZE = 4;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039 private static AttributeCache sInstance = null;
Jeff Sharkey98bf12f2016-05-26 11:56:57 -060040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041 private final Context mContext;
Jeff Sharkey98bf12f2016-05-26 11:56:57 -060042
43 @GuardedBy("this")
Adam Lesinski6aec4522016-06-27 12:30:02 -070044 private final LruCache<String, Package> mPackages = new LruCache<>(CACHE_SIZE);
45
Jeff Sharkey98bf12f2016-05-26 11:56:57 -060046 @GuardedBy("this")
Dianne Hackbornde7faf62009-06-30 13:27:30 -070047 private final Configuration mConfiguration = new Configuration();
Jeff Sharkey98bf12f2016-05-26 11:56:57 -060048
Dianne Hackbornde7faf62009-06-30 13:27:30 -070049 public final static class Package {
50 public final Context context;
Jeff Sharkey98bf12f2016-05-26 11:56:57 -060051 private final SparseArray<ArrayMap<int[], Entry>> mMap = new SparseArray<>();
52
Dianne Hackbornde7faf62009-06-30 13:27:30 -070053 public Package(Context c) {
54 context = c;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055 }
56 }
57
58 public final static class Entry {
59 public final Context context;
60 public final TypedArray array;
61
62 public Entry(Context c, TypedArray ta) {
63 context = c;
64 array = ta;
65 }
Jeff Sharkey98bf12f2016-05-26 11:56:57 -060066
67 void recycle() {
68 if (array != null) {
69 array.recycle();
70 }
71 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072 }
73
74 public static void init(Context context) {
75 if (sInstance == null) {
76 sInstance = new AttributeCache(context);
77 }
78 }
79
80 public static AttributeCache instance() {
81 return sInstance;
82 }
83
84 public AttributeCache(Context context) {
85 mContext = context;
86 }
Jeff Sharkey98bf12f2016-05-26 11:56:57 -060087
Dianne Hackbornde7faf62009-06-30 13:27:30 -070088 public void removePackage(String packageName) {
89 synchronized (this) {
Adam Lesinski6aec4522016-06-27 12:30:02 -070090 final Package pkg = mPackages.remove(packageName);
Jeff Sharkey98bf12f2016-05-26 11:56:57 -060091 if (pkg != null) {
Adam Lesinski6aec4522016-06-27 12:30:02 -070092 for (int i = 0; i < pkg.mMap.size(); i++) {
93 final ArrayMap<int[], Entry> map = pkg.mMap.valueAt(i);
94 for (int j = 0; j < map.size(); j++) {
95 map.valueAt(j).recycle();
Jeff Sharkey98bf12f2016-05-26 11:56:57 -060096 }
97 }
98
99 final Resources res = pkg.context.getResources();
100 res.flushLayoutCache();
101 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -0700102 }
103 }
Jeff Sharkey98bf12f2016-05-26 11:56:57 -0600104
Dianne Hackbornde7faf62009-06-30 13:27:30 -0700105 public void updateConfiguration(Configuration config) {
106 synchronized (this) {
107 int changes = mConfiguration.updateFrom(config);
108 if ((changes & ~(ActivityInfo.CONFIG_FONT_SCALE |
109 ActivityInfo.CONFIG_KEYBOARD_HIDDEN |
110 ActivityInfo.CONFIG_ORIENTATION)) != 0) {
111 // The configurations being masked out are ones that commonly
112 // change so we don't want flushing the cache... all others
113 // will flush the cache.
Adam Lesinski6aec4522016-06-27 12:30:02 -0700114 mPackages.evictAll();
Dianne Hackbornde7faf62009-06-30 13:27:30 -0700115 }
116 }
117 }
118
Amith Yamasani4befbec2013-07-10 16:18:01 -0700119 public Entry get(String packageName, int resId, int[] styleable, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 synchronized (this) {
Adam Lesinski6aec4522016-06-27 12:30:02 -0700121 Package pkg = mPackages.get(packageName);
Jeff Sharkey98bf12f2016-05-26 11:56:57 -0600122 ArrayMap<int[], Entry> map = null;
Dianne Hackbornde7faf62009-06-30 13:27:30 -0700123 Entry ent = null;
124 if (pkg != null) {
125 map = pkg.mMap.get(resId);
126 if (map != null) {
127 ent = map.get(styleable);
128 if (ent != null) {
129 return ent;
130 }
131 }
132 } else {
133 Context context;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 try {
Amith Yamasani4befbec2013-07-10 16:18:01 -0700135 context = mContext.createPackageContextAsUser(packageName, 0,
136 new UserHandle(userId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137 if (context == null) {
138 return null;
139 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 } catch (PackageManager.NameNotFoundException e) {
141 return null;
142 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -0700143 pkg = new Package(context);
Adam Lesinski6aec4522016-06-27 12:30:02 -0700144 mPackages.put(packageName, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -0700146
147 if (map == null) {
Jeff Sharkey98bf12f2016-05-26 11:56:57 -0600148 map = new ArrayMap<>();
Dianne Hackbornde7faf62009-06-30 13:27:30 -0700149 pkg.mMap.put(resId, map);
150 }
151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 try {
Dianne Hackbornde7faf62009-06-30 13:27:30 -0700153 ent = new Entry(pkg.context,
154 pkg.context.obtainStyledAttributes(resId, styleable));
155 map.put(styleable, ent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 } catch (Resources.NotFoundException e) {
157 return null;
158 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -0700159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 return ent;
161 }
162 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163}
164