blob: a29a46debba095d89a915974378de4ee5a620ae7 [file] [log] [blame]
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001/*
2 * Copyright (C) 2007 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 com.android.providers.settings;
18
Svetoslav683914b2015-01-15 14:22:26 -080019import android.Manifest;
Christopher Tated5fe1472012-09-10 15:48:38 -070020import android.app.ActivityManager;
Xiaohui Chen43765b72015-08-31 10:57:33 -070021import android.app.AppGlobals;
Christopher Tate45281862010-03-05 15:46:30 -080022import android.app.backup.BackupManager;
Christopher Tate06efb532012-08-24 15:29:27 -070023import android.content.BroadcastReceiver;
Ruben Brunk98576cf2016-03-07 18:54:28 -080024import android.content.ComponentName;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070025import android.content.ContentProvider;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070026import android.content.ContentValues;
27import android.content.Context;
Christopher Tate06efb532012-08-24 15:29:27 -070028import android.content.Intent;
29import android.content.IntentFilter;
Svetoslav683914b2015-01-15 14:22:26 -080030import android.content.pm.ApplicationInfo;
Xiaohui Chen43765b72015-08-31 10:57:33 -070031import android.content.pm.IPackageManager;
Svetoslav683914b2015-01-15 14:22:26 -080032import android.content.pm.PackageInfo;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070033import android.content.pm.PackageManager;
Christopher Tate38e7a602013-09-03 16:57:34 -070034import android.content.pm.UserInfo;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070035import android.database.Cursor;
Svetoslav683914b2015-01-15 14:22:26 -080036import android.database.MatrixCursor;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070037import android.database.sqlite.SQLiteDatabase;
38import android.database.sqlite.SQLiteQueryBuilder;
Svetoslav683914b2015-01-15 14:22:26 -080039import android.hardware.camera2.utils.ArrayUtils;
John Spurlocke11ae112015-05-11 16:09:03 -040040import android.media.AudioManager;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070041import android.net.Uri;
Christopher Tate06efb532012-08-24 15:29:27 -070042import android.os.Binder;
Svetoslav683914b2015-01-15 14:22:26 -080043import android.os.Build;
Brad Fitzpatrick1877d012010-03-04 17:48:13 -080044import android.os.Bundle;
Amith Yamasani5cdf7f52013-06-27 15:12:01 -070045import android.os.DropBoxManager;
Svetoslav683914b2015-01-15 14:22:26 -080046import android.os.Environment;
Svetoslav7e0683b2015-08-03 16:02:52 -070047import android.os.Handler;
Svet Ganova8f90262016-05-10 08:44:48 -070048import android.os.HandlerThread;
Svetoslav7e0683b2015-08-03 16:02:52 -070049import android.os.Looper;
50import android.os.Message;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070051import android.os.ParcelFileDescriptor;
Christopher Tate0da13572013-10-13 17:34:49 -070052import android.os.Process;
Xiaohui Chen43765b72015-08-31 10:57:33 -070053import android.os.RemoteException;
Jeff Sharkey413573a2016-02-22 17:52:45 -070054import android.os.SELinux;
Dianne Hackborn32f40ee2016-10-20 15:54:14 -070055import android.os.ServiceManager;
Christopher Tate06efb532012-08-24 15:29:27 -070056import android.os.UserHandle;
57import android.os.UserManager;
Svet Ganov53a441c2016-04-19 19:38:00 -070058import android.os.UserManagerInternal;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070059import android.provider.Settings;
Jeremy Joslin8bdad342016-12-14 11:46:47 -080060import android.provider.Settings.Global;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070061import android.text.TextUtils;
Andre Lago3fa139c2016-08-04 13:53:44 +010062import android.util.ArrayMap;
Svetoslav683914b2015-01-15 14:22:26 -080063import android.util.ArraySet;
Christopher Tate06efb532012-08-24 15:29:27 -070064import android.util.Slog;
65import android.util.SparseArray;
Dianne Hackborn32f40ee2016-10-20 15:54:14 -070066import android.util.SparseBooleanArray;
John Spurlocke11ae112015-05-11 16:09:03 -040067
Svetoslav683914b2015-01-15 14:22:26 -080068import com.android.internal.annotations.GuardedBy;
69import com.android.internal.content.PackageMonitor;
70import com.android.internal.os.BackgroundThread;
Suprabh Shukla269c11e2015-12-02 16:51:16 -080071import com.android.providers.settings.SettingsState.Setting;
Svet Ganov53a441c2016-04-19 19:38:00 -070072import com.android.server.LocalServices;
Ruben Brunk98576cf2016-03-07 18:54:28 -080073import com.android.server.SystemConfig;
John Spurlocke11ae112015-05-11 16:09:03 -040074
Svetoslav683914b2015-01-15 14:22:26 -080075import java.io.File;
Svetoslavb505ccc2015-02-17 12:41:04 -080076import java.io.FileDescriptor;
Svetoslav683914b2015-01-15 14:22:26 -080077import java.io.FileNotFoundException;
Svetoslavb505ccc2015-02-17 12:41:04 -080078import java.io.PrintWriter;
Svetoslav683914b2015-01-15 14:22:26 -080079import java.security.SecureRandom;
Dianne Hackborn32f40ee2016-10-20 15:54:14 -070080import java.util.ArrayList;
Svetoslav683914b2015-01-15 14:22:26 -080081import java.util.Arrays;
82import java.util.List;
Andre Lago3fa139c2016-08-04 13:53:44 +010083import java.util.Map;
Svetoslav683914b2015-01-15 14:22:26 -080084import java.util.Set;
85import java.util.regex.Pattern;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070086
Svetoslav Ganove080da92016-12-21 17:10:35 -080087import static android.os.Process.ROOT_UID;
88import static android.os.Process.SYSTEM_UID;
89import static android.os.Process.SHELL_UID;
90
Svetoslav683914b2015-01-15 14:22:26 -080091/**
92 * <p>
93 * This class is a content provider that publishes the system settings.
94 * It can be accessed via the content provider APIs or via custom call
95 * commands. The latter is a bit faster and is the preferred way to access
96 * the platform settings.
97 * </p>
98 * <p>
99 * There are three settings types, global (with signature level protection
100 * and shared across users), secure (with signature permission level
101 * protection and per user), and system (with dangerous permission level
102 * protection and per user). Global settings are stored under the device owner.
103 * Each of these settings is represented by a {@link
104 * com.android.providers.settings.SettingsState} object mapped to an integer
105 * key derived from the setting type in the most significant bits and user
106 * id in the least significant bits. Settings are synchronously loaded on
107 * instantiation of a SettingsState and asynchronously persisted on mutation.
108 * Settings are stored in the user specific system directory.
109 * </p>
110 * <p>
111 * Apps targeting APIs Lollipop MR1 and lower can add custom settings entries
112 * and get a warning. Targeting higher API version prohibits this as the
113 * system settings are not a place for apps to save their state. When a package
114 * is removed the settings it added are deleted. Apps cannot delete system
115 * settings added by the platform. System settings values are validated to
116 * ensure the clients do not put bad values. Global and secure settings are
117 * changed only by trusted parties, therefore no validation is performed. Also
118 * there is a limit on the amount of app specific settings that can be added
119 * to prevent unlimited growth of the system process memory footprint.
120 * </p>
121 */
122@SuppressWarnings("deprecation")
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700123public class SettingsProvider extends ContentProvider {
Dianne Hackborn32f40ee2016-10-20 15:54:14 -0700124 static final boolean DEBUG = false;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700125
Svetoslav Ganov264c7a92016-08-24 17:31:14 -0700126 private static final boolean DROP_DATABASE_ON_MIGRATION = true;
Svetoslav683914b2015-01-15 14:22:26 -0800127
128 private static final String LOG_TAG = "SettingsProvider";
Christopher Tate0da13572013-10-13 17:34:49 -0700129
Christopher Tate06efb532012-08-24 15:29:27 -0700130 private static final String TABLE_SYSTEM = "system";
131 private static final String TABLE_SECURE = "secure";
132 private static final String TABLE_GLOBAL = "global";
Svetoslav683914b2015-01-15 14:22:26 -0800133
134 // Old tables no longer exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 private static final String TABLE_FAVORITES = "favorites";
136 private static final String TABLE_OLD_FAVORITES = "old_favorites";
Svetoslav683914b2015-01-15 14:22:26 -0800137 private static final String TABLE_BLUETOOTH_DEVICES = "bluetooth_devices";
138 private static final String TABLE_BOOKMARKS = "bookmarks";
139 private static final String TABLE_ANDROID_METADATA = "android_metadata";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140
Svetoslav683914b2015-01-15 14:22:26 -0800141 // The set of removed legacy tables.
142 private static final Set<String> REMOVED_LEGACY_TABLES = new ArraySet<>();
Christopher Tate06efb532012-08-24 15:29:27 -0700143 static {
Svetoslav683914b2015-01-15 14:22:26 -0800144 REMOVED_LEGACY_TABLES.add(TABLE_FAVORITES);
145 REMOVED_LEGACY_TABLES.add(TABLE_OLD_FAVORITES);
146 REMOVED_LEGACY_TABLES.add(TABLE_BLUETOOTH_DEVICES);
147 REMOVED_LEGACY_TABLES.add(TABLE_BOOKMARKS);
148 REMOVED_LEGACY_TABLES.add(TABLE_ANDROID_METADATA);
149 }
Christopher Tate06efb532012-08-24 15:29:27 -0700150
Svetoslav683914b2015-01-15 14:22:26 -0800151 private static final int MUTATION_OPERATION_INSERT = 1;
152 private static final int MUTATION_OPERATION_DELETE = 2;
153 private static final int MUTATION_OPERATION_UPDATE = 3;
Svetoslav Ganove080da92016-12-21 17:10:35 -0800154 private static final int MUTATION_OPERATION_RESET = 4;
Julia Reynolds5e458dd2014-07-07 16:07:01 -0400155
Svetoslav683914b2015-01-15 14:22:26 -0800156 private static final String[] ALL_COLUMNS = new String[] {
157 Settings.NameValueTable._ID,
158 Settings.NameValueTable.NAME,
159 Settings.NameValueTable.VALUE
160 };
161
Svet Ganov53a441c2016-04-19 19:38:00 -0700162 public static final int SETTINGS_TYPE_GLOBAL = 0;
163 public static final int SETTINGS_TYPE_SYSTEM = 1;
164 public static final int SETTINGS_TYPE_SECURE = 2;
Svetoslav683914b2015-01-15 14:22:26 -0800165
Svet Ganov53a441c2016-04-19 19:38:00 -0700166 public static final int SETTINGS_TYPE_MASK = 0xF0000000;
167 public static final int SETTINGS_TYPE_SHIFT = 28;
168
169 private static final Bundle NULL_SETTING_BUNDLE = Bundle.forPair(
170 Settings.NameValueTable.VALUE, null);
Christopher Tate06efb532012-08-24 15:29:27 -0700171
Svetoslav683914b2015-01-15 14:22:26 -0800172 // Per user secure settings that moved to the for all users global settings.
173 static final Set<String> sSecureMovedToGlobalSettings = new ArraySet<>();
174 static {
175 Settings.Secure.getMovedToGlobalSettings(sSecureMovedToGlobalSettings);
Christopher Tate06efb532012-08-24 15:29:27 -0700176 }
177
Svetoslav683914b2015-01-15 14:22:26 -0800178 // Per user system settings that moved to the for all users global settings.
179 static final Set<String> sSystemMovedToGlobalSettings = new ArraySet<>();
180 static {
181 Settings.System.getMovedToGlobalSettings(sSystemMovedToGlobalSettings);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700182 }
183
Svetoslav683914b2015-01-15 14:22:26 -0800184 // Per user system settings that moved to the per user secure settings.
185 static final Set<String> sSystemMovedToSecureSettings = new ArraySet<>();
186 static {
187 Settings.System.getMovedToSecureSettings(sSystemMovedToSecureSettings);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700188 }
189
Svetoslav683914b2015-01-15 14:22:26 -0800190 // Per all users global settings that moved to the per user secure settings.
191 static final Set<String> sGlobalMovedToSecureSettings = new ArraySet<>();
192 static {
193 Settings.Global.getMovedToSecureSettings(sGlobalMovedToSecureSettings);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700194 }
195
Svetoslav683914b2015-01-15 14:22:26 -0800196 // Per user secure settings that are cloned for the managed profiles of the user.
197 private static final Set<String> sSecureCloneToManagedSettings = new ArraySet<>();
198 static {
199 Settings.Secure.getCloneToManagedProfileSettings(sSecureCloneToManagedSettings);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700200 }
201
Svetoslav683914b2015-01-15 14:22:26 -0800202 // Per user system settings that are cloned for the managed profiles of the user.
203 private static final Set<String> sSystemCloneToManagedSettings = new ArraySet<>();
204 static {
205 Settings.System.getCloneToManagedProfileSettings(sSystemCloneToManagedSettings);
Julia Reynolds5e458dd2014-07-07 16:07:01 -0400206 }
207
Andre Lago3fa139c2016-08-04 13:53:44 +0100208 // Per user system settings that are cloned from the profile's parent when a dependency
209 // in {@link Settings.Secure} is set to "1".
210 public static final Map<String, String> sSystemCloneFromParentOnDependency = new ArrayMap<>();
211 static {
212 Settings.System.getCloneFromParentOnValueSettings(sSystemCloneFromParentOnDependency);
213 }
214
Svetoslav683914b2015-01-15 14:22:26 -0800215 private final Object mLock = new Object();
Brad Fitzpatrickf366a9b2010-08-24 16:14:07 -0700216
Svetoslav683914b2015-01-15 14:22:26 -0800217 @GuardedBy("mLock")
218 private SettingsRegistry mSettingsRegistry;
Brad Fitzpatrickf366a9b2010-08-24 16:14:07 -0700219
Svet Ganova8f90262016-05-10 08:44:48 -0700220 @GuardedBy("mLock")
221 private HandlerThread mHandlerThread;
222
Svetoslav7ec28e82015-05-20 17:01:10 -0700223 // We have to call in the user manager with no lock held,
224 private volatile UserManager mUserManager;
Svetoslav683914b2015-01-15 14:22:26 -0800225
Svetoslav7ec28e82015-05-20 17:01:10 -0700226 // We have to call in the package manager with no lock held,
Xiaohui Chen43765b72015-08-31 10:57:33 -0700227 private volatile IPackageManager mPackageManager;
Brad Fitzpatrickf366a9b2010-08-24 16:14:07 -0700228
Svet Ganov53a441c2016-04-19 19:38:00 -0700229 public static int makeKey(int type, int userId) {
230 return (type << SETTINGS_TYPE_SHIFT) | userId;
231 }
232
233 public static int getTypeFromKey(int key) {
234 return key >>> SETTINGS_TYPE_SHIFT;
235 }
236
237 public static int getUserIdFromKey(int key) {
238 return key & ~SETTINGS_TYPE_MASK;
239 }
240
241 public static String settingTypeToString(int type) {
242 switch (type) {
243 case SETTINGS_TYPE_GLOBAL: {
244 return "SETTINGS_GLOBAL";
245 }
246 case SETTINGS_TYPE_SECURE: {
247 return "SETTINGS_SECURE";
248 }
249 case SETTINGS_TYPE_SYSTEM: {
250 return "SETTINGS_SYSTEM";
251 }
252 default: {
253 return "UNKNOWN";
254 }
255 }
256 }
257
258 public static String keyToString(int key) {
259 return "Key[user=" + getUserIdFromKey(key) + ";type="
260 + settingTypeToString(getTypeFromKey(key)) + "]";
261 }
262
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700263 @Override
264 public boolean onCreate() {
Chad Brubaker97bccee2017-01-05 15:51:41 -0800265 Settings.setInSystemServer();
Svetoslav683914b2015-01-15 14:22:26 -0800266 synchronized (mLock) {
Xiaohui Chen43765b72015-08-31 10:57:33 -0700267 mUserManager = UserManager.get(getContext());
268 mPackageManager = AppGlobals.getPackageManager();
Svet Ganova8f90262016-05-10 08:44:48 -0700269 mHandlerThread = new HandlerThread(LOG_TAG,
270 Process.THREAD_PRIORITY_BACKGROUND);
271 mHandlerThread.start();
Svetoslav683914b2015-01-15 14:22:26 -0800272 mSettingsRegistry = new SettingsRegistry();
273 }
274 registerBroadcastReceivers();
Svet Ganov53a441c2016-04-19 19:38:00 -0700275 startWatchingUserRestrictionChanges();
Dianne Hackborn32f40ee2016-10-20 15:54:14 -0700276 ServiceManager.addService("settings", new SettingsService(this));
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700277 return true;
278 }
279
Svetoslav683914b2015-01-15 14:22:26 -0800280 @Override
281 public Bundle call(String method, String name, Bundle args) {
Svetoslav7ec28e82015-05-20 17:01:10 -0700282 final int requestingUserId = getRequestingUserId(args);
283 switch (method) {
284 case Settings.CALL_METHOD_GET_GLOBAL: {
285 Setting setting = getGlobalSetting(name);
Svet Ganov53a441c2016-04-19 19:38:00 -0700286 return packageValueForCallResult(setting, isTrackingGeneration(args));
Svetoslav683914b2015-01-15 14:22:26 -0800287 }
Svetoslav7ec28e82015-05-20 17:01:10 -0700288
289 case Settings.CALL_METHOD_GET_SECURE: {
290 Setting setting = getSecureSetting(name, requestingUserId);
Svet Ganov53a441c2016-04-19 19:38:00 -0700291 return packageValueForCallResult(setting, isTrackingGeneration(args));
Svetoslav7ec28e82015-05-20 17:01:10 -0700292 }
293
294 case Settings.CALL_METHOD_GET_SYSTEM: {
295 Setting setting = getSystemSetting(name, requestingUserId);
Svet Ganov53a441c2016-04-19 19:38:00 -0700296 return packageValueForCallResult(setting, isTrackingGeneration(args));
Svetoslav7ec28e82015-05-20 17:01:10 -0700297 }
298
299 case Settings.CALL_METHOD_PUT_GLOBAL: {
300 String value = getSettingValue(args);
Svetoslav Ganove080da92016-12-21 17:10:35 -0800301 String tag = getSettingTag(args);
302 final boolean makeDefault = getSettingMakeDefault(args);
303 insertGlobalSetting(name, value, tag, makeDefault, requestingUserId, false);
Svetoslav7ec28e82015-05-20 17:01:10 -0700304 break;
305 }
306
307 case Settings.CALL_METHOD_PUT_SECURE: {
308 String value = getSettingValue(args);
Svetoslav Ganove080da92016-12-21 17:10:35 -0800309 String tag = getSettingTag(args);
310 final boolean makeDefault = getSettingMakeDefault(args);
311 insertSecureSetting(name, value, tag, makeDefault, requestingUserId, false);
Svetoslav7ec28e82015-05-20 17:01:10 -0700312 break;
313 }
314
315 case Settings.CALL_METHOD_PUT_SYSTEM: {
316 String value = getSettingValue(args);
317 insertSystemSetting(name, value, requestingUserId);
318 break;
319 }
320
Svetoslav Ganove080da92016-12-21 17:10:35 -0800321 case Settings.CALL_METHOD_RESET_GLOBAL: {
322 final int mode = getResetModeEnforcingPermission(args);
323 String tag = getSettingTag(args);
324 resetGlobalSetting(requestingUserId, mode, tag);
325 break;
326 }
327
328 case Settings.CALL_METHOD_RESET_SECURE: {
329 final int mode = getResetModeEnforcingPermission(args);
330 String tag = getSettingTag(args);
331 resetSecureSetting(requestingUserId, mode, tag);
332 break;
333 }
334
Svetoslav7ec28e82015-05-20 17:01:10 -0700335 default: {
336 Slog.w(LOG_TAG, "call() with invalid method: " + method);
337 } break;
Christopher Tate06efb532012-08-24 15:29:27 -0700338 }
Svetoslav7ec28e82015-05-20 17:01:10 -0700339
Christopher Tate06efb532012-08-24 15:29:27 -0700340 return null;
341 }
342
Brad Fitzpatrick1877d012010-03-04 17:48:13 -0800343 @Override
Svetoslav683914b2015-01-15 14:22:26 -0800344 public String getType(Uri uri) {
345 Arguments args = new Arguments(uri, null, null, true);
346 if (TextUtils.isEmpty(args.name)) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700347 return "vnd.android.cursor.dir/" + args.table;
348 } else {
Svetoslav7ec28e82015-05-20 17:01:10 -0700349 return "vnd.android.cursor.item/" + args.table;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700350 }
351 }
352
353 @Override
Svetoslav683914b2015-01-15 14:22:26 -0800354 public Cursor query(Uri uri, String[] projection, String where, String[] whereArgs,
355 String order) {
356 if (DEBUG) {
357 Slog.v(LOG_TAG, "query() for user: " + UserHandle.getCallingUserId());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700358 }
359
Svetoslav683914b2015-01-15 14:22:26 -0800360 Arguments args = new Arguments(uri, where, whereArgs, true);
361 String[] normalizedProjection = normalizeProjection(projection);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700362
Svetoslav683914b2015-01-15 14:22:26 -0800363 // If a legacy table that is gone, done.
364 if (REMOVED_LEGACY_TABLES.contains(args.table)) {
365 return new MatrixCursor(normalizedProjection, 0);
366 }
Mike Lockwoodbd2a7122009-04-02 23:41:33 -0700367
Svetoslav7ec28e82015-05-20 17:01:10 -0700368 switch (args.table) {
369 case TABLE_GLOBAL: {
370 if (args.name != null) {
371 Setting setting = getGlobalSetting(args.name);
372 return packageSettingForQuery(setting, normalizedProjection);
373 } else {
374 return getAllGlobalSettings(projection);
Mike Lockwoodbd2a7122009-04-02 23:41:33 -0700375 }
Svetoslav7ec28e82015-05-20 17:01:10 -0700376 }
Mike Lockwoodbd2a7122009-04-02 23:41:33 -0700377
Svetoslav7ec28e82015-05-20 17:01:10 -0700378 case TABLE_SECURE: {
379 final int userId = UserHandle.getCallingUserId();
380 if (args.name != null) {
381 Setting setting = getSecureSetting(args.name, userId);
382 return packageSettingForQuery(setting, normalizedProjection);
383 } else {
384 return getAllSecureSettings(userId, projection);
Svetoslav683914b2015-01-15 14:22:26 -0800385 }
Svetoslav7ec28e82015-05-20 17:01:10 -0700386 }
Svetoslav683914b2015-01-15 14:22:26 -0800387
Svetoslav7ec28e82015-05-20 17:01:10 -0700388 case TABLE_SYSTEM: {
389 final int userId = UserHandle.getCallingUserId();
390 if (args.name != null) {
391 Setting setting = getSystemSetting(args.name, userId);
392 return packageSettingForQuery(setting, normalizedProjection);
393 } else {
394 return getAllSystemSettings(userId, projection);
Svetoslav683914b2015-01-15 14:22:26 -0800395 }
Svetoslav7ec28e82015-05-20 17:01:10 -0700396 }
Svetoslav683914b2015-01-15 14:22:26 -0800397
Svetoslav7ec28e82015-05-20 17:01:10 -0700398 default: {
399 throw new IllegalArgumentException("Invalid Uri path:" + uri);
Mike Lockwoodbd2a7122009-04-02 23:41:33 -0700400 }
401 }
Mike Lockwoodbd2a7122009-04-02 23:41:33 -0700402 }
403
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700404 @Override
Svetoslav683914b2015-01-15 14:22:26 -0800405 public Uri insert(Uri uri, ContentValues values) {
406 if (DEBUG) {
407 Slog.v(LOG_TAG, "insert() for user: " + UserHandle.getCallingUserId());
Christopher Tate06efb532012-08-24 15:29:27 -0700408 }
409
Svetoslav683914b2015-01-15 14:22:26 -0800410 String table = getValidTableOrThrow(uri);
Christopher Tate06efb532012-08-24 15:29:27 -0700411
Svetoslav683914b2015-01-15 14:22:26 -0800412 // If a legacy table that is gone, done.
413 if (REMOVED_LEGACY_TABLES.contains(table)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 return null;
415 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700416
Svetoslav683914b2015-01-15 14:22:26 -0800417 String name = values.getAsString(Settings.Secure.NAME);
Makoto Onuki3a2c35782015-06-18 11:21:58 -0700418 if (!isKeyValid(name)) {
Svetoslav683914b2015-01-15 14:22:26 -0800419 return null;
Mike Lockwoodbd2a7122009-04-02 23:41:33 -0700420 }
421
Svetoslav683914b2015-01-15 14:22:26 -0800422 String value = values.getAsString(Settings.Secure.VALUE);
423
Svetoslav7ec28e82015-05-20 17:01:10 -0700424 switch (table) {
425 case TABLE_GLOBAL: {
Svetoslav Ganove080da92016-12-21 17:10:35 -0800426 if (insertGlobalSetting(name, value, null, false,
427 UserHandle.getCallingUserId(), false)) {
Svetoslav7ec28e82015-05-20 17:01:10 -0700428 return Uri.withAppendedPath(Settings.Global.CONTENT_URI, name);
Christopher Tatec221d2b2012-10-03 18:33:52 -0700429 }
Svetoslav7ec28e82015-05-20 17:01:10 -0700430 } break;
431
432 case TABLE_SECURE: {
Svetoslav Ganove080da92016-12-21 17:10:35 -0800433 if (insertSecureSetting(name, value, null, false,
434 UserHandle.getCallingUserId(), false)) {
Svetoslav7ec28e82015-05-20 17:01:10 -0700435 return Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name);
436 }
437 } break;
438
439 case TABLE_SYSTEM: {
440 if (insertSystemSetting(name, value, UserHandle.getCallingUserId())) {
441 return Uri.withAppendedPath(Settings.System.CONTENT_URI, name);
442 }
443 } break;
444
445 default: {
446 throw new IllegalArgumentException("Bad Uri path:" + uri);
Christopher Tatec221d2b2012-10-03 18:33:52 -0700447 }
448 }
449
Svetoslav683914b2015-01-15 14:22:26 -0800450 return null;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700451 }
452
453 @Override
Svetoslav683914b2015-01-15 14:22:26 -0800454 public int bulkInsert(Uri uri, ContentValues[] allValues) {
455 if (DEBUG) {
456 Slog.v(LOG_TAG, "bulkInsert() for user: " + UserHandle.getCallingUserId());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700458
Svetoslav683914b2015-01-15 14:22:26 -0800459 int insertionCount = 0;
460 final int valuesCount = allValues.length;
461 for (int i = 0; i < valuesCount; i++) {
462 ContentValues values = allValues[i];
463 if (insert(uri, values) != null) {
464 insertionCount++;
465 }
Dianne Hackborn8d051722014-10-01 14:59:58 -0700466 }
Svetoslav683914b2015-01-15 14:22:26 -0800467
468 return insertionCount;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700469 }
470
471 @Override
Svetoslav683914b2015-01-15 14:22:26 -0800472 public int delete(Uri uri, String where, String[] whereArgs) {
473 if (DEBUG) {
474 Slog.v(LOG_TAG, "delete() for user: " + UserHandle.getCallingUserId());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700476
Svetoslav683914b2015-01-15 14:22:26 -0800477 Arguments args = new Arguments(uri, where, whereArgs, false);
478
479 // If a legacy table that is gone, done.
480 if (REMOVED_LEGACY_TABLES.contains(args.table)) {
481 return 0;
Dianne Hackborn8d051722014-10-01 14:59:58 -0700482 }
Svetoslav683914b2015-01-15 14:22:26 -0800483
Makoto Onuki3a2c35782015-06-18 11:21:58 -0700484 if (!isKeyValid(args.name)) {
Svetoslav683914b2015-01-15 14:22:26 -0800485 return 0;
Dianne Hackborn8d051722014-10-01 14:59:58 -0700486 }
Svetoslav683914b2015-01-15 14:22:26 -0800487
Svetoslav7ec28e82015-05-20 17:01:10 -0700488 switch (args.table) {
489 case TABLE_GLOBAL: {
490 final int userId = UserHandle.getCallingUserId();
Svet Ganov53a441c2016-04-19 19:38:00 -0700491 return deleteGlobalSetting(args.name, userId, false) ? 1 : 0;
Svetoslav7ec28e82015-05-20 17:01:10 -0700492 }
Svetoslav683914b2015-01-15 14:22:26 -0800493
Svetoslav7ec28e82015-05-20 17:01:10 -0700494 case TABLE_SECURE: {
495 final int userId = UserHandle.getCallingUserId();
Svet Ganov53a441c2016-04-19 19:38:00 -0700496 return deleteSecureSetting(args.name, userId, false) ? 1 : 0;
Svetoslav7ec28e82015-05-20 17:01:10 -0700497 }
Svetoslav683914b2015-01-15 14:22:26 -0800498
Svetoslav7ec28e82015-05-20 17:01:10 -0700499 case TABLE_SYSTEM: {
500 final int userId = UserHandle.getCallingUserId();
501 return deleteSystemSetting(args.name, userId) ? 1 : 0;
502 }
503
504 default: {
505 throw new IllegalArgumentException("Bad Uri path:" + uri);
Svetoslav683914b2015-01-15 14:22:26 -0800506 }
Dianne Hackborn8d051722014-10-01 14:59:58 -0700507 }
Svetoslav683914b2015-01-15 14:22:26 -0800508 }
509
510 @Override
511 public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
512 if (DEBUG) {
513 Slog.v(LOG_TAG, "update() for user: " + UserHandle.getCallingUserId());
Christopher Tate06efb532012-08-24 15:29:27 -0700514 }
Svetoslav683914b2015-01-15 14:22:26 -0800515
516 Arguments args = new Arguments(uri, where, whereArgs, false);
517
518 // If a legacy table that is gone, done.
519 if (REMOVED_LEGACY_TABLES.contains(args.table)) {
520 return 0;
521 }
522
Makoto Onuki3a2c35782015-06-18 11:21:58 -0700523 String name = values.getAsString(Settings.Secure.NAME);
524 if (!isKeyValid(name)) {
Svetoslav683914b2015-01-15 14:22:26 -0800525 return 0;
526 }
Makoto Onuki3a2c35782015-06-18 11:21:58 -0700527 String value = values.getAsString(Settings.Secure.VALUE);
Svetoslav683914b2015-01-15 14:22:26 -0800528
Svetoslav7ec28e82015-05-20 17:01:10 -0700529 switch (args.table) {
530 case TABLE_GLOBAL: {
531 final int userId = UserHandle.getCallingUserId();
Svetoslav Ganove080da92016-12-21 17:10:35 -0800532 return updateGlobalSetting(args.name, value, null, false,
533 userId, false) ? 1 : 0;
Svetoslav7ec28e82015-05-20 17:01:10 -0700534 }
Svetoslav683914b2015-01-15 14:22:26 -0800535
Svetoslav7ec28e82015-05-20 17:01:10 -0700536 case TABLE_SECURE: {
537 final int userId = UserHandle.getCallingUserId();
Svetoslav Ganove080da92016-12-21 17:10:35 -0800538 return updateSecureSetting(args.name, value, null, false,
539 userId, false) ? 1 : 0;
Svetoslav7ec28e82015-05-20 17:01:10 -0700540 }
Svetoslav683914b2015-01-15 14:22:26 -0800541
Svetoslav7ec28e82015-05-20 17:01:10 -0700542 case TABLE_SYSTEM: {
543 final int userId = UserHandle.getCallingUserId();
544 return updateSystemSetting(args.name, value, userId) ? 1 : 0;
545 }
Svetoslav683914b2015-01-15 14:22:26 -0800546
Svetoslav7ec28e82015-05-20 17:01:10 -0700547 default: {
548 throw new IllegalArgumentException("Invalid Uri path:" + uri);
Svetoslav683914b2015-01-15 14:22:26 -0800549 }
550 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700551 }
552
553 @Override
554 public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
Robin Lee2ab02e22016-07-28 18:41:23 +0100555 final int userId = getUserIdFromUri(uri, UserHandle.getCallingUserId());
556 if (userId != UserHandle.getCallingUserId()) {
557 getContext().enforceCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS,
558 "Access files from the settings of another user");
559 }
560 uri = ContentProvider.getUriWithoutUserId(uri);
561
Andre Lago3fa139c2016-08-04 13:53:44 +0100562 final String cacheRingtoneSetting;
Jeff Sharkey413573a2016-02-22 17:52:45 -0700563 final String cacheName;
564 if (Settings.System.RINGTONE_CACHE_URI.equals(uri)) {
Andre Lago3fa139c2016-08-04 13:53:44 +0100565 cacheRingtoneSetting = Settings.System.RINGTONE;
Jeff Sharkey413573a2016-02-22 17:52:45 -0700566 cacheName = Settings.System.RINGTONE_CACHE;
567 } else if (Settings.System.NOTIFICATION_SOUND_CACHE_URI.equals(uri)) {
Andre Lago3fa139c2016-08-04 13:53:44 +0100568 cacheRingtoneSetting = Settings.System.NOTIFICATION_SOUND;
Jeff Sharkey413573a2016-02-22 17:52:45 -0700569 cacheName = Settings.System.NOTIFICATION_SOUND_CACHE;
570 } else if (Settings.System.ALARM_ALERT_CACHE_URI.equals(uri)) {
Andre Lago3fa139c2016-08-04 13:53:44 +0100571 cacheRingtoneSetting = Settings.System.ALARM_ALERT;
Jeff Sharkey413573a2016-02-22 17:52:45 -0700572 cacheName = Settings.System.ALARM_ALERT_CACHE;
573 } else {
574 throw new FileNotFoundException("Direct file access no longer supported; "
575 + "ringtone playback is available through android.media.Ringtone");
576 }
577
Andre Lago3fa139c2016-08-04 13:53:44 +0100578 int actualCacheOwner;
579 // Redirect cache to parent if ringtone setting is owned by profile parent
580 synchronized (mLock) {
581 actualCacheOwner = resolveOwningUserIdForSystemSettingLocked(userId,
582 cacheRingtoneSetting);
583 }
584 final File cacheFile = new File(getRingtoneCacheDir(actualCacheOwner), cacheName);
Jeff Sharkey413573a2016-02-22 17:52:45 -0700585 return ParcelFileDescriptor.open(cacheFile, ParcelFileDescriptor.parseMode(mode));
586 }
587
588 private File getRingtoneCacheDir(int userId) {
589 final File cacheDir = new File(Environment.getDataSystemDeDirectory(userId), "ringtones");
590 cacheDir.mkdir();
591 SELinux.restorecon(cacheDir);
592 return cacheDir;
Marco Nelissen69f593c2009-07-28 09:55:04 -0700593 }
Brad Fitzpatrick1bd62bd2010-03-08 18:30:52 -0800594
Dianne Hackborn32f40ee2016-10-20 15:54:14 -0700595 public void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
Svetoslavb505ccc2015-02-17 12:41:04 -0800596 synchronized (mLock) {
597 final long identity = Binder.clearCallingIdentity();
598 try {
Dianne Hackborn32f40ee2016-10-20 15:54:14 -0700599 SparseBooleanArray users = mSettingsRegistry.getKnownUsersLocked();
Svetoslavb505ccc2015-02-17 12:41:04 -0800600 final int userCount = users.size();
601 for (int i = 0; i < userCount; i++) {
Dianne Hackborn32f40ee2016-10-20 15:54:14 -0700602 dumpForUserLocked(users.keyAt(i), pw);
Svetoslavb505ccc2015-02-17 12:41:04 -0800603 }
604 } finally {
605 Binder.restoreCallingIdentity(identity);
606 }
607 }
608 }
609
Svetoslav Ganova340bfd2016-08-02 18:24:49 -0700610 private void dumpForUserLocked(int userId, PrintWriter pw) {
Xiaohui Chen43765b72015-08-31 10:57:33 -0700611 if (userId == UserHandle.USER_SYSTEM) {
Svetoslavb505ccc2015-02-17 12:41:04 -0800612 pw.println("GLOBAL SETTINGS (user " + userId + ")");
Svetoslav Ganova340bfd2016-08-02 18:24:49 -0700613 SettingsState globalSettings = mSettingsRegistry.getSettingsLocked(
614 SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
Dianne Hackborn32f40ee2016-10-20 15:54:14 -0700615 if (globalSettings != null) {
616 dumpSettingsLocked(globalSettings, pw);
Svetoslav Ganove080da92016-12-21 17:10:35 -0800617 pw.println();
618 globalSettings.dumpHistoricalOperations(pw);
Dianne Hackborn32f40ee2016-10-20 15:54:14 -0700619 }
Svetoslavb505ccc2015-02-17 12:41:04 -0800620 }
621
622 pw.println("SECURE SETTINGS (user " + userId + ")");
Svetoslav Ganova340bfd2016-08-02 18:24:49 -0700623 SettingsState secureSettings = mSettingsRegistry.getSettingsLocked(
624 SETTINGS_TYPE_SECURE, userId);
Dianne Hackborn32f40ee2016-10-20 15:54:14 -0700625 if (secureSettings != null) {
626 dumpSettingsLocked(secureSettings, pw);
Svetoslav Ganove080da92016-12-21 17:10:35 -0800627 pw.println();
628 secureSettings.dumpHistoricalOperations(pw);
Dianne Hackborn32f40ee2016-10-20 15:54:14 -0700629 }
Svetoslav Ganova340bfd2016-08-02 18:24:49 -0700630
Svetoslavb505ccc2015-02-17 12:41:04 -0800631 pw.println("SYSTEM SETTINGS (user " + userId + ")");
Svetoslav Ganova340bfd2016-08-02 18:24:49 -0700632 SettingsState systemSettings = mSettingsRegistry.getSettingsLocked(
633 SETTINGS_TYPE_SYSTEM, userId);
Dianne Hackborn32f40ee2016-10-20 15:54:14 -0700634 if (systemSettings != null) {
635 dumpSettingsLocked(systemSettings, pw);
Svetoslav Ganove080da92016-12-21 17:10:35 -0800636 pw.println();
637 systemSettings.dumpHistoricalOperations(pw);
Dianne Hackborn32f40ee2016-10-20 15:54:14 -0700638 }
Svetoslavb505ccc2015-02-17 12:41:04 -0800639 }
640
Dianne Hackborn32f40ee2016-10-20 15:54:14 -0700641 private void dumpSettingsLocked(SettingsState settingsState, PrintWriter pw) {
642 List<String> names = settingsState.getSettingNamesLocked();
Svetoslavb505ccc2015-02-17 12:41:04 -0800643
Dianne Hackborn32f40ee2016-10-20 15:54:14 -0700644 final int nameCount = names.size();
Svetoslavb505ccc2015-02-17 12:41:04 -0800645
Dianne Hackborn32f40ee2016-10-20 15:54:14 -0700646 for (int i = 0; i < nameCount; i++) {
647 String name = names.get(i);
648 Setting setting = settingsState.getSettingLocked(name);
649 pw.print("_id:"); pw.print(toDumpString(setting.getId()));
650 pw.print(" name:"); pw.print(toDumpString(name));
651 if (setting.getPackageName() != null) {
Svetoslav Ganove080da92016-12-21 17:10:35 -0800652 pw.print(" pkg:"); pw.print(setting.getPackageName());
Dianne Hackborn32f40ee2016-10-20 15:54:14 -0700653 }
654 pw.print(" value:"); pw.print(toDumpString(setting.getValue()));
Svetoslav Ganove080da92016-12-21 17:10:35 -0800655 if (setting.getDefaultValue() != null) {
656 pw.print(" default:"); pw.print(setting.getDefaultValue());
657 pw.print(" defaultSystemSet:"); pw.print(setting.isDefaultSystemSet());
658 }
659 if (setting.getTag() != null) {
660 pw.print(" tag:"); pw.print(setting.getTag());
661 }
Svetoslavb505ccc2015-02-17 12:41:04 -0800662 pw.println();
Dianne Hackborn32f40ee2016-10-20 15:54:14 -0700663 }
Svetoslavb505ccc2015-02-17 12:41:04 -0800664 }
665
Svetoslav7e0683b2015-08-03 16:02:52 -0700666 private static String toDumpString(String s) {
Makoto Onuki3a2c35782015-06-18 11:21:58 -0700667 if (s != null) {
668 return s;
669 }
670 return "{null}";
671 }
672
Svetoslav683914b2015-01-15 14:22:26 -0800673 private void registerBroadcastReceivers() {
674 IntentFilter userFilter = new IntentFilter();
675 userFilter.addAction(Intent.ACTION_USER_REMOVED);
676 userFilter.addAction(Intent.ACTION_USER_STOPPED);
677
678 getContext().registerReceiver(new BroadcastReceiver() {
679 @Override
680 public void onReceive(Context context, Intent intent) {
681 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
Xiaohui Chen43765b72015-08-31 10:57:33 -0700682 UserHandle.USER_SYSTEM);
Svetoslav683914b2015-01-15 14:22:26 -0800683
684 switch (intent.getAction()) {
685 case Intent.ACTION_USER_REMOVED: {
Svet Ganov53a441c2016-04-19 19:38:00 -0700686 synchronized (mLock) {
687 mSettingsRegistry.removeUserStateLocked(userId, true);
688 }
Svetoslav683914b2015-01-15 14:22:26 -0800689 } break;
690
691 case Intent.ACTION_USER_STOPPED: {
Svet Ganov53a441c2016-04-19 19:38:00 -0700692 synchronized (mLock) {
693 mSettingsRegistry.removeUserStateLocked(userId, false);
694 }
Svetoslav683914b2015-01-15 14:22:26 -0800695 } break;
696 }
697 }
698 }, userFilter);
699
700 PackageMonitor monitor = new PackageMonitor() {
701 @Override
702 public void onPackageRemoved(String packageName, int uid) {
703 synchronized (mLock) {
704 mSettingsRegistry.onPackageRemovedLocked(packageName,
705 UserHandle.getUserId(uid));
706 }
707 }
708 };
709
710 // package changes
711 monitor.register(getContext(), BackgroundThread.getHandler().getLooper(),
712 UserHandle.ALL, true);
713 }
714
Svet Ganov53a441c2016-04-19 19:38:00 -0700715 private void startWatchingUserRestrictionChanges() {
716 // TODO: The current design of settings looking different based on user restrictions
717 // should be reworked to keep them separate and system code should check the setting
718 // first followed by checking the user restriction before performing an operation.
719 UserManagerInternal userManager = LocalServices.getService(UserManagerInternal.class);
720 userManager.addUserRestrictionsListener((int userId, Bundle newRestrictions,
721 Bundle prevRestrictions) -> {
722 // We are changing the settings affected by restrictions to their current
723 // value with a forced update to ensure that all cross profile dependencies
724 // are taken into account. Also make sure the settings update to.. the same
725 // value passes the security checks, so clear binder calling id.
Svetoslav Ganove080da92016-12-21 17:10:35 -0800726 if (newRestrictions.getBoolean(UserManager.DISALLOW_SHARE_LOCATION)
727 != prevRestrictions.getBoolean(UserManager.DISALLOW_SHARE_LOCATION)) {
Svet Ganov53a441c2016-04-19 19:38:00 -0700728 final long identity = Binder.clearCallingIdentity();
729 try {
730 synchronized (mLock) {
731 Setting setting = getSecureSetting(
732 Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
733 updateSecureSetting(Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
Svetoslav Ganove080da92016-12-21 17:10:35 -0800734 setting != null ? setting.getValue() : null, null,
735 true, userId, true);
Svet Ganov53a441c2016-04-19 19:38:00 -0700736 }
737 } finally {
738 Binder.restoreCallingIdentity(identity);
739 }
740 }
Svetoslav Ganove080da92016-12-21 17:10:35 -0800741 if (newRestrictions.getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)
742 != prevRestrictions.getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)) {
Svet Ganov53a441c2016-04-19 19:38:00 -0700743 final long identity = Binder.clearCallingIdentity();
744 try {
745 synchronized (mLock) {
746 Setting setting = getGlobalSetting(Settings.Global.INSTALL_NON_MARKET_APPS);
Svetoslav Ganove080da92016-12-21 17:10:35 -0800747 String value = setting != null ? setting.getValue() : null;
Svet Ganov53a441c2016-04-19 19:38:00 -0700748 updateGlobalSetting(Settings.Global.INSTALL_NON_MARKET_APPS,
Svetoslav Ganove080da92016-12-21 17:10:35 -0800749 value, null, true, userId, true);
Svet Ganov53a441c2016-04-19 19:38:00 -0700750 }
751 } finally {
752 Binder.restoreCallingIdentity(identity);
753 }
754 }
Svetoslav Ganove080da92016-12-21 17:10:35 -0800755 if (newRestrictions.getBoolean(UserManager.DISALLOW_DEBUGGING_FEATURES)
756 != prevRestrictions.getBoolean(UserManager.DISALLOW_DEBUGGING_FEATURES)) {
Svet Ganov53a441c2016-04-19 19:38:00 -0700757 final long identity = Binder.clearCallingIdentity();
758 try {
759 synchronized (mLock) {
760 Setting setting = getGlobalSetting(Settings.Global.ADB_ENABLED);
Svetoslav Ganove080da92016-12-21 17:10:35 -0800761 String value = setting != null ? setting.getValue() : null;
Svet Ganov53a441c2016-04-19 19:38:00 -0700762 updateGlobalSetting(Settings.Global.ADB_ENABLED,
Svetoslav Ganove080da92016-12-21 17:10:35 -0800763 value, null, true, userId, true);
Svet Ganov53a441c2016-04-19 19:38:00 -0700764 }
765 } finally {
766 Binder.restoreCallingIdentity(identity);
767 }
768 }
Svetoslav Ganove080da92016-12-21 17:10:35 -0800769 if (newRestrictions.getBoolean(UserManager.ENSURE_VERIFY_APPS)
770 != prevRestrictions.getBoolean(UserManager.ENSURE_VERIFY_APPS)) {
Svet Ganov53a441c2016-04-19 19:38:00 -0700771 final long identity = Binder.clearCallingIdentity();
772 try {
773 synchronized (mLock) {
774 Setting enable = getGlobalSetting(
775 Settings.Global.PACKAGE_VERIFIER_ENABLE);
Svetoslav Ganove080da92016-12-21 17:10:35 -0800776 String enableValue = enable != null ? enable.getValue() : null;
Svet Ganov53a441c2016-04-19 19:38:00 -0700777 updateGlobalSetting(Settings.Global.PACKAGE_VERIFIER_ENABLE,
Svetoslav Ganove080da92016-12-21 17:10:35 -0800778 enableValue, null, true, userId, true);
Svet Ganov53a441c2016-04-19 19:38:00 -0700779 Setting include = getGlobalSetting(
780 Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB);
Svetoslav Ganove080da92016-12-21 17:10:35 -0800781 String includeValue = include != null ? include.getValue() : null;
Svet Ganov53a441c2016-04-19 19:38:00 -0700782 updateGlobalSetting(Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB,
Svetoslav Ganove080da92016-12-21 17:10:35 -0800783 includeValue, null, true, userId, true);
Svet Ganov53a441c2016-04-19 19:38:00 -0700784 }
785 } finally {
786 Binder.restoreCallingIdentity(identity);
787 }
788 }
Svetoslav Ganove080da92016-12-21 17:10:35 -0800789 if (newRestrictions.getBoolean(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)
790 != prevRestrictions.getBoolean(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
Svet Ganov53a441c2016-04-19 19:38:00 -0700791 final long identity = Binder.clearCallingIdentity();
792 try {
793 synchronized (mLock) {
794 Setting setting = getGlobalSetting(
795 Settings.Global.PREFERRED_NETWORK_MODE);
Svetoslav Ganove080da92016-12-21 17:10:35 -0800796 String value = setting != null ? setting.getValue() : null;
Svet Ganov53a441c2016-04-19 19:38:00 -0700797 updateGlobalSetting(Settings.Global.PREFERRED_NETWORK_MODE,
Svetoslav Ganove080da92016-12-21 17:10:35 -0800798 value, null, true, userId, true);
Svet Ganov53a441c2016-04-19 19:38:00 -0700799 }
800 } finally {
801 Binder.restoreCallingIdentity(identity);
802 }
803 }
804 });
805 }
806
Svetoslav7ec28e82015-05-20 17:01:10 -0700807 private Cursor getAllGlobalSettings(String[] projection) {
Svetoslav683914b2015-01-15 14:22:26 -0800808 if (DEBUG) {
Svetoslav7ec28e82015-05-20 17:01:10 -0700809 Slog.v(LOG_TAG, "getAllGlobalSettings()");
Svetoslav683914b2015-01-15 14:22:26 -0800810 }
811
Svetoslav7ec28e82015-05-20 17:01:10 -0700812 synchronized (mLock) {
813 // Get the settings.
814 SettingsState settingsState = mSettingsRegistry.getSettingsLocked(
Svet Ganov53a441c2016-04-19 19:38:00 -0700815 SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
Svetoslav683914b2015-01-15 14:22:26 -0800816
Chad Brubaker97bccee2017-01-05 15:51:41 -0800817 List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_GLOBAL,
818 UserHandle.USER_SYSTEM);
Svetoslav683914b2015-01-15 14:22:26 -0800819
Svetoslav7ec28e82015-05-20 17:01:10 -0700820 final int nameCount = names.size();
Svetoslav683914b2015-01-15 14:22:26 -0800821
Svetoslav7ec28e82015-05-20 17:01:10 -0700822 String[] normalizedProjection = normalizeProjection(projection);
823 MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount);
Svetoslav683914b2015-01-15 14:22:26 -0800824
Svetoslav7ec28e82015-05-20 17:01:10 -0700825 // Anyone can get the global settings, so no security checks.
826 for (int i = 0; i < nameCount; i++) {
827 String name = names.get(i);
828 Setting setting = settingsState.getSettingLocked(name);
829 appendSettingToCursor(result, setting);
830 }
831
832 return result;
Svetoslav683914b2015-01-15 14:22:26 -0800833 }
Svetoslav683914b2015-01-15 14:22:26 -0800834 }
835
Svetoslav7ec28e82015-05-20 17:01:10 -0700836 private Setting getGlobalSetting(String name) {
Svetoslav683914b2015-01-15 14:22:26 -0800837 if (DEBUG) {
838 Slog.v(LOG_TAG, "getGlobalSetting(" + name + ")");
839 }
840
Chad Brubaker97bccee2017-01-05 15:51:41 -0800841 // Ensure the caller can access the setting.
842 enforceSettingReadable(name, SETTINGS_TYPE_GLOBAL, UserHandle.getCallingUserId());
843
Svetoslav683914b2015-01-15 14:22:26 -0800844 // Get the value.
Svetoslav7ec28e82015-05-20 17:01:10 -0700845 synchronized (mLock) {
Svet Ganov53a441c2016-04-19 19:38:00 -0700846 return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_GLOBAL,
Xiaohui Chen43765b72015-08-31 10:57:33 -0700847 UserHandle.USER_SYSTEM, name);
Svetoslav683914b2015-01-15 14:22:26 -0800848 }
Svetoslav683914b2015-01-15 14:22:26 -0800849 }
850
Svetoslav Ganove080da92016-12-21 17:10:35 -0800851 private boolean updateGlobalSetting(String name, String value, String tag,
852 boolean makeDefault, int requestingUserId, boolean forceNotify) {
Svetoslav683914b2015-01-15 14:22:26 -0800853 if (DEBUG) {
Svetoslav Ganove080da92016-12-21 17:10:35 -0800854 Slog.v(LOG_TAG, "updateGlobalSetting(" + name + ", " + value + ", "
855 + ", " + tag + ", " + makeDefault + ", " + requestingUserId
856 + ", " + forceNotify + ")");
Svetoslav683914b2015-01-15 14:22:26 -0800857 }
Svetoslav Ganove080da92016-12-21 17:10:35 -0800858 return mutateGlobalSetting(name, value, tag, makeDefault, requestingUserId,
859 MUTATION_OPERATION_UPDATE, forceNotify, 0);
Svetoslav683914b2015-01-15 14:22:26 -0800860 }
861
Svetoslav Ganove080da92016-12-21 17:10:35 -0800862 private boolean insertGlobalSetting(String name, String value, String tag,
863 boolean makeDefault, int requestingUserId, boolean forceNotify) {
Svetoslav7ec28e82015-05-20 17:01:10 -0700864 if (DEBUG) {
Svetoslav Ganove080da92016-12-21 17:10:35 -0800865 Slog.v(LOG_TAG, "insertGlobalSetting(" + name + ", " + value + ", "
866 + ", " + tag + ", " + makeDefault + ", " + requestingUserId
867 + ", " + forceNotify + ")");
Svetoslav7ec28e82015-05-20 17:01:10 -0700868 }
Svetoslav Ganove080da92016-12-21 17:10:35 -0800869 return mutateGlobalSetting(name, value, tag, makeDefault, requestingUserId,
870 MUTATION_OPERATION_INSERT, forceNotify, 0);
Svetoslav7ec28e82015-05-20 17:01:10 -0700871 }
872
Svet Ganov53a441c2016-04-19 19:38:00 -0700873 private boolean deleteGlobalSetting(String name, int requestingUserId, boolean forceNotify) {
Svetoslav683914b2015-01-15 14:22:26 -0800874 if (DEBUG) {
Svetoslav Ganove080da92016-12-21 17:10:35 -0800875 Slog.v(LOG_TAG, "deleteGlobalSetting(" + name + ", " + requestingUserId
876 + ", " + forceNotify + ")");
Svetoslav683914b2015-01-15 14:22:26 -0800877 }
Svetoslav Ganove080da92016-12-21 17:10:35 -0800878 return mutateGlobalSetting(name, null, null, false, requestingUserId,
879 MUTATION_OPERATION_DELETE, forceNotify, 0);
Svetoslav683914b2015-01-15 14:22:26 -0800880 }
881
Svetoslav Ganove080da92016-12-21 17:10:35 -0800882 private void resetGlobalSetting(int requestingUserId, int mode, String tag) {
883 if (DEBUG) {
884 Slog.v(LOG_TAG, "resetGlobalSetting(" + requestingUserId + ", "
885 + mode + ", " + tag + ")");
886 }
887 mutateGlobalSetting(null, null, tag, false, requestingUserId,
888 MUTATION_OPERATION_RESET, false, mode);
889 }
890
891 private boolean mutateGlobalSetting(String name, String value, String tag,
892 boolean makeDefault, int requestingUserId, int operation, boolean forceNotify,
893 int mode) {
Svetoslav683914b2015-01-15 14:22:26 -0800894 // Make sure the caller can change the settings - treated as secure.
895 enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
896
Svetoslav683914b2015-01-15 14:22:26 -0800897 // Resolve the userId on whose behalf the call is made.
898 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
899
Makoto Onuki28da2e32015-11-20 11:30:44 -0800900 // If this is a setting that is currently restricted for this user, do not allow
901 // unrestricting changes.
Svetoslav Ganove080da92016-12-21 17:10:35 -0800902 if (name != null && isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value,
Victor Chang9c7b7062016-07-12 23:47:29 +0100903 Binder.getCallingUid())) {
Svetoslav683914b2015-01-15 14:22:26 -0800904 return false;
905 }
906
907 // Perform the mutation.
Svetoslav7ec28e82015-05-20 17:01:10 -0700908 synchronized (mLock) {
909 switch (operation) {
910 case MUTATION_OPERATION_INSERT: {
Svetoslav Ganove080da92016-12-21 17:10:35 -0800911 return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_GLOBAL,
912 UserHandle.USER_SYSTEM, name, value, tag, makeDefault,
913 getCallingPackage(), forceNotify);
Svetoslav7ec28e82015-05-20 17:01:10 -0700914 }
Svetoslav683914b2015-01-15 14:22:26 -0800915
Svetoslav7ec28e82015-05-20 17:01:10 -0700916 case MUTATION_OPERATION_DELETE: {
Svet Ganov53a441c2016-04-19 19:38:00 -0700917 return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_GLOBAL,
918 UserHandle.USER_SYSTEM, name, forceNotify);
Svetoslav7ec28e82015-05-20 17:01:10 -0700919 }
Svetoslav683914b2015-01-15 14:22:26 -0800920
Svetoslav7ec28e82015-05-20 17:01:10 -0700921 case MUTATION_OPERATION_UPDATE: {
Svetoslav Ganove080da92016-12-21 17:10:35 -0800922 return mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_GLOBAL,
923 UserHandle.USER_SYSTEM, name, value, tag, makeDefault,
924 getCallingPackage(), forceNotify);
Svetoslav7ec28e82015-05-20 17:01:10 -0700925 }
Svetoslav Ganove080da92016-12-21 17:10:35 -0800926
927 case MUTATION_OPERATION_RESET: {
928 mSettingsRegistry.resetSettingsLocked(SETTINGS_TYPE_GLOBAL,
929 UserHandle.USER_SYSTEM, getCallingPackage(), mode, tag);
930 } return true;
Svetoslav683914b2015-01-15 14:22:26 -0800931 }
932 }
933
934 return false;
935 }
936
Svetoslav7ec28e82015-05-20 17:01:10 -0700937 private Cursor getAllSecureSettings(int userId, String[] projection) {
Svetoslav683914b2015-01-15 14:22:26 -0800938 if (DEBUG) {
939 Slog.v(LOG_TAG, "getAllSecureSettings(" + userId + ")");
940 }
941
942 // Resolve the userId on whose behalf the call is made.
943 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId);
944
Svetoslav7ec28e82015-05-20 17:01:10 -0700945 synchronized (mLock) {
Chad Brubaker97bccee2017-01-05 15:51:41 -0800946 List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_SECURE, callingUserId);
Svetoslav683914b2015-01-15 14:22:26 -0800947
Svetoslav7ec28e82015-05-20 17:01:10 -0700948 final int nameCount = names.size();
Svetoslav683914b2015-01-15 14:22:26 -0800949
Svetoslav7ec28e82015-05-20 17:01:10 -0700950 String[] normalizedProjection = normalizeProjection(projection);
951 MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount);
Svetoslav683914b2015-01-15 14:22:26 -0800952
Svetoslav7ec28e82015-05-20 17:01:10 -0700953 for (int i = 0; i < nameCount; i++) {
954 String name = names.get(i);
955 // Determine the owning user as some profile settings are cloned from the parent.
956 final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId,
957 name);
Svetoslav683914b2015-01-15 14:22:26 -0800958
Svetoslav7ec28e82015-05-20 17:01:10 -0700959 // Special case for location (sigh).
960 if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) {
Svetoslav Ganov83a1f7f2016-04-27 13:50:49 -0700961 continue;
Svetoslav7ec28e82015-05-20 17:01:10 -0700962 }
Svetoslav683914b2015-01-15 14:22:26 -0800963
Svetoslav7ec28e82015-05-20 17:01:10 -0700964 Setting setting = mSettingsRegistry.getSettingLocked(
Svet Ganov53a441c2016-04-19 19:38:00 -0700965 SETTINGS_TYPE_SECURE, owningUserId, name);
Svetoslav7ec28e82015-05-20 17:01:10 -0700966 appendSettingToCursor(result, setting);
Svetoslav683914b2015-01-15 14:22:26 -0800967 }
968
Svetoslav7ec28e82015-05-20 17:01:10 -0700969 return result;
Svetoslav683914b2015-01-15 14:22:26 -0800970 }
Svetoslav683914b2015-01-15 14:22:26 -0800971 }
972
Svetoslav7ec28e82015-05-20 17:01:10 -0700973 private Setting getSecureSetting(String name, int requestingUserId) {
Svetoslav683914b2015-01-15 14:22:26 -0800974 if (DEBUG) {
975 Slog.v(LOG_TAG, "getSecureSetting(" + name + ", " + requestingUserId + ")");
976 }
977
978 // Resolve the userId on whose behalf the call is made.
979 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
980
Chad Brubaker97bccee2017-01-05 15:51:41 -0800981 // Ensure the caller can access the setting.
982 enforceSettingReadable(name, SETTINGS_TYPE_SECURE, callingUserId);
983
Svetoslav683914b2015-01-15 14:22:26 -0800984 // Determine the owning user as some profile settings are cloned from the parent.
985 final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name);
986
987 // Special case for location (sigh).
988 if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) {
Dianne Hackborn32f40ee2016-10-20 15:54:14 -0700989 SettingsState settings = mSettingsRegistry.getSettingsLocked(SETTINGS_TYPE_SECURE,
990 owningUserId);
991 return settings != null ? settings.getNullSetting() : null;
Svetoslav683914b2015-01-15 14:22:26 -0800992 }
993
994 // Get the value.
Svetoslav7ec28e82015-05-20 17:01:10 -0700995 synchronized (mLock) {
Svet Ganov53a441c2016-04-19 19:38:00 -0700996 return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SECURE,
Svetoslav7ec28e82015-05-20 17:01:10 -0700997 owningUserId, name);
998 }
Svetoslav683914b2015-01-15 14:22:26 -0800999 }
1000
Svetoslav Ganove080da92016-12-21 17:10:35 -08001001 private boolean insertSecureSetting(String name, String value, String tag,
1002 boolean makeDefault, int requestingUserId, boolean forceNotify) {
Svetoslav683914b2015-01-15 14:22:26 -08001003 if (DEBUG) {
Svetoslav7ec28e82015-05-20 17:01:10 -07001004 Slog.v(LOG_TAG, "insertSecureSetting(" + name + ", " + value + ", "
Svetoslav Ganove080da92016-12-21 17:10:35 -08001005 + ", " + tag + ", " + makeDefault + ", " + requestingUserId
1006 + ", " + forceNotify + ")");
Svetoslav683914b2015-01-15 14:22:26 -08001007 }
1008
Svetoslav Ganove080da92016-12-21 17:10:35 -08001009 return mutateSecureSetting(name, value, tag, makeDefault, requestingUserId,
1010 MUTATION_OPERATION_INSERT, forceNotify, 0);
Svetoslav683914b2015-01-15 14:22:26 -08001011 }
1012
Svet Ganov53a441c2016-04-19 19:38:00 -07001013 private boolean deleteSecureSetting(String name, int requestingUserId, boolean forceNotify) {
Svetoslav683914b2015-01-15 14:22:26 -08001014 if (DEBUG) {
Svetoslav Ganove080da92016-12-21 17:10:35 -08001015 Slog.v(LOG_TAG, "deleteSecureSetting(" + name + ", " + requestingUserId
1016 + ", " + forceNotify + ")");
Svetoslav683914b2015-01-15 14:22:26 -08001017 }
1018
Svetoslav Ganove080da92016-12-21 17:10:35 -08001019 return mutateSecureSetting(name, null, null, false, requestingUserId,
1020 MUTATION_OPERATION_DELETE, forceNotify, 0);
Svetoslav683914b2015-01-15 14:22:26 -08001021 }
1022
Svetoslav Ganove080da92016-12-21 17:10:35 -08001023 private boolean updateSecureSetting(String name, String value, String tag,
1024 boolean makeDefault, int requestingUserId, boolean forceNotify) {
Svetoslav683914b2015-01-15 14:22:26 -08001025 if (DEBUG) {
Svetoslav7ec28e82015-05-20 17:01:10 -07001026 Slog.v(LOG_TAG, "updateSecureSetting(" + name + ", " + value + ", "
Svetoslav Ganove080da92016-12-21 17:10:35 -08001027 + ", " + tag + ", " + makeDefault + ", " + requestingUserId
1028 + ", " + forceNotify +")");
Svetoslav683914b2015-01-15 14:22:26 -08001029 }
1030
Svetoslav Ganove080da92016-12-21 17:10:35 -08001031 return mutateSecureSetting(name, value, tag, makeDefault, requestingUserId,
1032 MUTATION_OPERATION_UPDATE, forceNotify, 0);
Svetoslav683914b2015-01-15 14:22:26 -08001033 }
1034
Svetoslav Ganove080da92016-12-21 17:10:35 -08001035 private void resetSecureSetting(int requestingUserId, int mode, String tag) {
1036 if (DEBUG) {
1037 Slog.v(LOG_TAG, "resetSecureSetting(" + requestingUserId + ", "
1038 + mode + ", " + tag + ")");
1039 }
1040
1041 mutateSecureSetting(null, null, tag, false, requestingUserId,
1042 MUTATION_OPERATION_RESET, false, mode);
1043 }
1044
1045 private boolean mutateSecureSetting(String name, String value, String tag,
1046 boolean makeDefault, int requestingUserId, int operation, boolean forceNotify,
1047 int mode) {
Svetoslav683914b2015-01-15 14:22:26 -08001048 // Make sure the caller can change the settings.
1049 enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
1050
Svetoslav683914b2015-01-15 14:22:26 -08001051 // Resolve the userId on whose behalf the call is made.
1052 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
1053
Makoto Onuki28da2e32015-11-20 11:30:44 -08001054 // If this is a setting that is currently restricted for this user, do not allow
1055 // unrestricting changes.
Svetoslav Ganove080da92016-12-21 17:10:35 -08001056 if (name != null && isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value,
Victor Chang9c7b7062016-07-12 23:47:29 +01001057 Binder.getCallingUid())) {
Svetoslav683914b2015-01-15 14:22:26 -08001058 return false;
1059 }
1060
1061 // Determine the owning user as some profile settings are cloned from the parent.
1062 final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name);
1063
1064 // Only the owning user can change the setting.
1065 if (owningUserId != callingUserId) {
1066 return false;
1067 }
1068
1069 // Special cases for location providers (sigh).
1070 if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
Svetoslav Ganove080da92016-12-21 17:10:35 -08001071 return updateLocationProvidersAllowedLocked(value, tag, owningUserId, makeDefault,
1072 forceNotify);
Svetoslav683914b2015-01-15 14:22:26 -08001073 }
1074
1075 // Mutate the value.
Svetoslav7ec28e82015-05-20 17:01:10 -07001076 synchronized (mLock) {
1077 switch (operation) {
1078 case MUTATION_OPERATION_INSERT: {
Svet Ganov53a441c2016-04-19 19:38:00 -07001079 return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SECURE,
Svetoslav Ganove080da92016-12-21 17:10:35 -08001080 owningUserId, name, value, tag, makeDefault,
1081 getCallingPackage(), forceNotify);
Svetoslav7ec28e82015-05-20 17:01:10 -07001082 }
Svetoslav683914b2015-01-15 14:22:26 -08001083
Svetoslav7ec28e82015-05-20 17:01:10 -07001084 case MUTATION_OPERATION_DELETE: {
Svet Ganov53a441c2016-04-19 19:38:00 -07001085 return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_SECURE,
1086 owningUserId, name, forceNotify);
Svetoslav7ec28e82015-05-20 17:01:10 -07001087 }
Svetoslav683914b2015-01-15 14:22:26 -08001088
Svetoslav7ec28e82015-05-20 17:01:10 -07001089 case MUTATION_OPERATION_UPDATE: {
Svet Ganov53a441c2016-04-19 19:38:00 -07001090 return mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_SECURE,
Svetoslav Ganove080da92016-12-21 17:10:35 -08001091 owningUserId, name, value, tag, makeDefault,
1092 getCallingPackage(), forceNotify);
Svetoslav7ec28e82015-05-20 17:01:10 -07001093 }
Svetoslav Ganove080da92016-12-21 17:10:35 -08001094
1095 case MUTATION_OPERATION_RESET: {
1096 mSettingsRegistry.resetSettingsLocked(SETTINGS_TYPE_SECURE,
1097 UserHandle.USER_SYSTEM, getCallingPackage(), mode, tag);
1098 } return true;
Svetoslav683914b2015-01-15 14:22:26 -08001099 }
1100 }
1101
1102 return false;
1103 }
1104
Svetoslav7ec28e82015-05-20 17:01:10 -07001105 private Cursor getAllSystemSettings(int userId, String[] projection) {
Svetoslav683914b2015-01-15 14:22:26 -08001106 if (DEBUG) {
Svetoslav7ec28e82015-05-20 17:01:10 -07001107 Slog.v(LOG_TAG, "getAllSecureSystem(" + userId + ")");
Svetoslav683914b2015-01-15 14:22:26 -08001108 }
1109
1110 // Resolve the userId on whose behalf the call is made.
1111 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId);
1112
Svetoslav7ec28e82015-05-20 17:01:10 -07001113 synchronized (mLock) {
Chad Brubaker97bccee2017-01-05 15:51:41 -08001114 List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_SYSTEM, callingUserId);
Svetoslav683914b2015-01-15 14:22:26 -08001115
Svetoslav7ec28e82015-05-20 17:01:10 -07001116 final int nameCount = names.size();
Svetoslav683914b2015-01-15 14:22:26 -08001117
Svetoslav7ec28e82015-05-20 17:01:10 -07001118 String[] normalizedProjection = normalizeProjection(projection);
1119 MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount);
Svetoslav683914b2015-01-15 14:22:26 -08001120
Svetoslav7ec28e82015-05-20 17:01:10 -07001121 for (int i = 0; i < nameCount; i++) {
1122 String name = names.get(i);
Svetoslav683914b2015-01-15 14:22:26 -08001123
Svetoslav7ec28e82015-05-20 17:01:10 -07001124 // Determine the owning user as some profile settings are cloned from the parent.
1125 final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId,
1126 name);
Svetoslav683914b2015-01-15 14:22:26 -08001127
Svetoslav7ec28e82015-05-20 17:01:10 -07001128 Setting setting = mSettingsRegistry.getSettingLocked(
Svet Ganov53a441c2016-04-19 19:38:00 -07001129 SETTINGS_TYPE_SYSTEM, owningUserId, name);
Svetoslav7ec28e82015-05-20 17:01:10 -07001130 appendSettingToCursor(result, setting);
1131 }
1132
1133 return result;
Svetoslav683914b2015-01-15 14:22:26 -08001134 }
Svetoslav683914b2015-01-15 14:22:26 -08001135 }
1136
Svetoslav7ec28e82015-05-20 17:01:10 -07001137 private Setting getSystemSetting(String name, int requestingUserId) {
Svetoslav683914b2015-01-15 14:22:26 -08001138 if (DEBUG) {
1139 Slog.v(LOG_TAG, "getSystemSetting(" + name + ", " + requestingUserId + ")");
1140 }
1141
1142 // Resolve the userId on whose behalf the call is made.
1143 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
1144
Chad Brubaker97bccee2017-01-05 15:51:41 -08001145 // Ensure the caller can access the setting.
1146 enforceSettingReadable(name, SETTINGS_TYPE_SYSTEM, callingUserId);
1147
Svetoslav683914b2015-01-15 14:22:26 -08001148 // Determine the owning user as some profile settings are cloned from the parent.
1149 final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name);
1150
1151 // Get the value.
Svetoslav7ec28e82015-05-20 17:01:10 -07001152 synchronized (mLock) {
Svet Ganov53a441c2016-04-19 19:38:00 -07001153 return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SYSTEM, owningUserId, name);
Svetoslav7ec28e82015-05-20 17:01:10 -07001154 }
Svetoslav683914b2015-01-15 14:22:26 -08001155 }
1156
Svetoslav7ec28e82015-05-20 17:01:10 -07001157 private boolean insertSystemSetting(String name, String value, int requestingUserId) {
Svetoslav683914b2015-01-15 14:22:26 -08001158 if (DEBUG) {
Svetoslav7ec28e82015-05-20 17:01:10 -07001159 Slog.v(LOG_TAG, "insertSystemSetting(" + name + ", " + value + ", "
Svetoslav683914b2015-01-15 14:22:26 -08001160 + requestingUserId + ")");
1161 }
1162
Svetoslav7ec28e82015-05-20 17:01:10 -07001163 return mutateSystemSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT);
Svetoslav683914b2015-01-15 14:22:26 -08001164 }
1165
Svetoslav7ec28e82015-05-20 17:01:10 -07001166 private boolean deleteSystemSetting(String name, int requestingUserId) {
Svetoslav683914b2015-01-15 14:22:26 -08001167 if (DEBUG) {
Svetoslav7ec28e82015-05-20 17:01:10 -07001168 Slog.v(LOG_TAG, "deleteSystemSetting(" + name + ", " + requestingUserId + ")");
Svetoslav683914b2015-01-15 14:22:26 -08001169 }
1170
Svetoslav7ec28e82015-05-20 17:01:10 -07001171 return mutateSystemSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE);
Svetoslav683914b2015-01-15 14:22:26 -08001172 }
1173
Svetoslav7ec28e82015-05-20 17:01:10 -07001174 private boolean updateSystemSetting(String name, String value, int requestingUserId) {
Svetoslav683914b2015-01-15 14:22:26 -08001175 if (DEBUG) {
Svetoslav7ec28e82015-05-20 17:01:10 -07001176 Slog.v(LOG_TAG, "updateSystemSetting(" + name + ", " + value + ", "
Svetoslav683914b2015-01-15 14:22:26 -08001177 + requestingUserId + ")");
1178 }
1179
Svetoslav7ec28e82015-05-20 17:01:10 -07001180 return mutateSystemSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE);
Svetoslav683914b2015-01-15 14:22:26 -08001181 }
1182
Svetoslav7ec28e82015-05-20 17:01:10 -07001183 private boolean mutateSystemSetting(String name, String value, int runAsUserId,
Svetoslav683914b2015-01-15 14:22:26 -08001184 int operation) {
Billy Lau6ad2d662015-07-18 00:26:58 +01001185 if (!hasWriteSecureSettingsPermission()) {
1186 // If the caller doesn't hold WRITE_SECURE_SETTINGS, we verify whether this
1187 // operation is allowed for the calling package through appops.
1188 if (!Settings.checkAndNoteWriteSettingsOperation(getContext(),
1189 Binder.getCallingUid(), getCallingPackage(), true)) {
1190 return false;
1191 }
Svetoslav683914b2015-01-15 14:22:26 -08001192 }
1193
Svetoslav683914b2015-01-15 14:22:26 -08001194 // Resolve the userId on whose behalf the call is made.
1195 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(runAsUserId);
1196
Svetoslavd8d25e02015-11-20 13:09:26 -08001197 // Enforce what the calling package can mutate the system settings.
1198 enforceRestrictedSystemSettingsMutationForCallingPackage(operation, name, callingUserId);
1199
Svetoslav683914b2015-01-15 14:22:26 -08001200 // Determine the owning user as some profile settings are cloned from the parent.
1201 final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name);
1202
1203 // Only the owning user id can change the setting.
1204 if (owningUserId != callingUserId) {
1205 return false;
1206 }
1207
Jeff Sharkey413573a2016-02-22 17:52:45 -07001208 // Invalidate any relevant cache files
1209 String cacheName = null;
1210 if (Settings.System.RINGTONE.equals(name)) {
1211 cacheName = Settings.System.RINGTONE_CACHE;
1212 } else if (Settings.System.NOTIFICATION_SOUND.equals(name)) {
1213 cacheName = Settings.System.NOTIFICATION_SOUND_CACHE;
1214 } else if (Settings.System.ALARM_ALERT.equals(name)) {
1215 cacheName = Settings.System.ALARM_ALERT_CACHE;
1216 }
1217 if (cacheName != null) {
1218 final File cacheFile = new File(
Andre Lago3fa139c2016-08-04 13:53:44 +01001219 getRingtoneCacheDir(owningUserId), cacheName);
Jeff Sharkey413573a2016-02-22 17:52:45 -07001220 cacheFile.delete();
1221 }
1222
Svetoslav683914b2015-01-15 14:22:26 -08001223 // Mutate the value.
Svetoslav7ec28e82015-05-20 17:01:10 -07001224 synchronized (mLock) {
1225 switch (operation) {
1226 case MUTATION_OPERATION_INSERT: {
1227 validateSystemSettingValue(name, value);
Svet Ganov53a441c2016-04-19 19:38:00 -07001228 return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SYSTEM,
Svetoslav Ganove080da92016-12-21 17:10:35 -08001229 owningUserId, name, value, null, false, getCallingPackage(), false);
Svetoslav7ec28e82015-05-20 17:01:10 -07001230 }
1231
1232 case MUTATION_OPERATION_DELETE: {
Svet Ganov53a441c2016-04-19 19:38:00 -07001233 return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_SYSTEM,
1234 owningUserId, name, false);
Svetoslav7ec28e82015-05-20 17:01:10 -07001235 }
1236
1237 case MUTATION_OPERATION_UPDATE: {
1238 validateSystemSettingValue(name, value);
Svet Ganov53a441c2016-04-19 19:38:00 -07001239 return mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_SYSTEM,
Svetoslav Ganove080da92016-12-21 17:10:35 -08001240 owningUserId, name, value, null, false, getCallingPackage(), false);
Svetoslav7ec28e82015-05-20 17:01:10 -07001241 }
Svetoslav683914b2015-01-15 14:22:26 -08001242 }
1243
Svetoslav7ec28e82015-05-20 17:01:10 -07001244 return false;
Svetoslav683914b2015-01-15 14:22:26 -08001245 }
Svetoslav683914b2015-01-15 14:22:26 -08001246 }
1247
Billy Lau6ad2d662015-07-18 00:26:58 +01001248 private boolean hasWriteSecureSettingsPermission() {
Svetoslavf41334b2015-06-23 12:06:03 -07001249 // Write secure settings is a more protected permission. If caller has it we are good.
1250 if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
1251 == PackageManager.PERMISSION_GRANTED) {
1252 return true;
1253 }
1254
Svetoslavf41334b2015-06-23 12:06:03 -07001255 return false;
1256 }
1257
Svetoslav683914b2015-01-15 14:22:26 -08001258 private void validateSystemSettingValue(String name, String value) {
1259 Settings.System.Validator validator = Settings.System.VALIDATORS.get(name);
1260 if (validator != null && !validator.validate(value)) {
1261 throw new IllegalArgumentException("Invalid value: " + value
1262 + " for setting: " + name);
1263 }
1264 }
1265
1266 private boolean isLocationProvidersAllowedRestricted(String name, int callingUserId,
1267 int owningUserId) {
1268 // Optimization - location providers are restricted only for managed profiles.
1269 if (callingUserId == owningUserId) {
1270 return false;
1271 }
1272 if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)
1273 && mUserManager.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION,
1274 new UserHandle(callingUserId))) {
1275 return true;
1276 }
1277 return false;
1278 }
1279
Makoto Onuki28da2e32015-11-20 11:30:44 -08001280 /**
1281 * Checks whether changing a setting to a value is prohibited by the corresponding user
1282 * restriction.
1283 *
Svet Ganov53a441c2016-04-19 19:38:00 -07001284 * <p>See also {@link com.android.server.pm.UserRestrictionsUtils#applyUserRestriction(
1285 * Context, int, String, boolean)}, which should be in sync with this method.
Makoto Onuki28da2e32015-11-20 11:30:44 -08001286 *
1287 * @return true if the change is prohibited, false if the change is allowed.
1288 */
1289 private boolean isGlobalOrSecureSettingRestrictedForUser(String setting, int userId,
Victor Chang9c7b7062016-07-12 23:47:29 +01001290 String value, int callingUid) {
Makoto Onuki28da2e32015-11-20 11:30:44 -08001291 String restriction;
1292 switch (setting) {
1293 case Settings.Secure.LOCATION_MODE:
1294 // Note LOCATION_MODE will be converted into LOCATION_PROVIDERS_ALLOWED
1295 // in android.provider.Settings.Secure.putStringForUser(), so we shouldn't come
1296 // here normally, but we still protect it here from a direct provider write.
1297 if (String.valueOf(Settings.Secure.LOCATION_MODE_OFF).equals(value)) return false;
1298 restriction = UserManager.DISALLOW_SHARE_LOCATION;
1299 break;
1300
1301 case Settings.Secure.LOCATION_PROVIDERS_ALLOWED:
1302 // See SettingsProvider.updateLocationProvidersAllowedLocked. "-" is to disable
1303 // a provider, which should be allowed even if the user restriction is set.
1304 if (value != null && value.startsWith("-")) return false;
1305 restriction = UserManager.DISALLOW_SHARE_LOCATION;
1306 break;
1307
1308 case Settings.Secure.INSTALL_NON_MARKET_APPS:
1309 if ("0".equals(value)) return false;
1310 restriction = UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES;
1311 break;
1312
1313 case Settings.Global.ADB_ENABLED:
1314 if ("0".equals(value)) return false;
1315 restriction = UserManager.DISALLOW_DEBUGGING_FEATURES;
1316 break;
1317
1318 case Settings.Global.PACKAGE_VERIFIER_ENABLE:
1319 case Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB:
1320 if ("1".equals(value)) return false;
1321 restriction = UserManager.ENSURE_VERIFY_APPS;
1322 break;
1323
1324 case Settings.Global.PREFERRED_NETWORK_MODE:
1325 restriction = UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS;
1326 break;
1327
Victor Chang9c7b7062016-07-12 23:47:29 +01001328 case Settings.Secure.ALWAYS_ON_VPN_APP:
1329 case Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN:
1330 // Whitelist system uid (ConnectivityService) and root uid to change always-on vpn
Svetoslav Ganove080da92016-12-21 17:10:35 -08001331 final int appId = UserHandle.getAppId(callingUid);
1332 if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID) {
Victor Chang9c7b7062016-07-12 23:47:29 +01001333 return false;
1334 }
1335 restriction = UserManager.DISALLOW_CONFIG_VPN;
1336 break;
1337
Benjamin Franz0ff13fc2016-07-12 13:42:21 +01001338 case Settings.Global.SAFE_BOOT_DISALLOWED:
1339 if ("1".equals(value)) return false;
1340 restriction = UserManager.DISALLOW_SAFE_BOOT;
1341 break;
1342
Makoto Onuki28da2e32015-11-20 11:30:44 -08001343 default:
Mahaver Chopra87648752016-01-08 19:23:57 +00001344 if (setting != null && setting.startsWith(Settings.Global.DATA_ROAMING)) {
Mahaver Chopradea471e2015-12-17 11:02:37 +00001345 if ("0".equals(value)) return false;
1346 restriction = UserManager.DISALLOW_DATA_ROAMING;
1347 break;
1348 }
Makoto Onuki28da2e32015-11-20 11:30:44 -08001349 return false;
Svetoslav683914b2015-01-15 14:22:26 -08001350 }
Makoto Onuki28da2e32015-11-20 11:30:44 -08001351
1352 return mUserManager.hasUserRestriction(restriction, UserHandle.of(userId));
Svetoslav683914b2015-01-15 14:22:26 -08001353 }
1354
1355 private int resolveOwningUserIdForSecureSettingLocked(int userId, String setting) {
1356 return resolveOwningUserIdLocked(userId, sSecureCloneToManagedSettings, setting);
1357 }
1358
1359 private int resolveOwningUserIdForSystemSettingLocked(int userId, String setting) {
Andre Lago3fa139c2016-08-04 13:53:44 +01001360 final int parentId;
1361 // Resolves dependency if setting has a dependency and the calling user has a parent
1362 if (sSystemCloneFromParentOnDependency.containsKey(setting)
1363 && (parentId = getGroupParentLocked(userId)) != userId) {
1364 // The setting has a dependency and the profile has a parent
1365 String dependency = sSystemCloneFromParentOnDependency.get(setting);
Chad Brubaker97bccee2017-01-05 15:51:41 -08001366 // Lookup the dependency setting as ourselves, some callers may not have access to it.
1367 final long token = Binder.clearCallingIdentity();
1368 try {
1369 Setting settingObj = getSecureSetting(dependency, userId);
1370 if (settingObj != null && settingObj.getValue().equals("1")) {
1371 return parentId;
1372 }
1373 } finally {
1374 Binder.restoreCallingIdentity(token);
Andre Lago3fa139c2016-08-04 13:53:44 +01001375 }
1376 }
Svetoslav683914b2015-01-15 14:22:26 -08001377 return resolveOwningUserIdLocked(userId, sSystemCloneToManagedSettings, setting);
1378 }
1379
1380 private int resolveOwningUserIdLocked(int userId, Set<String> keys, String name) {
1381 final int parentId = getGroupParentLocked(userId);
1382 if (parentId != userId && keys.contains(name)) {
1383 return parentId;
1384 }
1385 return userId;
1386 }
1387
Svetoslavf41334b2015-06-23 12:06:03 -07001388 private void enforceRestrictedSystemSettingsMutationForCallingPackage(int operation,
Xiaohui Chen43765b72015-08-31 10:57:33 -07001389 String name, int userId) {
Svetoslav683914b2015-01-15 14:22:26 -08001390 // System/root/shell can mutate whatever secure settings they want.
1391 final int callingUid = Binder.getCallingUid();
Svetoslav Ganove080da92016-12-21 17:10:35 -08001392 final int appId = UserHandle.getAppId(callingUid);
1393 if (appId == android.os.Process.SYSTEM_UID
1394 || appId == Process.SHELL_UID
1395 || appId == Process.ROOT_UID) {
Svetoslav683914b2015-01-15 14:22:26 -08001396 return;
1397 }
1398
1399 switch (operation) {
1400 case MUTATION_OPERATION_INSERT:
1401 // Insert updates.
1402 case MUTATION_OPERATION_UPDATE: {
1403 if (Settings.System.PUBLIC_SETTINGS.contains(name)) {
1404 return;
1405 }
1406
1407 // The calling package is already verified.
Xiaohui Chen43765b72015-08-31 10:57:33 -07001408 PackageInfo packageInfo = getCallingPackageInfoOrThrow(userId);
Svetoslav683914b2015-01-15 14:22:26 -08001409
1410 // Privileged apps can do whatever they want.
1411 if ((packageInfo.applicationInfo.privateFlags
1412 & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
1413 return;
1414 }
1415
1416 warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
1417 packageInfo.applicationInfo.targetSdkVersion, name);
1418 } break;
1419
1420 case MUTATION_OPERATION_DELETE: {
1421 if (Settings.System.PUBLIC_SETTINGS.contains(name)
1422 || Settings.System.PRIVATE_SETTINGS.contains(name)) {
1423 throw new IllegalArgumentException("You cannot delete system defined"
1424 + " secure settings.");
1425 }
1426
1427 // The calling package is already verified.
Xiaohui Chen43765b72015-08-31 10:57:33 -07001428 PackageInfo packageInfo = getCallingPackageInfoOrThrow(userId);
Svetoslav683914b2015-01-15 14:22:26 -08001429
1430 // Privileged apps can do whatever they want.
1431 if ((packageInfo.applicationInfo.privateFlags &
1432 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
1433 return;
1434 }
1435
1436 warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
1437 packageInfo.applicationInfo.targetSdkVersion, name);
1438 } break;
1439 }
1440 }
1441
Chad Brubaker97bccee2017-01-05 15:51:41 -08001442 private Set<String> getEphemeralAccessibleSettings(int settingsType) {
1443 switch (settingsType) {
1444 case SETTINGS_TYPE_GLOBAL:
1445 return Settings.Global.EPHEMERAL_SETTINGS;
1446 case SETTINGS_TYPE_SECURE:
1447 return Settings.Secure.EPHEMERAL_SETTINGS;
1448 case SETTINGS_TYPE_SYSTEM:
1449 return Settings.System.EPHEMERAL_SETTINGS;
1450 default:
1451 throw new IllegalArgumentException("Invalid settings type: " + settingsType);
1452 }
1453 }
1454
1455 private List<String> getSettingsNamesLocked(int settingsType, int userId) {
1456 ApplicationInfo ai = getCallingApplicationInfoOrThrow(userId);
1457 if (ai.isEphemeralApp()) {
1458 return new ArrayList<String>(getEphemeralAccessibleSettings(settingsType));
1459 } else {
1460 return mSettingsRegistry.getSettingsNamesLocked(settingsType, userId);
1461 }
1462 }
1463
1464 private void enforceSettingReadable(String settingName, int settingsType, int userId) {
1465 if (UserHandle.getAppId(Binder.getCallingUid()) < Process.FIRST_APPLICATION_UID) {
1466 return;
1467 }
1468 ApplicationInfo ai = getCallingApplicationInfoOrThrow(userId);
1469 if (!ai.isEphemeralApp()) {
1470 return;
1471 }
1472 if (!getEphemeralAccessibleSettings(settingsType).contains(settingName)) {
1473 throw new SecurityException("Setting " + settingName + " is not accessible from"
1474 + " ephemeral package " + getCallingPackage());
1475 }
1476 }
1477
1478 private ApplicationInfo getCallingApplicationInfoOrThrow(int userId) {
1479 ApplicationInfo ai = null;
1480 try {
1481 ai = mPackageManager.getApplicationInfo(getCallingPackage(), 0 , userId);
1482 } catch (RemoteException ignored) {
1483 }
1484 if (ai == null) {
1485 throw new IllegalStateException("Failed to lookup info for package "
1486 + getCallingPackage());
1487 }
1488 return ai;
1489 }
1490
Xiaohui Chen43765b72015-08-31 10:57:33 -07001491 private PackageInfo getCallingPackageInfoOrThrow(int userId) {
Svetoslav683914b2015-01-15 14:22:26 -08001492 try {
Svetoslav Ganov67a8d352016-03-02 13:26:40 -08001493 PackageInfo packageInfo = mPackageManager.getPackageInfo(
1494 getCallingPackage(), 0, userId);
1495 if (packageInfo != null) {
1496 return packageInfo;
1497 }
Xiaohui Chen43765b72015-08-31 10:57:33 -07001498 } catch (RemoteException e) {
Svetoslav Ganov67a8d352016-03-02 13:26:40 -08001499 /* ignore */
Svetoslav683914b2015-01-15 14:22:26 -08001500 }
Svetoslav Ganov67a8d352016-03-02 13:26:40 -08001501 throw new IllegalStateException("Calling package doesn't exist");
Svetoslav683914b2015-01-15 14:22:26 -08001502 }
1503
1504 private int getGroupParentLocked(int userId) {
1505 // Most frequent use case.
Xiaohui Chen43765b72015-08-31 10:57:33 -07001506 if (userId == UserHandle.USER_SYSTEM) {
Svetoslav683914b2015-01-15 14:22:26 -08001507 return userId;
1508 }
1509 // We are in the same process with the user manager and the returned
1510 // user info is a cached instance, so just look up instead of cache.
1511 final long identity = Binder.clearCallingIdentity();
1512 try {
Svetoslav7ec28e82015-05-20 17:01:10 -07001513 // Just a lookup and not reentrant, so holding a lock is fine.
Svetoslav683914b2015-01-15 14:22:26 -08001514 UserInfo userInfo = mUserManager.getProfileParent(userId);
1515 return (userInfo != null) ? userInfo.id : userId;
1516 } finally {
1517 Binder.restoreCallingIdentity(identity);
1518 }
1519 }
1520
Svetoslav683914b2015-01-15 14:22:26 -08001521 private void enforceWritePermission(String permission) {
1522 if (getContext().checkCallingOrSelfPermission(permission)
1523 != PackageManager.PERMISSION_GRANTED) {
1524 throw new SecurityException("Permission denial: writing to settings requires:"
1525 + permission);
1526 }
1527 }
1528
1529 /*
1530 * Used to parse changes to the value of Settings.Secure.LOCATION_PROVIDERS_ALLOWED.
1531 * This setting contains a list of the currently enabled location providers.
1532 * But helper functions in android.providers.Settings can enable or disable
1533 * a single provider by using a "+" or "-" prefix before the provider name.
1534 *
Makoto Onuki28da2e32015-11-20 11:30:44 -08001535 * <p>See also {@link #isGlobalOrSecureSettingRestrictedForUser()}. If DISALLOW_SHARE_LOCATION
1536 * is set, the said method will only allow values with the "-" prefix.
1537 *
Svetoslav683914b2015-01-15 14:22:26 -08001538 * @returns whether the enabled location providers changed.
Brad Fitzpatrick1bd62bd2010-03-08 18:30:52 -08001539 */
Svetoslav Ganove080da92016-12-21 17:10:35 -08001540 private boolean updateLocationProvidersAllowedLocked(String value, String tag,
1541 int owningUserId, boolean makeDefault, boolean forceNotify) {
Svetoslav683914b2015-01-15 14:22:26 -08001542 if (TextUtils.isEmpty(value)) {
1543 return false;
Brad Fitzpatrickf366a9b2010-08-24 16:14:07 -07001544 }
1545
Svetoslav683914b2015-01-15 14:22:26 -08001546 final char prefix = value.charAt(0);
1547 if (prefix != '+' && prefix != '-') {
Svet Ganov53a441c2016-04-19 19:38:00 -07001548 if (forceNotify) {
1549 final int key = makeKey(SETTINGS_TYPE_SECURE, owningUserId);
1550 mSettingsRegistry.notifyForSettingsChange(key,
1551 Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
1552 }
Svetoslav683914b2015-01-15 14:22:26 -08001553 return false;
1554 }
1555
1556 // skip prefix
1557 value = value.substring(1);
1558
Svetoslav7ec28e82015-05-20 17:01:10 -07001559 Setting settingValue = getSecureSetting(
Chad Brubaker97bccee2017-01-05 15:51:41 -08001560 Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId);
Dianne Hackborn32f40ee2016-10-20 15:54:14 -07001561 if (settingValue == null) {
1562 return false;
1563 }
Svetoslav683914b2015-01-15 14:22:26 -08001564
1565 String oldProviders = (settingValue != null) ? settingValue.getValue() : "";
1566
1567 int index = oldProviders.indexOf(value);
1568 int end = index + value.length();
1569
1570 // check for commas to avoid matching on partial string
1571 if (index > 0 && oldProviders.charAt(index - 1) != ',') {
1572 index = -1;
1573 }
1574
1575 // check for commas to avoid matching on partial string
1576 if (end < oldProviders.length() && oldProviders.charAt(end) != ',') {
1577 index = -1;
1578 }
1579
1580 String newProviders;
1581
1582 if (prefix == '+' && index < 0) {
1583 // append the provider to the list if not present
1584 if (oldProviders.length() == 0) {
1585 newProviders = value;
1586 } else {
1587 newProviders = oldProviders + ',' + value;
1588 }
1589 } else if (prefix == '-' && index >= 0) {
1590 // remove the provider from the list if present
1591 // remove leading or trailing comma
1592 if (index > 0) {
1593 index--;
1594 } else if (end < oldProviders.length()) {
1595 end++;
1596 }
1597
1598 newProviders = oldProviders.substring(0, index);
1599 if (end < oldProviders.length()) {
1600 newProviders += oldProviders.substring(end);
1601 }
1602 } else {
1603 // nothing changed, so no need to update the database
Svet Ganov53a441c2016-04-19 19:38:00 -07001604 if (forceNotify) {
1605 final int key = makeKey(SETTINGS_TYPE_SECURE, owningUserId);
1606 mSettingsRegistry.notifyForSettingsChange(key,
1607 Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
1608 }
Svetoslav683914b2015-01-15 14:22:26 -08001609 return false;
1610 }
1611
Svet Ganov53a441c2016-04-19 19:38:00 -07001612 return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SECURE,
Svetoslavb596a2c2015-02-17 21:37:09 -08001613 owningUserId, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, newProviders,
Svetoslav Ganove080da92016-12-21 17:10:35 -08001614 tag, makeDefault, getCallingPackage(), forceNotify);
Svetoslav683914b2015-01-15 14:22:26 -08001615 }
1616
Svetoslav683914b2015-01-15 14:22:26 -08001617 private static void warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
1618 int targetSdkVersion, String name) {
1619 // If the app targets Lollipop MR1 or older SDK we warn, otherwise crash.
1620 if (targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1) {
1621 if (Settings.System.PRIVATE_SETTINGS.contains(name)) {
1622 Slog.w(LOG_TAG, "You shouldn't not change private system settings."
1623 + " This will soon become an error.");
1624 } else {
1625 Slog.w(LOG_TAG, "You shouldn't keep your settings in the secure settings."
1626 + " This will soon become an error.");
1627 }
1628 } else {
1629 if (Settings.System.PRIVATE_SETTINGS.contains(name)) {
1630 throw new IllegalArgumentException("You cannot change private secure settings.");
1631 } else {
1632 throw new IllegalArgumentException("You cannot keep your settings in"
1633 + " the secure settings.");
1634 }
1635 }
1636 }
1637
1638 private static int resolveCallingUserIdEnforcingPermissionsLocked(int requestingUserId) {
1639 if (requestingUserId == UserHandle.getCallingUserId()) {
1640 return requestingUserId;
1641 }
1642 return ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1643 Binder.getCallingUid(), requestingUserId, false, true,
1644 "get/set setting for user", null);
1645 }
1646
Svet Ganov53a441c2016-04-19 19:38:00 -07001647 private Bundle packageValueForCallResult(Setting setting,
1648 boolean trackingGeneration) {
1649 if (!trackingGeneration) {
Dianne Hackborn32f40ee2016-10-20 15:54:14 -07001650 if (setting == null || setting.isNull()) {
Svet Ganov53a441c2016-04-19 19:38:00 -07001651 return NULL_SETTING_BUNDLE;
1652 }
1653 return Bundle.forPair(Settings.NameValueTable.VALUE, setting.getValue());
Svetoslav683914b2015-01-15 14:22:26 -08001654 }
Svet Ganov53a441c2016-04-19 19:38:00 -07001655 Bundle result = new Bundle();
1656 result.putString(Settings.NameValueTable.VALUE,
Svetoslav Ganove080da92016-12-21 17:10:35 -08001657 !setting.isNull() ? setting.getValue() : null);
1658 mSettingsRegistry.mGenerationRegistry.addGenerationData(result, setting.getKey());
Svet Ganov53a441c2016-04-19 19:38:00 -07001659 return result;
Svetoslav683914b2015-01-15 14:22:26 -08001660 }
1661
1662 private static int getRequestingUserId(Bundle args) {
1663 final int callingUserId = UserHandle.getCallingUserId();
1664 return (args != null) ? args.getInt(Settings.CALL_METHOD_USER_KEY, callingUserId)
1665 : callingUserId;
1666 }
1667
Svet Ganov53a441c2016-04-19 19:38:00 -07001668 private boolean isTrackingGeneration(Bundle args) {
1669 return args != null && args.containsKey(Settings.CALL_METHOD_TRACK_GENERATION_KEY);
1670 }
1671
Svetoslav683914b2015-01-15 14:22:26 -08001672 private static String getSettingValue(Bundle args) {
1673 return (args != null) ? args.getString(Settings.NameValueTable.VALUE) : null;
1674 }
1675
Svetoslav Ganove080da92016-12-21 17:10:35 -08001676 private static String getSettingTag(Bundle args) {
1677 return (args != null) ? args.getString(Settings.CALL_METHOD_TAG_KEY) : null;
1678 }
1679
1680 private static boolean getSettingMakeDefault(Bundle args) {
1681 return (args != null) && args.getBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY);
1682 }
1683
1684 private static int getResetModeEnforcingPermission(Bundle args) {
1685 final int mode = (args != null) ? args.getInt(Settings.CALL_METHOD_RESET_MODE_KEY) : 0;
1686 switch (mode) {
1687 case Settings.RESET_MODE_UNTRUSTED_DEFAULTS: {
1688 if (!isCallerSystemOrShellOrRootOnDebuggableBuild()) {
1689 throw new SecurityException("Only system, shell/root on a "
1690 + "debuggable build can reset to untrusted defaults");
1691 }
1692 return mode;
1693 }
1694 case Settings.RESET_MODE_UNTRUSTED_CHANGES: {
1695 if (!isCallerSystemOrShellOrRootOnDebuggableBuild()) {
1696 throw new SecurityException("Only system, shell/root on a "
1697 + "debuggable build can reset untrusted changes");
1698 }
1699 return mode;
1700 }
1701 case Settings.RESET_MODE_TRUSTED_DEFAULTS: {
1702 if (!isCallerSystemOrShellOrRootOnDebuggableBuild()) {
1703 throw new SecurityException("Only system, shell/root on a "
1704 + "debuggable build can reset to trusted defaults");
1705 }
1706 return mode;
1707 }
1708 case Settings.RESET_MODE_PACKAGE_DEFAULTS: {
1709 return mode;
1710 }
1711 }
1712 throw new IllegalArgumentException("Invalid reset mode: " + mode);
1713 }
1714
1715 private static boolean isCallerSystemOrShellOrRootOnDebuggableBuild() {
1716 final int appId = UserHandle.getAppId(Binder.getCallingUid());
1717 return appId == SYSTEM_UID || (Build.IS_DEBUGGABLE
1718 && (appId == SHELL_UID || appId == ROOT_UID));
1719 }
1720
Svetoslav683914b2015-01-15 14:22:26 -08001721 private static String getValidTableOrThrow(Uri uri) {
1722 if (uri.getPathSegments().size() > 0) {
1723 String table = uri.getPathSegments().get(0);
1724 if (DatabaseHelper.isValidTable(table)) {
1725 return table;
1726 }
1727 throw new IllegalArgumentException("Bad root path: " + table);
1728 }
1729 throw new IllegalArgumentException("Invalid URI:" + uri);
1730 }
1731
1732 private static MatrixCursor packageSettingForQuery(Setting setting, String[] projection) {
Svetoslav Ganovfedb2302016-04-26 18:36:42 -07001733 if (setting.isNull()) {
Svetoslav683914b2015-01-15 14:22:26 -08001734 return new MatrixCursor(projection, 0);
1735 }
1736 MatrixCursor cursor = new MatrixCursor(projection, 1);
1737 appendSettingToCursor(cursor, setting);
1738 return cursor;
1739 }
1740
1741 private static String[] normalizeProjection(String[] projection) {
1742 if (projection == null) {
1743 return ALL_COLUMNS;
1744 }
1745
1746 final int columnCount = projection.length;
1747 for (int i = 0; i < columnCount; i++) {
1748 String column = projection[i];
1749 if (!ArrayUtils.contains(ALL_COLUMNS, column)) {
1750 throw new IllegalArgumentException("Invalid column: " + column);
Brad Fitzpatrickf366a9b2010-08-24 16:14:07 -07001751 }
1752 }
1753
Svetoslav683914b2015-01-15 14:22:26 -08001754 return projection;
1755 }
1756
1757 private static void appendSettingToCursor(MatrixCursor cursor, Setting setting) {
Dianne Hackborn32f40ee2016-10-20 15:54:14 -07001758 if (setting == null || setting.isNull()) {
Suprabh Shuklac9d064a2016-04-12 18:45:34 -07001759 return;
1760 }
Svetoslav683914b2015-01-15 14:22:26 -08001761 final int columnCount = cursor.getColumnCount();
1762
1763 String[] values = new String[columnCount];
1764
1765 for (int i = 0; i < columnCount; i++) {
1766 String column = cursor.getColumnName(i);
1767
1768 switch (column) {
1769 case Settings.NameValueTable._ID: {
1770 values[i] = setting.getId();
1771 } break;
1772
1773 case Settings.NameValueTable.NAME: {
1774 values[i] = setting.getName();
1775 } break;
1776
1777 case Settings.NameValueTable.VALUE: {
1778 values[i] = setting.getValue();
1779 } break;
Brad Fitzpatrickf366a9b2010-08-24 16:14:07 -07001780 }
Brad Fitzpatrick1bd62bd2010-03-08 18:30:52 -08001781 }
1782
Svetoslav683914b2015-01-15 14:22:26 -08001783 cursor.addRow(values);
1784 }
Brad Fitzpatrick1bd62bd2010-03-08 18:30:52 -08001785
Makoto Onuki3a2c35782015-06-18 11:21:58 -07001786 private static boolean isKeyValid(String key) {
1787 return !(TextUtils.isEmpty(key) || SettingsState.isBinary(key));
1788 }
1789
Svetoslav683914b2015-01-15 14:22:26 -08001790 private static final class Arguments {
1791 private static final Pattern WHERE_PATTERN_WITH_PARAM_NO_BRACKETS =
1792 Pattern.compile("[\\s]*name[\\s]*=[\\s]*\\?[\\s]*");
1793
1794 private static final Pattern WHERE_PATTERN_WITH_PARAM_IN_BRACKETS =
1795 Pattern.compile("[\\s]*\\([\\s]*name[\\s]*=[\\s]*\\?[\\s]*\\)[\\s]*");
1796
1797 private static final Pattern WHERE_PATTERN_NO_PARAM_IN_BRACKETS =
1798 Pattern.compile("[\\s]*\\([\\s]*name[\\s]*=[\\s]*['\"].*['\"][\\s]*\\)[\\s]*");
1799
1800 private static final Pattern WHERE_PATTERN_NO_PARAM_NO_BRACKETS =
1801 Pattern.compile("[\\s]*name[\\s]*=[\\s]*['\"].*['\"][\\s]*");
1802
1803 public final String table;
1804 public final String name;
1805
1806 public Arguments(Uri uri, String where, String[] whereArgs, boolean supportAll) {
1807 final int segmentSize = uri.getPathSegments().size();
1808 switch (segmentSize) {
1809 case 1: {
1810 if (where != null
1811 && (WHERE_PATTERN_WITH_PARAM_NO_BRACKETS.matcher(where).matches()
1812 || WHERE_PATTERN_WITH_PARAM_IN_BRACKETS.matcher(where).matches())
1813 && whereArgs.length == 1) {
1814 name = whereArgs[0];
1815 table = computeTableForSetting(uri, name);
Svetoslav28494652015-02-12 14:11:42 -08001816 return;
Svetoslav683914b2015-01-15 14:22:26 -08001817 } else if (where != null
1818 && (WHERE_PATTERN_NO_PARAM_NO_BRACKETS.matcher(where).matches()
1819 || WHERE_PATTERN_NO_PARAM_IN_BRACKETS.matcher(where).matches())) {
1820 final int startIndex = Math.max(where.indexOf("'"),
1821 where.indexOf("\"")) + 1;
1822 final int endIndex = Math.max(where.lastIndexOf("'"),
1823 where.lastIndexOf("\""));
1824 name = where.substring(startIndex, endIndex);
1825 table = computeTableForSetting(uri, name);
Svetoslav28494652015-02-12 14:11:42 -08001826 return;
Svetoslav683914b2015-01-15 14:22:26 -08001827 } else if (supportAll && where == null && whereArgs == null) {
1828 name = null;
1829 table = computeTableForSetting(uri, null);
Svetoslav28494652015-02-12 14:11:42 -08001830 return;
Brad Fitzpatrick342984a2010-03-09 16:59:30 -08001831 }
Svetoslav683914b2015-01-15 14:22:26 -08001832 } break;
1833
Svetoslav28494652015-02-12 14:11:42 -08001834 case 2: {
1835 if (where == null && whereArgs == null) {
1836 name = uri.getPathSegments().get(1);
1837 table = computeTableForSetting(uri, name);
1838 return;
1839 }
1840 } break;
Brad Fitzpatrick1bd62bd2010-03-08 18:30:52 -08001841 }
Svetoslav28494652015-02-12 14:11:42 -08001842
1843 EventLogTags.writeUnsupportedSettingsQuery(
1844 uri.toSafeString(), where, Arrays.toString(whereArgs));
1845 String message = String.format( "Supported SQL:\n"
1846 + " uri content://some_table/some_property with null where and where args\n"
1847 + " uri content://some_table with query name=? and single name as arg\n"
1848 + " uri content://some_table with query name=some_name and null args\n"
1849 + " but got - uri:%1s, where:%2s whereArgs:%3s", uri, where,
1850 Arrays.toString(whereArgs));
1851 throw new IllegalArgumentException(message);
Brad Fitzpatrick1bd62bd2010-03-08 18:30:52 -08001852 }
1853
Svetoslav28494652015-02-12 14:11:42 -08001854 private static String computeTableForSetting(Uri uri, String name) {
Svetoslav683914b2015-01-15 14:22:26 -08001855 String table = getValidTableOrThrow(uri);
1856
1857 if (name != null) {
1858 if (sSystemMovedToSecureSettings.contains(name)) {
1859 table = TABLE_SECURE;
1860 }
1861
1862 if (sSystemMovedToGlobalSettings.contains(name)) {
1863 table = TABLE_GLOBAL;
1864 }
1865
1866 if (sSecureMovedToGlobalSettings.contains(name)) {
1867 table = TABLE_GLOBAL;
1868 }
1869
1870 if (sGlobalMovedToSecureSettings.contains(name)) {
1871 table = TABLE_SECURE;
1872 }
Brad Fitzpatrick1bd62bd2010-03-08 18:30:52 -08001873 }
Svetoslav683914b2015-01-15 14:22:26 -08001874
1875 return table;
1876 }
1877 }
1878
1879 final class SettingsRegistry {
1880 private static final String DROPBOX_TAG_USERLOG = "restricted_profile_ssaid";
1881
Svetoslav683914b2015-01-15 14:22:26 -08001882 private static final String SETTINGS_FILE_GLOBAL = "settings_global.xml";
1883 private static final String SETTINGS_FILE_SYSTEM = "settings_system.xml";
1884 private static final String SETTINGS_FILE_SECURE = "settings_secure.xml";
1885
1886 private final SparseArray<SettingsState> mSettingsStates = new SparseArray<>();
1887
Svet Ganov53a441c2016-04-19 19:38:00 -07001888 private GenerationRegistry mGenerationRegistry;
Svetoslav683914b2015-01-15 14:22:26 -08001889
Svetoslav7e0683b2015-08-03 16:02:52 -07001890 private final Handler mHandler;
1891
Svet Ganov53a441c2016-04-19 19:38:00 -07001892 private final BackupManager mBackupManager;
1893
Svetoslav683914b2015-01-15 14:22:26 -08001894 public SettingsRegistry() {
Svetoslav7e0683b2015-08-03 16:02:52 -07001895 mHandler = new MyHandler(getContext().getMainLooper());
Svet Ganov53a441c2016-04-19 19:38:00 -07001896 mGenerationRegistry = new GenerationRegistry(mLock);
1897 mBackupManager = new BackupManager(getContext());
Svetoslav683914b2015-01-15 14:22:26 -08001898 migrateAllLegacySettingsIfNeeded();
Brad Fitzpatrickf366a9b2010-08-24 16:14:07 -07001899 }
1900
Svetoslav683914b2015-01-15 14:22:26 -08001901 public List<String> getSettingsNamesLocked(int type, int userId) {
1902 final int key = makeKey(type, userId);
1903 SettingsState settingsState = peekSettingsStateLocked(key);
Dianne Hackborn32f40ee2016-10-20 15:54:14 -07001904 if (settingsState == null) {
1905 return new ArrayList<String>();
1906 }
Svetoslav683914b2015-01-15 14:22:26 -08001907 return settingsState.getSettingNamesLocked();
1908 }
1909
Dianne Hackborn32f40ee2016-10-20 15:54:14 -07001910 public SparseBooleanArray getKnownUsersLocked() {
1911 SparseBooleanArray users = new SparseBooleanArray();
1912 for (int i = mSettingsStates.size()-1; i >= 0; i--) {
1913 users.put(getUserIdFromKey(mSettingsStates.keyAt(i)), true);
1914 }
1915 return users;
1916 }
1917
Svetoslav683914b2015-01-15 14:22:26 -08001918 public SettingsState getSettingsLocked(int type, int userId) {
1919 final int key = makeKey(type, userId);
1920 return peekSettingsStateLocked(key);
1921 }
1922
Dianne Hackborn32f40ee2016-10-20 15:54:14 -07001923 public boolean ensureSettingsForUserLocked(int userId) {
1924 // First make sure this user actually exists.
1925 if (mUserManager.getUserInfo(userId) == null) {
1926 Slog.wtf(LOG_TAG, "Requested user " + userId + " does not exist");
1927 return false;
1928 }
1929
Svetoslav683914b2015-01-15 14:22:26 -08001930 // Migrate the setting for this user if needed.
1931 migrateLegacySettingsForUserIfNeededLocked(userId);
1932
1933 // Ensure global settings loaded if owner.
Xiaohui Chen43765b72015-08-31 10:57:33 -07001934 if (userId == UserHandle.USER_SYSTEM) {
1935 final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
Svetoslav683914b2015-01-15 14:22:26 -08001936 ensureSettingsStateLocked(globalKey);
1937 }
1938
1939 // Ensure secure settings loaded.
1940 final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
1941 ensureSettingsStateLocked(secureKey);
1942
1943 // Make sure the secure settings have an Android id set.
1944 SettingsState secureSettings = getSettingsLocked(SETTINGS_TYPE_SECURE, userId);
1945 ensureSecureSettingAndroidIdSetLocked(secureSettings);
1946
1947 // Ensure system settings loaded.
1948 final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
1949 ensureSettingsStateLocked(systemKey);
1950
1951 // Upgrade the settings to the latest version.
1952 UpgradeController upgrader = new UpgradeController(userId);
1953 upgrader.upgradeIfNeededLocked();
Dianne Hackborn32f40ee2016-10-20 15:54:14 -07001954 return true;
Svetoslav683914b2015-01-15 14:22:26 -08001955 }
1956
1957 private void ensureSettingsStateLocked(int key) {
1958 if (mSettingsStates.get(key) == null) {
1959 final int maxBytesPerPackage = getMaxBytesPerPackageForType(getTypeFromKey(key));
Svetoslav Ganove080da92016-12-21 17:10:35 -08001960 SettingsState settingsState = new SettingsState(getContext(), mLock,
1961 getSettingsFile(key), key, maxBytesPerPackage, mHandlerThread.getLooper());
Svetoslav683914b2015-01-15 14:22:26 -08001962 mSettingsStates.put(key, settingsState);
1963 }
1964 }
1965
1966 public void removeUserStateLocked(int userId, boolean permanently) {
1967 // We always keep the global settings in memory.
1968
1969 // Nuke system settings.
1970 final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
1971 final SettingsState systemSettingsState = mSettingsStates.get(systemKey);
1972 if (systemSettingsState != null) {
1973 if (permanently) {
1974 mSettingsStates.remove(systemKey);
1975 systemSettingsState.destroyLocked(null);
Brad Fitzpatrick342984a2010-03-09 16:59:30 -08001976 } else {
Svetoslav683914b2015-01-15 14:22:26 -08001977 systemSettingsState.destroyLocked(new Runnable() {
1978 @Override
1979 public void run() {
1980 mSettingsStates.remove(systemKey);
1981 }
1982 });
1983 }
1984 }
1985
1986 // Nuke secure settings.
1987 final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
1988 final SettingsState secureSettingsState = mSettingsStates.get(secureKey);
1989 if (secureSettingsState != null) {
1990 if (permanently) {
1991 mSettingsStates.remove(secureKey);
1992 secureSettingsState.destroyLocked(null);
1993 } else {
1994 secureSettingsState.destroyLocked(new Runnable() {
1995 @Override
1996 public void run() {
1997 mSettingsStates.remove(secureKey);
1998 }
1999 });
Brad Fitzpatrick342984a2010-03-09 16:59:30 -08002000 }
Brad Fitzpatrick1bd62bd2010-03-08 18:30:52 -08002001 }
Svet Ganov53a441c2016-04-19 19:38:00 -07002002
2003 // Nuke generation tracking data
2004 mGenerationRegistry.onUserRemoved(userId);
Brad Fitzpatrick1bd62bd2010-03-08 18:30:52 -08002005 }
2006
Svetoslav683914b2015-01-15 14:22:26 -08002007 public boolean insertSettingLocked(int type, int userId, String name, String value,
Svetoslav Ganove080da92016-12-21 17:10:35 -08002008 String tag, boolean makeDefault, String packageName, boolean forceNotify) {
Svetoslav683914b2015-01-15 14:22:26 -08002009 final int key = makeKey(type, userId);
2010
Svetoslav Ganove080da92016-12-21 17:10:35 -08002011 boolean success = false;
Svetoslav683914b2015-01-15 14:22:26 -08002012 SettingsState settingsState = peekSettingsStateLocked(key);
Svetoslav Ganove080da92016-12-21 17:10:35 -08002013 if (settingsState != null) {
2014 success = settingsState.insertSettingLocked(name, value,
2015 tag, makeDefault, packageName);
2016 }
Svetoslav683914b2015-01-15 14:22:26 -08002017
Svet Ganov53a441c2016-04-19 19:38:00 -07002018 if (forceNotify || success) {
Svetoslav683914b2015-01-15 14:22:26 -08002019 notifyForSettingsChange(key, name);
2020 }
2021 return success;
2022 }
2023
Svet Ganov53a441c2016-04-19 19:38:00 -07002024 public boolean deleteSettingLocked(int type, int userId, String name, boolean forceNotify) {
Svetoslav683914b2015-01-15 14:22:26 -08002025 final int key = makeKey(type, userId);
2026
Svetoslav Ganove080da92016-12-21 17:10:35 -08002027 boolean success = false;
Svetoslav683914b2015-01-15 14:22:26 -08002028 SettingsState settingsState = peekSettingsStateLocked(key);
Svetoslav Ganove080da92016-12-21 17:10:35 -08002029 if (settingsState != null) {
2030 success = settingsState.deleteSettingLocked(name);
Dianne Hackborn32f40ee2016-10-20 15:54:14 -07002031 }
Svetoslav683914b2015-01-15 14:22:26 -08002032
Svet Ganov53a441c2016-04-19 19:38:00 -07002033 if (forceNotify || success) {
Svetoslav683914b2015-01-15 14:22:26 -08002034 notifyForSettingsChange(key, name);
2035 }
2036 return success;
2037 }
2038
2039 public Setting getSettingLocked(int type, int userId, String name) {
2040 final int key = makeKey(type, userId);
2041
2042 SettingsState settingsState = peekSettingsStateLocked(key);
Dianne Hackborn32f40ee2016-10-20 15:54:14 -07002043 if (settingsState == null) {
2044 return null;
2045 }
Svetoslav683914b2015-01-15 14:22:26 -08002046 return settingsState.getSettingLocked(name);
2047 }
2048
2049 public boolean updateSettingLocked(int type, int userId, String name, String value,
Svetoslav Ganove080da92016-12-21 17:10:35 -08002050 String tag, boolean makeDefault, String packageName, boolean forceNotify) {
Svetoslav683914b2015-01-15 14:22:26 -08002051 final int key = makeKey(type, userId);
2052
Svetoslav Ganove080da92016-12-21 17:10:35 -08002053 boolean success = false;
Svetoslav683914b2015-01-15 14:22:26 -08002054 SettingsState settingsState = peekSettingsStateLocked(key);
Svetoslav Ganove080da92016-12-21 17:10:35 -08002055 if (settingsState != null) {
2056 success = settingsState.updateSettingLocked(name, value, tag,
2057 makeDefault, packageName);
2058 }
Svetoslav683914b2015-01-15 14:22:26 -08002059
Svet Ganov53a441c2016-04-19 19:38:00 -07002060 if (forceNotify || success) {
Svetoslav683914b2015-01-15 14:22:26 -08002061 notifyForSettingsChange(key, name);
2062 }
2063
2064 return success;
2065 }
2066
Svetoslav Ganove080da92016-12-21 17:10:35 -08002067 public void resetSettingsLocked(int type, int userId, String packageName, int mode,
2068 String tag) {
2069 final int key = makeKey(type, userId);
2070 SettingsState settingsState = peekSettingsStateLocked(key);
2071 if (settingsState == null) {
2072 return;
2073 }
2074
2075 switch (mode) {
2076 case Settings.RESET_MODE_PACKAGE_DEFAULTS: {
2077 for (String name : settingsState.getSettingNamesLocked()) {
2078 Setting setting = settingsState.getSettingLocked(name);
2079 if (packageName.equals(setting.getPackageName())) {
2080 if (tag != null && !tag.equals(setting.getTag())) {
2081 continue;
2082 }
2083 if (settingsState.resetSettingLocked(name, packageName)) {
2084 notifyForSettingsChange(key, name);
2085 }
2086 }
2087 }
2088 } break;
2089
2090 case Settings.RESET_MODE_UNTRUSTED_DEFAULTS: {
2091 for (String name : settingsState.getSettingNamesLocked()) {
2092 Setting setting = settingsState.getSettingLocked(name);
2093 if (!SettingsState.isSystemPackage(getContext(),
2094 setting.getPackageName())) {
2095 if (settingsState.resetSettingLocked(name, packageName)) {
2096 notifyForSettingsChange(key, name);
2097 }
2098 }
2099 }
2100 } break;
2101
2102 case Settings.RESET_MODE_UNTRUSTED_CHANGES: {
2103 for (String name : settingsState.getSettingNamesLocked()) {
2104 Setting setting = settingsState.getSettingLocked(name);
2105 if (!SettingsState.isSystemPackage(getContext(),
2106 setting.getPackageName())) {
2107 if (setting.isDefaultSystemSet()) {
2108 if (settingsState.resetSettingLocked(name, packageName)) {
2109 notifyForSettingsChange(key, name);
2110 }
2111 } else if (settingsState.deleteSettingLocked(name)) {
2112 notifyForSettingsChange(key, name);
2113 }
2114 }
2115 }
2116 } break;
2117
2118 case Settings.RESET_MODE_TRUSTED_DEFAULTS: {
2119 for (String name : settingsState.getSettingNamesLocked()) {
2120 Setting setting = settingsState.getSettingLocked(name);
2121 if (setting.isDefaultSystemSet()) {
2122 if (settingsState.resetSettingLocked(name, packageName)) {
2123 notifyForSettingsChange(key, name);
2124 }
2125 } else if (settingsState.deleteSettingLocked(name)) {
2126 notifyForSettingsChange(key, name);
2127 }
2128 }
2129 } break;
2130 }
2131 }
2132
Svetoslav683914b2015-01-15 14:22:26 -08002133 public void onPackageRemovedLocked(String packageName, int userId) {
Svet Ganov8de34802015-04-27 09:33:40 -07002134 // Global and secure settings are signature protected. Apps signed
2135 // by the platform certificate are generally not uninstalled and
2136 // the main exception is tests. We trust components signed
2137 // by the platform certificate and do not do a clean up after them.
Svetoslav683914b2015-01-15 14:22:26 -08002138
2139 final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
2140 SettingsState systemSettings = mSettingsStates.get(systemKey);
Svet Ganov8de34802015-04-27 09:33:40 -07002141 if (systemSettings != null) {
2142 systemSettings.onPackageRemovedLocked(packageName);
2143 }
Svetoslav683914b2015-01-15 14:22:26 -08002144 }
2145
2146 private SettingsState peekSettingsStateLocked(int key) {
2147 SettingsState settingsState = mSettingsStates.get(key);
2148 if (settingsState != null) {
2149 return settingsState;
2150 }
2151
Dianne Hackborn32f40ee2016-10-20 15:54:14 -07002152 if (!ensureSettingsForUserLocked(getUserIdFromKey(key))) {
2153 return null;
2154 }
Svetoslav683914b2015-01-15 14:22:26 -08002155 return mSettingsStates.get(key);
2156 }
2157
2158 private void migrateAllLegacySettingsIfNeeded() {
2159 synchronized (mLock) {
Xiaohui Chen43765b72015-08-31 10:57:33 -07002160 final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
Svetoslav683914b2015-01-15 14:22:26 -08002161 File globalFile = getSettingsFile(key);
2162 if (globalFile.exists()) {
2163 return;
2164 }
2165
2166 final long identity = Binder.clearCallingIdentity();
2167 try {
2168 List<UserInfo> users = mUserManager.getUsers(true);
2169
2170 final int userCount = users.size();
2171 for (int i = 0; i < userCount; i++) {
2172 final int userId = users.get(i).id;
2173
2174 DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId);
2175 SQLiteDatabase database = dbHelper.getWritableDatabase();
2176 migrateLegacySettingsForUserLocked(dbHelper, database, userId);
2177
2178 // Upgrade to the latest version.
2179 UpgradeController upgrader = new UpgradeController(userId);
2180 upgrader.upgradeIfNeededLocked();
2181
2182 // Drop from memory if not a running user.
2183 if (!mUserManager.isUserRunning(new UserHandle(userId))) {
2184 removeUserStateLocked(userId, false);
2185 }
2186 }
2187 } finally {
2188 Binder.restoreCallingIdentity(identity);
2189 }
2190 }
2191 }
2192
2193 private void migrateLegacySettingsForUserIfNeededLocked(int userId) {
2194 // Every user has secure settings and if no file we need to migrate.
2195 final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
2196 File secureFile = getSettingsFile(secureKey);
2197 if (secureFile.exists()) {
2198 return;
2199 }
2200
2201 DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId);
2202 SQLiteDatabase database = dbHelper.getWritableDatabase();
2203
2204 migrateLegacySettingsForUserLocked(dbHelper, database, userId);
2205 }
2206
2207 private void migrateLegacySettingsForUserLocked(DatabaseHelper dbHelper,
2208 SQLiteDatabase database, int userId) {
Amith Yamasanibf2ef612016-03-07 16:37:18 -08002209 // Move over the system settings.
2210 final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
2211 ensureSettingsStateLocked(systemKey);
2212 SettingsState systemSettings = mSettingsStates.get(systemKey);
2213 migrateLegacySettingsLocked(systemSettings, database, TABLE_SYSTEM);
2214 systemSettings.persistSyncLocked();
Svetoslav683914b2015-01-15 14:22:26 -08002215
2216 // Move over the secure settings.
Amith Yamasanibf2ef612016-03-07 16:37:18 -08002217 // Do this after System settings, since this is the first thing we check when deciding
2218 // to skip over migration from db to xml for a secondary user.
Svetoslav683914b2015-01-15 14:22:26 -08002219 final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
2220 ensureSettingsStateLocked(secureKey);
2221 SettingsState secureSettings = mSettingsStates.get(secureKey);
2222 migrateLegacySettingsLocked(secureSettings, database, TABLE_SECURE);
2223 ensureSecureSettingAndroidIdSetLocked(secureSettings);
2224 secureSettings.persistSyncLocked();
2225
Amith Yamasanibf2ef612016-03-07 16:37:18 -08002226 // Move over the global settings if owner.
2227 // Do this last, since this is the first thing we check when deciding
2228 // to skip over migration from db to xml for owner user.
2229 if (userId == UserHandle.USER_SYSTEM) {
2230 final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, userId);
2231 ensureSettingsStateLocked(globalKey);
2232 SettingsState globalSettings = mSettingsStates.get(globalKey);
2233 migrateLegacySettingsLocked(globalSettings, database, TABLE_GLOBAL);
2234 globalSettings.persistSyncLocked();
2235 }
Svetoslav683914b2015-01-15 14:22:26 -08002236
2237 // Drop the database as now all is moved and persisted.
2238 if (DROP_DATABASE_ON_MIGRATION) {
2239 dbHelper.dropDatabase();
2240 } else {
2241 dbHelper.backupDatabase();
2242 }
2243 }
2244
2245 private void migrateLegacySettingsLocked(SettingsState settingsState,
2246 SQLiteDatabase database, String table) {
2247 SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
2248 queryBuilder.setTables(table);
2249
2250 Cursor cursor = queryBuilder.query(database, ALL_COLUMNS,
2251 null, null, null, null, null);
2252
2253 if (cursor == null) {
2254 return;
2255 }
2256
2257 try {
2258 if (!cursor.moveToFirst()) {
2259 return;
2260 }
2261
2262 final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME);
2263 final int valueColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.VALUE);
2264
2265 settingsState.setVersionLocked(database.getVersion());
2266
2267 while (!cursor.isAfterLast()) {
2268 String name = cursor.getString(nameColumnIdx);
2269 String value = cursor.getString(valueColumnIdx);
Svetoslav Ganove080da92016-12-21 17:10:35 -08002270 settingsState.insertSettingLocked(name, value, null, true,
Svetoslav683914b2015-01-15 14:22:26 -08002271 SettingsState.SYSTEM_PACKAGE_NAME);
2272 cursor.moveToNext();
2273 }
2274 } finally {
2275 cursor.close();
2276 }
2277 }
2278
2279 private void ensureSecureSettingAndroidIdSetLocked(SettingsState secureSettings) {
2280 Setting value = secureSettings.getSettingLocked(Settings.Secure.ANDROID_ID);
2281
Seigo Nonaka6e5b6022016-04-27 16:32:44 +09002282 if (!value.isNull()) {
Svetoslav683914b2015-01-15 14:22:26 -08002283 return;
2284 }
2285
2286 final int userId = getUserIdFromKey(secureSettings.mKey);
2287
2288 final UserInfo user;
2289 final long identity = Binder.clearCallingIdentity();
2290 try {
2291 user = mUserManager.getUserInfo(userId);
2292 } finally {
2293 Binder.restoreCallingIdentity(identity);
2294 }
2295 if (user == null) {
2296 // Can happen due to races when deleting users - treat as benign.
2297 return;
2298 }
2299
2300 String androidId = Long.toHexString(new SecureRandom().nextLong());
2301 secureSettings.insertSettingLocked(Settings.Secure.ANDROID_ID, androidId,
Svetoslav Ganove080da92016-12-21 17:10:35 -08002302 null, true, SettingsState.SYSTEM_PACKAGE_NAME);
Svetoslav683914b2015-01-15 14:22:26 -08002303
2304 Slog.d(LOG_TAG, "Generated and saved new ANDROID_ID [" + androidId
2305 + "] for user " + userId);
2306
2307 // Write a drop box entry if it's a restricted profile
2308 if (user.isRestricted()) {
2309 DropBoxManager dbm = (DropBoxManager) getContext().getSystemService(
2310 Context.DROPBOX_SERVICE);
2311 if (dbm != null && dbm.isTagEnabled(DROPBOX_TAG_USERLOG)) {
2312 dbm.addText(DROPBOX_TAG_USERLOG, System.currentTimeMillis()
2313 + "," + DROPBOX_TAG_USERLOG + "," + androidId + "\n");
2314 }
2315 }
2316 }
2317
2318 private void notifyForSettingsChange(int key, String name) {
Svetoslav683914b2015-01-15 14:22:26 -08002319 final int userId = getUserIdFromKey(key);
2320 Uri uri = getNotificationUriFor(key, name);
2321
Phil Weaver83fec002016-05-11 10:55:29 -07002322 mGenerationRegistry.incrementGeneration(key);
2323
Svetoslav7e0683b2015-08-03 16:02:52 -07002324 mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
2325 userId, 0, uri).sendToTarget();
2326
Nicolas Prevot310e1ee2015-07-02 14:03:06 +01002327 if (isSecureSettingsKey(key)) {
Svet Ganov53a441c2016-04-19 19:38:00 -07002328 maybeNotifyProfiles(getTypeFromKey(key), userId, uri, name,
2329 sSecureCloneToManagedSettings);
Nicolas Prevot310e1ee2015-07-02 14:03:06 +01002330 } else if (isSystemSettingsKey(key)) {
Svet Ganov53a441c2016-04-19 19:38:00 -07002331 maybeNotifyProfiles(getTypeFromKey(key), userId, uri, name,
2332 sSystemCloneToManagedSettings);
Nicolas Prevot310e1ee2015-07-02 14:03:06 +01002333 }
Svet Ganov53a441c2016-04-19 19:38:00 -07002334
Svet Ganov53a441c2016-04-19 19:38:00 -07002335 mHandler.obtainMessage(MyHandler.MSG_NOTIFY_DATA_CHANGED).sendToTarget();
Nicolas Prevot310e1ee2015-07-02 14:03:06 +01002336 }
2337
Svet Ganov53a441c2016-04-19 19:38:00 -07002338 private void maybeNotifyProfiles(int type, int userId, Uri uri, String name,
Nicolas Prevot310e1ee2015-07-02 14:03:06 +01002339 Set<String> keysCloned) {
2340 if (keysCloned.contains(name)) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -07002341 for (int profileId : mUserManager.getProfileIdsWithDisabled(userId)) {
Nicolas Prevot310e1ee2015-07-02 14:03:06 +01002342 // the notification for userId has already been sent.
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -07002343 if (profileId != userId) {
Svetoslav7e0683b2015-08-03 16:02:52 -07002344 mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -07002345 profileId, 0, uri).sendToTarget();
Svet Ganov53a441c2016-04-19 19:38:00 -07002346 final int key = makeKey(type, profileId);
2347 mGenerationRegistry.incrementGeneration(key);
2348
2349 mHandler.obtainMessage(MyHandler.MSG_NOTIFY_DATA_CHANGED).sendToTarget();
Nicolas Prevot310e1ee2015-07-02 14:03:06 +01002350 }
2351 }
2352 }
Svetoslav683914b2015-01-15 14:22:26 -08002353 }
2354
Svetoslav683914b2015-01-15 14:22:26 -08002355 private boolean isGlobalSettingsKey(int key) {
2356 return getTypeFromKey(key) == SETTINGS_TYPE_GLOBAL;
2357 }
2358
2359 private boolean isSystemSettingsKey(int key) {
2360 return getTypeFromKey(key) == SETTINGS_TYPE_SYSTEM;
2361 }
2362
2363 private boolean isSecureSettingsKey(int key) {
2364 return getTypeFromKey(key) == SETTINGS_TYPE_SECURE;
2365 }
2366
2367 private File getSettingsFile(int key) {
2368 if (isGlobalSettingsKey(key)) {
2369 final int userId = getUserIdFromKey(key);
2370 return new File(Environment.getUserSystemDirectory(userId),
2371 SETTINGS_FILE_GLOBAL);
2372 } else if (isSystemSettingsKey(key)) {
2373 final int userId = getUserIdFromKey(key);
2374 return new File(Environment.getUserSystemDirectory(userId),
2375 SETTINGS_FILE_SYSTEM);
2376 } else if (isSecureSettingsKey(key)) {
2377 final int userId = getUserIdFromKey(key);
2378 return new File(Environment.getUserSystemDirectory(userId),
2379 SETTINGS_FILE_SECURE);
2380 } else {
2381 throw new IllegalArgumentException("Invalid settings key:" + key);
2382 }
2383 }
2384
2385 private Uri getNotificationUriFor(int key, String name) {
2386 if (isGlobalSettingsKey(key)) {
2387 return (name != null) ? Uri.withAppendedPath(Settings.Global.CONTENT_URI, name)
2388 : Settings.Global.CONTENT_URI;
2389 } else if (isSecureSettingsKey(key)) {
2390 return (name != null) ? Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name)
2391 : Settings.Secure.CONTENT_URI;
2392 } else if (isSystemSettingsKey(key)) {
2393 return (name != null) ? Uri.withAppendedPath(Settings.System.CONTENT_URI, name)
2394 : Settings.System.CONTENT_URI;
2395 } else {
2396 throw new IllegalArgumentException("Invalid settings key:" + key);
2397 }
2398 }
2399
2400 private int getMaxBytesPerPackageForType(int type) {
2401 switch (type) {
2402 case SETTINGS_TYPE_GLOBAL:
2403 case SETTINGS_TYPE_SECURE: {
2404 return SettingsState.MAX_BYTES_PER_APP_PACKAGE_UNLIMITED;
2405 }
2406
2407 default: {
2408 return SettingsState.MAX_BYTES_PER_APP_PACKAGE_LIMITED;
2409 }
2410 }
2411 }
2412
Svetoslav7e0683b2015-08-03 16:02:52 -07002413 private final class MyHandler extends Handler {
2414 private static final int MSG_NOTIFY_URI_CHANGED = 1;
2415 private static final int MSG_NOTIFY_DATA_CHANGED = 2;
2416
2417 public MyHandler(Looper looper) {
2418 super(looper);
2419 }
2420
2421 @Override
2422 public void handleMessage(Message msg) {
2423 switch (msg.what) {
2424 case MSG_NOTIFY_URI_CHANGED: {
2425 final int userId = msg.arg1;
2426 Uri uri = (Uri) msg.obj;
2427 getContext().getContentResolver().notifyChange(uri, null, true, userId);
2428 if (DEBUG) {
2429 Slog.v(LOG_TAG, "Notifying for " + userId + ": " + uri);
2430 }
2431 } break;
2432
2433 case MSG_NOTIFY_DATA_CHANGED: {
2434 mBackupManager.dataChanged();
2435 } break;
2436 }
2437 }
2438 }
2439
Svetoslav683914b2015-01-15 14:22:26 -08002440 private final class UpgradeController {
Jeremy Joslin8bdad342016-12-14 11:46:47 -08002441 private static final int SETTINGS_VERSION = 136;
Svetoslav683914b2015-01-15 14:22:26 -08002442
2443 private final int mUserId;
2444
2445 public UpgradeController(int userId) {
2446 mUserId = userId;
2447 }
2448
2449 public void upgradeIfNeededLocked() {
2450 // The version of all settings for a user is the same (all users have secure).
2451 SettingsState secureSettings = getSettingsLocked(
Svet Ganov53a441c2016-04-19 19:38:00 -07002452 SETTINGS_TYPE_SECURE, mUserId);
Svetoslav683914b2015-01-15 14:22:26 -08002453
2454 // Try an update from the current state.
2455 final int oldVersion = secureSettings.getVersionLocked();
2456 final int newVersion = SETTINGS_VERSION;
2457
Svet Ganovc9755bc2015-03-28 13:21:22 -07002458 // If up do date - done.
Svetoslav683914b2015-01-15 14:22:26 -08002459 if (oldVersion == newVersion) {
2460 return;
2461 }
2462
2463 // Try to upgrade.
2464 final int curVersion = onUpgradeLocked(mUserId, oldVersion, newVersion);
2465
2466 // If upgrade failed start from scratch and upgrade.
2467 if (curVersion != newVersion) {
2468 // Drop state we have for this user.
2469 removeUserStateLocked(mUserId, true);
2470
2471 // Recreate the database.
2472 DatabaseHelper dbHelper = new DatabaseHelper(getContext(), mUserId);
2473 SQLiteDatabase database = dbHelper.getWritableDatabase();
2474 dbHelper.recreateDatabase(database, newVersion, curVersion, oldVersion);
2475
2476 // Migrate the settings for this user.
2477 migrateLegacySettingsForUserLocked(dbHelper, database, mUserId);
2478
2479 // Now upgrade should work fine.
2480 onUpgradeLocked(mUserId, oldVersion, newVersion);
Svetoslav Ganov264c7a92016-08-24 17:31:14 -07002481
2482 // Make a note what happened, so we don't wonder why data was lost
2483 String reason = "Settings rebuilt! Current version: "
2484 + curVersion + " while expected: " + newVersion;
2485 getGlobalSettingsLocked().insertSettingLocked(
Svetoslav Ganove080da92016-12-21 17:10:35 -08002486 Settings.Global.DATABASE_DOWNGRADE_REASON,
2487 reason, null, true, SettingsState.SYSTEM_PACKAGE_NAME);
Svetoslav683914b2015-01-15 14:22:26 -08002488 }
2489
2490 // Set the global settings version if owner.
Xiaohui Chen43765b72015-08-31 10:57:33 -07002491 if (mUserId == UserHandle.USER_SYSTEM) {
Svetoslav683914b2015-01-15 14:22:26 -08002492 SettingsState globalSettings = getSettingsLocked(
Svet Ganov53a441c2016-04-19 19:38:00 -07002493 SETTINGS_TYPE_GLOBAL, mUserId);
Svetoslav683914b2015-01-15 14:22:26 -08002494 globalSettings.setVersionLocked(newVersion);
2495 }
2496
2497 // Set the secure settings version.
2498 secureSettings.setVersionLocked(newVersion);
2499
2500 // Set the system settings version.
2501 SettingsState systemSettings = getSettingsLocked(
Svet Ganov53a441c2016-04-19 19:38:00 -07002502 SETTINGS_TYPE_SYSTEM, mUserId);
Svetoslav683914b2015-01-15 14:22:26 -08002503 systemSettings.setVersionLocked(newVersion);
2504 }
2505
2506 private SettingsState getGlobalSettingsLocked() {
Xiaohui Chen43765b72015-08-31 10:57:33 -07002507 return getSettingsLocked(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
Svetoslav683914b2015-01-15 14:22:26 -08002508 }
2509
2510 private SettingsState getSecureSettingsLocked(int userId) {
2511 return getSettingsLocked(SETTINGS_TYPE_SECURE, userId);
2512 }
2513
2514 private SettingsState getSystemSettingsLocked(int userId) {
2515 return getSettingsLocked(SETTINGS_TYPE_SYSTEM, userId);
2516 }
2517
Jeff Brown503cffc2015-03-26 18:08:51 -07002518 /**
2519 * You must perform all necessary mutations to bring the settings
2520 * for this user from the old to the new version. When you add a new
2521 * upgrade step you *must* update SETTINGS_VERSION.
2522 *
2523 * This is an example of moving a setting from secure to global.
2524 *
2525 * // v119: Example settings changes.
2526 * if (currentVersion == 118) {
2527 * if (userId == UserHandle.USER_OWNER) {
2528 * // Remove from the secure settings.
2529 * SettingsState secureSettings = getSecureSettingsLocked(userId);
2530 * String name = "example_setting_to_move";
2531 * String value = secureSettings.getSetting(name);
2532 * secureSettings.deleteSetting(name);
2533 *
2534 * // Add to the global settings.
2535 * SettingsState globalSettings = getGlobalSettingsLocked();
2536 * globalSettings.insertSetting(name, value, SettingsState.SYSTEM_PACKAGE_NAME);
2537 * }
2538 *
2539 * // Update the current version.
2540 * currentVersion = 119;
2541 * }
2542 */
Svetoslav683914b2015-01-15 14:22:26 -08002543 private int onUpgradeLocked(int userId, int oldVersion, int newVersion) {
2544 if (DEBUG) {
2545 Slog.w(LOG_TAG, "Upgrading settings for user: " + userId + " from version: "
2546 + oldVersion + " to version: " + newVersion);
2547 }
2548
Jeff Brown503cffc2015-03-26 18:08:51 -07002549 int currentVersion = oldVersion;
Svetoslav683914b2015-01-15 14:22:26 -08002550
John Spurlocke11ae112015-05-11 16:09:03 -04002551 // v119: Reset zen + ringer mode.
2552 if (currentVersion == 118) {
Xiaohui Chen43765b72015-08-31 10:57:33 -07002553 if (userId == UserHandle.USER_SYSTEM) {
John Spurlocke11ae112015-05-11 16:09:03 -04002554 final SettingsState globalSettings = getGlobalSettingsLocked();
2555 globalSettings.updateSettingLocked(Settings.Global.ZEN_MODE,
Svetoslav Ganove080da92016-12-21 17:10:35 -08002556 Integer.toString(Settings.Global.ZEN_MODE_OFF), null,
2557 true, SettingsState.SYSTEM_PACKAGE_NAME);
John Spurlocke11ae112015-05-11 16:09:03 -04002558 globalSettings.updateSettingLocked(Settings.Global.MODE_RINGER,
Svetoslav Ganove080da92016-12-21 17:10:35 -08002559 Integer.toString(AudioManager.RINGER_MODE_NORMAL), null,
2560 true, SettingsState.SYSTEM_PACKAGE_NAME);
John Spurlocke11ae112015-05-11 16:09:03 -04002561 }
2562 currentVersion = 119;
2563 }
2564
Jason Monk27bbb2d2015-03-31 16:46:39 -04002565 // v120: Add double tap to wake setting.
2566 if (currentVersion == 119) {
2567 SettingsState secureSettings = getSecureSettingsLocked(userId);
2568 secureSettings.insertSettingLocked(Settings.Secure.DOUBLE_TAP_TO_WAKE,
2569 getContext().getResources().getBoolean(
Svetoslav Ganove080da92016-12-21 17:10:35 -08002570 R.bool.def_double_tap_to_wake) ? "1" : "0", null, true,
Jason Monk27bbb2d2015-03-31 16:46:39 -04002571 SettingsState.SYSTEM_PACKAGE_NAME);
2572
2573 currentVersion = 120;
2574 }
2575
Svetoslav7e0683b2015-08-03 16:02:52 -07002576 if (currentVersion == 120) {
2577 // Before 121, we used a different string encoding logic. We just bump the
2578 // version here; SettingsState knows how to handle pre-version 120 files.
2579 currentVersion = 121;
2580 }
Makoto Onuki3a2c35782015-06-18 11:21:58 -07002581
Martijn Coenen7ab4b7f2015-07-27 15:58:32 +02002582 if (currentVersion == 121) {
2583 // Version 122: allow OEMs to set a default payment component in resources.
2584 // Note that we only write the default if no default has been set;
2585 // if there is, we just leave the default at whatever it currently is.
2586 final SettingsState secureSettings = getSecureSettingsLocked(userId);
2587 String defaultComponent = (getContext().getResources().getString(
2588 R.string.def_nfc_payment_component));
2589 Setting currentSetting = secureSettings.getSettingLocked(
2590 Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT);
2591 if (defaultComponent != null && !defaultComponent.isEmpty() &&
Svetoslav Ganovfedb2302016-04-26 18:36:42 -07002592 currentSetting.isNull()) {
Martijn Coenen7ab4b7f2015-07-27 15:58:32 +02002593 secureSettings.insertSettingLocked(
2594 Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT,
Svetoslav Ganove080da92016-12-21 17:10:35 -08002595 defaultComponent, null, true, SettingsState.SYSTEM_PACKAGE_NAME);
Martijn Coenen7ab4b7f2015-07-27 15:58:32 +02002596 }
2597 currentVersion = 122;
2598 }
Suprabh Shukla269c11e2015-12-02 16:51:16 -08002599
2600 if (currentVersion == 122) {
2601 // Version 123: Adding a default value for the ability to add a user from
2602 // the lock screen.
2603 if (userId == UserHandle.USER_SYSTEM) {
2604 final SettingsState globalSettings = getGlobalSettingsLocked();
2605 Setting currentSetting = globalSettings.getSettingLocked(
2606 Settings.Global.ADD_USERS_WHEN_LOCKED);
Svetoslav Ganovfedb2302016-04-26 18:36:42 -07002607 if (currentSetting.isNull()) {
Suprabh Shukla269c11e2015-12-02 16:51:16 -08002608 globalSettings.insertSettingLocked(
2609 Settings.Global.ADD_USERS_WHEN_LOCKED,
2610 getContext().getResources().getBoolean(
2611 R.bool.def_add_users_from_lockscreen) ? "1" : "0",
Svetoslav Ganove080da92016-12-21 17:10:35 -08002612 null, true, SettingsState.SYSTEM_PACKAGE_NAME);
Suprabh Shukla269c11e2015-12-02 16:51:16 -08002613 }
2614 }
2615 currentVersion = 123;
2616 }
Bryce Leebd179282015-12-17 19:01:37 -08002617
2618 if (currentVersion == 123) {
Bryce Leeec85f342015-12-16 13:32:28 -08002619 final SettingsState globalSettings = getGlobalSettingsLocked();
2620 String defaultDisabledProfiles = (getContext().getResources().getString(
2621 R.string.def_bluetooth_disabled_profiles));
2622 globalSettings.insertSettingLocked(Settings.Global.BLUETOOTH_DISABLED_PROFILES,
Svetoslav Ganove080da92016-12-21 17:10:35 -08002623 defaultDisabledProfiles, null, true, SettingsState.SYSTEM_PACKAGE_NAME);
Bryce Leebd179282015-12-17 19:01:37 -08002624 currentVersion = 124;
Bryce Leeec85f342015-12-16 13:32:28 -08002625 }
2626
Prathmesh Prabhude16b862016-03-04 15:22:24 -08002627 if (currentVersion == 124) {
2628 // Version 124: allow OEMs to set a default value for whether IME should be
2629 // shown when a physical keyboard is connected.
2630 final SettingsState secureSettings = getSecureSettingsLocked(userId);
2631 Setting currentSetting = secureSettings.getSettingLocked(
2632 Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
Svetoslav Ganovfedb2302016-04-26 18:36:42 -07002633 if (currentSetting.isNull()) {
Prathmesh Prabhude16b862016-03-04 15:22:24 -08002634 secureSettings.insertSettingLocked(
2635 Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
2636 getContext().getResources().getBoolean(
2637 R.bool.def_show_ime_with_hard_keyboard) ? "1" : "0",
Svetoslav Ganove080da92016-12-21 17:10:35 -08002638 null, true, SettingsState.SYSTEM_PACKAGE_NAME);
Prathmesh Prabhude16b862016-03-04 15:22:24 -08002639 }
2640 currentVersion = 125;
2641 }
2642
Ruben Brunk98576cf2016-03-07 18:54:28 -08002643 if (currentVersion == 125) {
2644 // Version 125: Allow OEMs to set the default VR service.
2645 final SettingsState secureSettings = getSecureSettingsLocked(userId);
2646
2647 Setting currentSetting = secureSettings.getSettingLocked(
2648 Settings.Secure.ENABLED_VR_LISTENERS);
Svetoslav Ganovfedb2302016-04-26 18:36:42 -07002649 if (currentSetting.isNull()) {
Ruben Brunk98576cf2016-03-07 18:54:28 -08002650 ArraySet<ComponentName> l =
2651 SystemConfig.getInstance().getDefaultVrComponents();
2652
2653 if (l != null && !l.isEmpty()) {
2654 StringBuilder b = new StringBuilder();
2655 boolean start = true;
2656 for (ComponentName c : l) {
2657 if (!start) {
2658 b.append(':');
2659 }
2660 b.append(c.flattenToString());
2661 start = false;
2662 }
2663 secureSettings.insertSettingLocked(
2664 Settings.Secure.ENABLED_VR_LISTENERS, b.toString(),
Svetoslav Ganove080da92016-12-21 17:10:35 -08002665 null, true, SettingsState.SYSTEM_PACKAGE_NAME);
Ruben Brunk98576cf2016-03-07 18:54:28 -08002666 }
2667
2668 }
2669 currentVersion = 126;
2670 }
2671
Daniel U02ba6122016-04-01 18:41:42 +01002672 if (currentVersion == 126) {
2673 // Version 126: copy the primary values of LOCK_SCREEN_SHOW_NOTIFICATIONS and
2674 // LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS into managed profile.
2675 if (mUserManager.isManagedProfile(userId)) {
2676 final SettingsState systemSecureSettings =
2677 getSecureSettingsLocked(UserHandle.USER_SYSTEM);
2678
2679 final Setting showNotifications = systemSecureSettings.getSettingLocked(
2680 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS);
Seigo Nonaka6e5b6022016-04-27 16:32:44 +09002681 if (!showNotifications.isNull()) {
Daniel U02ba6122016-04-01 18:41:42 +01002682 final SettingsState secureSettings = getSecureSettingsLocked(userId);
2683 secureSettings.insertSettingLocked(
2684 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
Svetoslav Ganove080da92016-12-21 17:10:35 -08002685 showNotifications.getValue(), null, true,
Daniel U02ba6122016-04-01 18:41:42 +01002686 SettingsState.SYSTEM_PACKAGE_NAME);
2687 }
2688
2689 final Setting allowPrivate = systemSecureSettings.getSettingLocked(
2690 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
Seigo Nonaka6e5b6022016-04-27 16:32:44 +09002691 if (!allowPrivate.isNull()) {
Daniel U02ba6122016-04-01 18:41:42 +01002692 final SettingsState secureSettings = getSecureSettingsLocked(userId);
2693 secureSettings.insertSettingLocked(
2694 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
Svetoslav Ganove080da92016-12-21 17:10:35 -08002695 allowPrivate.getValue(), null, true,
Daniel U02ba6122016-04-01 18:41:42 +01002696 SettingsState.SYSTEM_PACKAGE_NAME);
2697 }
2698 }
2699 currentVersion = 127;
2700 }
2701
Steven Ngdc20ba62016-04-26 18:19:04 +01002702 if (currentVersion == 127) {
Mahaver Chopra3d9805d2016-07-07 16:25:05 +01002703 // version 127 is no longer used.
Steven Ngdc20ba62016-04-26 18:19:04 +01002704 currentVersion = 128;
2705 }
2706
Julia Reynolds1f721e12016-07-11 08:50:58 -04002707 if (currentVersion == 128) {
2708 // Version 128: Allow OEMs to grant DND access to default apps. Note that
2709 // the new apps are appended to the list of already approved apps.
2710 final SettingsState systemSecureSettings =
2711 getSecureSettingsLocked(userId);
2712
2713 final Setting policyAccess = systemSecureSettings.getSettingLocked(
2714 Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES);
2715 String defaultPolicyAccess = getContext().getResources().getString(
2716 com.android.internal.R.string.config_defaultDndAccessPackages);
2717 if (!TextUtils.isEmpty(defaultPolicyAccess)) {
2718 if (policyAccess.isNull()) {
2719 systemSecureSettings.insertSettingLocked(
2720 Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES,
Svetoslav Ganove080da92016-12-21 17:10:35 -08002721 defaultPolicyAccess, null, true,
Julia Reynolds1f721e12016-07-11 08:50:58 -04002722 SettingsState.SYSTEM_PACKAGE_NAME);
2723 } else {
2724 StringBuilder currentSetting =
2725 new StringBuilder(policyAccess.getValue());
2726 currentSetting.append(":");
2727 currentSetting.append(defaultPolicyAccess);
2728 systemSecureSettings.updateSettingLocked(
2729 Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES,
Svetoslav Ganove080da92016-12-21 17:10:35 -08002730 currentSetting.toString(), null, true,
Julia Reynolds1f721e12016-07-11 08:50:58 -04002731 SettingsState.SYSTEM_PACKAGE_NAME);
2732 }
2733 }
2734
2735 currentVersion = 129;
2736 }
2737
Dan Sandler71f85e92016-07-20 13:46:05 -04002738 if (currentVersion == 129) {
2739 // default longpress timeout changed from 500 to 400. If unchanged from the old
2740 // default, update to the new default.
2741 final SettingsState systemSecureSettings =
2742 getSecureSettingsLocked(userId);
2743 final String oldValue = systemSecureSettings.getSettingLocked(
2744 Settings.Secure.LONG_PRESS_TIMEOUT).getValue();
2745 if (TextUtils.equals("500", oldValue)) {
2746 systemSecureSettings.insertSettingLocked(
2747 Settings.Secure.LONG_PRESS_TIMEOUT,
2748 String.valueOf(getContext().getResources().getInteger(
2749 R.integer.def_long_press_timeout_millis)),
Svetoslav Ganove080da92016-12-21 17:10:35 -08002750 null, true, SettingsState.SYSTEM_PACKAGE_NAME);
Dan Sandler71f85e92016-07-20 13:46:05 -04002751 }
2752 currentVersion = 130;
2753 }
2754
Anthony Hugh96e9cc52016-07-12 15:17:24 -07002755 if (currentVersion == 130) {
Adrian Roos69741a22016-10-21 14:49:17 -07002756 // Split Ambient settings
2757 final SettingsState secureSettings = getSecureSettingsLocked(userId);
2758 boolean dozeExplicitlyDisabled = "0".equals(secureSettings.
2759 getSettingLocked(Settings.Secure.DOZE_ENABLED).getValue());
2760
2761 if (dozeExplicitlyDisabled) {
2762 secureSettings.insertSettingLocked(Settings.Secure.DOZE_PULSE_ON_PICK_UP,
Svetoslav Ganove080da92016-12-21 17:10:35 -08002763 "0", null, true, SettingsState.SYSTEM_PACKAGE_NAME);
Adrian Roos69741a22016-10-21 14:49:17 -07002764 secureSettings.insertSettingLocked(Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP,
Svetoslav Ganove080da92016-12-21 17:10:35 -08002765 "0", null, true, SettingsState.SYSTEM_PACKAGE_NAME);
Adrian Roos69741a22016-10-21 14:49:17 -07002766 }
2767 currentVersion = 131;
2768 }
2769
2770 if (currentVersion == 131) {
Anthony Hugh96e9cc52016-07-12 15:17:24 -07002771 // Initialize new multi-press timeout to default value
2772 final SettingsState systemSecureSettings = getSecureSettingsLocked(userId);
2773 final String oldValue = systemSecureSettings.getSettingLocked(
2774 Settings.Secure.MULTI_PRESS_TIMEOUT).getValue();
2775 if (TextUtils.equals(null, oldValue)) {
2776 systemSecureSettings.insertSettingLocked(
2777 Settings.Secure.MULTI_PRESS_TIMEOUT,
2778 String.valueOf(getContext().getResources().getInteger(
2779 R.integer.def_multi_press_timeout_millis)),
Svetoslav Ganove080da92016-12-21 17:10:35 -08002780 null, true, SettingsState.SYSTEM_PACKAGE_NAME);
Anthony Hugh96e9cc52016-07-12 15:17:24 -07002781 }
2782
Adrian Roos69741a22016-10-21 14:49:17 -07002783 currentVersion = 132;
Anthony Hugh96e9cc52016-07-12 15:17:24 -07002784 }
2785
Adrian Roos69741a22016-10-21 14:49:17 -07002786 if (currentVersion == 132) {
2787 // Version 132: Allow managed profile to optionally use the parent's ringtones
Andre Lagoea35e072016-08-04 13:41:13 +01002788 final SettingsState systemSecureSettings = getSecureSettingsLocked(userId);
2789 String defaultSyncParentSounds = (getContext().getResources()
2790 .getBoolean(R.bool.def_sync_parent_sounds) ? "1" : "0");
2791 systemSecureSettings.insertSettingLocked(
Svetoslav Ganove080da92016-12-21 17:10:35 -08002792 Settings.Secure.SYNC_PARENT_SOUNDS, defaultSyncParentSounds,
2793 null, true, SettingsState.SYSTEM_PACKAGE_NAME);
Adrian Roos69741a22016-10-21 14:49:17 -07002794 currentVersion = 133;
Andre Lagoea35e072016-08-04 13:41:13 +01002795 }
2796
Adrian Roos69741a22016-10-21 14:49:17 -07002797 if (currentVersion == 133) {
2798 // Version 133: Add default end button behavior
Keun-young Parkec7a1182016-10-18 11:52:38 -07002799 final SettingsState systemSettings = getSystemSettingsLocked(userId);
2800 if (systemSettings.getSettingLocked(Settings.System.END_BUTTON_BEHAVIOR) ==
2801 null) {
2802 String defaultEndButtonBehavior = Integer.toString(getContext()
2803 .getResources().getInteger(R.integer.def_end_button_behavior));
2804 systemSettings.insertSettingLocked(Settings.System.END_BUTTON_BEHAVIOR,
Svetoslav Ganove080da92016-12-21 17:10:35 -08002805 defaultEndButtonBehavior, null, true,
2806 SettingsState.SYSTEM_PACKAGE_NAME);
Keun-young Parkec7a1182016-10-18 11:52:38 -07002807 }
Adrian Roos69741a22016-10-21 14:49:17 -07002808 currentVersion = 134;
Keun-young Parkec7a1182016-10-18 11:52:38 -07002809 }
2810
Phil Weaver89e3ffc2016-09-19 13:51:10 -07002811 if (currentVersion == 134) {
2812 // Remove setting that specifies if magnification values should be preserved.
2813 // This setting defaulted to true and never has a UI.
2814 getSecureSettingsLocked(userId).deleteSettingLocked(
2815 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE);
2816 currentVersion = 135;
2817 }
2818
Jeremy Joslin8bdad342016-12-14 11:46:47 -08002819 if (currentVersion == 135) {
2820 // Version 135: Migrating the NETWORK_SCORER_APP setting to the
2821 // NETWORK_RECOMMENDATIONS_ENABLED setting.
2822 if (userId == UserHandle.USER_SYSTEM) {
2823 final SettingsState globalSettings = getGlobalSettingsLocked();
2824 Setting currentSetting = globalSettings.getSettingLocked(
2825 Global.NETWORK_SCORER_APP);
2826 if (!currentSetting.isNull()) {
2827 // A scorer was set so enable recommendations.
2828 globalSettings.insertSettingLocked(
2829 Global.NETWORK_RECOMMENDATIONS_ENABLED,
Svetoslav Ganove080da92016-12-21 17:10:35 -08002830 "1", null, true,
Jeremy Joslin8bdad342016-12-14 11:46:47 -08002831 SettingsState.SYSTEM_PACKAGE_NAME);
2832
2833 // and clear the scorer setting since it's no longer needed.
2834 globalSettings.insertSettingLocked(
2835 Global.NETWORK_SCORER_APP,
Svetoslav Ganove080da92016-12-21 17:10:35 -08002836 null, null, true,
Jeremy Joslin8bdad342016-12-14 11:46:47 -08002837 SettingsState.SYSTEM_PACKAGE_NAME);
2838 }
2839 }
2840 currentVersion = 136;
2841 }
2842
Dan Sandler71f85e92016-07-20 13:46:05 -04002843 if (currentVersion != newVersion) {
Svetoslav Ganov264c7a92016-08-24 17:31:14 -07002844 Slog.wtf("SettingsProvider", "warning: upgrading settings database to version "
Dan Sandler71f85e92016-07-20 13:46:05 -04002845 + newVersion + " left it at "
2846 + currentVersion + " instead; this is probably a bug", new Throwable());
2847 if (DEBUG) {
2848 throw new RuntimeException("db upgrade error");
2849 }
2850 }
2851
Jeff Brown503cffc2015-03-26 18:08:51 -07002852 // vXXX: Add new settings above this point.
Svetoslav683914b2015-01-15 14:22:26 -08002853
Jeff Brown503cffc2015-03-26 18:08:51 -07002854 // Return the current version.
2855 return currentVersion;
Brad Fitzpatrick547a96b2010-03-09 17:58:53 -08002856 }
2857 }
Brad Fitzpatrick1bd62bd2010-03-08 18:30:52 -08002858 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002859}