OSDN Git Service

987b5ea2db09231058155852b3826d3664da9963
[android-x86/frameworks-base.git] / packages / SettingsProvider / src / com / android / providers / settings / SettingsProvider.java
1 /*
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
17 package com.android.providers.settings;
18
19 import android.Manifest;
20 import android.app.ActivityManager;
21 import android.app.AppGlobals;
22 import android.app.backup.BackupManager;
23 import android.content.BroadcastReceiver;
24 import android.content.ContentProvider;
25 import android.content.ContentValues;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.IntentFilter;
29 import android.content.pm.ApplicationInfo;
30 import android.content.pm.IPackageManager;
31 import android.content.pm.PackageInfo;
32 import android.content.pm.PackageManager;
33 import android.content.pm.UserInfo;
34 import android.database.Cursor;
35 import android.database.MatrixCursor;
36 import android.database.sqlite.SQLiteDatabase;
37 import android.database.sqlite.SQLiteQueryBuilder;
38 import android.hardware.camera2.utils.ArrayUtils;
39 import android.media.AudioManager;
40 import android.net.Uri;
41 import android.os.Binder;
42 import android.os.Build;
43 import android.os.Bundle;
44 import android.os.DropBoxManager;
45 import android.os.Environment;
46 import android.os.Handler;
47 import android.os.Looper;
48 import android.os.Message;
49 import android.os.ParcelFileDescriptor;
50 import android.os.Process;
51 import android.os.RemoteException;
52 import android.os.SELinux;
53 import android.os.SystemProperties;
54 import android.os.UserHandle;
55 import android.os.UserManager;
56 import android.provider.Settings;
57 import android.text.TextUtils;
58 import android.util.ArraySet;
59 import android.util.Slog;
60 import android.util.SparseArray;
61
62 import com.android.internal.annotations.GuardedBy;
63 import com.android.internal.content.PackageMonitor;
64 import com.android.internal.os.BackgroundThread;
65 import com.android.providers.settings.SettingsState.Setting;
66
67 import java.io.File;
68 import java.io.FileDescriptor;
69 import java.io.FileNotFoundException;
70 import java.io.PrintWriter;
71 import java.security.SecureRandom;
72 import java.util.Arrays;
73 import java.util.List;
74 import java.util.Set;
75 import java.util.regex.Pattern;
76
77 /**
78  * <p>
79  * This class is a content provider that publishes the system settings.
80  * It can be accessed via the content provider APIs or via custom call
81  * commands. The latter is a bit faster and is the preferred way to access
82  * the platform settings.
83  * </p>
84  * <p>
85  * There are three settings types, global (with signature level protection
86  * and shared across users), secure (with signature permission level
87  * protection and per user), and system (with dangerous permission level
88  * protection and per user). Global settings are stored under the device owner.
89  * Each of these settings is represented by a {@link
90  * com.android.providers.settings.SettingsState} object mapped to an integer
91  * key derived from the setting type in the most significant bits and user
92  * id in the least significant bits. Settings are synchronously loaded on
93  * instantiation of a SettingsState and asynchronously persisted on mutation.
94  * Settings are stored in the user specific system directory.
95  * </p>
96  * <p>
97  * Apps targeting APIs Lollipop MR1 and lower can add custom settings entries
98  * and get a warning. Targeting higher API version prohibits this as the
99  * system settings are not a place for apps to save their state. When a package
100  * is removed the settings it added are deleted. Apps cannot delete system
101  * settings added by the platform. System settings values are validated to
102  * ensure the clients do not put bad values. Global and secure settings are
103  * changed only by trusted parties, therefore no validation is performed. Also
104  * there is a limit on the amount of app specific settings that can be added
105  * to prevent unlimited growth of the system process memory footprint.
106  * </p>
107  */
108 @SuppressWarnings("deprecation")
109 public class SettingsProvider extends ContentProvider {
110     private static final boolean DEBUG = false;
111
112     private static final boolean DROP_DATABASE_ON_MIGRATION = !Build.IS_DEBUGGABLE;
113
114     private static final String LOG_TAG = "SettingsProvider";
115
116     private static final String TABLE_SYSTEM = "system";
117     private static final String TABLE_SECURE = "secure";
118     private static final String TABLE_GLOBAL = "global";
119
120     // Old tables no longer exist.
121     private static final String TABLE_FAVORITES = "favorites";
122     private static final String TABLE_OLD_FAVORITES = "old_favorites";
123     private static final String TABLE_BLUETOOTH_DEVICES = "bluetooth_devices";
124     private static final String TABLE_BOOKMARKS = "bookmarks";
125     private static final String TABLE_ANDROID_METADATA = "android_metadata";
126
127     // The set of removed legacy tables.
128     private static final Set<String> REMOVED_LEGACY_TABLES = new ArraySet<>();
129     static {
130         REMOVED_LEGACY_TABLES.add(TABLE_FAVORITES);
131         REMOVED_LEGACY_TABLES.add(TABLE_OLD_FAVORITES);
132         REMOVED_LEGACY_TABLES.add(TABLE_BLUETOOTH_DEVICES);
133         REMOVED_LEGACY_TABLES.add(TABLE_BOOKMARKS);
134         REMOVED_LEGACY_TABLES.add(TABLE_ANDROID_METADATA);
135     }
136
137     private static final int MUTATION_OPERATION_INSERT = 1;
138     private static final int MUTATION_OPERATION_DELETE = 2;
139     private static final int MUTATION_OPERATION_UPDATE = 3;
140
141     private static final String[] ALL_COLUMNS = new String[] {
142             Settings.NameValueTable._ID,
143             Settings.NameValueTable.NAME,
144             Settings.NameValueTable.VALUE
145     };
146
147     private static final Bundle NULL_SETTING = Bundle.forPair(Settings.NameValueTable.VALUE, null);
148
149
150     // Per user secure settings that moved to the for all users global settings.
151     static final Set<String> sSecureMovedToGlobalSettings = new ArraySet<>();
152     static {
153         Settings.Secure.getMovedToGlobalSettings(sSecureMovedToGlobalSettings);
154     }
155
156     // Per user system settings that moved to the for all users global settings.
157     static final Set<String> sSystemMovedToGlobalSettings = new ArraySet<>();
158     static {
159         Settings.System.getMovedToGlobalSettings(sSystemMovedToGlobalSettings);
160     }
161
162     // Per user system settings that moved to the per user secure settings.
163     static final Set<String> sSystemMovedToSecureSettings = new ArraySet<>();
164     static {
165         Settings.System.getMovedToSecureSettings(sSystemMovedToSecureSettings);
166     }
167
168     // Per all users global settings that moved to the per user secure settings.
169     static final Set<String> sGlobalMovedToSecureSettings = new ArraySet<>();
170     static {
171         Settings.Global.getMovedToSecureSettings(sGlobalMovedToSecureSettings);
172     }
173
174     // Per user secure settings that are cloned for the managed profiles of the user.
175     private static final Set<String> sSecureCloneToManagedSettings = new ArraySet<>();
176     static {
177         Settings.Secure.getCloneToManagedProfileSettings(sSecureCloneToManagedSettings);
178     }
179
180     // Per user system settings that are cloned for the managed profiles of the user.
181     private static final Set<String> sSystemCloneToManagedSettings = new ArraySet<>();
182     static {
183         Settings.System.getCloneToManagedProfileSettings(sSystemCloneToManagedSettings);
184     }
185
186     private final Object mLock = new Object();
187
188     @GuardedBy("mLock")
189     private SettingsRegistry mSettingsRegistry;
190
191     // We have to call in the user manager with no lock held,
192     private volatile UserManager mUserManager;
193
194     // We have to call in the package manager with no lock held,
195     private volatile IPackageManager mPackageManager;
196
197     @Override
198     public boolean onCreate() {
199         synchronized (mLock) {
200             mUserManager = UserManager.get(getContext());
201             mPackageManager = AppGlobals.getPackageManager();
202             mSettingsRegistry = new SettingsRegistry();
203         }
204         registerBroadcastReceivers();
205         return true;
206     }
207
208     @Override
209     public Bundle call(String method, String name, Bundle args) {
210         final int requestingUserId = getRequestingUserId(args);
211         switch (method) {
212             case Settings.CALL_METHOD_GET_GLOBAL: {
213                 Setting setting = getGlobalSetting(name);
214                 return packageValueForCallResult(setting);
215             }
216
217             case Settings.CALL_METHOD_GET_SECURE: {
218                 Setting setting = getSecureSetting(name, requestingUserId);
219                 return packageValueForCallResult(setting);
220             }
221
222             case Settings.CALL_METHOD_GET_SYSTEM: {
223                 Setting setting = getSystemSetting(name, requestingUserId);
224                 return packageValueForCallResult(setting);
225             }
226
227             case Settings.CALL_METHOD_PUT_GLOBAL: {
228                 String value = getSettingValue(args);
229                 insertGlobalSetting(name, value, requestingUserId);
230                 break;
231             }
232
233             case Settings.CALL_METHOD_PUT_SECURE: {
234                 String value = getSettingValue(args);
235                 insertSecureSetting(name, value, requestingUserId);
236                 break;
237             }
238
239             case Settings.CALL_METHOD_PUT_SYSTEM: {
240                 String value = getSettingValue(args);
241                 insertSystemSetting(name, value, requestingUserId);
242                 break;
243             }
244
245             default: {
246                 Slog.w(LOG_TAG, "call() with invalid method: " + method);
247             } break;
248         }
249
250         return null;
251     }
252
253     @Override
254     public String getType(Uri uri) {
255         Arguments args = new Arguments(uri, null, null, true);
256         if (TextUtils.isEmpty(args.name)) {
257             return "vnd.android.cursor.dir/" + args.table;
258         } else {
259             return "vnd.android.cursor.item/" + args.table;
260         }
261     }
262
263     @Override
264     public Cursor query(Uri uri, String[] projection, String where, String[] whereArgs,
265             String order) {
266         if (DEBUG) {
267             Slog.v(LOG_TAG, "query() for user: " + UserHandle.getCallingUserId());
268         }
269
270         Arguments args = new Arguments(uri, where, whereArgs, true);
271         String[] normalizedProjection = normalizeProjection(projection);
272
273         // If a legacy table that is gone, done.
274         if (REMOVED_LEGACY_TABLES.contains(args.table)) {
275             return new MatrixCursor(normalizedProjection, 0);
276         }
277
278         switch (args.table) {
279             case TABLE_GLOBAL: {
280                 if (args.name != null) {
281                     Setting setting = getGlobalSetting(args.name);
282                     return packageSettingForQuery(setting, normalizedProjection);
283                 } else {
284                     return getAllGlobalSettings(projection);
285                 }
286             }
287
288             case TABLE_SECURE: {
289                 final int userId = UserHandle.getCallingUserId();
290                 if (args.name != null) {
291                     Setting setting = getSecureSetting(args.name, userId);
292                     return packageSettingForQuery(setting, normalizedProjection);
293                 } else {
294                     return getAllSecureSettings(userId, projection);
295                 }
296             }
297
298             case TABLE_SYSTEM: {
299                 final int userId = UserHandle.getCallingUserId();
300                 if (args.name != null) {
301                     Setting setting = getSystemSetting(args.name, userId);
302                     return packageSettingForQuery(setting, normalizedProjection);
303                 } else {
304                     return getAllSystemSettings(userId, projection);
305                 }
306             }
307
308             default: {
309                 throw new IllegalArgumentException("Invalid Uri path:" + uri);
310             }
311         }
312     }
313
314     @Override
315     public Uri insert(Uri uri, ContentValues values) {
316         if (DEBUG) {
317             Slog.v(LOG_TAG, "insert() for user: " + UserHandle.getCallingUserId());
318         }
319
320         String table = getValidTableOrThrow(uri);
321
322         // If a legacy table that is gone, done.
323         if (REMOVED_LEGACY_TABLES.contains(table)) {
324             return null;
325         }
326
327         String name = values.getAsString(Settings.Secure.NAME);
328         if (!isKeyValid(name)) {
329             return null;
330         }
331
332         String value = values.getAsString(Settings.Secure.VALUE);
333
334         switch (table) {
335             case TABLE_GLOBAL: {
336                 if (insertGlobalSetting(name, value, UserHandle.getCallingUserId())) {
337                     return Uri.withAppendedPath(Settings.Global.CONTENT_URI, name);
338                 }
339             } break;
340
341             case TABLE_SECURE: {
342                 if (insertSecureSetting(name, value, UserHandle.getCallingUserId())) {
343                     return Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name);
344                 }
345             } break;
346
347             case TABLE_SYSTEM: {
348                 if (insertSystemSetting(name, value, UserHandle.getCallingUserId())) {
349                     return Uri.withAppendedPath(Settings.System.CONTENT_URI, name);
350                 }
351             } break;
352
353             default: {
354                 throw new IllegalArgumentException("Bad Uri path:" + uri);
355             }
356         }
357
358         return null;
359     }
360
361     @Override
362     public int bulkInsert(Uri uri, ContentValues[] allValues) {
363         if (DEBUG) {
364             Slog.v(LOG_TAG, "bulkInsert() for user: " + UserHandle.getCallingUserId());
365         }
366
367         int insertionCount = 0;
368         final int valuesCount = allValues.length;
369         for (int i = 0; i < valuesCount; i++) {
370             ContentValues values = allValues[i];
371             if (insert(uri, values) != null) {
372                 insertionCount++;
373             }
374         }
375
376         return insertionCount;
377     }
378
379     @Override
380     public int delete(Uri uri, String where, String[] whereArgs) {
381         if (DEBUG) {
382             Slog.v(LOG_TAG, "delete() for user: " + UserHandle.getCallingUserId());
383         }
384
385         Arguments args = new Arguments(uri, where, whereArgs, false);
386
387         // If a legacy table that is gone, done.
388         if (REMOVED_LEGACY_TABLES.contains(args.table)) {
389             return 0;
390         }
391
392         if (!isKeyValid(args.name)) {
393             return 0;
394         }
395
396         switch (args.table) {
397             case TABLE_GLOBAL: {
398                 final int userId = UserHandle.getCallingUserId();
399                 return deleteGlobalSetting(args.name, userId) ? 1 : 0;
400             }
401
402             case TABLE_SECURE: {
403                 final int userId = UserHandle.getCallingUserId();
404                 return deleteSecureSetting(args.name, userId) ? 1 : 0;
405             }
406
407             case TABLE_SYSTEM: {
408                 final int userId = UserHandle.getCallingUserId();
409                 return deleteSystemSetting(args.name, userId) ? 1 : 0;
410             }
411
412             default: {
413                 throw new IllegalArgumentException("Bad Uri path:" + uri);
414             }
415         }
416     }
417
418     @Override
419     public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
420         if (DEBUG) {
421             Slog.v(LOG_TAG, "update() for user: " + UserHandle.getCallingUserId());
422         }
423
424         Arguments args = new Arguments(uri, where, whereArgs, false);
425
426         // If a legacy table that is gone, done.
427         if (REMOVED_LEGACY_TABLES.contains(args.table)) {
428             return 0;
429         }
430
431         String name = values.getAsString(Settings.Secure.NAME);
432         if (!isKeyValid(name)) {
433             return 0;
434         }
435         String value = values.getAsString(Settings.Secure.VALUE);
436
437         switch (args.table) {
438             case TABLE_GLOBAL: {
439                 final int userId = UserHandle.getCallingUserId();
440                 return updateGlobalSetting(args.name, value, userId) ? 1 : 0;
441             }
442
443             case TABLE_SECURE: {
444                 final int userId = UserHandle.getCallingUserId();
445                 return updateSecureSetting(args.name, value, userId) ? 1 : 0;
446             }
447
448             case TABLE_SYSTEM: {
449                 final int userId = UserHandle.getCallingUserId();
450                 return updateSystemSetting(args.name, value, userId) ? 1 : 0;
451             }
452
453             default: {
454                 throw new IllegalArgumentException("Invalid Uri path:" + uri);
455             }
456         }
457     }
458
459     @Override
460     public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
461         final String cacheName;
462         if (Settings.System.RINGTONE_CACHE_URI.equals(uri)) {
463             cacheName = Settings.System.RINGTONE_CACHE;
464         } else if (Settings.System.NOTIFICATION_SOUND_CACHE_URI.equals(uri)) {
465             cacheName = Settings.System.NOTIFICATION_SOUND_CACHE;
466         } else if (Settings.System.ALARM_ALERT_CACHE_URI.equals(uri)) {
467             cacheName = Settings.System.ALARM_ALERT_CACHE;
468         } else {
469             throw new FileNotFoundException("Direct file access no longer supported; "
470                     + "ringtone playback is available through android.media.Ringtone");
471         }
472
473         final File cacheFile = new File(
474                 getRingtoneCacheDir(UserHandle.getCallingUserId()), cacheName);
475         return ParcelFileDescriptor.open(cacheFile, ParcelFileDescriptor.parseMode(mode));
476     }
477
478     private File getRingtoneCacheDir(int userId) {
479         final File cacheDir = new File(Environment.getDataSystemDeDirectory(userId), "ringtones");
480         cacheDir.mkdir();
481         SELinux.restorecon(cacheDir);
482         return cacheDir;
483     }
484
485     @Override
486     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
487         synchronized (mLock) {
488             final long identity = Binder.clearCallingIdentity();
489             try {
490                 List<UserInfo> users = mUserManager.getUsers(true);
491                 final int userCount = users.size();
492                 for (int i = 0; i < userCount; i++) {
493                     UserInfo user = users.get(i);
494                     dumpForUser(user.id, pw);
495                 }
496             } finally {
497                 Binder.restoreCallingIdentity(identity);
498             }
499         }
500     }
501
502     private void dumpForUser(int userId, PrintWriter pw) {
503         if (userId == UserHandle.USER_SYSTEM) {
504             pw.println("GLOBAL SETTINGS (user " + userId + ")");
505             Cursor globalCursor = getAllGlobalSettings(ALL_COLUMNS);
506             dumpSettings(globalCursor, pw);
507             pw.println();
508         }
509
510         pw.println("SECURE SETTINGS (user " + userId + ")");
511         Cursor secureCursor = getAllSecureSettings(userId, ALL_COLUMNS);
512         dumpSettings(secureCursor, pw);
513         pw.println();
514
515         pw.println("SYSTEM SETTINGS (user " + userId + ")");
516         Cursor systemCursor = getAllSystemSettings(userId, ALL_COLUMNS);
517         dumpSettings(systemCursor, pw);
518         pw.println();
519     }
520
521     private void dumpSettings(Cursor cursor, PrintWriter pw) {
522         if (cursor == null || !cursor.moveToFirst()) {
523             return;
524         }
525
526         final int idColumnIdx = cursor.getColumnIndex(Settings.NameValueTable._ID);
527         final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME);
528         final int valueColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.VALUE);
529
530         do {
531             pw.append("_id:").append(toDumpString(cursor.getString(idColumnIdx)));
532             pw.append(" name:").append(toDumpString(cursor.getString(nameColumnIdx)));
533             pw.append(" value:").append(toDumpString(cursor.getString(valueColumnIdx)));
534             pw.println();
535         } while (cursor.moveToNext());
536     }
537
538     private static String toDumpString(String s) {
539         if (s != null) {
540             return s;
541         }
542         return "{null}";
543     }
544
545     private void registerBroadcastReceivers() {
546         IntentFilter userFilter = new IntentFilter();
547         userFilter.addAction(Intent.ACTION_USER_REMOVED);
548         userFilter.addAction(Intent.ACTION_USER_STOPPED);
549
550         getContext().registerReceiver(new BroadcastReceiver() {
551             @Override
552             public void onReceive(Context context, Intent intent) {
553                 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
554                         UserHandle.USER_SYSTEM);
555
556                 switch (intent.getAction()) {
557                     case Intent.ACTION_USER_REMOVED: {
558                         mSettingsRegistry.removeUserStateLocked(userId, true);
559                     } break;
560
561                     case Intent.ACTION_USER_STOPPED: {
562                         mSettingsRegistry.removeUserStateLocked(userId, false);
563                     } break;
564                 }
565             }
566         }, userFilter);
567
568         PackageMonitor monitor = new PackageMonitor() {
569             @Override
570             public void onPackageRemoved(String packageName, int uid) {
571                 synchronized (mLock) {
572                     mSettingsRegistry.onPackageRemovedLocked(packageName,
573                             UserHandle.getUserId(uid));
574                 }
575             }
576         };
577
578         // package changes
579         monitor.register(getContext(), BackgroundThread.getHandler().getLooper(),
580                 UserHandle.ALL, true);
581     }
582
583     private Cursor getAllGlobalSettings(String[] projection) {
584         if (DEBUG) {
585             Slog.v(LOG_TAG, "getAllGlobalSettings()");
586         }
587
588         synchronized (mLock) {
589             // Get the settings.
590             SettingsState settingsState = mSettingsRegistry.getSettingsLocked(
591                     SettingsRegistry.SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
592
593             List<String> names = settingsState.getSettingNamesLocked();
594
595             final int nameCount = names.size();
596
597             String[] normalizedProjection = normalizeProjection(projection);
598             MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount);
599
600             // Anyone can get the global settings, so no security checks.
601             for (int i = 0; i < nameCount; i++) {
602                 String name = names.get(i);
603                 Setting setting = settingsState.getSettingLocked(name);
604                 appendSettingToCursor(result, setting);
605             }
606
607             return result;
608         }
609     }
610
611     private Setting getGlobalSetting(String name) {
612         if (DEBUG) {
613             Slog.v(LOG_TAG, "getGlobalSetting(" + name + ")");
614         }
615
616         // Get the value.
617         synchronized (mLock) {
618             return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
619                     UserHandle.USER_SYSTEM, name);
620         }
621     }
622
623     private boolean updateGlobalSetting(String name, String value, int requestingUserId) {
624         if (DEBUG) {
625             Slog.v(LOG_TAG, "updateGlobalSetting(" + name + ", " + value + ")");
626         }
627         return mutateGlobalSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE);
628     }
629
630     private boolean insertGlobalSetting(String name, String value, int requestingUserId) {
631         if (DEBUG) {
632             Slog.v(LOG_TAG, "insertGlobalSetting(" + name + ", " + value + ")");
633         }
634         return mutateGlobalSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT);
635     }
636
637     private boolean deleteGlobalSetting(String name, int requestingUserId) {
638         if (DEBUG) {
639             Slog.v(LOG_TAG, "deleteGlobalSettingLocked(" + name + ")");
640         }
641         return mutateGlobalSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE);
642     }
643
644     private boolean mutateGlobalSetting(String name, String value, int requestingUserId,
645             int operation) {
646         // Make sure the caller can change the settings - treated as secure.
647         enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
648
649         // Resolve the userId on whose behalf the call is made.
650         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
651
652         // If this is a setting that is currently restricted for this user, do not allow
653         // unrestricting changes.
654         if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value)) {
655             return false;
656         }
657
658         // Perform the mutation.
659         synchronized (mLock) {
660             switch (operation) {
661                 case MUTATION_OPERATION_INSERT: {
662                     return mSettingsRegistry
663                             .insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
664                                     UserHandle.USER_SYSTEM, name, value, getCallingPackage());
665                 }
666
667                 case MUTATION_OPERATION_DELETE: {
668                     return mSettingsRegistry.deleteSettingLocked(
669                             SettingsRegistry.SETTINGS_TYPE_GLOBAL,
670                             UserHandle.USER_SYSTEM, name);
671                 }
672
673                 case MUTATION_OPERATION_UPDATE: {
674                     return mSettingsRegistry
675                             .updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
676                                     UserHandle.USER_SYSTEM, name, value, getCallingPackage());
677                 }
678             }
679         }
680
681         return false;
682     }
683
684     private Cursor getAllSecureSettings(int userId, String[] projection) {
685         if (DEBUG) {
686             Slog.v(LOG_TAG, "getAllSecureSettings(" + userId + ")");
687         }
688
689         // Resolve the userId on whose behalf the call is made.
690         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId);
691
692         synchronized (mLock) {
693             List<String> names = mSettingsRegistry.getSettingsNamesLocked(
694                     SettingsRegistry.SETTINGS_TYPE_SECURE, callingUserId);
695
696             final int nameCount = names.size();
697
698             String[] normalizedProjection = normalizeProjection(projection);
699             MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount);
700
701             for (int i = 0; i < nameCount; i++) {
702                 String name = names.get(i);
703                 // Determine the owning user as some profile settings are cloned from the parent.
704                 final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId,
705                         name);
706
707                 // Special case for location (sigh).
708                 if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) {
709                     return null;
710                 }
711
712                 Setting setting = mSettingsRegistry.getSettingLocked(
713                         SettingsRegistry.SETTINGS_TYPE_SECURE, owningUserId, name);
714                 appendSettingToCursor(result, setting);
715             }
716
717             return result;
718         }
719     }
720
721     private Setting getSecureSetting(String name, int requestingUserId) {
722         if (DEBUG) {
723             Slog.v(LOG_TAG, "getSecureSetting(" + name + ", " + requestingUserId + ")");
724         }
725
726         // Resolve the userId on whose behalf the call is made.
727         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
728
729         // Determine the owning user as some profile settings are cloned from the parent.
730         final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name);
731
732         // Special case for location (sigh).
733         if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) {
734             return null;
735         }
736
737         // Get the value.
738         synchronized (mLock) {
739             return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
740                     owningUserId, name);
741         }
742     }
743
744     private boolean insertSecureSetting(String name, String value, int requestingUserId) {
745         if (DEBUG) {
746             Slog.v(LOG_TAG, "insertSecureSetting(" + name + ", " + value + ", "
747                     + requestingUserId + ")");
748         }
749
750         return mutateSecureSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT);
751     }
752
753     private boolean deleteSecureSetting(String name, int requestingUserId) {
754         if (DEBUG) {
755             Slog.v(LOG_TAG, "deleteSecureSetting(" + name + ", " + requestingUserId + ")");
756         }
757
758         return mutateSecureSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE);
759     }
760
761     private boolean updateSecureSetting(String name, String value, int requestingUserId) {
762         if (DEBUG) {
763             Slog.v(LOG_TAG, "updateSecureSetting(" + name + ", " + value + ", "
764                     + requestingUserId + ")");
765         }
766
767         return mutateSecureSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE);
768     }
769
770     private boolean mutateSecureSetting(String name, String value, int requestingUserId,
771             int operation) {
772         // Make sure the caller can change the settings.
773         enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
774
775         // Resolve the userId on whose behalf the call is made.
776         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
777
778         // If this is a setting that is currently restricted for this user, do not allow
779         // unrestricting changes.
780         if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value)) {
781             return false;
782         }
783
784         // Determine the owning user as some profile settings are cloned from the parent.
785         final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name);
786
787         // Only the owning user can change the setting.
788         if (owningUserId != callingUserId) {
789             return false;
790         }
791
792         // Special cases for location providers (sigh).
793         if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
794             return updateLocationProvidersAllowedLocked(value, owningUserId);
795         }
796
797         // Mutate the value.
798         synchronized (mLock) {
799             switch (operation) {
800                 case MUTATION_OPERATION_INSERT: {
801                     return mSettingsRegistry
802                             .insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
803                                     owningUserId, name, value, getCallingPackage());
804                 }
805
806                 case MUTATION_OPERATION_DELETE: {
807                     return mSettingsRegistry.deleteSettingLocked(
808                             SettingsRegistry.SETTINGS_TYPE_SECURE,
809                             owningUserId, name);
810                 }
811
812                 case MUTATION_OPERATION_UPDATE: {
813                     return mSettingsRegistry
814                             .updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
815                                     owningUserId, name, value, getCallingPackage());
816                 }
817             }
818         }
819
820         return false;
821     }
822
823     private Cursor getAllSystemSettings(int userId, String[] projection) {
824         if (DEBUG) {
825             Slog.v(LOG_TAG, "getAllSecureSystem(" + userId + ")");
826         }
827
828         // Resolve the userId on whose behalf the call is made.
829         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId);
830
831         synchronized (mLock) {
832             List<String> names = mSettingsRegistry.getSettingsNamesLocked(
833                     SettingsRegistry.SETTINGS_TYPE_SYSTEM, callingUserId);
834
835             final int nameCount = names.size();
836
837             String[] normalizedProjection = normalizeProjection(projection);
838             MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount);
839
840             for (int i = 0; i < nameCount; i++) {
841                 String name = names.get(i);
842
843                 // Determine the owning user as some profile settings are cloned from the parent.
844                 final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId,
845                         name);
846
847                 Setting setting = mSettingsRegistry.getSettingLocked(
848                         SettingsRegistry.SETTINGS_TYPE_SYSTEM, owningUserId, name);
849                 appendSettingToCursor(result, setting);
850             }
851
852             return result;
853         }
854     }
855
856     private Setting getSystemSetting(String name, int requestingUserId) {
857         if (DEBUG) {
858             Slog.v(LOG_TAG, "getSystemSetting(" + name + ", " + requestingUserId + ")");
859         }
860
861         // Resolve the userId on whose behalf the call is made.
862         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
863
864         // Determine the owning user as some profile settings are cloned from the parent.
865         final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name);
866
867         // Get the value.
868         synchronized (mLock) {
869             return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM,
870                     owningUserId, name);
871         }
872     }
873
874     private boolean insertSystemSetting(String name, String value, int requestingUserId) {
875         if (DEBUG) {
876             Slog.v(LOG_TAG, "insertSystemSetting(" + name + ", " + value + ", "
877                     + requestingUserId + ")");
878         }
879
880         return mutateSystemSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT);
881     }
882
883     private boolean deleteSystemSetting(String name, int requestingUserId) {
884         if (DEBUG) {
885             Slog.v(LOG_TAG, "deleteSystemSetting(" + name + ", " + requestingUserId + ")");
886         }
887
888         return mutateSystemSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE);
889     }
890
891     private boolean updateSystemSetting(String name, String value, int requestingUserId) {
892         if (DEBUG) {
893             Slog.v(LOG_TAG, "updateSystemSetting(" + name + ", " + value + ", "
894                     + requestingUserId + ")");
895         }
896
897         return mutateSystemSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE);
898     }
899
900     private boolean mutateSystemSetting(String name, String value, int runAsUserId,
901             int operation) {
902         if (!hasWriteSecureSettingsPermission()) {
903             // If the caller doesn't hold WRITE_SECURE_SETTINGS, we verify whether this
904             // operation is allowed for the calling package through appops.
905             if (!Settings.checkAndNoteWriteSettingsOperation(getContext(),
906                     Binder.getCallingUid(), getCallingPackage(), true)) {
907                 return false;
908             }
909         }
910
911         // Resolve the userId on whose behalf the call is made.
912         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(runAsUserId);
913
914         // Enforce what the calling package can mutate the system settings.
915         enforceRestrictedSystemSettingsMutationForCallingPackage(operation, name, callingUserId);
916
917         // Determine the owning user as some profile settings are cloned from the parent.
918         final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name);
919
920         // Only the owning user id can change the setting.
921         if (owningUserId != callingUserId) {
922             return false;
923         }
924
925         // Invalidate any relevant cache files
926         String cacheName = null;
927         if (Settings.System.RINGTONE.equals(name)) {
928             cacheName = Settings.System.RINGTONE_CACHE;
929         } else if (Settings.System.NOTIFICATION_SOUND.equals(name)) {
930             cacheName = Settings.System.NOTIFICATION_SOUND_CACHE;
931         } else if (Settings.System.ALARM_ALERT.equals(name)) {
932             cacheName = Settings.System.ALARM_ALERT_CACHE;
933         }
934         if (cacheName != null) {
935             final File cacheFile = new File(
936                     getRingtoneCacheDir(UserHandle.getCallingUserId()), cacheName);
937             cacheFile.delete();
938         }
939
940         // Mutate the value.
941         synchronized (mLock) {
942             switch (operation) {
943                 case MUTATION_OPERATION_INSERT: {
944                     validateSystemSettingValue(name, value);
945                     return mSettingsRegistry
946                             .insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM,
947                                     owningUserId, name, value, getCallingPackage());
948                 }
949
950                 case MUTATION_OPERATION_DELETE: {
951                     return mSettingsRegistry.deleteSettingLocked(
952                             SettingsRegistry.SETTINGS_TYPE_SYSTEM,
953                             owningUserId, name);
954                 }
955
956                 case MUTATION_OPERATION_UPDATE: {
957                     validateSystemSettingValue(name, value);
958                     return mSettingsRegistry
959                             .updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM,
960                                     owningUserId, name, value, getCallingPackage());
961                 }
962             }
963
964             return false;
965         }
966     }
967
968     private boolean hasWriteSecureSettingsPermission() {
969         // Write secure settings is a more protected permission. If caller has it we are good.
970         if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
971                 == PackageManager.PERMISSION_GRANTED) {
972             return true;
973         }
974
975         return false;
976     }
977
978     private void validateSystemSettingValue(String name, String value) {
979         Settings.System.Validator validator = Settings.System.VALIDATORS.get(name);
980         if (validator != null && !validator.validate(value)) {
981             throw new IllegalArgumentException("Invalid value: " + value
982                     + " for setting: " + name);
983         }
984     }
985
986     private boolean isLocationProvidersAllowedRestricted(String name, int callingUserId,
987             int owningUserId) {
988         // Optimization - location providers are restricted only for managed profiles.
989         if (callingUserId == owningUserId) {
990             return false;
991         }
992         if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)
993                 && mUserManager.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION,
994                 new UserHandle(callingUserId))) {
995             return true;
996         }
997         return false;
998     }
999
1000     /**
1001      * Checks whether changing a setting to a value is prohibited by the corresponding user
1002      * restriction.
1003      *
1004      * <p>See also {@link com.android.server.pm.UserRestrictionsUtils#applyUserRestrictionLR},
1005      * which should be in sync with this method.
1006      *
1007      * @return true if the change is prohibited, false if the change is allowed.
1008      */
1009     private boolean isGlobalOrSecureSettingRestrictedForUser(String setting, int userId,
1010             String value) {
1011         String restriction;
1012         switch (setting) {
1013             case Settings.Secure.LOCATION_MODE:
1014                 // Note LOCATION_MODE will be converted into LOCATION_PROVIDERS_ALLOWED
1015                 // in android.provider.Settings.Secure.putStringForUser(), so we shouldn't come
1016                 // here normally, but we still protect it here from a direct provider write.
1017                 if (String.valueOf(Settings.Secure.LOCATION_MODE_OFF).equals(value)) return false;
1018                 restriction = UserManager.DISALLOW_SHARE_LOCATION;
1019                 break;
1020
1021             case Settings.Secure.LOCATION_PROVIDERS_ALLOWED:
1022                 // See SettingsProvider.updateLocationProvidersAllowedLocked.  "-" is to disable
1023                 // a provider, which should be allowed even if the user restriction is set.
1024                 if (value != null && value.startsWith("-")) return false;
1025                 restriction = UserManager.DISALLOW_SHARE_LOCATION;
1026                 break;
1027
1028             case Settings.Secure.INSTALL_NON_MARKET_APPS:
1029                 if ("0".equals(value)) return false;
1030                 restriction = UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES;
1031                 break;
1032
1033             case Settings.Global.ADB_ENABLED:
1034                 if ("0".equals(value)) return false;
1035                 restriction = UserManager.DISALLOW_DEBUGGING_FEATURES;
1036                 break;
1037
1038             case Settings.Global.PACKAGE_VERIFIER_ENABLE:
1039             case Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB:
1040                 if ("1".equals(value)) return false;
1041                 restriction = UserManager.ENSURE_VERIFY_APPS;
1042                 break;
1043
1044             case Settings.Global.PREFERRED_NETWORK_MODE:
1045                 restriction = UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS;
1046                 break;
1047
1048             default:
1049                 if (setting != null && setting.startsWith(Settings.Global.DATA_ROAMING)) {
1050                     if ("0".equals(value)) return false;
1051                     restriction = UserManager.DISALLOW_DATA_ROAMING;
1052                     break;
1053                 }
1054                 return false;
1055         }
1056
1057         return mUserManager.hasUserRestriction(restriction, UserHandle.of(userId));
1058     }
1059
1060     private int resolveOwningUserIdForSecureSettingLocked(int userId, String setting) {
1061         return resolveOwningUserIdLocked(userId, sSecureCloneToManagedSettings, setting);
1062     }
1063
1064     private int resolveOwningUserIdForSystemSettingLocked(int userId, String setting) {
1065         return resolveOwningUserIdLocked(userId, sSystemCloneToManagedSettings, setting);
1066     }
1067
1068     private int resolveOwningUserIdLocked(int userId, Set<String> keys, String name) {
1069         final int parentId = getGroupParentLocked(userId);
1070         if (parentId != userId && keys.contains(name)) {
1071             return parentId;
1072         }
1073         return userId;
1074     }
1075
1076     private void enforceRestrictedSystemSettingsMutationForCallingPackage(int operation,
1077             String name, int userId) {
1078         // System/root/shell can mutate whatever secure settings they want.
1079         final int callingUid = Binder.getCallingUid();
1080         if (callingUid == android.os.Process.SYSTEM_UID
1081                 || callingUid == Process.SHELL_UID
1082                 || callingUid == Process.ROOT_UID) {
1083             return;
1084         }
1085
1086         switch (operation) {
1087             case MUTATION_OPERATION_INSERT:
1088                 // Insert updates.
1089             case MUTATION_OPERATION_UPDATE: {
1090                 if (Settings.System.PUBLIC_SETTINGS.contains(name)) {
1091                     return;
1092                 }
1093
1094                 // The calling package is already verified.
1095                 PackageInfo packageInfo = getCallingPackageInfoOrThrow(userId);
1096
1097                 // Privileged apps can do whatever they want.
1098                 if ((packageInfo.applicationInfo.privateFlags
1099                         & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
1100                     return;
1101                 }
1102
1103                 warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
1104                         packageInfo.applicationInfo.targetSdkVersion, name);
1105             } break;
1106
1107             case MUTATION_OPERATION_DELETE: {
1108                 if (Settings.System.PUBLIC_SETTINGS.contains(name)
1109                         || Settings.System.PRIVATE_SETTINGS.contains(name)) {
1110                     throw new IllegalArgumentException("You cannot delete system defined"
1111                             + " secure settings.");
1112                 }
1113
1114                 // The calling package is already verified.
1115                 PackageInfo packageInfo = getCallingPackageInfoOrThrow(userId);
1116
1117                 // Privileged apps can do whatever they want.
1118                 if ((packageInfo.applicationInfo.privateFlags &
1119                         ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
1120                     return;
1121                 }
1122
1123                 warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
1124                         packageInfo.applicationInfo.targetSdkVersion, name);
1125             } break;
1126         }
1127     }
1128
1129     private PackageInfo getCallingPackageInfoOrThrow(int userId) {
1130         try {
1131             PackageInfo packageInfo = mPackageManager.getPackageInfo(
1132                     getCallingPackage(), 0, userId);
1133             if (packageInfo != null) {
1134                 return packageInfo;
1135             }
1136         } catch (RemoteException e) {
1137             /* ignore */
1138         }
1139         throw new IllegalStateException("Calling package doesn't exist");
1140     }
1141
1142     private int getGroupParentLocked(int userId) {
1143         // Most frequent use case.
1144         if (userId == UserHandle.USER_SYSTEM) {
1145             return userId;
1146         }
1147         // We are in the same process with the user manager and the returned
1148         // user info is a cached instance, so just look up instead of cache.
1149         final long identity = Binder.clearCallingIdentity();
1150         try {
1151             // Just a lookup and not reentrant, so holding a lock is fine.
1152             UserInfo userInfo = mUserManager.getProfileParent(userId);
1153             return (userInfo != null) ? userInfo.id : userId;
1154         } finally {
1155             Binder.restoreCallingIdentity(identity);
1156         }
1157     }
1158
1159     private void enforceWritePermission(String permission) {
1160         if (getContext().checkCallingOrSelfPermission(permission)
1161                 != PackageManager.PERMISSION_GRANTED) {
1162             throw new SecurityException("Permission denial: writing to settings requires:"
1163                     + permission);
1164         }
1165     }
1166
1167     /*
1168      * Used to parse changes to the value of Settings.Secure.LOCATION_PROVIDERS_ALLOWED.
1169      * This setting contains a list of the currently enabled location providers.
1170      * But helper functions in android.providers.Settings can enable or disable
1171      * a single provider by using a "+" or "-" prefix before the provider name.
1172      *
1173      * <p>See also {@link #isGlobalOrSecureSettingRestrictedForUser()}.  If DISALLOW_SHARE_LOCATION
1174      * is set, the said method will only allow values with the "-" prefix.
1175      *
1176      * @returns whether the enabled location providers changed.
1177      */
1178     private boolean updateLocationProvidersAllowedLocked(String value, int owningUserId) {
1179         if (TextUtils.isEmpty(value)) {
1180             return false;
1181         }
1182
1183         final char prefix = value.charAt(0);
1184         if (prefix != '+' && prefix != '-') {
1185             return false;
1186         }
1187
1188         // skip prefix
1189         value = value.substring(1);
1190
1191         Setting settingValue = getSecureSetting(
1192                 Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId);
1193
1194         String oldProviders = (settingValue != null) ? settingValue.getValue() : "";
1195
1196         int index = oldProviders.indexOf(value);
1197         int end = index + value.length();
1198
1199         // check for commas to avoid matching on partial string
1200         if (index > 0 && oldProviders.charAt(index - 1) != ',') {
1201             index = -1;
1202         }
1203
1204         // check for commas to avoid matching on partial string
1205         if (end < oldProviders.length() && oldProviders.charAt(end) != ',') {
1206             index = -1;
1207         }
1208
1209         String newProviders;
1210
1211         if (prefix == '+' && index < 0) {
1212             // append the provider to the list if not present
1213             if (oldProviders.length() == 0) {
1214                 newProviders = value;
1215             } else {
1216                 newProviders = oldProviders + ',' + value;
1217             }
1218         } else if (prefix == '-' && index >= 0) {
1219             // remove the provider from the list if present
1220             // remove leading or trailing comma
1221             if (index > 0) {
1222                 index--;
1223             } else if (end < oldProviders.length()) {
1224                 end++;
1225             }
1226
1227             newProviders = oldProviders.substring(0, index);
1228             if (end < oldProviders.length()) {
1229                 newProviders += oldProviders.substring(end);
1230             }
1231         } else {
1232             // nothing changed, so no need to update the database
1233             return false;
1234         }
1235
1236         return mSettingsRegistry.insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
1237                 owningUserId, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, newProviders,
1238                 getCallingPackage());
1239     }
1240
1241     private static void warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
1242             int targetSdkVersion, String name) {
1243         // If the app targets Lollipop MR1 or older SDK we warn, otherwise crash.
1244         if (targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1) {
1245             if (Settings.System.PRIVATE_SETTINGS.contains(name)) {
1246                 Slog.w(LOG_TAG, "You shouldn't not change private system settings."
1247                         + " This will soon become an error.");
1248             } else {
1249                 Slog.w(LOG_TAG, "You shouldn't keep your settings in the secure settings."
1250                         + " This will soon become an error.");
1251             }
1252         } else {
1253             if (Settings.System.PRIVATE_SETTINGS.contains(name)) {
1254                 throw new IllegalArgumentException("You cannot change private secure settings.");
1255             } else {
1256                 throw new IllegalArgumentException("You cannot keep your settings in"
1257                         + " the secure settings.");
1258             }
1259         }
1260     }
1261
1262     private static int resolveCallingUserIdEnforcingPermissionsLocked(int requestingUserId) {
1263         if (requestingUserId == UserHandle.getCallingUserId()) {
1264             return requestingUserId;
1265         }
1266         return ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1267                 Binder.getCallingUid(), requestingUserId, false, true,
1268                 "get/set setting for user", null);
1269     }
1270
1271     private static Bundle packageValueForCallResult(Setting setting) {
1272         if (setting == null) {
1273             return NULL_SETTING;
1274         }
1275         return Bundle.forPair(Settings.NameValueTable.VALUE, setting.getValue());
1276     }
1277
1278     private static int getRequestingUserId(Bundle args) {
1279         final int callingUserId = UserHandle.getCallingUserId();
1280         return (args != null) ? args.getInt(Settings.CALL_METHOD_USER_KEY, callingUserId)
1281                 : callingUserId;
1282     }
1283
1284     private static String getSettingValue(Bundle args) {
1285         return (args != null) ? args.getString(Settings.NameValueTable.VALUE) : null;
1286     }
1287
1288     private static String getValidTableOrThrow(Uri uri) {
1289         if (uri.getPathSegments().size() > 0) {
1290             String table = uri.getPathSegments().get(0);
1291             if (DatabaseHelper.isValidTable(table)) {
1292                 return table;
1293             }
1294             throw new IllegalArgumentException("Bad root path: " + table);
1295         }
1296         throw new IllegalArgumentException("Invalid URI:" + uri);
1297     }
1298
1299     private static MatrixCursor packageSettingForQuery(Setting setting, String[] projection) {
1300         if (setting == null) {
1301             return new MatrixCursor(projection, 0);
1302         }
1303         MatrixCursor cursor = new MatrixCursor(projection, 1);
1304         appendSettingToCursor(cursor, setting);
1305         return cursor;
1306     }
1307
1308     private static String[] normalizeProjection(String[] projection) {
1309         if (projection == null) {
1310             return ALL_COLUMNS;
1311         }
1312
1313         final int columnCount = projection.length;
1314         for (int i = 0; i < columnCount; i++) {
1315             String column = projection[i];
1316             if (!ArrayUtils.contains(ALL_COLUMNS, column)) {
1317                 throw new IllegalArgumentException("Invalid column: " + column);
1318             }
1319         }
1320
1321         return projection;
1322     }
1323
1324     private static void appendSettingToCursor(MatrixCursor cursor, Setting setting) {
1325         final int columnCount = cursor.getColumnCount();
1326
1327         String[] values =  new String[columnCount];
1328
1329         for (int i = 0; i < columnCount; i++) {
1330             String column = cursor.getColumnName(i);
1331
1332             switch (column) {
1333                 case Settings.NameValueTable._ID: {
1334                     values[i] = setting.getId();
1335                 } break;
1336
1337                 case Settings.NameValueTable.NAME: {
1338                     values[i] = setting.getName();
1339                 } break;
1340
1341                 case Settings.NameValueTable.VALUE: {
1342                     values[i] = setting.getValue();
1343                 } break;
1344             }
1345         }
1346
1347         cursor.addRow(values);
1348     }
1349
1350     private static boolean isKeyValid(String key) {
1351         return !(TextUtils.isEmpty(key) || SettingsState.isBinary(key));
1352     }
1353
1354     private static final class Arguments {
1355         private static final Pattern WHERE_PATTERN_WITH_PARAM_NO_BRACKETS =
1356                 Pattern.compile("[\\s]*name[\\s]*=[\\s]*\\?[\\s]*");
1357
1358         private static final Pattern WHERE_PATTERN_WITH_PARAM_IN_BRACKETS =
1359                 Pattern.compile("[\\s]*\\([\\s]*name[\\s]*=[\\s]*\\?[\\s]*\\)[\\s]*");
1360
1361         private static final Pattern WHERE_PATTERN_NO_PARAM_IN_BRACKETS =
1362                 Pattern.compile("[\\s]*\\([\\s]*name[\\s]*=[\\s]*['\"].*['\"][\\s]*\\)[\\s]*");
1363
1364         private static final Pattern WHERE_PATTERN_NO_PARAM_NO_BRACKETS =
1365                 Pattern.compile("[\\s]*name[\\s]*=[\\s]*['\"].*['\"][\\s]*");
1366
1367         public final String table;
1368         public final String name;
1369
1370         public Arguments(Uri uri, String where, String[] whereArgs, boolean supportAll) {
1371             final int segmentSize = uri.getPathSegments().size();
1372             switch (segmentSize) {
1373                 case 1: {
1374                     if (where != null
1375                             && (WHERE_PATTERN_WITH_PARAM_NO_BRACKETS.matcher(where).matches()
1376                                 || WHERE_PATTERN_WITH_PARAM_IN_BRACKETS.matcher(where).matches())
1377                             && whereArgs.length == 1) {
1378                         name = whereArgs[0];
1379                         table = computeTableForSetting(uri, name);
1380                         return;
1381                     } else if (where != null
1382                             && (WHERE_PATTERN_NO_PARAM_NO_BRACKETS.matcher(where).matches()
1383                                 || WHERE_PATTERN_NO_PARAM_IN_BRACKETS.matcher(where).matches())) {
1384                         final int startIndex = Math.max(where.indexOf("'"),
1385                                 where.indexOf("\"")) + 1;
1386                         final int endIndex = Math.max(where.lastIndexOf("'"),
1387                                 where.lastIndexOf("\""));
1388                         name = where.substring(startIndex, endIndex);
1389                         table = computeTableForSetting(uri, name);
1390                         return;
1391                     } else if (supportAll && where == null && whereArgs == null) {
1392                         name = null;
1393                         table = computeTableForSetting(uri, null);
1394                         return;
1395                     }
1396                 } break;
1397
1398                 case 2: {
1399                     if (where == null && whereArgs == null) {
1400                         name = uri.getPathSegments().get(1);
1401                         table = computeTableForSetting(uri, name);
1402                         return;
1403                     }
1404                 } break;
1405             }
1406
1407             EventLogTags.writeUnsupportedSettingsQuery(
1408                     uri.toSafeString(), where, Arrays.toString(whereArgs));
1409             String message = String.format( "Supported SQL:\n"
1410                     + "  uri content://some_table/some_property with null where and where args\n"
1411                     + "  uri content://some_table with query name=? and single name as arg\n"
1412                     + "  uri content://some_table with query name=some_name and null args\n"
1413                     + "  but got - uri:%1s, where:%2s whereArgs:%3s", uri, where,
1414                     Arrays.toString(whereArgs));
1415             throw new IllegalArgumentException(message);
1416         }
1417
1418         private static String computeTableForSetting(Uri uri, String name) {
1419             String table = getValidTableOrThrow(uri);
1420
1421             if (name != null) {
1422                 if (sSystemMovedToSecureSettings.contains(name)) {
1423                     table = TABLE_SECURE;
1424                 }
1425
1426                 if (sSystemMovedToGlobalSettings.contains(name)) {
1427                     table = TABLE_GLOBAL;
1428                 }
1429
1430                 if (sSecureMovedToGlobalSettings.contains(name)) {
1431                     table = TABLE_GLOBAL;
1432                 }
1433
1434                 if (sGlobalMovedToSecureSettings.contains(name)) {
1435                     table = TABLE_SECURE;
1436                 }
1437             }
1438
1439             return table;
1440         }
1441     }
1442
1443     final class SettingsRegistry {
1444         private static final String DROPBOX_TAG_USERLOG = "restricted_profile_ssaid";
1445
1446         private static final int SETTINGS_TYPE_GLOBAL = 0;
1447         private static final int SETTINGS_TYPE_SYSTEM = 1;
1448         private static final int SETTINGS_TYPE_SECURE = 2;
1449
1450         private static final int SETTINGS_TYPE_MASK = 0xF0000000;
1451         private static final int SETTINGS_TYPE_SHIFT = 28;
1452
1453         private static final String SETTINGS_FILE_GLOBAL = "settings_global.xml";
1454         private static final String SETTINGS_FILE_SYSTEM = "settings_system.xml";
1455         private static final String SETTINGS_FILE_SECURE = "settings_secure.xml";
1456
1457         private final SparseArray<SettingsState> mSettingsStates = new SparseArray<>();
1458
1459         private final BackupManager mBackupManager;
1460
1461         private final Handler mHandler;
1462
1463         public SettingsRegistry() {
1464             mBackupManager = new BackupManager(getContext());
1465             mHandler = new MyHandler(getContext().getMainLooper());
1466             migrateAllLegacySettingsIfNeeded();
1467         }
1468
1469         public List<String> getSettingsNamesLocked(int type, int userId) {
1470             final int key = makeKey(type, userId);
1471             SettingsState settingsState = peekSettingsStateLocked(key);
1472             return settingsState.getSettingNamesLocked();
1473         }
1474
1475         public SettingsState getSettingsLocked(int type, int userId) {
1476             final int key = makeKey(type, userId);
1477             return peekSettingsStateLocked(key);
1478         }
1479
1480         public void ensureSettingsForUserLocked(int userId) {
1481             // Migrate the setting for this user if needed.
1482             migrateLegacySettingsForUserIfNeededLocked(userId);
1483
1484             // Ensure global settings loaded if owner.
1485             if (userId == UserHandle.USER_SYSTEM) {
1486                 final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
1487                 ensureSettingsStateLocked(globalKey);
1488             }
1489
1490             // Ensure secure settings loaded.
1491             final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
1492             ensureSettingsStateLocked(secureKey);
1493
1494             // Make sure the secure settings have an Android id set.
1495             SettingsState secureSettings = getSettingsLocked(SETTINGS_TYPE_SECURE, userId);
1496             ensureSecureSettingAndroidIdSetLocked(secureSettings);
1497
1498             // Ensure system settings loaded.
1499             final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
1500             ensureSettingsStateLocked(systemKey);
1501
1502             // Upgrade the settings to the latest version.
1503             UpgradeController upgrader = new UpgradeController(userId);
1504             upgrader.upgradeIfNeededLocked();
1505         }
1506
1507         private void ensureSettingsStateLocked(int key) {
1508             if (mSettingsStates.get(key) == null) {
1509                 final int maxBytesPerPackage = getMaxBytesPerPackageForType(getTypeFromKey(key));
1510                 SettingsState settingsState = new SettingsState(mLock, getSettingsFile(key), key,
1511                         maxBytesPerPackage);
1512                 mSettingsStates.put(key, settingsState);
1513             }
1514         }
1515
1516         public void removeUserStateLocked(int userId, boolean permanently) {
1517             // We always keep the global settings in memory.
1518
1519             // Nuke system settings.
1520             final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
1521             final SettingsState systemSettingsState = mSettingsStates.get(systemKey);
1522             if (systemSettingsState != null) {
1523                 if (permanently) {
1524                     mSettingsStates.remove(systemKey);
1525                     systemSettingsState.destroyLocked(null);
1526                 } else {
1527                     systemSettingsState.destroyLocked(new Runnable() {
1528                         @Override
1529                         public void run() {
1530                             mSettingsStates.remove(systemKey);
1531                         }
1532                     });
1533                 }
1534             }
1535
1536             // Nuke secure settings.
1537             final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
1538             final SettingsState secureSettingsState = mSettingsStates.get(secureKey);
1539             if (secureSettingsState != null) {
1540                 if (permanently) {
1541                     mSettingsStates.remove(secureKey);
1542                     secureSettingsState.destroyLocked(null);
1543                 } else {
1544                     secureSettingsState.destroyLocked(new Runnable() {
1545                         @Override
1546                         public void run() {
1547                             mSettingsStates.remove(secureKey);
1548                         }
1549                     });
1550                 }
1551             }
1552         }
1553
1554         public boolean insertSettingLocked(int type, int userId, String name, String value,
1555                 String packageName) {
1556             final int key = makeKey(type, userId);
1557
1558             SettingsState settingsState = peekSettingsStateLocked(key);
1559             final boolean success = settingsState.insertSettingLocked(name, value, packageName);
1560
1561             if (success) {
1562                 notifyForSettingsChange(key, name);
1563             }
1564             return success;
1565         }
1566
1567         public boolean deleteSettingLocked(int type, int userId, String name) {
1568             final int key = makeKey(type, userId);
1569
1570             SettingsState settingsState = peekSettingsStateLocked(key);
1571             final boolean success = settingsState.deleteSettingLocked(name);
1572
1573             if (success) {
1574                 notifyForSettingsChange(key, name);
1575             }
1576             return success;
1577         }
1578
1579         public Setting getSettingLocked(int type, int userId, String name) {
1580             final int key = makeKey(type, userId);
1581
1582             SettingsState settingsState = peekSettingsStateLocked(key);
1583             return settingsState.getSettingLocked(name);
1584         }
1585
1586         public boolean updateSettingLocked(int type, int userId, String name, String value,
1587                 String packageName) {
1588             final int key = makeKey(type, userId);
1589
1590             SettingsState settingsState = peekSettingsStateLocked(key);
1591             final boolean success = settingsState.updateSettingLocked(name, value, packageName);
1592
1593             if (success) {
1594                 notifyForSettingsChange(key, name);
1595             }
1596
1597             return success;
1598         }
1599
1600         public void onPackageRemovedLocked(String packageName, int userId) {
1601             // Global and secure settings are signature protected. Apps signed
1602             // by the platform certificate are generally not uninstalled  and
1603             // the main exception is tests. We trust components signed
1604             // by the platform certificate and do not do a clean up after them.
1605
1606             final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
1607             SettingsState systemSettings = mSettingsStates.get(systemKey);
1608             if (systemSettings != null) {
1609                 systemSettings.onPackageRemovedLocked(packageName);
1610             }
1611         }
1612
1613         private SettingsState peekSettingsStateLocked(int key) {
1614             SettingsState settingsState = mSettingsStates.get(key);
1615             if (settingsState != null) {
1616                 return settingsState;
1617             }
1618
1619             ensureSettingsForUserLocked(getUserIdFromKey(key));
1620             return mSettingsStates.get(key);
1621         }
1622
1623         private void migrateAllLegacySettingsIfNeeded() {
1624             synchronized (mLock) {
1625                 final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
1626                 File globalFile = getSettingsFile(key);
1627                 if (globalFile.exists()) {
1628                     return;
1629                 }
1630
1631                 final long identity = Binder.clearCallingIdentity();
1632                 try {
1633                     List<UserInfo> users = mUserManager.getUsers(true);
1634
1635                     final int userCount = users.size();
1636                     for (int i = 0; i < userCount; i++) {
1637                         final int userId = users.get(i).id;
1638
1639                         DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId);
1640                         SQLiteDatabase database = dbHelper.getWritableDatabase();
1641                         migrateLegacySettingsForUserLocked(dbHelper, database, userId);
1642
1643                         // Upgrade to the latest version.
1644                         UpgradeController upgrader = new UpgradeController(userId);
1645                         upgrader.upgradeIfNeededLocked();
1646
1647                         // Drop from memory if not a running user.
1648                         if (!mUserManager.isUserRunning(new UserHandle(userId))) {
1649                             removeUserStateLocked(userId, false);
1650                         }
1651                     }
1652                 } finally {
1653                     Binder.restoreCallingIdentity(identity);
1654                 }
1655             }
1656         }
1657
1658         private void migrateLegacySettingsForUserIfNeededLocked(int userId) {
1659             // Every user has secure settings and if no file we need to migrate.
1660             final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
1661             File secureFile = getSettingsFile(secureKey);
1662             if (secureFile.exists()) {
1663                 return;
1664             }
1665
1666             DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId);
1667             SQLiteDatabase database = dbHelper.getWritableDatabase();
1668
1669             migrateLegacySettingsForUserLocked(dbHelper, database, userId);
1670         }
1671
1672         private void migrateLegacySettingsForUserLocked(DatabaseHelper dbHelper,
1673                 SQLiteDatabase database, int userId) {
1674             // Move over the system settings.
1675             final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
1676             ensureSettingsStateLocked(systemKey);
1677             SettingsState systemSettings = mSettingsStates.get(systemKey);
1678             migrateLegacySettingsLocked(systemSettings, database, TABLE_SYSTEM);
1679             systemSettings.persistSyncLocked();
1680
1681             // Move over the secure settings.
1682             // Do this after System settings, since this is the first thing we check when deciding
1683             // to skip over migration from db to xml for a secondary user.
1684             final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
1685             ensureSettingsStateLocked(secureKey);
1686             SettingsState secureSettings = mSettingsStates.get(secureKey);
1687             migrateLegacySettingsLocked(secureSettings, database, TABLE_SECURE);
1688             ensureSecureSettingAndroidIdSetLocked(secureSettings);
1689             secureSettings.persistSyncLocked();
1690
1691             // Move over the global settings if owner.
1692             // Do this last, since this is the first thing we check when deciding
1693             // to skip over migration from db to xml for owner user.
1694             if (userId == UserHandle.USER_SYSTEM) {
1695                 final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, userId);
1696                 ensureSettingsStateLocked(globalKey);
1697                 SettingsState globalSettings = mSettingsStates.get(globalKey);
1698                 migrateLegacySettingsLocked(globalSettings, database, TABLE_GLOBAL);
1699                 globalSettings.persistSyncLocked();
1700             }
1701
1702             // Drop the database as now all is moved and persisted.
1703             if (DROP_DATABASE_ON_MIGRATION) {
1704                 dbHelper.dropDatabase();
1705             } else {
1706                 dbHelper.backupDatabase();
1707             }
1708         }
1709
1710         private void migrateLegacySettingsLocked(SettingsState settingsState,
1711                 SQLiteDatabase database, String table) {
1712             SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
1713             queryBuilder.setTables(table);
1714
1715             Cursor cursor = queryBuilder.query(database, ALL_COLUMNS,
1716                     null, null, null, null, null);
1717
1718             if (cursor == null) {
1719                 return;
1720             }
1721
1722             try {
1723                 if (!cursor.moveToFirst()) {
1724                     return;
1725                 }
1726
1727                 final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME);
1728                 final int valueColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.VALUE);
1729
1730                 settingsState.setVersionLocked(database.getVersion());
1731
1732                 while (!cursor.isAfterLast()) {
1733                     String name = cursor.getString(nameColumnIdx);
1734                     String value = cursor.getString(valueColumnIdx);
1735                     settingsState.insertSettingLocked(name, value,
1736                             SettingsState.SYSTEM_PACKAGE_NAME);
1737                     cursor.moveToNext();
1738                 }
1739             } finally {
1740                 cursor.close();
1741             }
1742         }
1743
1744         private void ensureSecureSettingAndroidIdSetLocked(SettingsState secureSettings) {
1745             Setting value = secureSettings.getSettingLocked(Settings.Secure.ANDROID_ID);
1746
1747             if (value != null) {
1748                 return;
1749             }
1750
1751             final int userId = getUserIdFromKey(secureSettings.mKey);
1752
1753             final UserInfo user;
1754             final long identity = Binder.clearCallingIdentity();
1755             try {
1756                 user = mUserManager.getUserInfo(userId);
1757             } finally {
1758                 Binder.restoreCallingIdentity(identity);
1759             }
1760             if (user == null) {
1761                 // Can happen due to races when deleting users - treat as benign.
1762                 return;
1763             }
1764
1765             String androidId = Long.toHexString(new SecureRandom().nextLong());
1766             secureSettings.insertSettingLocked(Settings.Secure.ANDROID_ID, androidId,
1767                     SettingsState.SYSTEM_PACKAGE_NAME);
1768
1769             Slog.d(LOG_TAG, "Generated and saved new ANDROID_ID [" + androidId
1770                     + "] for user " + userId);
1771
1772             // Write a drop box entry if it's a restricted profile
1773             if (user.isRestricted()) {
1774                 DropBoxManager dbm = (DropBoxManager) getContext().getSystemService(
1775                         Context.DROPBOX_SERVICE);
1776                 if (dbm != null && dbm.isTagEnabled(DROPBOX_TAG_USERLOG)) {
1777                     dbm.addText(DROPBOX_TAG_USERLOG, System.currentTimeMillis()
1778                             + "," + DROPBOX_TAG_USERLOG + "," + androidId + "\n");
1779                 }
1780             }
1781         }
1782
1783         private void notifyForSettingsChange(int key, String name) {
1784             // Update the system property *first*, so if someone is listening for
1785             // a notification and then using the contract class to get their data,
1786             // the system property will be updated and they'll get the new data.
1787
1788             boolean backedUpDataChanged = false;
1789             String property = null;
1790             if (isGlobalSettingsKey(key)) {
1791                 property = Settings.Global.SYS_PROP_SETTING_VERSION;
1792                 backedUpDataChanged = true;
1793             } else if (isSecureSettingsKey(key)) {
1794                 property = Settings.Secure.SYS_PROP_SETTING_VERSION;
1795                 backedUpDataChanged = true;
1796             } else if (isSystemSettingsKey(key)) {
1797                 property = Settings.System.SYS_PROP_SETTING_VERSION;
1798                 backedUpDataChanged = true;
1799             }
1800
1801             if (property != null) {
1802                 final long version = SystemProperties.getLong(property, 0) + 1;
1803                 SystemProperties.set(property, Long.toString(version));
1804                 if (DEBUG) {
1805                     Slog.v(LOG_TAG, "System property " + property + "=" + version);
1806                 }
1807             }
1808
1809             // Inform the backup manager about a data change
1810             if (backedUpDataChanged) {
1811                 mHandler.obtainMessage(MyHandler.MSG_NOTIFY_DATA_CHANGED).sendToTarget();
1812             }
1813
1814             // Now send the notification through the content framework.
1815
1816             final int userId = getUserIdFromKey(key);
1817             Uri uri = getNotificationUriFor(key, name);
1818
1819             mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
1820                     userId, 0, uri).sendToTarget();
1821
1822             if (isSecureSettingsKey(key)) {
1823                 maybeNotifyProfiles(userId, uri, name, sSecureCloneToManagedSettings);
1824             } else if (isSystemSettingsKey(key)) {
1825                 maybeNotifyProfiles(userId, uri, name, sSystemCloneToManagedSettings);
1826             }
1827         }
1828
1829         private void maybeNotifyProfiles(int userId, Uri uri, String name,
1830                 Set<String> keysCloned) {
1831             if (keysCloned.contains(name)) {
1832                 List<UserInfo> profiles = mUserManager.getProfiles(userId);
1833                 int size = profiles.size();
1834                 for (int i = 0; i < size; i++) {
1835                     UserInfo profile = profiles.get(i);
1836                     // the notification for userId has already been sent.
1837                     if (profile.id != userId) {
1838                         mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
1839                                 profile.id, 0, uri).sendToTarget();
1840                     }
1841                 }
1842             }
1843         }
1844
1845         private int makeKey(int type, int userId) {
1846             return (type << SETTINGS_TYPE_SHIFT) | userId;
1847         }
1848
1849         private int getTypeFromKey(int key) {
1850             return key >> SETTINGS_TYPE_SHIFT;
1851         }
1852
1853         private int getUserIdFromKey(int key) {
1854             return key & ~SETTINGS_TYPE_MASK;
1855         }
1856
1857         private boolean isGlobalSettingsKey(int key) {
1858             return getTypeFromKey(key) == SETTINGS_TYPE_GLOBAL;
1859         }
1860
1861         private boolean isSystemSettingsKey(int key) {
1862             return getTypeFromKey(key) == SETTINGS_TYPE_SYSTEM;
1863         }
1864
1865         private boolean isSecureSettingsKey(int key) {
1866             return getTypeFromKey(key) == SETTINGS_TYPE_SECURE;
1867         }
1868
1869         private File getSettingsFile(int key) {
1870             if (isGlobalSettingsKey(key)) {
1871                 final int userId = getUserIdFromKey(key);
1872                 return new File(Environment.getUserSystemDirectory(userId),
1873                         SETTINGS_FILE_GLOBAL);
1874             } else if (isSystemSettingsKey(key)) {
1875                 final int userId = getUserIdFromKey(key);
1876                 return new File(Environment.getUserSystemDirectory(userId),
1877                         SETTINGS_FILE_SYSTEM);
1878             } else if (isSecureSettingsKey(key)) {
1879                 final int userId = getUserIdFromKey(key);
1880                 return new File(Environment.getUserSystemDirectory(userId),
1881                         SETTINGS_FILE_SECURE);
1882             } else {
1883                 throw new IllegalArgumentException("Invalid settings key:" + key);
1884             }
1885         }
1886
1887         private Uri getNotificationUriFor(int key, String name) {
1888             if (isGlobalSettingsKey(key)) {
1889                 return (name != null) ? Uri.withAppendedPath(Settings.Global.CONTENT_URI, name)
1890                         : Settings.Global.CONTENT_URI;
1891             } else if (isSecureSettingsKey(key)) {
1892                 return (name != null) ? Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name)
1893                         : Settings.Secure.CONTENT_URI;
1894             } else if (isSystemSettingsKey(key)) {
1895                 return (name != null) ? Uri.withAppendedPath(Settings.System.CONTENT_URI, name)
1896                         : Settings.System.CONTENT_URI;
1897             } else {
1898                 throw new IllegalArgumentException("Invalid settings key:" + key);
1899             }
1900         }
1901
1902         private int getMaxBytesPerPackageForType(int type) {
1903             switch (type) {
1904                 case SETTINGS_TYPE_GLOBAL:
1905                 case SETTINGS_TYPE_SECURE: {
1906                     return SettingsState.MAX_BYTES_PER_APP_PACKAGE_UNLIMITED;
1907                 }
1908
1909                 default: {
1910                     return SettingsState.MAX_BYTES_PER_APP_PACKAGE_LIMITED;
1911                 }
1912             }
1913         }
1914
1915         private final class MyHandler extends Handler {
1916             private static final int MSG_NOTIFY_URI_CHANGED = 1;
1917             private static final int MSG_NOTIFY_DATA_CHANGED = 2;
1918
1919             public MyHandler(Looper looper) {
1920                 super(looper);
1921             }
1922
1923             @Override
1924             public void handleMessage(Message msg) {
1925                 switch (msg.what) {
1926                     case MSG_NOTIFY_URI_CHANGED: {
1927                         final int userId = msg.arg1;
1928                         Uri uri = (Uri) msg.obj;
1929                         getContext().getContentResolver().notifyChange(uri, null, true, userId);
1930                         if (DEBUG) {
1931                             Slog.v(LOG_TAG, "Notifying for " + userId + ": " + uri);
1932                         }
1933                     } break;
1934
1935                     case MSG_NOTIFY_DATA_CHANGED: {
1936                         mBackupManager.dataChanged();
1937                     } break;
1938                 }
1939             }
1940         }
1941
1942         private final class UpgradeController {
1943             private static final int SETTINGS_VERSION = 125;
1944
1945             private final int mUserId;
1946
1947             public UpgradeController(int userId) {
1948                 mUserId = userId;
1949             }
1950
1951             public void upgradeIfNeededLocked() {
1952                 // The version of all settings for a user is the same (all users have secure).
1953                 SettingsState secureSettings = getSettingsLocked(
1954                         SettingsRegistry.SETTINGS_TYPE_SECURE, mUserId);
1955
1956                 // Try an update from the current state.
1957                 final int oldVersion = secureSettings.getVersionLocked();
1958                 final int newVersion = SETTINGS_VERSION;
1959
1960                 // If up do date - done.
1961                 if (oldVersion == newVersion) {
1962                     return;
1963                 }
1964
1965                 // Try to upgrade.
1966                 final int curVersion = onUpgradeLocked(mUserId, oldVersion, newVersion);
1967
1968                 // If upgrade failed start from scratch and upgrade.
1969                 if (curVersion != newVersion) {
1970                     // Drop state we have for this user.
1971                     removeUserStateLocked(mUserId, true);
1972
1973                     // Recreate the database.
1974                     DatabaseHelper dbHelper = new DatabaseHelper(getContext(), mUserId);
1975                     SQLiteDatabase database = dbHelper.getWritableDatabase();
1976                     dbHelper.recreateDatabase(database, newVersion, curVersion, oldVersion);
1977
1978                     // Migrate the settings for this user.
1979                     migrateLegacySettingsForUserLocked(dbHelper, database, mUserId);
1980
1981                     // Now upgrade should work fine.
1982                     onUpgradeLocked(mUserId, oldVersion, newVersion);
1983                 }
1984
1985                 // Set the global settings version if owner.
1986                 if (mUserId == UserHandle.USER_SYSTEM) {
1987                     SettingsState globalSettings = getSettingsLocked(
1988                             SettingsRegistry.SETTINGS_TYPE_GLOBAL, mUserId);
1989                     globalSettings.setVersionLocked(newVersion);
1990                 }
1991
1992                 // Set the secure settings version.
1993                 secureSettings.setVersionLocked(newVersion);
1994
1995                 // Set the system settings version.
1996                 SettingsState systemSettings = getSettingsLocked(
1997                         SettingsRegistry.SETTINGS_TYPE_SYSTEM, mUserId);
1998                 systemSettings.setVersionLocked(newVersion);
1999             }
2000
2001             private SettingsState getGlobalSettingsLocked() {
2002                 return getSettingsLocked(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
2003             }
2004
2005             private SettingsState getSecureSettingsLocked(int userId) {
2006                 return getSettingsLocked(SETTINGS_TYPE_SECURE, userId);
2007             }
2008
2009             private SettingsState getSystemSettingsLocked(int userId) {
2010                 return getSettingsLocked(SETTINGS_TYPE_SYSTEM, userId);
2011             }
2012
2013             /**
2014              * You must perform all necessary mutations to bring the settings
2015              * for this user from the old to the new version. When you add a new
2016              * upgrade step you *must* update SETTINGS_VERSION.
2017              *
2018              * This is an example of moving a setting from secure to global.
2019              *
2020              * // v119: Example settings changes.
2021              * if (currentVersion == 118) {
2022              *     if (userId == UserHandle.USER_OWNER) {
2023              *         // Remove from the secure settings.
2024              *         SettingsState secureSettings = getSecureSettingsLocked(userId);
2025              *         String name = "example_setting_to_move";
2026              *         String value = secureSettings.getSetting(name);
2027              *         secureSettings.deleteSetting(name);
2028              *
2029              *         // Add to the global settings.
2030              *         SettingsState globalSettings = getGlobalSettingsLocked();
2031              *         globalSettings.insertSetting(name, value, SettingsState.SYSTEM_PACKAGE_NAME);
2032              *     }
2033              *
2034              *     // Update the current version.
2035              *     currentVersion = 119;
2036              * }
2037              */
2038             private int onUpgradeLocked(int userId, int oldVersion, int newVersion) {
2039                 if (DEBUG) {
2040                     Slog.w(LOG_TAG, "Upgrading settings for user: " + userId + " from version: "
2041                             + oldVersion + " to version: " + newVersion);
2042                 }
2043
2044                 int currentVersion = oldVersion;
2045
2046                 // v119: Reset zen + ringer mode.
2047                 if (currentVersion == 118) {
2048                     if (userId == UserHandle.USER_SYSTEM) {
2049                         final SettingsState globalSettings = getGlobalSettingsLocked();
2050                         globalSettings.updateSettingLocked(Settings.Global.ZEN_MODE,
2051                                 Integer.toString(Settings.Global.ZEN_MODE_OFF),
2052                                 SettingsState.SYSTEM_PACKAGE_NAME);
2053                         globalSettings.updateSettingLocked(Settings.Global.MODE_RINGER,
2054                                 Integer.toString(AudioManager.RINGER_MODE_NORMAL),
2055                                 SettingsState.SYSTEM_PACKAGE_NAME);
2056                     }
2057                     currentVersion = 119;
2058                 }
2059
2060                 // v120: Add double tap to wake setting.
2061                 if (currentVersion == 119) {
2062                     SettingsState secureSettings = getSecureSettingsLocked(userId);
2063                     secureSettings.insertSettingLocked(Settings.Secure.DOUBLE_TAP_TO_WAKE,
2064                             getContext().getResources().getBoolean(
2065                                     R.bool.def_double_tap_to_wake) ? "1" : "0",
2066                             SettingsState.SYSTEM_PACKAGE_NAME);
2067
2068                     currentVersion = 120;
2069                 }
2070
2071                 if (currentVersion == 120) {
2072                     // Before 121, we used a different string encoding logic.  We just bump the
2073                     // version here; SettingsState knows how to handle pre-version 120 files.
2074                     currentVersion = 121;
2075                 }
2076
2077                 if (currentVersion == 121) {
2078                     // Version 122: allow OEMs to set a default payment component in resources.
2079                     // Note that we only write the default if no default has been set;
2080                     // if there is, we just leave the default at whatever it currently is.
2081                     final SettingsState secureSettings = getSecureSettingsLocked(userId);
2082                     String defaultComponent = (getContext().getResources().getString(
2083                             R.string.def_nfc_payment_component));
2084                     Setting currentSetting = secureSettings.getSettingLocked(
2085                             Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT);
2086                     if (defaultComponent != null && !defaultComponent.isEmpty() &&
2087                         currentSetting == null) {
2088                         secureSettings.insertSettingLocked(
2089                                 Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT,
2090                                 defaultComponent,
2091                                 SettingsState.SYSTEM_PACKAGE_NAME);
2092                     }
2093                     currentVersion = 122;
2094                 }
2095
2096                 if (currentVersion == 122) {
2097                     // Version 123: Adding a default value for the ability to add a user from
2098                     // the lock screen.
2099                     if (userId == UserHandle.USER_SYSTEM) {
2100                         final SettingsState globalSettings = getGlobalSettingsLocked();
2101                         Setting currentSetting = globalSettings.getSettingLocked(
2102                                 Settings.Global.ADD_USERS_WHEN_LOCKED);
2103                         if (currentSetting == null) {
2104                             globalSettings.insertSettingLocked(
2105                                     Settings.Global.ADD_USERS_WHEN_LOCKED,
2106                                     getContext().getResources().getBoolean(
2107                                             R.bool.def_add_users_from_lockscreen) ? "1" : "0",
2108                                     SettingsState.SYSTEM_PACKAGE_NAME);
2109                         }
2110                     }
2111                     currentVersion = 123;
2112                 }
2113
2114                 if (currentVersion == 123) {
2115                     final SettingsState globalSettings = getGlobalSettingsLocked();
2116                     String defaultDisabledProfiles = (getContext().getResources().getString(
2117                             R.string.def_bluetooth_disabled_profiles));
2118                     globalSettings.insertSettingLocked(Settings.Global.BLUETOOTH_DISABLED_PROFILES,
2119                             defaultDisabledProfiles, SettingsState.SYSTEM_PACKAGE_NAME);
2120                     currentVersion = 124;
2121                 }
2122
2123                 if (currentVersion == 124) {
2124                     // Version 124: allow OEMs to set a default value for whether IME should be
2125                     // shown when a physical keyboard is connected.
2126                     final SettingsState secureSettings = getSecureSettingsLocked(userId);
2127                     Setting currentSetting = secureSettings.getSettingLocked(
2128                             Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
2129                     if (currentSetting == null) {
2130                         secureSettings.insertSettingLocked(
2131                                 Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
2132                                 getContext().getResources().getBoolean(
2133                                         R.bool.def_show_ime_with_hard_keyboard) ? "1" : "0",
2134                                 SettingsState.SYSTEM_PACKAGE_NAME);
2135                     }
2136                     currentVersion = 125;
2137                 }
2138
2139                 // vXXX: Add new settings above this point.
2140
2141                 // Return the current version.
2142                 return currentVersion;
2143             }
2144         }
2145     }
2146 }