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;
26de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackbornimport android.util.SparseArray;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
28de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackbornimport java.util.HashMap;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.WeakHashMap;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
31de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn/**
32de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn * TODO: This should be better integrated into the system so it doesn't need
33de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn * special calls from the activity manager to clear it.
34de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn */
35de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackbornpublic final class AttributeCache {
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static AttributeCache sInstance = null;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Context mContext;
39de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn    private final WeakHashMap<String, Package> mPackages =
40de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn            new WeakHashMap<String, Package>();
41de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn    private final Configuration mConfiguration = new Configuration();
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
43de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn    public final static class Package {
44de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn        public final Context context;
45de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn        private final SparseArray<HashMap<int[], Entry>> mMap
46de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                = new SparseArray<HashMap<int[], Entry>>();
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
48de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn        public Package(Context c) {
49de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn            context = c;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static class Entry {
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final Context context;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final TypedArray array;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Entry(Context c, TypedArray ta) {
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            context = c;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            array = ta;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void init(Context context) {
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sInstance == null) {
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sInstance = new AttributeCache(context);
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static AttributeCache instance() {
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sInstance;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public AttributeCache(Context context) {
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
77de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn    public void removePackage(String packageName) {
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (this) {
79de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn            mPackages.remove(packageName);
80de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn        }
81de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn    }
82de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn
83de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn    public void updateConfiguration(Configuration config) {
84de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn        synchronized (this) {
85de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn            int changes = mConfiguration.updateFrom(config);
86de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn            if ((changes & ~(ActivityInfo.CONFIG_FONT_SCALE |
87de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                    ActivityInfo.CONFIG_KEYBOARD_HIDDEN |
88de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                    ActivityInfo.CONFIG_ORIENTATION)) != 0) {
89de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                // The configurations being masked out are ones that commonly
90de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                // change so we don't want flushing the cache... all others
91de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                // will flush the cache.
92de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                mPackages.clear();
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
94de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn        }
95de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn    }
96de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn
97de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn    public Entry get(String packageName, int resId, int[] styleable) {
98de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn        synchronized (this) {
99de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn            Package pkg = mPackages.get(packageName);
100de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn            HashMap<int[], Entry> map = null;
101de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn            Entry ent = null;
102de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn            if (pkg != null) {
103de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                map = pkg.mMap.get(resId);
104de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                if (map != null) {
105de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                    ent = map.get(styleable);
106de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                    if (ent != null) {
107de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                        return ent;
108de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                    }
109de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                }
110de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn            } else {
111de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                Context context;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    context = mContext.createPackageContext(packageName, 0);
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (context == null) {
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        return null;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (PackageManager.NameNotFoundException e) {
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return null;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
120de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                pkg = new Package(context);
121de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                mPackages.put(packageName, pkg);
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
123de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn
124de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn            if (map == null) {
125de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                map = new HashMap<int[], Entry>();
126de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                pkg.mMap.put(resId, map);
127de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn            }
128de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
130de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                ent = new Entry(pkg.context,
131de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                        pkg.context.obtainStyledAttributes(resId, styleable));
132de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn                map.put(styleable, ent);
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (Resources.NotFoundException e) {
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
136de7faf658cd40d34c08a98b39477055da8e19172Dianne Hackborn
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ent;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
142