The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 20 | import android.content.Context; |
Dianne Hackborn | de7faf6 | 2009-06-30 13:27:30 -0700 | [diff] [blame] | 21 | import android.content.pm.ActivityInfo; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 22 | import android.content.pm.PackageManager; |
Dianne Hackborn | de7faf6 | 2009-06-30 13:27:30 -0700 | [diff] [blame] | 23 | import android.content.res.Configuration; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 24 | import android.content.res.Resources; |
| 25 | import android.content.res.TypedArray; |
Amith Yamasani | 4befbec | 2013-07-10 16:18:01 -0700 | [diff] [blame] | 26 | import android.os.UserHandle; |
Jeff Sharkey | 98bf12f | 2016-05-26 11:56:57 -0600 | [diff] [blame] | 27 | import android.util.ArrayMap; |
Adam Lesinski | 6aec452 | 2016-06-27 12:30:02 -0700 | [diff] [blame] | 28 | import android.util.LruCache; |
Dianne Hackborn | de7faf6 | 2009-06-30 13:27:30 -0700 | [diff] [blame] | 29 | import android.util.SparseArray; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 30 | |
Jeff Sharkey | 98bf12f | 2016-05-26 11:56:57 -0600 | [diff] [blame] | 31 | import com.android.internal.annotations.GuardedBy; |
| 32 | |
Dianne Hackborn | de7faf6 | 2009-06-30 13:27:30 -0700 | [diff] [blame] | 33 | /** |
| 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 | */ |
| 37 | public final class AttributeCache { |
Adam Lesinski | 6aec452 | 2016-06-27 12:30:02 -0700 | [diff] [blame] | 38 | private static final int CACHE_SIZE = 4; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 39 | private static AttributeCache sInstance = null; |
Jeff Sharkey | 98bf12f | 2016-05-26 11:56:57 -0600 | [diff] [blame] | 40 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 41 | private final Context mContext; |
Jeff Sharkey | 98bf12f | 2016-05-26 11:56:57 -0600 | [diff] [blame] | 42 | |
| 43 | @GuardedBy("this") |
Adam Lesinski | 6aec452 | 2016-06-27 12:30:02 -0700 | [diff] [blame] | 44 | private final LruCache<String, Package> mPackages = new LruCache<>(CACHE_SIZE); |
| 45 | |
Jeff Sharkey | 98bf12f | 2016-05-26 11:56:57 -0600 | [diff] [blame] | 46 | @GuardedBy("this") |
Dianne Hackborn | de7faf6 | 2009-06-30 13:27:30 -0700 | [diff] [blame] | 47 | private final Configuration mConfiguration = new Configuration(); |
Jeff Sharkey | 98bf12f | 2016-05-26 11:56:57 -0600 | [diff] [blame] | 48 | |
Dianne Hackborn | de7faf6 | 2009-06-30 13:27:30 -0700 | [diff] [blame] | 49 | public final static class Package { |
| 50 | public final Context context; |
Jeff Sharkey | 98bf12f | 2016-05-26 11:56:57 -0600 | [diff] [blame] | 51 | private final SparseArray<ArrayMap<int[], Entry>> mMap = new SparseArray<>(); |
| 52 | |
Dianne Hackborn | de7faf6 | 2009-06-30 13:27:30 -0700 | [diff] [blame] | 53 | public Package(Context c) { |
| 54 | context = c; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 55 | } |
| 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 Sharkey | 98bf12f | 2016-05-26 11:56:57 -0600 | [diff] [blame] | 66 | |
| 67 | void recycle() { |
| 68 | if (array != null) { |
| 69 | array.recycle(); |
| 70 | } |
| 71 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 72 | } |
| 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 Sharkey | 98bf12f | 2016-05-26 11:56:57 -0600 | [diff] [blame] | 87 | |
Dianne Hackborn | de7faf6 | 2009-06-30 13:27:30 -0700 | [diff] [blame] | 88 | public void removePackage(String packageName) { |
| 89 | synchronized (this) { |
Adam Lesinski | 6aec452 | 2016-06-27 12:30:02 -0700 | [diff] [blame] | 90 | final Package pkg = mPackages.remove(packageName); |
Jeff Sharkey | 98bf12f | 2016-05-26 11:56:57 -0600 | [diff] [blame] | 91 | if (pkg != null) { |
Adam Lesinski | 6aec452 | 2016-06-27 12:30:02 -0700 | [diff] [blame] | 92 | 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 Sharkey | 98bf12f | 2016-05-26 11:56:57 -0600 | [diff] [blame] | 96 | } |
| 97 | } |
| 98 | |
| 99 | final Resources res = pkg.context.getResources(); |
| 100 | res.flushLayoutCache(); |
| 101 | } |
Dianne Hackborn | de7faf6 | 2009-06-30 13:27:30 -0700 | [diff] [blame] | 102 | } |
| 103 | } |
Jeff Sharkey | 98bf12f | 2016-05-26 11:56:57 -0600 | [diff] [blame] | 104 | |
Dianne Hackborn | de7faf6 | 2009-06-30 13:27:30 -0700 | [diff] [blame] | 105 | 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 Lesinski | 6aec452 | 2016-06-27 12:30:02 -0700 | [diff] [blame] | 114 | mPackages.evictAll(); |
Dianne Hackborn | de7faf6 | 2009-06-30 13:27:30 -0700 | [diff] [blame] | 115 | } |
| 116 | } |
| 117 | } |
| 118 | |
Amith Yamasani | 4befbec | 2013-07-10 16:18:01 -0700 | [diff] [blame] | 119 | public Entry get(String packageName, int resId, int[] styleable, int userId) { |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 120 | synchronized (this) { |
Adam Lesinski | 6aec452 | 2016-06-27 12:30:02 -0700 | [diff] [blame] | 121 | Package pkg = mPackages.get(packageName); |
Jeff Sharkey | 98bf12f | 2016-05-26 11:56:57 -0600 | [diff] [blame] | 122 | ArrayMap<int[], Entry> map = null; |
Dianne Hackborn | de7faf6 | 2009-06-30 13:27:30 -0700 | [diff] [blame] | 123 | 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 Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 134 | try { |
Amith Yamasani | 4befbec | 2013-07-10 16:18:01 -0700 | [diff] [blame] | 135 | context = mContext.createPackageContextAsUser(packageName, 0, |
| 136 | new UserHandle(userId)); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 137 | if (context == null) { |
| 138 | return null; |
| 139 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 140 | } catch (PackageManager.NameNotFoundException e) { |
| 141 | return null; |
| 142 | } |
Dianne Hackborn | de7faf6 | 2009-06-30 13:27:30 -0700 | [diff] [blame] | 143 | pkg = new Package(context); |
Adam Lesinski | 6aec452 | 2016-06-27 12:30:02 -0700 | [diff] [blame] | 144 | mPackages.put(packageName, pkg); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 145 | } |
Dianne Hackborn | de7faf6 | 2009-06-30 13:27:30 -0700 | [diff] [blame] | 146 | |
| 147 | if (map == null) { |
Jeff Sharkey | 98bf12f | 2016-05-26 11:56:57 -0600 | [diff] [blame] | 148 | map = new ArrayMap<>(); |
Dianne Hackborn | de7faf6 | 2009-06-30 13:27:30 -0700 | [diff] [blame] | 149 | pkg.mMap.put(resId, map); |
| 150 | } |
| 151 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 152 | try { |
Dianne Hackborn | de7faf6 | 2009-06-30 13:27:30 -0700 | [diff] [blame] | 153 | ent = new Entry(pkg.context, |
| 154 | pkg.context.obtainStyledAttributes(resId, styleable)); |
| 155 | map.put(styleable, ent); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 156 | } catch (Resources.NotFoundException e) { |
| 157 | return null; |
| 158 | } |
Dianne Hackborn | de7faf6 | 2009-06-30 13:27:30 -0700 | [diff] [blame] | 159 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 160 | return ent; |
| 161 | } |
| 162 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 163 | } |
| 164 | |