• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006-2011 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 
17 package com.android.server.am;
18 
19 import android.annotation.NonNull;
20 import android.app.ActivityThread;
21 import android.content.Context;
22 import android.database.ContentObserver;
23 import android.net.Uri;
24 import android.os.Bundle;
25 import android.provider.DeviceConfig;
26 import android.provider.Settings;
27 import android.widget.WidgetFlags;
28 
29 import com.android.internal.annotations.VisibleForTesting;
30 
31 import java.util.ArrayList;
32 import java.util.HashMap;
33 import java.util.HashSet;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Objects;
37 
38 /**
39  * Helper class for watching a set of core settings which the framework
40  * propagates to application processes to avoid multiple lookups and potentially
41  * disk I/O operations. Note: This class assumes that all core settings reside
42  * in {@link Settings.Secure}.
43  */
44 final class CoreSettingsObserver extends ContentObserver {
45     private static final String LOG_TAG = CoreSettingsObserver.class.getSimpleName();
46 
47     private static class DeviceConfigEntry<T> {
48         String namespace;
49         String flag;
50         String coreSettingKey;
51         Class<T> type;
52         T defaultValue;
53 
DeviceConfigEntry(String namespace, String flag, String coreSettingKey, Class<T> type, @NonNull T defaultValue)54         DeviceConfigEntry(String namespace, String flag, String coreSettingKey, Class<T> type,
55                 @NonNull T defaultValue) {
56             this.namespace = namespace;
57             this.flag = flag;
58             this.coreSettingKey = coreSettingKey;
59             this.type = type;
60             this.defaultValue = Objects.requireNonNull(defaultValue);
61         }
62     }
63 
64     // mapping form property name to its type
65     @VisibleForTesting
66     static final Map<String, Class<?>> sSecureSettingToTypeMap = new HashMap<
67             String, Class<?>>();
68     @VisibleForTesting
69     static final Map<String, Class<?>> sSystemSettingToTypeMap = new HashMap<
70             String, Class<?>>();
71     @VisibleForTesting
72     static final Map<String, Class<?>> sGlobalSettingToTypeMap = new HashMap<
73             String, Class<?>>();
74     static final List<DeviceConfigEntry> sDeviceConfigEntries = new ArrayList<DeviceConfigEntry>();
75     static {
sSecureSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class)76         sSecureSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class);
sSecureSettingToTypeMap.put(Settings.Secure.MULTI_PRESS_TIMEOUT, int.class)77         sSecureSettingToTypeMap.put(Settings.Secure.MULTI_PRESS_TIMEOUT, int.class);
78         // add other secure settings here...
79 
sSystemSettingToTypeMap.put(Settings.System.TIME_12_24, String.class)80         sSystemSettingToTypeMap.put(Settings.System.TIME_12_24, String.class);
81         // add other system settings here...
82 
sGlobalSettingToTypeMap.put(Settings.Global.DEBUG_VIEW_ATTRIBUTES, int.class)83         sGlobalSettingToTypeMap.put(Settings.Global.DEBUG_VIEW_ATTRIBUTES, int.class);
sGlobalSettingToTypeMap.put( Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE, String.class)84         sGlobalSettingToTypeMap.put(
85                 Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE, String.class);
sGlobalSettingToTypeMap.put( Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE, String.class)86         sGlobalSettingToTypeMap.put(
87                 Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE, String.class);
sGlobalSettingToTypeMap.put( Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE, String.class)88         sGlobalSettingToTypeMap.put(
89                 Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE, String.class);
sGlobalSettingToTypeMap.put( Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS, String.class)90         sGlobalSettingToTypeMap.put(
91                 Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS, String.class);
sGlobalSettingToTypeMap.put( Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES, String.class)92         sGlobalSettingToTypeMap.put(
93                 Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES, String.class);
sGlobalSettingToTypeMap.put( Settings.Global.GLOBAL_SETTINGS_ANGLE_WHITELIST, String.class)94         sGlobalSettingToTypeMap.put(
95                 Settings.Global.GLOBAL_SETTINGS_ANGLE_WHITELIST, String.class);
sGlobalSettingToTypeMap.put( Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX, String.class)96         sGlobalSettingToTypeMap.put(
97                 Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.ENABLE_GPU_DEBUG_LAYERS, int.class)98         sGlobalSettingToTypeMap.put(Settings.Global.ENABLE_GPU_DEBUG_LAYERS, int.class);
sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_APP, String.class)99         sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_APP, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS, String.class)100         sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS_GLES, String.class)101         sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS_GLES, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYER_APP, String.class)102         sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYER_APP, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_ALL_APPS, int.class)103         sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_ALL_APPS, int.class);
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_OPT_IN_APPS, String.class)104         sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_OPT_IN_APPS, String.class);
sGlobalSettingToTypeMap.put( Settings.Global.GAME_DRIVER_PRERELEASE_OPT_IN_APPS, String.class)105         sGlobalSettingToTypeMap.put(
106                 Settings.Global.GAME_DRIVER_PRERELEASE_OPT_IN_APPS, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_OPT_OUT_APPS, String.class)107         sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_OPT_OUT_APPS, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLIST, String.class)108         sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLIST, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_WHITELIST, String.class)109         sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_WHITELIST, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLISTS, String.class)110         sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLISTS, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, String.class)111         sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, String.class);
112         // add other global settings here...
113 
sDeviceConfigEntries.add(new DeviceConfigEntry<Boolean>( DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_CURSOR_DRAG_FROM_ANYWHERE, WidgetFlags.KEY_ENABLE_CURSOR_DRAG_FROM_ANYWHERE, boolean.class, WidgetFlags.ENABLE_CURSOR_DRAG_FROM_ANYWHERE_DEFAULT))114         sDeviceConfigEntries.add(new DeviceConfigEntry<Boolean>(
115                 DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_CURSOR_DRAG_FROM_ANYWHERE,
116                 WidgetFlags.KEY_ENABLE_CURSOR_DRAG_FROM_ANYWHERE, boolean.class,
117                 WidgetFlags.ENABLE_CURSOR_DRAG_FROM_ANYWHERE_DEFAULT));
sDeviceConfigEntries.add(new DeviceConfigEntry<Integer>( DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.CURSOR_DRAG_MIN_ANGLE_FROM_VERTICAL, WidgetFlags.KEY_CURSOR_DRAG_MIN_ANGLE_FROM_VERTICAL, int.class, WidgetFlags.CURSOR_DRAG_MIN_ANGLE_FROM_VERTICAL_DEFAULT))118         sDeviceConfigEntries.add(new DeviceConfigEntry<Integer>(
119                 DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.CURSOR_DRAG_MIN_ANGLE_FROM_VERTICAL,
120                 WidgetFlags.KEY_CURSOR_DRAG_MIN_ANGLE_FROM_VERTICAL, int.class,
121                 WidgetFlags.CURSOR_DRAG_MIN_ANGLE_FROM_VERTICAL_DEFAULT));
sDeviceConfigEntries.add(new DeviceConfigEntry<Integer>( DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.FINGER_TO_CURSOR_DISTANCE, WidgetFlags.KEY_FINGER_TO_CURSOR_DISTANCE, int.class, WidgetFlags.FINGER_TO_CURSOR_DISTANCE_DEFAULT))122         sDeviceConfigEntries.add(new DeviceConfigEntry<Integer>(
123                 DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.FINGER_TO_CURSOR_DISTANCE,
124                 WidgetFlags.KEY_FINGER_TO_CURSOR_DISTANCE, int.class,
125                 WidgetFlags.FINGER_TO_CURSOR_DISTANCE_DEFAULT));
sDeviceConfigEntries.add(new DeviceConfigEntry<Boolean>( DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_INSERTION_HANDLE_GESTURES, WidgetFlags.KEY_ENABLE_INSERTION_HANDLE_GESTURES, boolean.class, WidgetFlags.ENABLE_INSERTION_HANDLE_GESTURES_DEFAULT))126         sDeviceConfigEntries.add(new DeviceConfigEntry<Boolean>(
127                 DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_INSERTION_HANDLE_GESTURES,
128                 WidgetFlags.KEY_ENABLE_INSERTION_HANDLE_GESTURES, boolean.class,
129                 WidgetFlags.ENABLE_INSERTION_HANDLE_GESTURES_DEFAULT));
sDeviceConfigEntries.add(new DeviceConfigEntry<Integer>( DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.INSERTION_HANDLE_DELTA_HEIGHT, WidgetFlags.KEY_INSERTION_HANDLE_DELTA_HEIGHT, int.class, WidgetFlags.INSERTION_HANDLE_DELTA_HEIGHT_DEFAULT))130         sDeviceConfigEntries.add(new DeviceConfigEntry<Integer>(
131                 DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.INSERTION_HANDLE_DELTA_HEIGHT,
132                 WidgetFlags.KEY_INSERTION_HANDLE_DELTA_HEIGHT, int.class,
133                 WidgetFlags.INSERTION_HANDLE_DELTA_HEIGHT_DEFAULT));
sDeviceConfigEntries.add(new DeviceConfigEntry<Integer>( DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.INSERTION_HANDLE_OPACITY, WidgetFlags.KEY_INSERTION_HANDLE_OPACITY, int.class, WidgetFlags.INSERTION_HANDLE_OPACITY_DEFAULT))134         sDeviceConfigEntries.add(new DeviceConfigEntry<Integer>(
135                 DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.INSERTION_HANDLE_OPACITY,
136                 WidgetFlags.KEY_INSERTION_HANDLE_OPACITY, int.class,
137                 WidgetFlags.INSERTION_HANDLE_OPACITY_DEFAULT));
sDeviceConfigEntries.add(new DeviceConfigEntry<Boolean>( DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_NEW_MAGNIFIER, WidgetFlags.KEY_ENABLE_NEW_MAGNIFIER, boolean.class, WidgetFlags.ENABLE_NEW_MAGNIFIER_DEFAULT))138         sDeviceConfigEntries.add(new DeviceConfigEntry<Boolean>(
139                 DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_NEW_MAGNIFIER,
140                 WidgetFlags.KEY_ENABLE_NEW_MAGNIFIER, boolean.class,
141                 WidgetFlags.ENABLE_NEW_MAGNIFIER_DEFAULT));
sDeviceConfigEntries.add(new DeviceConfigEntry<Float>( DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.MAGNIFIER_ZOOM_FACTOR, WidgetFlags.KEY_MAGNIFIER_ZOOM_FACTOR, float.class, WidgetFlags.MAGNIFIER_ZOOM_FACTOR_DEFAULT))142         sDeviceConfigEntries.add(new DeviceConfigEntry<Float>(
143                 DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.MAGNIFIER_ZOOM_FACTOR,
144                 WidgetFlags.KEY_MAGNIFIER_ZOOM_FACTOR, float.class,
145                 WidgetFlags.MAGNIFIER_ZOOM_FACTOR_DEFAULT));
sDeviceConfigEntries.add(new DeviceConfigEntry<Float>( DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.MAGNIFIER_ASPECT_RATIO, WidgetFlags.KEY_MAGNIFIER_ASPECT_RATIO, float.class, WidgetFlags.MAGNIFIER_ASPECT_RATIO_DEFAULT))146         sDeviceConfigEntries.add(new DeviceConfigEntry<Float>(
147                 DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.MAGNIFIER_ASPECT_RATIO,
148                 WidgetFlags.KEY_MAGNIFIER_ASPECT_RATIO, float.class,
149                 WidgetFlags.MAGNIFIER_ASPECT_RATIO_DEFAULT));
150         // add other device configs here...
151     }
152 
153     private final Bundle mCoreSettings = new Bundle();
154 
155     private final ActivityManagerService mActivityManagerService;
156 
CoreSettingsObserver(ActivityManagerService activityManagerService)157     public CoreSettingsObserver(ActivityManagerService activityManagerService) {
158         super(activityManagerService.mHandler);
159         mActivityManagerService = activityManagerService;
160         beginObserveCoreSettings();
161         sendCoreSettings();
162     }
163 
getCoreSettingsLocked()164     public Bundle getCoreSettingsLocked() {
165         return (Bundle) mCoreSettings.clone();
166     }
167 
168     @Override
onChange(boolean selfChange)169     public void onChange(boolean selfChange) {
170         synchronized (mActivityManagerService) {
171             sendCoreSettings();
172         }
173     }
174 
sendCoreSettings()175     private void sendCoreSettings() {
176         populateSettings(mCoreSettings, sSecureSettingToTypeMap);
177         populateSettings(mCoreSettings, sSystemSettingToTypeMap);
178         populateSettings(mCoreSettings, sGlobalSettingToTypeMap);
179         populateSettingsFromDeviceConfig();
180         mActivityManagerService.onCoreSettingsChange(mCoreSettings);
181     }
182 
beginObserveCoreSettings()183     private void beginObserveCoreSettings() {
184         for (String setting : sSecureSettingToTypeMap.keySet()) {
185             Uri uri = Settings.Secure.getUriFor(setting);
186             mActivityManagerService.mContext.getContentResolver().registerContentObserver(
187                     uri, false, this);
188         }
189 
190         for (String setting : sSystemSettingToTypeMap.keySet()) {
191             Uri uri = Settings.System.getUriFor(setting);
192             mActivityManagerService.mContext.getContentResolver().registerContentObserver(
193                     uri, false, this);
194         }
195 
196         for (String setting : sGlobalSettingToTypeMap.keySet()) {
197             Uri uri = Settings.Global.getUriFor(setting);
198             mActivityManagerService.mContext.getContentResolver().registerContentObserver(
199                     uri, false, this);
200         }
201 
202         HashSet<String> deviceConfigNamespaces = new HashSet<>();
203         for (DeviceConfigEntry entry : sDeviceConfigEntries) {
204             if (!deviceConfigNamespaces.contains(entry.namespace)) {
205                 DeviceConfig.addOnPropertiesChangedListener(
206                         entry.namespace, ActivityThread.currentApplication().getMainExecutor(),
207                         (DeviceConfig.Properties prop) -> onChange(false));
208                 deviceConfigNamespaces.add(entry.namespace);
209             }
210         }
211     }
212 
213     @VisibleForTesting
populateSettings(Bundle snapshot, Map<String, Class<?>> map)214     void populateSettings(Bundle snapshot, Map<String, Class<?>> map) {
215         Context context = mActivityManagerService.mContext;
216         for (Map.Entry<String, Class<?>> entry : map.entrySet()) {
217             String setting = entry.getKey();
218             final String value;
219             if (map == sSecureSettingToTypeMap) {
220                 value = Settings.Secure.getString(context.getContentResolver(), setting);
221             } else if (map == sSystemSettingToTypeMap) {
222                 value = Settings.System.getString(context.getContentResolver(), setting);
223             } else {
224                 value = Settings.Global.getString(context.getContentResolver(), setting);
225             }
226             if (value == null) {
227                 snapshot.remove(setting);
228                 continue;
229             }
230             Class<?> type = entry.getValue();
231             if (type == String.class) {
232                 snapshot.putString(setting, value);
233             } else if (type == int.class) {
234                 snapshot.putInt(setting, Integer.parseInt(value));
235             } else if (type == float.class) {
236                 snapshot.putFloat(setting, Float.parseFloat(value));
237             } else if (type == long.class) {
238                 snapshot.putLong(setting, Long.parseLong(value));
239             }
240         }
241     }
242 
243     @SuppressWarnings("unchecked")
populateSettingsFromDeviceConfig()244     private void populateSettingsFromDeviceConfig() {
245         for (DeviceConfigEntry<?> entry : sDeviceConfigEntries) {
246             if (entry.type == String.class) {
247                 String defaultValue = ((DeviceConfigEntry<String>) entry).defaultValue;
248                 mCoreSettings.putString(entry.coreSettingKey,
249                         DeviceConfig.getString(entry.namespace, entry.flag, defaultValue));
250             } else if (entry.type == int.class) {
251                 int defaultValue = ((DeviceConfigEntry<Integer>) entry).defaultValue;
252                 mCoreSettings.putInt(entry.coreSettingKey,
253                         DeviceConfig.getInt(entry.namespace, entry.flag, defaultValue));
254             } else if (entry.type == float.class) {
255                 float defaultValue = ((DeviceConfigEntry<Float>) entry).defaultValue;
256                 mCoreSettings.putFloat(entry.coreSettingKey,
257                         DeviceConfig.getFloat(entry.namespace, entry.flag, defaultValue));
258             } else if (entry.type == long.class) {
259                 long defaultValue = ((DeviceConfigEntry<Long>) entry).defaultValue;
260                 mCoreSettings.putLong(entry.coreSettingKey,
261                         DeviceConfig.getLong(entry.namespace, entry.flag, defaultValue));
262             } else if (entry.type == boolean.class) {
263                 boolean defaultValue = ((DeviceConfigEntry<Boolean>) entry).defaultValue;
264                 mCoreSettings.putInt(entry.coreSettingKey,
265                         DeviceConfig.getBoolean(entry.namespace, entry.flag, defaultValue) ? 1 : 0);
266             }
267         }
268     }
269 }
270