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