Settings.java revision f4acd3cf076435ce836a6d4a9027b73ec3050def
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package android.support.v17.leanback.system;
18
19import android.content.Context;
20import android.content.Intent;
21import android.content.pm.ApplicationInfo;
22import android.content.pm.PackageManager;
23import android.content.pm.ResolveInfo;
24import android.content.res.Resources;
25import android.support.v17.leanback.widget.ShadowOverlayContainer;
26import android.util.Log;
27
28/**
29 * Provides various preferences affecting Leanback runtime behavior.
30 * <p>Note this class is not thread safe and its methods should only
31 * be invoked from the UI thread
32 * </p>
33 */
34public class Settings {
35    static private final String TAG = "Settings";
36    static private final boolean DEBUG = false;
37
38    // The intent action that must be provided by a broadcast receiver
39    // in a customization package.
40    private static final String ACTION_PARTNER_CUSTOMIZATION =
41            "android.support.v17.leanback.action.PARTNER_CUSTOMIZATION";
42
43    static public final String PREFER_STATIC_SHADOWS = "PREFER_STATIC_SHADOWS";
44
45    static private Settings sInstance;
46
47    private boolean mPreferStaticShadows;
48
49    /**
50     * Returns the singleton Settings instance.
51     */
52    static public Settings getInstance(Context context) {
53        if (sInstance == null) {
54            sInstance = new Settings(context);
55        }
56        return sInstance;
57    }
58
59    private Settings(Context context) {
60        if (DEBUG) Log.v(TAG, "generating preferences");
61        Customizations customizations = getCustomizations(context);
62        generateShadowSetting(customizations);
63    }
64
65    /**
66     * Returns true if static shadows are recommended.
67     * @hide
68     */
69    public boolean preferStaticShadows() {
70        return mPreferStaticShadows;
71    }
72
73    /**
74     * Returns the boolean preference for the given key.
75     */
76    public boolean getBoolean(String key) {
77        return getOrSetBoolean(key, false, false);
78    }
79
80    /**
81     * Sets the boolean preference for the given key.  If an app uses this api to override
82     * a default preference, it must do so on every activity create.
83     */
84    public void setBoolean(String key, boolean value) {
85        getOrSetBoolean(key, true, value);
86    }
87
88    boolean getOrSetBoolean(String key, boolean set, boolean value) {
89        if (key.compareTo(PREFER_STATIC_SHADOWS) == 0) {
90            return set ? (mPreferStaticShadows = value) : mPreferStaticShadows;
91        }
92        throw new IllegalArgumentException("Invalid key");
93    }
94
95    private void generateShadowSetting(Customizations customizations) {
96        if (ShadowOverlayContainer.supportsDynamicShadow()) {
97            mPreferStaticShadows = false;
98            if (customizations != null) {
99                mPreferStaticShadows = customizations.getBoolean(
100                        "leanback_prefer_static_shadows", mPreferStaticShadows);
101            }
102        } else {
103            mPreferStaticShadows = true;
104        }
105
106        if (DEBUG) Log.v(TAG, "generated preference " + PREFER_STATIC_SHADOWS + ": "
107                + mPreferStaticShadows);
108    }
109
110    static class Customizations {
111        Resources mResources;
112        String mPackageName;
113
114        public Customizations(Resources resources, String packageName) {
115            mResources = resources;
116            mPackageName = packageName;
117        }
118
119        public boolean getBoolean(String resourceName, boolean defaultValue) {
120            int resId = mResources.getIdentifier(resourceName, "bool", mPackageName);
121            return resId > 0 ? mResources.getBoolean(resId) : defaultValue;
122        }
123    };
124
125    private Customizations getCustomizations(Context context) {
126        final PackageManager pm = context.getPackageManager();
127        final Intent intent = new Intent(ACTION_PARTNER_CUSTOMIZATION);
128        if (DEBUG) Log.v(TAG, "getting oem customizations by intent: " +
129                ACTION_PARTNER_CUSTOMIZATION);
130
131        Resources resources = null;
132        String packageName = null;
133        for (ResolveInfo info : pm.queryBroadcastReceivers(intent, 0)) {
134            packageName = info.activityInfo.packageName;
135            if (DEBUG) Log.v(TAG, "got package " + packageName);
136            if (packageName != null && isSystemApp(info)) try {
137                resources = pm.getResourcesForApplication(packageName);
138            } catch (PackageManager.NameNotFoundException ex) {
139                // Do nothing
140            }
141            if (resources != null) {
142                if (DEBUG) Log.v(TAG, "found customization package: " + packageName);
143                break;
144            }
145        }
146        return resources == null ? null : new Customizations(resources, packageName);
147    }
148
149    private static boolean isSystemApp(ResolveInfo info) {
150        return (info.activityInfo != null &&
151                (info.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
152    }
153}
154