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
17package com.android.providers.settings;
18
19import static android.os.Process.ROOT_UID;
20import static android.os.Process.SHELL_UID;
21import static android.os.Process.SYSTEM_UID;
22
23import android.Manifest;
24import android.annotation.NonNull;
25import android.annotation.Nullable;
26import android.app.ActivityManager;
27import android.app.AppGlobals;
28import android.app.backup.BackupManager;
29import android.content.BroadcastReceiver;
30import android.content.ComponentName;
31import android.content.ContentProvider;
32import android.content.ContentValues;
33import android.content.Context;
34import android.content.Intent;
35import android.content.IntentFilter;
36import android.content.pm.ApplicationInfo;
37import android.content.pm.IPackageManager;
38import android.content.pm.PackageInfo;
39import android.content.pm.PackageManager;
40import android.content.pm.UserInfo;
41import android.content.res.Resources;
42import android.database.Cursor;
43import android.database.MatrixCursor;
44import android.database.sqlite.SQLiteDatabase;
45import android.database.sqlite.SQLiteQueryBuilder;
46import android.hardware.camera2.utils.ArrayUtils;
47import android.media.AudioManager;
48import android.net.Uri;
49import android.os.Binder;
50import android.os.Build;
51import android.os.Bundle;
52import android.os.DropBoxManager;
53import android.os.Environment;
54import android.os.Handler;
55import android.os.HandlerThread;
56import android.os.Looper;
57import android.os.Message;
58import android.os.ParcelFileDescriptor;
59import android.os.Process;
60import android.os.RemoteException;
61import android.os.SELinux;
62import android.os.ServiceManager;
63import android.os.UserHandle;
64import android.os.UserManager;
65import android.os.UserManagerInternal;
66import android.provider.Settings;
67import android.provider.Settings.Global;
68import android.provider.Settings.Secure;
69import android.provider.SettingsValidators;
70import android.text.TextUtils;
71import android.util.ArrayMap;
72import android.util.ArraySet;
73import android.util.ByteStringUtils;
74import android.util.Slog;
75import android.util.SparseArray;
76import android.util.SparseBooleanArray;
77import android.util.proto.ProtoOutputStream;
78
79import com.android.internal.annotations.GuardedBy;
80import com.android.internal.content.PackageMonitor;
81import com.android.internal.os.BackgroundThread;
82import com.android.providers.settings.SettingsState.Setting;
83import com.android.server.LocalServices;
84import com.android.server.SystemConfig;
85
86import java.io.File;
87import java.io.FileDescriptor;
88import java.io.FileNotFoundException;
89import java.io.PrintWriter;
90import java.nio.ByteBuffer;
91import java.security.InvalidKeyException;
92import java.security.NoSuchAlgorithmException;
93import java.security.SecureRandom;
94import java.util.ArrayList;
95import java.util.Arrays;
96import java.util.Collection;
97import java.util.HashSet;
98import java.util.List;
99import java.util.Locale;
100import java.util.Map;
101import java.util.Set;
102import java.util.regex.Pattern;
103
104import javax.crypto.Mac;
105import javax.crypto.spec.SecretKeySpec;
106
107
108/**
109 * <p>
110 * This class is a content provider that publishes the system settings.
111 * It can be accessed via the content provider APIs or via custom call
112 * commands. The latter is a bit faster and is the preferred way to access
113 * the platform settings.
114 * </p>
115 * <p>
116 * There are three settings types, global (with signature level protection
117 * and shared across users), secure (with signature permission level
118 * protection and per user), and system (with dangerous permission level
119 * protection and per user). Global settings are stored under the device owner.
120 * Each of these settings is represented by a {@link
121 * com.android.providers.settings.SettingsState} object mapped to an integer
122 * key derived from the setting type in the most significant bits and user
123 * id in the least significant bits. Settings are synchronously loaded on
124 * instantiation of a SettingsState and asynchronously persisted on mutation.
125 * Settings are stored in the user specific system directory.
126 * </p>
127 * <p>
128 * Apps targeting APIs Lollipop MR1 and lower can add custom settings entries
129 * and get a warning. Targeting higher API version prohibits this as the
130 * system settings are not a place for apps to save their state. When a package
131 * is removed the settings it added are deleted. Apps cannot delete system
132 * settings added by the platform. System settings values are validated to
133 * ensure the clients do not put bad values. Global and secure settings are
134 * changed only by trusted parties, therefore no validation is performed. Also
135 * there is a limit on the amount of app specific settings that can be added
136 * to prevent unlimited growth of the system process memory footprint.
137 * </p>
138 */
139@SuppressWarnings("deprecation")
140public class SettingsProvider extends ContentProvider {
141    static final boolean DEBUG = false;
142
143    private static final boolean DROP_DATABASE_ON_MIGRATION = true;
144
145    private static final String LOG_TAG = "SettingsProvider";
146
147    private static final String TABLE_SYSTEM = "system";
148    private static final String TABLE_SECURE = "secure";
149    private static final String TABLE_GLOBAL = "global";
150
151    // Old tables no longer exist.
152    private static final String TABLE_FAVORITES = "favorites";
153    private static final String TABLE_OLD_FAVORITES = "old_favorites";
154    private static final String TABLE_BLUETOOTH_DEVICES = "bluetooth_devices";
155    private static final String TABLE_BOOKMARKS = "bookmarks";
156    private static final String TABLE_ANDROID_METADATA = "android_metadata";
157
158    // The set of removed legacy tables.
159    private static final Set<String> REMOVED_LEGACY_TABLES = new ArraySet<>();
160    static {
161        REMOVED_LEGACY_TABLES.add(TABLE_FAVORITES);
162        REMOVED_LEGACY_TABLES.add(TABLE_OLD_FAVORITES);
163        REMOVED_LEGACY_TABLES.add(TABLE_BLUETOOTH_DEVICES);
164        REMOVED_LEGACY_TABLES.add(TABLE_BOOKMARKS);
165        REMOVED_LEGACY_TABLES.add(TABLE_ANDROID_METADATA);
166    }
167
168    private static final int MUTATION_OPERATION_INSERT = 1;
169    private static final int MUTATION_OPERATION_DELETE = 2;
170    private static final int MUTATION_OPERATION_UPDATE = 3;
171    private static final int MUTATION_OPERATION_RESET = 4;
172
173    private static final String[] ALL_COLUMNS = new String[] {
174            Settings.NameValueTable._ID,
175            Settings.NameValueTable.NAME,
176            Settings.NameValueTable.VALUE
177    };
178
179    public static final int SETTINGS_TYPE_GLOBAL = SettingsState.SETTINGS_TYPE_GLOBAL;
180    public static final int SETTINGS_TYPE_SYSTEM = SettingsState.SETTINGS_TYPE_SYSTEM;
181    public static final int SETTINGS_TYPE_SECURE = SettingsState.SETTINGS_TYPE_SECURE;
182    public static final int SETTINGS_TYPE_SSAID = SettingsState.SETTINGS_TYPE_SSAID;
183
184    private static final Bundle NULL_SETTING_BUNDLE = Bundle.forPair(
185            Settings.NameValueTable.VALUE, null);
186
187    // Overlay specified settings whitelisted for Instant Apps
188    private static final Set<String> OVERLAY_ALLOWED_GLOBAL_INSTANT_APP_SETTINGS = new ArraySet<>();
189    private static final Set<String> OVERLAY_ALLOWED_SYSTEM_INSTANT_APP_SETTINGS = new ArraySet<>();
190    private static final Set<String> OVERLAY_ALLOWED_SECURE_INSTANT_APP_SETTINGS = new ArraySet<>();
191
192    static {
193        for (String name : Resources.getSystem().getStringArray(
194                com.android.internal.R.array.config_allowedGlobalInstantAppSettings)) {
195            OVERLAY_ALLOWED_GLOBAL_INSTANT_APP_SETTINGS.add(name);
196        }
197        for (String name : Resources.getSystem().getStringArray(
198                com.android.internal.R.array.config_allowedSystemInstantAppSettings)) {
199            OVERLAY_ALLOWED_SYSTEM_INSTANT_APP_SETTINGS.add(name);
200        }
201        for (String name : Resources.getSystem().getStringArray(
202                com.android.internal.R.array.config_allowedSecureInstantAppSettings)) {
203            OVERLAY_ALLOWED_SECURE_INSTANT_APP_SETTINGS.add(name);
204        }
205    }
206
207    // Changes to these global settings are synchronously persisted
208    private static final Set<String> CRITICAL_GLOBAL_SETTINGS = new ArraySet<>();
209    static {
210        CRITICAL_GLOBAL_SETTINGS.add(Settings.Global.DEVICE_PROVISIONED);
211    }
212
213    // Changes to these secure settings are synchronously persisted
214    private static final Set<String> CRITICAL_SECURE_SETTINGS = new ArraySet<>();
215    static {
216        CRITICAL_SECURE_SETTINGS.add(Settings.Secure.USER_SETUP_COMPLETE);
217    }
218
219    // Per user secure settings that moved to the for all users global settings.
220    static final Set<String> sSecureMovedToGlobalSettings = new ArraySet<>();
221    static {
222        Settings.Secure.getMovedToGlobalSettings(sSecureMovedToGlobalSettings);
223    }
224
225    // Per user system settings that moved to the for all users global settings.
226    static final Set<String> sSystemMovedToGlobalSettings = new ArraySet<>();
227    static {
228        Settings.System.getMovedToGlobalSettings(sSystemMovedToGlobalSettings);
229    }
230
231    // Per user system settings that moved to the per user secure settings.
232    static final Set<String> sSystemMovedToSecureSettings = new ArraySet<>();
233    static {
234        Settings.System.getMovedToSecureSettings(sSystemMovedToSecureSettings);
235    }
236
237    // Per all users global settings that moved to the per user secure settings.
238    static final Set<String> sGlobalMovedToSecureSettings = new ArraySet<>();
239    static {
240        Settings.Global.getMovedToSecureSettings(sGlobalMovedToSecureSettings);
241    }
242
243    // Per user secure settings that are cloned for the managed profiles of the user.
244    private static final Set<String> sSecureCloneToManagedSettings = new ArraySet<>();
245    static {
246        Settings.Secure.getCloneToManagedProfileSettings(sSecureCloneToManagedSettings);
247    }
248
249    // Per user system settings that are cloned for the managed profiles of the user.
250    private static final Set<String> sSystemCloneToManagedSettings = new ArraySet<>();
251    static {
252        Settings.System.getCloneToManagedProfileSettings(sSystemCloneToManagedSettings);
253    }
254
255    // Per user system settings that are cloned from the profile's parent when a dependency
256    // in {@link Settings.Secure} is set to "1".
257    public static final Map<String, String> sSystemCloneFromParentOnDependency = new ArrayMap<>();
258    static {
259        Settings.System.getCloneFromParentOnValueSettings(sSystemCloneFromParentOnDependency);
260    }
261
262    private final Object mLock = new Object();
263
264    @GuardedBy("mLock")
265    private SettingsRegistry mSettingsRegistry;
266
267    @GuardedBy("mLock")
268    private HandlerThread mHandlerThread;
269
270    @GuardedBy("mLock")
271    private Handler mHandler;
272
273    // We have to call in the user manager with no lock held,
274    private volatile UserManager mUserManager;
275
276    private UserManagerInternal mUserManagerInternal;
277
278    // We have to call in the package manager with no lock held,
279    private volatile IPackageManager mPackageManager;
280
281    public static int makeKey(int type, int userId) {
282        return SettingsState.makeKey(type, userId);
283    }
284
285    public static int getTypeFromKey(int key) {
286        return SettingsState.getTypeFromKey(key);
287    }
288
289    public static int getUserIdFromKey(int key) {
290        return SettingsState.getUserIdFromKey(key);
291    }
292
293    public static String settingTypeToString(int type) {
294        return SettingsState.settingTypeToString(type);
295    }
296
297    public static String keyToString(int key) {
298        return SettingsState.keyToString(key);
299    }
300
301    @Override
302    public boolean onCreate() {
303        Settings.setInSystemServer();
304
305        // fail to boot if there're any backed up settings that don't have a non-null validator
306        ensureAllBackedUpSystemSettingsHaveValidators();
307        ensureAllBackedUpGlobalSettingsHaveValidators();
308        ensureAllBackedUpSecureSettingsHaveValidators();
309
310        synchronized (mLock) {
311            mUserManager = UserManager.get(getContext());
312            mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
313            mPackageManager = AppGlobals.getPackageManager();
314            mHandlerThread = new HandlerThread(LOG_TAG,
315                    Process.THREAD_PRIORITY_BACKGROUND);
316            mHandlerThread.start();
317            mHandler = new Handler(mHandlerThread.getLooper());
318            mSettingsRegistry = new SettingsRegistry();
319        }
320        mHandler.post(() -> {
321            registerBroadcastReceivers();
322            startWatchingUserRestrictionChanges();
323        });
324        ServiceManager.addService("settings", new SettingsService(this));
325        return true;
326    }
327
328    private void ensureAllBackedUpSystemSettingsHaveValidators() {
329        String offenders = getOffenders(concat(Settings.System.SETTINGS_TO_BACKUP,
330                Settings.System.LEGACY_RESTORE_SETTINGS), Settings.System.VALIDATORS);
331
332        failToBootIfOffendersPresent(offenders, "Settings.System");
333    }
334
335    private void ensureAllBackedUpGlobalSettingsHaveValidators() {
336        String offenders = getOffenders(concat(Settings.Global.SETTINGS_TO_BACKUP,
337                Settings.Global.LEGACY_RESTORE_SETTINGS), Settings.Global.VALIDATORS);
338
339        failToBootIfOffendersPresent(offenders, "Settings.Global");
340    }
341
342    private void ensureAllBackedUpSecureSettingsHaveValidators() {
343        String offenders = getOffenders(concat(Settings.Secure.SETTINGS_TO_BACKUP,
344                Settings.Secure.LEGACY_RESTORE_SETTINGS), Settings.Secure.VALIDATORS);
345
346        failToBootIfOffendersPresent(offenders, "Settings.Secure");
347    }
348
349    private void failToBootIfOffendersPresent(String offenders, String settingsType) {
350        if (offenders.length() > 0) {
351            throw new RuntimeException("All " + settingsType + " settings that are backed up"
352                    + " have to have a non-null validator, but those don't: " + offenders);
353        }
354    }
355
356    private String getOffenders(String[] settingsToBackup, Map<String,
357            SettingsValidators.Validator> validators) {
358        StringBuilder offenders = new StringBuilder();
359        for (String setting : settingsToBackup) {
360            if (validators.get(setting) == null) {
361                offenders.append(setting).append(" ");
362            }
363        }
364        return offenders.toString();
365    }
366
367    private final String[] concat(String[] first, String[] second) {
368        if (second == null || second.length == 0) {
369            return first;
370        }
371        final int firstLen = first.length;
372        final int secondLen = second.length;
373        String[] both = new String[firstLen + secondLen];
374        System.arraycopy(first, 0, both, 0, firstLen);
375        System.arraycopy(second, 0, both, firstLen, secondLen);
376        return both;
377    }
378
379    @Override
380    public Bundle call(String method, String name, Bundle args) {
381        final int requestingUserId = getRequestingUserId(args);
382        switch (method) {
383            case Settings.CALL_METHOD_GET_GLOBAL: {
384                Setting setting = getGlobalSetting(name);
385                return packageValueForCallResult(setting, isTrackingGeneration(args));
386            }
387
388            case Settings.CALL_METHOD_GET_SECURE: {
389                Setting setting = getSecureSetting(name, requestingUserId,
390                        /*enableOverride=*/ true);
391                return packageValueForCallResult(setting, isTrackingGeneration(args));
392            }
393
394            case Settings.CALL_METHOD_GET_SYSTEM: {
395                Setting setting = getSystemSetting(name, requestingUserId);
396                return packageValueForCallResult(setting, isTrackingGeneration(args));
397            }
398
399            case Settings.CALL_METHOD_PUT_GLOBAL: {
400                String value = getSettingValue(args);
401                String tag = getSettingTag(args);
402                final boolean makeDefault = getSettingMakeDefault(args);
403                insertGlobalSetting(name, value, tag, makeDefault, requestingUserId, false);
404                break;
405            }
406
407            case Settings.CALL_METHOD_PUT_SECURE: {
408                String value = getSettingValue(args);
409                String tag = getSettingTag(args);
410                final boolean makeDefault = getSettingMakeDefault(args);
411                insertSecureSetting(name, value, tag, makeDefault, requestingUserId, false);
412                break;
413            }
414
415            case Settings.CALL_METHOD_PUT_SYSTEM: {
416                String value = getSettingValue(args);
417                insertSystemSetting(name, value, requestingUserId);
418                break;
419            }
420
421            case Settings.CALL_METHOD_RESET_GLOBAL: {
422                final int mode = getResetModeEnforcingPermission(args);
423                String tag = getSettingTag(args);
424                resetGlobalSetting(requestingUserId, mode, tag);
425                break;
426            }
427
428            case Settings.CALL_METHOD_RESET_SECURE: {
429                final int mode = getResetModeEnforcingPermission(args);
430                String tag = getSettingTag(args);
431                resetSecureSetting(requestingUserId, mode, tag);
432                break;
433            }
434
435            default: {
436                Slog.w(LOG_TAG, "call() with invalid method: " + method);
437            } break;
438        }
439
440        return null;
441    }
442
443    @Override
444    public String getType(Uri uri) {
445        Arguments args = new Arguments(uri, null, null, true);
446        if (TextUtils.isEmpty(args.name)) {
447            return "vnd.android.cursor.dir/" + args.table;
448        } else {
449            return "vnd.android.cursor.item/" + args.table;
450        }
451    }
452
453    @Override
454    public Cursor query(Uri uri, String[] projection, String where, String[] whereArgs,
455            String order) {
456        if (DEBUG) {
457            Slog.v(LOG_TAG, "query() for user: " + UserHandle.getCallingUserId());
458        }
459
460        Arguments args = new Arguments(uri, where, whereArgs, true);
461        String[] normalizedProjection = normalizeProjection(projection);
462
463        // If a legacy table that is gone, done.
464        if (REMOVED_LEGACY_TABLES.contains(args.table)) {
465            return new MatrixCursor(normalizedProjection, 0);
466        }
467
468        switch (args.table) {
469            case TABLE_GLOBAL: {
470                if (args.name != null) {
471                    Setting setting = getGlobalSetting(args.name);
472                    return packageSettingForQuery(setting, normalizedProjection);
473                } else {
474                    return getAllGlobalSettings(projection);
475                }
476            }
477
478            case TABLE_SECURE: {
479                final int userId = UserHandle.getCallingUserId();
480                if (args.name != null) {
481                    Setting setting = getSecureSetting(args.name, userId);
482                    return packageSettingForQuery(setting, normalizedProjection);
483                } else {
484                    return getAllSecureSettings(userId, projection);
485                }
486            }
487
488            case TABLE_SYSTEM: {
489                final int userId = UserHandle.getCallingUserId();
490                if (args.name != null) {
491                    Setting setting = getSystemSetting(args.name, userId);
492                    return packageSettingForQuery(setting, normalizedProjection);
493                } else {
494                    return getAllSystemSettings(userId, projection);
495                }
496            }
497
498            default: {
499                throw new IllegalArgumentException("Invalid Uri path:" + uri);
500            }
501        }
502    }
503
504    @Override
505    public Uri insert(Uri uri, ContentValues values) {
506        if (DEBUG) {
507            Slog.v(LOG_TAG, "insert() for user: " + UserHandle.getCallingUserId());
508        }
509
510        String table = getValidTableOrThrow(uri);
511
512        // If a legacy table that is gone, done.
513        if (REMOVED_LEGACY_TABLES.contains(table)) {
514            return null;
515        }
516
517        String name = values.getAsString(Settings.Secure.NAME);
518        if (!isKeyValid(name)) {
519            return null;
520        }
521
522        String value = values.getAsString(Settings.Secure.VALUE);
523
524        switch (table) {
525            case TABLE_GLOBAL: {
526                if (insertGlobalSetting(name, value, null, false,
527                        UserHandle.getCallingUserId(), false)) {
528                    return Uri.withAppendedPath(Settings.Global.CONTENT_URI, name);
529                }
530            } break;
531
532            case TABLE_SECURE: {
533                if (insertSecureSetting(name, value, null, false,
534                        UserHandle.getCallingUserId(), false)) {
535                    return Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name);
536                }
537            } break;
538
539            case TABLE_SYSTEM: {
540                if (insertSystemSetting(name, value, UserHandle.getCallingUserId())) {
541                    return Uri.withAppendedPath(Settings.System.CONTENT_URI, name);
542                }
543            } break;
544
545            default: {
546                throw new IllegalArgumentException("Bad Uri path:" + uri);
547            }
548        }
549
550        return null;
551    }
552
553    @Override
554    public int bulkInsert(Uri uri, ContentValues[] allValues) {
555        if (DEBUG) {
556            Slog.v(LOG_TAG, "bulkInsert() for user: " + UserHandle.getCallingUserId());
557        }
558
559        int insertionCount = 0;
560        final int valuesCount = allValues.length;
561        for (int i = 0; i < valuesCount; i++) {
562            ContentValues values = allValues[i];
563            if (insert(uri, values) != null) {
564                insertionCount++;
565            }
566        }
567
568        return insertionCount;
569    }
570
571    @Override
572    public int delete(Uri uri, String where, String[] whereArgs) {
573        if (DEBUG) {
574            Slog.v(LOG_TAG, "delete() for user: " + UserHandle.getCallingUserId());
575        }
576
577        Arguments args = new Arguments(uri, where, whereArgs, false);
578
579        // If a legacy table that is gone, done.
580        if (REMOVED_LEGACY_TABLES.contains(args.table)) {
581            return 0;
582        }
583
584        if (!isKeyValid(args.name)) {
585            return 0;
586        }
587
588        switch (args.table) {
589            case TABLE_GLOBAL: {
590                final int userId = UserHandle.getCallingUserId();
591                return deleteGlobalSetting(args.name, userId, false) ? 1 : 0;
592            }
593
594            case TABLE_SECURE: {
595                final int userId = UserHandle.getCallingUserId();
596                return deleteSecureSetting(args.name, userId, false) ? 1 : 0;
597            }
598
599            case TABLE_SYSTEM: {
600                final int userId = UserHandle.getCallingUserId();
601                return deleteSystemSetting(args.name, userId) ? 1 : 0;
602            }
603
604            default: {
605                throw new IllegalArgumentException("Bad Uri path:" + uri);
606            }
607        }
608    }
609
610    @Override
611    public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
612        if (DEBUG) {
613            Slog.v(LOG_TAG, "update() for user: " + UserHandle.getCallingUserId());
614        }
615
616        Arguments args = new Arguments(uri, where, whereArgs, false);
617
618        // If a legacy table that is gone, done.
619        if (REMOVED_LEGACY_TABLES.contains(args.table)) {
620            return 0;
621        }
622
623        String name = values.getAsString(Settings.Secure.NAME);
624        if (!isKeyValid(name)) {
625            return 0;
626        }
627        String value = values.getAsString(Settings.Secure.VALUE);
628
629        switch (args.table) {
630            case TABLE_GLOBAL: {
631                final int userId = UserHandle.getCallingUserId();
632                return updateGlobalSetting(args.name, value, null, false,
633                        userId, false) ? 1 : 0;
634            }
635
636            case TABLE_SECURE: {
637                final int userId = UserHandle.getCallingUserId();
638                return updateSecureSetting(args.name, value, null, false,
639                        userId, false) ? 1 : 0;
640            }
641
642            case TABLE_SYSTEM: {
643                final int userId = UserHandle.getCallingUserId();
644                return updateSystemSetting(args.name, value, userId) ? 1 : 0;
645            }
646
647            default: {
648                throw new IllegalArgumentException("Invalid Uri path:" + uri);
649            }
650        }
651    }
652
653    @Override
654    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
655        final int userId = getUserIdFromUri(uri, UserHandle.getCallingUserId());
656        if (userId != UserHandle.getCallingUserId()) {
657            getContext().enforceCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS,
658                    "Access files from the settings of another user");
659        }
660        uri = ContentProvider.getUriWithoutUserId(uri);
661
662        final String cacheRingtoneSetting;
663        final String cacheName;
664        if (Settings.System.RINGTONE_CACHE_URI.equals(uri)) {
665            cacheRingtoneSetting = Settings.System.RINGTONE;
666            cacheName = Settings.System.RINGTONE_CACHE;
667        } else if (Settings.System.NOTIFICATION_SOUND_CACHE_URI.equals(uri)) {
668            cacheRingtoneSetting = Settings.System.NOTIFICATION_SOUND;
669            cacheName = Settings.System.NOTIFICATION_SOUND_CACHE;
670        } else if (Settings.System.ALARM_ALERT_CACHE_URI.equals(uri)) {
671            cacheRingtoneSetting = Settings.System.ALARM_ALERT;
672            cacheName = Settings.System.ALARM_ALERT_CACHE;
673        } else {
674            throw new FileNotFoundException("Direct file access no longer supported; "
675                    + "ringtone playback is available through android.media.Ringtone");
676        }
677
678        int actualCacheOwner;
679        // Redirect cache to parent if ringtone setting is owned by profile parent
680        synchronized (mLock) {
681            actualCacheOwner = resolveOwningUserIdForSystemSettingLocked(userId,
682                    cacheRingtoneSetting);
683        }
684        final File cacheFile = new File(getRingtoneCacheDir(actualCacheOwner), cacheName);
685        return ParcelFileDescriptor.open(cacheFile, ParcelFileDescriptor.parseMode(mode));
686    }
687
688    private File getRingtoneCacheDir(int userId) {
689        final File cacheDir = new File(Environment.getDataSystemDeDirectory(userId), "ringtones");
690        cacheDir.mkdir();
691        SELinux.restorecon(cacheDir);
692        return cacheDir;
693    }
694
695    /**
696     * Dump all settings as a proto buf.
697     *
698     * @param fd The file to dump to
699     */
700    void dumpProto(@NonNull FileDescriptor fd) {
701        ProtoOutputStream proto = new ProtoOutputStream(fd);
702
703        synchronized (mLock) {
704            SettingsProtoDumpUtil.dumpProtoLocked(mSettingsRegistry, proto);
705        }
706
707        proto.flush();
708    }
709
710    public void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
711        synchronized (mLock) {
712            final long identity = Binder.clearCallingIdentity();
713            try {
714                SparseBooleanArray users = mSettingsRegistry.getKnownUsersLocked();
715                final int userCount = users.size();
716                for (int i = 0; i < userCount; i++) {
717                    dumpForUserLocked(users.keyAt(i), pw);
718                }
719            } finally {
720                Binder.restoreCallingIdentity(identity);
721            }
722        }
723    }
724
725    private void dumpForUserLocked(int userId, PrintWriter pw) {
726        if (userId == UserHandle.USER_SYSTEM) {
727            pw.println("GLOBAL SETTINGS (user " + userId + ")");
728            SettingsState globalSettings = mSettingsRegistry.getSettingsLocked(
729                    SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
730            if (globalSettings != null) {
731                dumpSettingsLocked(globalSettings, pw);
732                pw.println();
733                globalSettings.dumpHistoricalOperations(pw);
734            }
735        }
736
737        pw.println("SECURE SETTINGS (user " + userId + ")");
738        SettingsState secureSettings = mSettingsRegistry.getSettingsLocked(
739                SETTINGS_TYPE_SECURE, userId);
740        if (secureSettings != null) {
741            dumpSettingsLocked(secureSettings, pw);
742            pw.println();
743            secureSettings.dumpHistoricalOperations(pw);
744        }
745
746        pw.println("SYSTEM SETTINGS (user " + userId + ")");
747        SettingsState systemSettings = mSettingsRegistry.getSettingsLocked(
748                SETTINGS_TYPE_SYSTEM, userId);
749        if (systemSettings != null) {
750            dumpSettingsLocked(systemSettings, pw);
751            pw.println();
752            systemSettings.dumpHistoricalOperations(pw);
753        }
754    }
755
756    private void dumpSettingsLocked(SettingsState settingsState, PrintWriter pw) {
757        List<String> names = settingsState.getSettingNamesLocked();
758
759        final int nameCount = names.size();
760
761        for (int i = 0; i < nameCount; i++) {
762            String name = names.get(i);
763            Setting setting = settingsState.getSettingLocked(name);
764            pw.print("_id:"); pw.print(toDumpString(setting.getId()));
765            pw.print(" name:"); pw.print(toDumpString(name));
766            if (setting.getPackageName() != null) {
767                pw.print(" pkg:"); pw.print(setting.getPackageName());
768            }
769            pw.print(" value:"); pw.print(toDumpString(setting.getValue()));
770            if (setting.getDefaultValue() != null) {
771                pw.print(" default:"); pw.print(setting.getDefaultValue());
772                pw.print(" defaultSystemSet:"); pw.print(setting.isDefaultFromSystem());
773            }
774            if (setting.getTag() != null) {
775                pw.print(" tag:"); pw.print(setting.getTag());
776            }
777            pw.println();
778        }
779    }
780
781    private static String toDumpString(String s) {
782        if (s != null) {
783            return s;
784        }
785        return "{null}";
786    }
787
788    private void registerBroadcastReceivers() {
789        IntentFilter userFilter = new IntentFilter();
790        userFilter.addAction(Intent.ACTION_USER_REMOVED);
791        userFilter.addAction(Intent.ACTION_USER_STOPPED);
792
793        getContext().registerReceiver(new BroadcastReceiver() {
794            @Override
795            public void onReceive(Context context, Intent intent) {
796                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
797                        UserHandle.USER_SYSTEM);
798
799                switch (intent.getAction()) {
800                    case Intent.ACTION_USER_REMOVED: {
801                        synchronized (mLock) {
802                            mSettingsRegistry.removeUserStateLocked(userId, true);
803                        }
804                    } break;
805
806                    case Intent.ACTION_USER_STOPPED: {
807                        synchronized (mLock) {
808                            mSettingsRegistry.removeUserStateLocked(userId, false);
809                        }
810                    } break;
811                }
812            }
813        }, userFilter);
814
815        PackageMonitor monitor = new PackageMonitor() {
816            @Override
817            public void onPackageRemoved(String packageName, int uid) {
818                synchronized (mLock) {
819                    mSettingsRegistry.onPackageRemovedLocked(packageName,
820                            UserHandle.getUserId(uid));
821                }
822            }
823
824            @Override
825            public void onUidRemoved(int uid) {
826                synchronized (mLock) {
827                    mSettingsRegistry.onUidRemovedLocked(uid);
828                }
829            }
830        };
831
832        // package changes
833        monitor.register(getContext(), BackgroundThread.getHandler().getLooper(),
834                UserHandle.ALL, true);
835    }
836
837    private void startWatchingUserRestrictionChanges() {
838        // TODO: The current design of settings looking different based on user restrictions
839        // should be reworked to keep them separate and system code should check the setting
840        // first followed by checking the user restriction before performing an operation.
841        UserManagerInternal userManager = LocalServices.getService(UserManagerInternal.class);
842        userManager.addUserRestrictionsListener((int userId, Bundle newRestrictions,
843                Bundle prevRestrictions) -> {
844            // We are changing the settings affected by restrictions to their current
845            // value with a forced update to ensure that all cross profile dependencies
846            // are taken into account. Also make sure the settings update to.. the same
847            // value passes the security checks, so clear binder calling id.
848            if (newRestrictions.getBoolean(UserManager.DISALLOW_SHARE_LOCATION)
849                    != prevRestrictions.getBoolean(UserManager.DISALLOW_SHARE_LOCATION)) {
850                final long identity = Binder.clearCallingIdentity();
851                try {
852                    synchronized (mLock) {
853                        Setting setting = getSecureSetting(
854                                Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
855                        updateSecureSetting(Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
856                                setting != null ? setting.getValue() : null, null,
857                                true, userId, true);
858                    }
859                } finally {
860                    Binder.restoreCallingIdentity(identity);
861                }
862            }
863            if (newRestrictions.getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)
864                    != prevRestrictions.getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)) {
865                final long identity = Binder.clearCallingIdentity();
866                try {
867                    synchronized (mLock) {
868                        Setting setting = getGlobalSetting(Settings.Global.INSTALL_NON_MARKET_APPS);
869                        String value = setting != null ? setting.getValue() : null;
870                        updateGlobalSetting(Settings.Global.INSTALL_NON_MARKET_APPS,
871                                value, null, true, userId, true);
872                    }
873                } finally {
874                    Binder.restoreCallingIdentity(identity);
875                }
876            }
877            if (newRestrictions.getBoolean(UserManager.DISALLOW_DEBUGGING_FEATURES)
878                    != prevRestrictions.getBoolean(UserManager.DISALLOW_DEBUGGING_FEATURES)) {
879                final long identity = Binder.clearCallingIdentity();
880                try {
881                    synchronized (mLock) {
882                        Setting setting = getGlobalSetting(Settings.Global.ADB_ENABLED);
883                        String value = setting != null ? setting.getValue() : null;
884                        updateGlobalSetting(Settings.Global.ADB_ENABLED,
885                                value, null, true, userId, true);
886                    }
887                } finally {
888                    Binder.restoreCallingIdentity(identity);
889                }
890            }
891            if (newRestrictions.getBoolean(UserManager.ENSURE_VERIFY_APPS)
892                    != prevRestrictions.getBoolean(UserManager.ENSURE_VERIFY_APPS)) {
893                final long identity = Binder.clearCallingIdentity();
894                try {
895                    synchronized (mLock) {
896                        Setting enable = getGlobalSetting(
897                                Settings.Global.PACKAGE_VERIFIER_ENABLE);
898                        String enableValue = enable != null ? enable.getValue() : null;
899                        updateGlobalSetting(Settings.Global.PACKAGE_VERIFIER_ENABLE,
900                                enableValue, null, true, userId, true);
901                        Setting include = getGlobalSetting(
902                                Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB);
903                        String includeValue = include != null ? include.getValue() : null;
904                        updateGlobalSetting(Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB,
905                                includeValue, null, true, userId, true);
906                    }
907                } finally {
908                    Binder.restoreCallingIdentity(identity);
909                }
910            }
911            if (newRestrictions.getBoolean(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)
912                    != prevRestrictions.getBoolean(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
913                final long identity = Binder.clearCallingIdentity();
914                try {
915                    synchronized (mLock) {
916                        Setting setting = getGlobalSetting(
917                                Settings.Global.PREFERRED_NETWORK_MODE);
918                        String value = setting != null ? setting.getValue() : null;
919                        updateGlobalSetting(Settings.Global.PREFERRED_NETWORK_MODE,
920                                value, null, true, userId, true);
921                    }
922                } finally {
923                    Binder.restoreCallingIdentity(identity);
924                }
925            }
926        });
927    }
928
929    private Cursor getAllGlobalSettings(String[] projection) {
930        if (DEBUG) {
931            Slog.v(LOG_TAG, "getAllGlobalSettings()");
932        }
933
934        synchronized (mLock) {
935            // Get the settings.
936            SettingsState settingsState = mSettingsRegistry.getSettingsLocked(
937                    SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
938
939            List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_GLOBAL,
940                    UserHandle.USER_SYSTEM);
941
942            final int nameCount = names.size();
943
944            String[] normalizedProjection = normalizeProjection(projection);
945            MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount);
946
947            // Anyone can get the global settings, so no security checks.
948            for (int i = 0; i < nameCount; i++) {
949                String name = names.get(i);
950                Setting setting = settingsState.getSettingLocked(name);
951                appendSettingToCursor(result, setting);
952            }
953
954            return result;
955        }
956    }
957
958    private Setting getGlobalSetting(String name) {
959        if (DEBUG) {
960            Slog.v(LOG_TAG, "getGlobalSetting(" + name + ")");
961        }
962
963        // Ensure the caller can access the setting.
964        enforceSettingReadable(name, SETTINGS_TYPE_GLOBAL, UserHandle.getCallingUserId());
965
966        // Get the value.
967        synchronized (mLock) {
968            return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_GLOBAL,
969                    UserHandle.USER_SYSTEM, name);
970        }
971    }
972
973    private boolean updateGlobalSetting(String name, String value, String tag,
974            boolean makeDefault, int requestingUserId, boolean forceNotify) {
975        if (DEBUG) {
976            Slog.v(LOG_TAG, "updateGlobalSetting(" + name + ", " + value + ", "
977                    + ", " + tag + ", " + makeDefault + ", " + requestingUserId
978                    + ", " + forceNotify + ")");
979        }
980        return mutateGlobalSetting(name, value, tag, makeDefault, requestingUserId,
981                MUTATION_OPERATION_UPDATE, forceNotify, 0);
982    }
983
984    private boolean insertGlobalSetting(String name, String value, String tag,
985            boolean makeDefault, int requestingUserId, boolean forceNotify) {
986        if (DEBUG) {
987            Slog.v(LOG_TAG, "insertGlobalSetting(" + name + ", " + value  + ", "
988                    + ", " + tag + ", " + makeDefault + ", " + requestingUserId
989                    + ", " + forceNotify + ")");
990        }
991        return mutateGlobalSetting(name, value, tag, makeDefault, requestingUserId,
992                MUTATION_OPERATION_INSERT, forceNotify, 0);
993    }
994
995    private boolean deleteGlobalSetting(String name, int requestingUserId, boolean forceNotify) {
996        if (DEBUG) {
997            Slog.v(LOG_TAG, "deleteGlobalSetting(" + name + ", " + requestingUserId
998                    + ", " + forceNotify + ")");
999        }
1000        return mutateGlobalSetting(name, null, null, false, requestingUserId,
1001                MUTATION_OPERATION_DELETE, forceNotify, 0);
1002    }
1003
1004    private void resetGlobalSetting(int requestingUserId, int mode, String tag) {
1005        if (DEBUG) {
1006            Slog.v(LOG_TAG, "resetGlobalSetting(" + requestingUserId + ", "
1007                    + mode + ", " + tag + ")");
1008        }
1009        mutateGlobalSetting(null, null, tag, false, requestingUserId,
1010                MUTATION_OPERATION_RESET, false, mode);
1011    }
1012
1013    private boolean mutateGlobalSetting(String name, String value, String tag,
1014            boolean makeDefault, int requestingUserId, int operation, boolean forceNotify,
1015            int mode) {
1016        // Make sure the caller can change the settings - treated as secure.
1017        enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
1018
1019        // Resolve the userId on whose behalf the call is made.
1020        final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
1021
1022        // If this is a setting that is currently restricted for this user, do not allow
1023        // unrestricting changes.
1024        if (name != null && mUserManagerInternal.isSettingRestrictedForUser(
1025                name, callingUserId, value, Binder.getCallingUid())) {
1026            return false;
1027        }
1028
1029        // Perform the mutation.
1030        synchronized (mLock) {
1031            switch (operation) {
1032                case MUTATION_OPERATION_INSERT: {
1033                    return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_GLOBAL,
1034                            UserHandle.USER_SYSTEM, name, value, tag, makeDefault,
1035                            getCallingPackage(), forceNotify, CRITICAL_GLOBAL_SETTINGS);
1036                }
1037
1038                case MUTATION_OPERATION_DELETE: {
1039                    return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_GLOBAL,
1040                            UserHandle.USER_SYSTEM, name, forceNotify, CRITICAL_GLOBAL_SETTINGS);
1041                }
1042
1043                case MUTATION_OPERATION_UPDATE: {
1044                    return mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_GLOBAL,
1045                            UserHandle.USER_SYSTEM, name, value, tag, makeDefault,
1046                            getCallingPackage(), forceNotify, CRITICAL_GLOBAL_SETTINGS);
1047                }
1048
1049                case MUTATION_OPERATION_RESET: {
1050                    mSettingsRegistry.resetSettingsLocked(SETTINGS_TYPE_GLOBAL,
1051                            UserHandle.USER_SYSTEM, getCallingPackage(), mode, tag);
1052                } return true;
1053            }
1054        }
1055
1056        return false;
1057    }
1058
1059    private PackageInfo getCallingPackageInfo(int userId) {
1060        try {
1061            return mPackageManager.getPackageInfo(getCallingPackage(),
1062                    PackageManager.GET_SIGNATURES, userId);
1063        } catch (RemoteException e) {
1064            throw new IllegalStateException("Package " + getCallingPackage() + " doesn't exist");
1065        }
1066    }
1067
1068    private Cursor getAllSecureSettings(int userId, String[] projection) {
1069        if (DEBUG) {
1070            Slog.v(LOG_TAG, "getAllSecureSettings(" + userId + ")");
1071        }
1072
1073        // Resolve the userId on whose behalf the call is made.
1074        final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId);
1075
1076        // The relevant "calling package" userId will be the owning userId for some
1077        // profiles, and we can't do the lookup inside our [lock held] loop, so work out
1078        // up front who the effective "new SSAID" user ID for that settings name will be.
1079        final int ssaidUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId,
1080                Settings.Secure.ANDROID_ID);
1081        final PackageInfo ssaidCallingPkg = getCallingPackageInfo(ssaidUserId);
1082
1083        synchronized (mLock) {
1084            List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_SECURE, callingUserId);
1085
1086            final int nameCount = names.size();
1087
1088            String[] normalizedProjection = normalizeProjection(projection);
1089            MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount);
1090
1091            for (int i = 0; i < nameCount; i++) {
1092                String name = names.get(i);
1093                // Determine the owning user as some profile settings are cloned from the parent.
1094                final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId,
1095                        name);
1096
1097                if (!isSecureSettingAccessible(name, callingUserId, owningUserId)) {
1098                    // This caller is not permitted to access this setting. Pretend the setting
1099                    // doesn't exist.
1100                    continue;
1101                }
1102
1103                // As of Android O, the SSAID is read from an app-specific entry in table
1104                // SETTINGS_FILE_SSAID, unless accessed by a system process.
1105                final Setting setting;
1106                if (isNewSsaidSetting(name)) {
1107                    setting = getSsaidSettingLocked(ssaidCallingPkg, owningUserId);
1108                } else {
1109                    setting = mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SECURE, owningUserId,
1110                            name);
1111                }
1112                appendSettingToCursor(result, setting);
1113            }
1114
1115            return result;
1116        }
1117    }
1118
1119    private Setting getSecureSetting(String name, int requestingUserId) {
1120        return getSecureSetting(name, requestingUserId, /*enableOverride=*/ false);
1121    }
1122
1123    private Setting getSecureSetting(String name, int requestingUserId, boolean enableOverride) {
1124        if (DEBUG) {
1125            Slog.v(LOG_TAG, "getSecureSetting(" + name + ", " + requestingUserId + ")");
1126        }
1127
1128        // Resolve the userId on whose behalf the call is made.
1129        final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
1130
1131        // Ensure the caller can access the setting.
1132        enforceSettingReadable(name, SETTINGS_TYPE_SECURE, UserHandle.getCallingUserId());
1133
1134        // Determine the owning user as some profile settings are cloned from the parent.
1135        final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name);
1136
1137        if (!isSecureSettingAccessible(name, callingUserId, owningUserId)) {
1138            // This caller is not permitted to access this setting. Pretend the setting doesn't
1139            // exist.
1140            SettingsState settings = mSettingsRegistry.getSettingsLocked(SETTINGS_TYPE_SECURE,
1141                    owningUserId);
1142            return settings != null ? settings.getNullSetting() : null;
1143        }
1144
1145        // As of Android O, the SSAID is read from an app-specific entry in table
1146        // SETTINGS_FILE_SSAID, unless accessed by a system process.
1147        if (isNewSsaidSetting(name)) {
1148            PackageInfo callingPkg = getCallingPackageInfo(owningUserId);
1149            synchronized (mLock) {
1150                return getSsaidSettingLocked(callingPkg, owningUserId);
1151            }
1152        }
1153        if (enableOverride) {
1154            if (Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
1155                final Setting overridden = getLocationProvidersAllowedSetting(owningUserId);
1156                if (overridden != null) {
1157                    return overridden;
1158                }
1159            }
1160        }
1161
1162        // Not the SSAID; do a straight lookup
1163        synchronized (mLock) {
1164            return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SECURE,
1165                    owningUserId, name);
1166        }
1167    }
1168
1169    private boolean isNewSsaidSetting(String name) {
1170        return Settings.Secure.ANDROID_ID.equals(name)
1171                && UserHandle.getAppId(Binder.getCallingUid()) >= Process.FIRST_APPLICATION_UID;
1172    }
1173
1174    private Setting getSsaidSettingLocked(PackageInfo callingPkg, int owningUserId) {
1175        // Get uid of caller (key) used to store ssaid value
1176        String name = Integer.toString(
1177                UserHandle.getUid(owningUserId, UserHandle.getAppId(Binder.getCallingUid())));
1178
1179        if (DEBUG) {
1180            Slog.v(LOG_TAG, "getSsaidSettingLocked(" + name + "," + owningUserId + ")");
1181        }
1182
1183        // Retrieve the ssaid from the table if present.
1184        final Setting ssaid = mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SSAID, owningUserId,
1185                name);
1186        // If the app is an Instant App use its stored SSAID instead of our own.
1187        final String instantSsaid;
1188        final long token = Binder.clearCallingIdentity();
1189        try {
1190            instantSsaid = mPackageManager.getInstantAppAndroidId(callingPkg.packageName,
1191                    owningUserId);
1192        } catch (RemoteException e) {
1193            Slog.e(LOG_TAG, "Failed to get Instant App Android ID", e);
1194            return null;
1195        } finally {
1196            Binder.restoreCallingIdentity(token);
1197        }
1198
1199        final SettingsState ssaidSettings = mSettingsRegistry.getSettingsLocked(
1200                SETTINGS_TYPE_SSAID, owningUserId);
1201
1202        if (instantSsaid != null) {
1203            // Use the stored value if it is still valid.
1204            if (ssaid != null && instantSsaid.equals(ssaid.getValue())) {
1205                return mascaradeSsaidSetting(ssaidSettings, ssaid);
1206            }
1207            // The value has changed, update the stored value.
1208            final boolean success = ssaidSettings.insertSettingLocked(name, instantSsaid, null,
1209                    true, callingPkg.packageName);
1210            if (!success) {
1211                throw new IllegalStateException("Failed to update instant app android id");
1212            }
1213            Setting setting = mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SSAID,
1214                    owningUserId, name);
1215            return mascaradeSsaidSetting(ssaidSettings, setting);
1216        }
1217
1218        // Lazy initialize ssaid if not yet present in ssaid table.
1219        if (ssaid == null || ssaid.isNull() || ssaid.getValue() == null) {
1220            Setting setting = mSettingsRegistry.generateSsaidLocked(callingPkg, owningUserId);
1221            return mascaradeSsaidSetting(ssaidSettings, setting);
1222        }
1223
1224        return mascaradeSsaidSetting(ssaidSettings, ssaid);
1225    }
1226
1227    private Setting mascaradeSsaidSetting(SettingsState settingsState, Setting ssaidSetting) {
1228        // SSAID settings are located in a dedicated table for internal bookkeeping
1229        // but for the world they reside in the secure table, so adjust the key here.
1230        // We have a special name when looking it up but want the world to see it as
1231        // "android_id".
1232        if (ssaidSetting != null) {
1233            return settingsState.new Setting(ssaidSetting) {
1234                @Override
1235                public int getKey() {
1236                    final int userId = getUserIdFromKey(super.getKey());
1237                    return makeKey(SETTINGS_TYPE_SECURE, userId);
1238                }
1239
1240                @Override
1241                public String getName() {
1242                    return Settings.Secure.ANDROID_ID;
1243                }
1244            };
1245        }
1246        return null;
1247    }
1248
1249    private Setting getLocationProvidersAllowedSetting(int owningUserId) {
1250        synchronized (mLock) {
1251            final Setting setting = getGlobalSetting(
1252                    Global.LOCATION_GLOBAL_KILL_SWITCH);
1253            if (!"1".equals(setting.getValue())) {
1254                return null;
1255            }
1256            // Global kill-switch is enabled. Return an empty value.
1257            final SettingsState settingsState = mSettingsRegistry.getSettingsLocked(
1258                    SETTINGS_TYPE_SECURE, owningUserId);
1259            return settingsState.new Setting(
1260                    Secure.LOCATION_PROVIDERS_ALLOWED,
1261                    "", // value
1262                    "", // tag
1263                    "", // default value
1264                    "", // package name
1265                    false, // from system
1266                    "0" // id
1267            ) {
1268                @Override
1269                public boolean update(String value, boolean setDefault, String packageName,
1270                        String tag, boolean forceNonSystemPackage) {
1271                    Slog.wtf(LOG_TAG, "update shoudln't be called on this instance.");
1272                    return false;
1273                }
1274            };
1275        }
1276    }
1277
1278    private boolean insertSecureSetting(String name, String value, String tag,
1279            boolean makeDefault, int requestingUserId, boolean forceNotify) {
1280        if (DEBUG) {
1281            Slog.v(LOG_TAG, "insertSecureSetting(" + name + ", " + value + ", "
1282                    + ", " + tag  + ", " + makeDefault + ", "  + requestingUserId
1283                    + ", " + forceNotify + ")");
1284        }
1285        return mutateSecureSetting(name, value, tag, makeDefault, requestingUserId,
1286                MUTATION_OPERATION_INSERT, forceNotify, 0);
1287    }
1288
1289    private boolean deleteSecureSetting(String name, int requestingUserId, boolean forceNotify) {
1290        if (DEBUG) {
1291            Slog.v(LOG_TAG, "deleteSecureSetting(" + name + ", " + requestingUserId
1292                    + ", " + forceNotify + ")");
1293        }
1294
1295        return mutateSecureSetting(name, null, null, false, requestingUserId,
1296                MUTATION_OPERATION_DELETE, forceNotify, 0);
1297    }
1298
1299    private boolean updateSecureSetting(String name, String value, String tag,
1300            boolean makeDefault, int requestingUserId, boolean forceNotify) {
1301        if (DEBUG) {
1302            Slog.v(LOG_TAG, "updateSecureSetting(" + name + ", " + value + ", "
1303                    + ", " + tag  + ", " + makeDefault + ", "  + requestingUserId
1304                    + ", "  + forceNotify +")");
1305        }
1306
1307        return mutateSecureSetting(name, value, tag, makeDefault, requestingUserId,
1308                MUTATION_OPERATION_UPDATE, forceNotify, 0);
1309    }
1310
1311    private void resetSecureSetting(int requestingUserId, int mode, String tag) {
1312        if (DEBUG) {
1313            Slog.v(LOG_TAG, "resetSecureSetting(" + requestingUserId + ", "
1314                    + mode + ", " + tag + ")");
1315        }
1316
1317        mutateSecureSetting(null, null, tag, false, requestingUserId,
1318                MUTATION_OPERATION_RESET, false, mode);
1319    }
1320
1321    private boolean mutateSecureSetting(String name, String value, String tag,
1322            boolean makeDefault, int requestingUserId, int operation, boolean forceNotify,
1323            int mode) {
1324        // Make sure the caller can change the settings.
1325        enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
1326
1327        // Resolve the userId on whose behalf the call is made.
1328        final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
1329
1330        // If this is a setting that is currently restricted for this user, do not allow
1331        // unrestricting changes.
1332        if (name != null && mUserManagerInternal.isSettingRestrictedForUser(
1333                name, callingUserId, value, Binder.getCallingUid())) {
1334            return false;
1335        }
1336
1337        // Determine the owning user as some profile settings are cloned from the parent.
1338        final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name);
1339
1340        // Only the owning user can change the setting.
1341        if (owningUserId != callingUserId) {
1342            return false;
1343        }
1344
1345        // Special cases for location providers (sigh).
1346        if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
1347            return updateLocationProvidersAllowedLocked(value, tag, owningUserId, makeDefault,
1348                    forceNotify);
1349        }
1350
1351        // Mutate the value.
1352        synchronized (mLock) {
1353            switch (operation) {
1354                case MUTATION_OPERATION_INSERT: {
1355                    return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SECURE,
1356                            owningUserId, name, value, tag, makeDefault,
1357                            getCallingPackage(), forceNotify, CRITICAL_SECURE_SETTINGS);
1358                }
1359
1360                case MUTATION_OPERATION_DELETE: {
1361                    return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_SECURE,
1362                            owningUserId, name, forceNotify, CRITICAL_SECURE_SETTINGS);
1363                }
1364
1365                case MUTATION_OPERATION_UPDATE: {
1366                    return mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_SECURE,
1367                            owningUserId, name, value, tag, makeDefault,
1368                            getCallingPackage(), forceNotify, CRITICAL_SECURE_SETTINGS);
1369                }
1370
1371                case MUTATION_OPERATION_RESET: {
1372                    mSettingsRegistry.resetSettingsLocked(SETTINGS_TYPE_SECURE,
1373                            UserHandle.USER_SYSTEM, getCallingPackage(), mode, tag);
1374                } return true;
1375            }
1376        }
1377
1378        return false;
1379    }
1380
1381    private Cursor getAllSystemSettings(int userId, String[] projection) {
1382        if (DEBUG) {
1383            Slog.v(LOG_TAG, "getAllSecureSystem(" + userId + ")");
1384        }
1385
1386        // Resolve the userId on whose behalf the call is made.
1387        final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId);
1388
1389        synchronized (mLock) {
1390            List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_SYSTEM, callingUserId);
1391
1392            final int nameCount = names.size();
1393
1394            String[] normalizedProjection = normalizeProjection(projection);
1395            MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount);
1396
1397            for (int i = 0; i < nameCount; i++) {
1398                String name = names.get(i);
1399
1400                // Determine the owning user as some profile settings are cloned from the parent.
1401                final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId,
1402                        name);
1403
1404                Setting setting = mSettingsRegistry.getSettingLocked(
1405                        SETTINGS_TYPE_SYSTEM, owningUserId, name);
1406                appendSettingToCursor(result, setting);
1407            }
1408
1409            return result;
1410        }
1411    }
1412
1413    private Setting getSystemSetting(String name, int requestingUserId) {
1414        if (DEBUG) {
1415            Slog.v(LOG_TAG, "getSystemSetting(" + name + ", " + requestingUserId + ")");
1416        }
1417
1418        // Resolve the userId on whose behalf the call is made.
1419        final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
1420
1421        // Ensure the caller can access the setting.
1422        enforceSettingReadable(name, SETTINGS_TYPE_SYSTEM, UserHandle.getCallingUserId());
1423
1424        // Determine the owning user as some profile settings are cloned from the parent.
1425        final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name);
1426
1427        // Get the value.
1428        synchronized (mLock) {
1429            return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SYSTEM, owningUserId, name);
1430        }
1431    }
1432
1433    private boolean insertSystemSetting(String name, String value, int requestingUserId) {
1434        if (DEBUG) {
1435            Slog.v(LOG_TAG, "insertSystemSetting(" + name + ", " + value + ", "
1436                    + requestingUserId + ")");
1437        }
1438
1439        return mutateSystemSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT);
1440    }
1441
1442    private boolean deleteSystemSetting(String name, int requestingUserId) {
1443        if (DEBUG) {
1444            Slog.v(LOG_TAG, "deleteSystemSetting(" + name + ", " + requestingUserId + ")");
1445        }
1446
1447        return mutateSystemSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE);
1448    }
1449
1450    private boolean updateSystemSetting(String name, String value, int requestingUserId) {
1451        if (DEBUG) {
1452            Slog.v(LOG_TAG, "updateSystemSetting(" + name + ", " + value + ", "
1453                    + requestingUserId + ")");
1454        }
1455
1456        return mutateSystemSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE);
1457    }
1458
1459    private boolean mutateSystemSetting(String name, String value, int runAsUserId,
1460            int operation) {
1461        if (!hasWriteSecureSettingsPermission()) {
1462            // If the caller doesn't hold WRITE_SECURE_SETTINGS, we verify whether this
1463            // operation is allowed for the calling package through appops.
1464            if (!Settings.checkAndNoteWriteSettingsOperation(getContext(),
1465                    Binder.getCallingUid(), getCallingPackage(), true)) {
1466                return false;
1467            }
1468        }
1469
1470        // Resolve the userId on whose behalf the call is made.
1471        final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(runAsUserId);
1472
1473        if (name != null && mUserManagerInternal.isSettingRestrictedForUser(
1474                name, callingUserId, value, Binder.getCallingUid())) {
1475            return false;
1476        }
1477
1478        // Enforce what the calling package can mutate the system settings.
1479        enforceRestrictedSystemSettingsMutationForCallingPackage(operation, name, callingUserId);
1480
1481        // Determine the owning user as some profile settings are cloned from the parent.
1482        final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name);
1483
1484        // Only the owning user id can change the setting.
1485        if (owningUserId != callingUserId) {
1486            return false;
1487        }
1488
1489        // Invalidate any relevant cache files
1490        String cacheName = null;
1491        if (Settings.System.RINGTONE.equals(name)) {
1492            cacheName = Settings.System.RINGTONE_CACHE;
1493        } else if (Settings.System.NOTIFICATION_SOUND.equals(name)) {
1494            cacheName = Settings.System.NOTIFICATION_SOUND_CACHE;
1495        } else if (Settings.System.ALARM_ALERT.equals(name)) {
1496            cacheName = Settings.System.ALARM_ALERT_CACHE;
1497        }
1498        if (cacheName != null) {
1499            final File cacheFile = new File(
1500                    getRingtoneCacheDir(owningUserId), cacheName);
1501            cacheFile.delete();
1502        }
1503
1504        // Mutate the value.
1505        synchronized (mLock) {
1506            switch (operation) {
1507                case MUTATION_OPERATION_INSERT: {
1508                    validateSystemSettingValue(name, value);
1509                    return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SYSTEM,
1510                            owningUserId, name, value, null, false, getCallingPackage(),
1511                            false, null);
1512                }
1513
1514                case MUTATION_OPERATION_DELETE: {
1515                    return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_SYSTEM,
1516                            owningUserId, name, false, null);
1517                }
1518
1519                case MUTATION_OPERATION_UPDATE: {
1520                    validateSystemSettingValue(name, value);
1521                    return mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_SYSTEM,
1522                            owningUserId, name, value, null, false, getCallingPackage(),
1523                            false, null);
1524                }
1525            }
1526
1527            return false;
1528        }
1529    }
1530
1531    private boolean hasWriteSecureSettingsPermission() {
1532        // Write secure settings is a more protected permission. If caller has it we are good.
1533        if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
1534                == PackageManager.PERMISSION_GRANTED) {
1535            return true;
1536        }
1537
1538        return false;
1539    }
1540
1541    private void validateSystemSettingValue(String name, String value) {
1542        SettingsValidators.Validator validator = Settings.System.VALIDATORS.get(name);
1543        if (validator != null && !validator.validate(value)) {
1544            throw new IllegalArgumentException("Invalid value: " + value
1545                    + " for setting: " + name);
1546        }
1547    }
1548
1549    /**
1550     * Returns {@code true} if the specified secure setting should be accessible to the caller.
1551     */
1552    private boolean isSecureSettingAccessible(String name, int callingUserId,
1553            int owningUserId) {
1554        // Special case for location (sigh).
1555        // This check is not inside the name-based checks below because this method performs checks
1556        // only if the calling user ID is not the same as the owning user ID.
1557        if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) {
1558            return false;
1559        }
1560
1561        switch (name) {
1562            case "bluetooth_address":
1563                // BluetoothManagerService for some reason stores the Android's Bluetooth MAC
1564                // address in this secure setting. Secure settings can normally be read by any app,
1565                // which thus enables them to bypass the recently introduced restrictions on access
1566                // to device identifiers.
1567                // To mitigate this we make this setting available only to callers privileged to see
1568                // this device's MAC addresses, same as through public API
1569                // BluetoothAdapter.getAddress() (see BluetoothManagerService for details).
1570                return getContext().checkCallingOrSelfPermission(
1571                        Manifest.permission.LOCAL_MAC_ADDRESS) == PackageManager.PERMISSION_GRANTED;
1572            default:
1573                return true;
1574        }
1575    }
1576
1577    private boolean isLocationProvidersAllowedRestricted(String name, int callingUserId,
1578            int owningUserId) {
1579        // Optimization - location providers are restricted only for managed profiles.
1580        if (callingUserId == owningUserId) {
1581            return false;
1582        }
1583        if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)
1584                && mUserManager.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION,
1585                new UserHandle(callingUserId))) {
1586            return true;
1587        }
1588        return false;
1589    }
1590
1591    private int resolveOwningUserIdForSecureSettingLocked(int userId, String setting) {
1592        return resolveOwningUserIdLocked(userId, sSecureCloneToManagedSettings, setting);
1593    }
1594
1595    private int resolveOwningUserIdForSystemSettingLocked(int userId, String setting) {
1596        final int parentId;
1597        // Resolves dependency if setting has a dependency and the calling user has a parent
1598        if (sSystemCloneFromParentOnDependency.containsKey(setting)
1599                && (parentId = getGroupParentLocked(userId)) != userId) {
1600            // The setting has a dependency and the profile has a parent
1601            String dependency = sSystemCloneFromParentOnDependency.get(setting);
1602            // Lookup the dependency setting as ourselves, some callers may not have access to it.
1603            final long token = Binder.clearCallingIdentity();
1604            try {
1605                Setting settingObj = getSecureSetting(dependency, userId);
1606                if (settingObj != null && settingObj.getValue().equals("1")) {
1607                    return parentId;
1608                }
1609            } finally {
1610                Binder.restoreCallingIdentity(token);
1611            }
1612        }
1613        return resolveOwningUserIdLocked(userId, sSystemCloneToManagedSettings, setting);
1614    }
1615
1616    private int resolveOwningUserIdLocked(int userId, Set<String> keys, String name) {
1617        final int parentId = getGroupParentLocked(userId);
1618        if (parentId != userId && keys.contains(name)) {
1619            return parentId;
1620        }
1621        return userId;
1622    }
1623
1624    private void enforceRestrictedSystemSettingsMutationForCallingPackage(int operation,
1625            String name, int userId) {
1626        // System/root/shell can mutate whatever secure settings they want.
1627        final int callingUid = Binder.getCallingUid();
1628        final int appId = UserHandle.getAppId(callingUid);
1629        if (appId == android.os.Process.SYSTEM_UID
1630                || appId == Process.SHELL_UID
1631                || appId == Process.ROOT_UID) {
1632            return;
1633        }
1634
1635        switch (operation) {
1636            case MUTATION_OPERATION_INSERT:
1637                // Insert updates.
1638            case MUTATION_OPERATION_UPDATE: {
1639                if (Settings.System.PUBLIC_SETTINGS.contains(name)) {
1640                    return;
1641                }
1642
1643                // The calling package is already verified.
1644                PackageInfo packageInfo = getCallingPackageInfoOrThrow(userId);
1645
1646                // Privileged apps can do whatever they want.
1647                if ((packageInfo.applicationInfo.privateFlags
1648                        & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
1649                    return;
1650                }
1651
1652                warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
1653                        packageInfo.applicationInfo.targetSdkVersion, name);
1654            } break;
1655
1656            case MUTATION_OPERATION_DELETE: {
1657                if (Settings.System.PUBLIC_SETTINGS.contains(name)
1658                        || Settings.System.PRIVATE_SETTINGS.contains(name)) {
1659                    throw new IllegalArgumentException("You cannot delete system defined"
1660                            + " secure settings.");
1661                }
1662
1663                // The calling package is already verified.
1664                PackageInfo packageInfo = getCallingPackageInfoOrThrow(userId);
1665
1666                // Privileged apps can do whatever they want.
1667                if ((packageInfo.applicationInfo.privateFlags &
1668                        ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
1669                    return;
1670                }
1671
1672                warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
1673                        packageInfo.applicationInfo.targetSdkVersion, name);
1674            } break;
1675        }
1676    }
1677
1678    private Set<String> getInstantAppAccessibleSettings(int settingsType) {
1679        switch (settingsType) {
1680            case SETTINGS_TYPE_GLOBAL:
1681                return Settings.Global.INSTANT_APP_SETTINGS;
1682            case SETTINGS_TYPE_SECURE:
1683                return Settings.Secure.INSTANT_APP_SETTINGS;
1684            case SETTINGS_TYPE_SYSTEM:
1685                return Settings.System.INSTANT_APP_SETTINGS;
1686            default:
1687                throw new IllegalArgumentException("Invalid settings type: " + settingsType);
1688        }
1689    }
1690
1691    private Set<String> getOverlayInstantAppAccessibleSettings(int settingsType) {
1692        switch (settingsType) {
1693            case SETTINGS_TYPE_GLOBAL:
1694                return OVERLAY_ALLOWED_GLOBAL_INSTANT_APP_SETTINGS;
1695            case SETTINGS_TYPE_SYSTEM:
1696                return OVERLAY_ALLOWED_SYSTEM_INSTANT_APP_SETTINGS;
1697            case SETTINGS_TYPE_SECURE:
1698                return OVERLAY_ALLOWED_SECURE_INSTANT_APP_SETTINGS;
1699            default:
1700                throw new IllegalArgumentException("Invalid settings type: " + settingsType);
1701        }
1702    }
1703
1704    private List<String> getSettingsNamesLocked(int settingsType, int userId) {
1705        // Don't enforce the instant app whitelist for now -- its too prone to unintended breakage
1706        // in the current form.
1707        return mSettingsRegistry.getSettingsNamesLocked(settingsType, userId);
1708    }
1709
1710    private void enforceSettingReadable(String settingName, int settingsType, int userId) {
1711        if (UserHandle.getAppId(Binder.getCallingUid()) < Process.FIRST_APPLICATION_UID) {
1712            return;
1713        }
1714        ApplicationInfo ai = getCallingApplicationInfoOrThrow();
1715        if (!ai.isInstantApp()) {
1716            return;
1717        }
1718        if (!getInstantAppAccessibleSettings(settingsType).contains(settingName)
1719                && !getOverlayInstantAppAccessibleSettings(settingsType).contains(settingName)) {
1720            // Don't enforce the instant app whitelist for now -- its too prone to unintended
1721            // breakage in the current form.
1722            Slog.w(LOG_TAG, "Instant App " + ai.packageName
1723                    + " trying to access unexposed setting, this will be an error in the future.");
1724        }
1725    }
1726
1727    private ApplicationInfo getCallingApplicationInfoOrThrow() {
1728        // We always use the callingUid for this lookup. This means that if hypothetically an
1729        // app was installed in user A with cross user and in user B as an Instant App
1730        // the app in A would be able to see all the settings in user B. However since cross
1731        // user is a system permission and the app must be uninstalled in B and then installed as
1732        // an Instant App that situation is not realistic or supported.
1733        ApplicationInfo ai = null;
1734        try {
1735            ai = mPackageManager.getApplicationInfo(getCallingPackage(), 0
1736                    , UserHandle.getCallingUserId());
1737        } catch (RemoteException ignored) {
1738        }
1739        if (ai == null) {
1740            throw new IllegalStateException("Failed to lookup info for package "
1741                    + getCallingPackage());
1742        }
1743        return ai;
1744    }
1745
1746    private PackageInfo getCallingPackageInfoOrThrow(int userId) {
1747        try {
1748            PackageInfo packageInfo = mPackageManager.getPackageInfo(
1749                    getCallingPackage(), 0, userId);
1750            if (packageInfo != null) {
1751                return packageInfo;
1752            }
1753        } catch (RemoteException e) {
1754            /* ignore */
1755        }
1756        throw new IllegalStateException("Calling package doesn't exist");
1757    }
1758
1759    private int getGroupParentLocked(int userId) {
1760        // Most frequent use case.
1761        if (userId == UserHandle.USER_SYSTEM) {
1762            return userId;
1763        }
1764        // We are in the same process with the user manager and the returned
1765        // user info is a cached instance, so just look up instead of cache.
1766        final long identity = Binder.clearCallingIdentity();
1767        try {
1768            // Just a lookup and not reentrant, so holding a lock is fine.
1769            UserInfo userInfo = mUserManager.getProfileParent(userId);
1770            return (userInfo != null) ? userInfo.id : userId;
1771        } finally {
1772            Binder.restoreCallingIdentity(identity);
1773        }
1774    }
1775
1776    private void enforceWritePermission(String permission) {
1777        if (getContext().checkCallingOrSelfPermission(permission)
1778                != PackageManager.PERMISSION_GRANTED) {
1779            throw new SecurityException("Permission denial: writing to settings requires:"
1780                    + permission);
1781        }
1782    }
1783
1784    /*
1785     * Used to parse changes to the value of Settings.Secure.LOCATION_PROVIDERS_ALLOWED.
1786     * This setting contains a list of the currently enabled location providers.
1787     * But helper functions in android.providers.Settings can enable or disable
1788     * a single provider by using a "+" or "-" prefix before the provider name.
1789     *
1790     * <p>See also {@link com.android.server.pm.UserRestrictionsUtils#isSettingRestrictedForUser()}.
1791     * If DISALLOW_SHARE_LOCATION is set, the said method will only allow values with
1792     * the "-" prefix.
1793     *
1794     * @returns whether the enabled location providers changed.
1795     */
1796    private boolean updateLocationProvidersAllowedLocked(String value, String tag,
1797            int owningUserId, boolean makeDefault, boolean forceNotify) {
1798        if (TextUtils.isEmpty(value)) {
1799            return false;
1800        }
1801        Setting oldSetting = getSecureSetting(
1802                Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId);
1803        if (oldSetting == null) {
1804            return false;
1805        }
1806        String oldProviders = oldSetting.getValue();
1807        List<String> oldProvidersList = TextUtils.isEmpty(oldProviders)
1808                ? new ArrayList<>() : new ArrayList<>(Arrays.asList(oldProviders.split(",")));
1809        Set<String> newProvidersSet = new ArraySet<>();
1810        newProvidersSet.addAll(oldProvidersList);
1811
1812        String[] providerUpdates = value.split(",");
1813        boolean inputError = false;
1814        for (String provider : providerUpdates) {
1815            // do not update location_providers_allowed when input is invalid
1816            if (TextUtils.isEmpty(provider)) {
1817                inputError = true;
1818                break;
1819            }
1820            final char prefix = provider.charAt(0);
1821            // do not update location_providers_allowed when input is invalid
1822            if (prefix != '+' && prefix != '-') {
1823                inputError = true;
1824                break;
1825            }
1826            // skip prefix
1827            provider = provider.substring(1);
1828            if (prefix == '+') {
1829                newProvidersSet.add(provider);
1830            } else if (prefix == '-') {
1831                newProvidersSet.remove(provider);
1832            }
1833        }
1834        String newProviders = TextUtils.join(",", newProvidersSet.toArray());
1835        if (inputError == true || newProviders.equals(oldProviders)) {
1836            // nothing changed, so no need to update the database
1837            if (forceNotify) {
1838                mSettingsRegistry.notifyForSettingsChange(
1839                        makeKey(SETTINGS_TYPE_SECURE, owningUserId),
1840                        Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
1841            }
1842            return false;
1843        }
1844        return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SECURE,
1845                owningUserId, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, newProviders, tag,
1846                makeDefault, getCallingPackage(), forceNotify, CRITICAL_SECURE_SETTINGS);
1847    }
1848
1849    private static void warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
1850            int targetSdkVersion, String name) {
1851        // If the app targets Lollipop MR1 or older SDK we warn, otherwise crash.
1852        if (targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1) {
1853            if (Settings.System.PRIVATE_SETTINGS.contains(name)) {
1854                Slog.w(LOG_TAG, "You shouldn't not change private system settings."
1855                        + " This will soon become an error.");
1856            } else {
1857                Slog.w(LOG_TAG, "You shouldn't keep your settings in the secure settings."
1858                        + " This will soon become an error.");
1859            }
1860        } else {
1861            if (Settings.System.PRIVATE_SETTINGS.contains(name)) {
1862                throw new IllegalArgumentException("You cannot change private secure settings.");
1863            } else {
1864                throw new IllegalArgumentException("You cannot keep your settings in"
1865                        + " the secure settings.");
1866            }
1867        }
1868    }
1869
1870    private static int resolveCallingUserIdEnforcingPermissionsLocked(int requestingUserId) {
1871        if (requestingUserId == UserHandle.getCallingUserId()) {
1872            return requestingUserId;
1873        }
1874        return ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1875                Binder.getCallingUid(), requestingUserId, false, true,
1876                "get/set setting for user", null);
1877    }
1878
1879    private Bundle packageValueForCallResult(Setting setting,
1880            boolean trackingGeneration) {
1881        if (!trackingGeneration) {
1882            if (setting == null || setting.isNull()) {
1883                return NULL_SETTING_BUNDLE;
1884            }
1885            return Bundle.forPair(Settings.NameValueTable.VALUE, setting.getValue());
1886        }
1887        Bundle result = new Bundle();
1888        result.putString(Settings.NameValueTable.VALUE,
1889                !setting.isNull() ? setting.getValue() : null);
1890
1891        mSettingsRegistry.mGenerationRegistry.addGenerationData(result, setting.getKey());
1892        return result;
1893    }
1894
1895    private static int getRequestingUserId(Bundle args) {
1896        final int callingUserId = UserHandle.getCallingUserId();
1897        return (args != null) ? args.getInt(Settings.CALL_METHOD_USER_KEY, callingUserId)
1898                : callingUserId;
1899    }
1900
1901    private boolean isTrackingGeneration(Bundle args) {
1902        return args != null && args.containsKey(Settings.CALL_METHOD_TRACK_GENERATION_KEY);
1903    }
1904
1905    private static String getSettingValue(Bundle args) {
1906        return (args != null) ? args.getString(Settings.NameValueTable.VALUE) : null;
1907    }
1908
1909    private static String getSettingTag(Bundle args) {
1910        return (args != null) ? args.getString(Settings.CALL_METHOD_TAG_KEY) : null;
1911    }
1912
1913    private static boolean getSettingMakeDefault(Bundle args) {
1914        return (args != null) && args.getBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY);
1915    }
1916
1917    private static int getResetModeEnforcingPermission(Bundle args) {
1918        final int mode = (args != null) ? args.getInt(Settings.CALL_METHOD_RESET_MODE_KEY) : 0;
1919        switch (mode) {
1920            case Settings.RESET_MODE_UNTRUSTED_DEFAULTS: {
1921                if (!isCallerSystemOrShellOrRootOnDebuggableBuild()) {
1922                    throw new SecurityException("Only system, shell/root on a "
1923                            + "debuggable build can reset to untrusted defaults");
1924                }
1925                return mode;
1926            }
1927            case Settings.RESET_MODE_UNTRUSTED_CHANGES: {
1928                if (!isCallerSystemOrShellOrRootOnDebuggableBuild()) {
1929                    throw new SecurityException("Only system, shell/root on a "
1930                            + "debuggable build can reset untrusted changes");
1931                }
1932                return mode;
1933            }
1934            case Settings.RESET_MODE_TRUSTED_DEFAULTS: {
1935                if (!isCallerSystemOrShellOrRootOnDebuggableBuild()) {
1936                    throw new SecurityException("Only system, shell/root on a "
1937                            + "debuggable build can reset to trusted defaults");
1938                }
1939                return mode;
1940            }
1941            case Settings.RESET_MODE_PACKAGE_DEFAULTS: {
1942                return mode;
1943            }
1944        }
1945        throw new IllegalArgumentException("Invalid reset mode: " + mode);
1946    }
1947
1948    private static boolean isCallerSystemOrShellOrRootOnDebuggableBuild() {
1949        final int appId = UserHandle.getAppId(Binder.getCallingUid());
1950        return appId == SYSTEM_UID || (Build.IS_DEBUGGABLE
1951                && (appId == SHELL_UID || appId == ROOT_UID));
1952    }
1953
1954    private static String getValidTableOrThrow(Uri uri) {
1955        if (uri.getPathSegments().size() > 0) {
1956            String table = uri.getPathSegments().get(0);
1957            if (DatabaseHelper.isValidTable(table)) {
1958                return table;
1959            }
1960            throw new IllegalArgumentException("Bad root path: " + table);
1961        }
1962        throw new IllegalArgumentException("Invalid URI:" + uri);
1963    }
1964
1965    private static MatrixCursor packageSettingForQuery(Setting setting, String[] projection) {
1966        if (setting.isNull()) {
1967            return new MatrixCursor(projection, 0);
1968        }
1969        MatrixCursor cursor = new MatrixCursor(projection, 1);
1970        appendSettingToCursor(cursor, setting);
1971        return cursor;
1972    }
1973
1974    private static String[] normalizeProjection(String[] projection) {
1975        if (projection == null) {
1976            return ALL_COLUMNS;
1977        }
1978
1979        final int columnCount = projection.length;
1980        for (int i = 0; i < columnCount; i++) {
1981            String column = projection[i];
1982            if (!ArrayUtils.contains(ALL_COLUMNS, column)) {
1983                throw new IllegalArgumentException("Invalid column: " + column);
1984            }
1985        }
1986
1987        return projection;
1988    }
1989
1990    private static void appendSettingToCursor(MatrixCursor cursor, Setting setting) {
1991        if (setting == null || setting.isNull()) {
1992            return;
1993        }
1994        final int columnCount = cursor.getColumnCount();
1995
1996        String[] values =  new String[columnCount];
1997
1998        for (int i = 0; i < columnCount; i++) {
1999            String column = cursor.getColumnName(i);
2000
2001            switch (column) {
2002                case Settings.NameValueTable._ID: {
2003                    values[i] = setting.getId();
2004                } break;
2005
2006                case Settings.NameValueTable.NAME: {
2007                    values[i] = setting.getName();
2008                } break;
2009
2010                case Settings.NameValueTable.VALUE: {
2011                    values[i] = setting.getValue();
2012                } break;
2013            }
2014        }
2015
2016        cursor.addRow(values);
2017    }
2018
2019    private static boolean isKeyValid(String key) {
2020        return !(TextUtils.isEmpty(key) || SettingsState.isBinary(key));
2021    }
2022
2023    private static final class Arguments {
2024        private static final Pattern WHERE_PATTERN_WITH_PARAM_NO_BRACKETS =
2025                Pattern.compile("[\\s]*name[\\s]*=[\\s]*\\?[\\s]*");
2026
2027        private static final Pattern WHERE_PATTERN_WITH_PARAM_IN_BRACKETS =
2028                Pattern.compile("[\\s]*\\([\\s]*name[\\s]*=[\\s]*\\?[\\s]*\\)[\\s]*");
2029
2030        private static final Pattern WHERE_PATTERN_NO_PARAM_IN_BRACKETS =
2031                Pattern.compile("[\\s]*\\([\\s]*name[\\s]*=[\\s]*['\"].*['\"][\\s]*\\)[\\s]*");
2032
2033        private static final Pattern WHERE_PATTERN_NO_PARAM_NO_BRACKETS =
2034                Pattern.compile("[\\s]*name[\\s]*=[\\s]*['\"].*['\"][\\s]*");
2035
2036        public final String table;
2037        public final String name;
2038
2039        public Arguments(Uri uri, String where, String[] whereArgs, boolean supportAll) {
2040            final int segmentSize = uri.getPathSegments().size();
2041            switch (segmentSize) {
2042                case 1: {
2043                    if (where != null
2044                            && (WHERE_PATTERN_WITH_PARAM_NO_BRACKETS.matcher(where).matches()
2045                                || WHERE_PATTERN_WITH_PARAM_IN_BRACKETS.matcher(where).matches())
2046                            && whereArgs.length == 1) {
2047                        name = whereArgs[0];
2048                        table = computeTableForSetting(uri, name);
2049                        return;
2050                    } else if (where != null
2051                            && (WHERE_PATTERN_NO_PARAM_NO_BRACKETS.matcher(where).matches()
2052                                || WHERE_PATTERN_NO_PARAM_IN_BRACKETS.matcher(where).matches())) {
2053                        final int startIndex = Math.max(where.indexOf("'"),
2054                                where.indexOf("\"")) + 1;
2055                        final int endIndex = Math.max(where.lastIndexOf("'"),
2056                                where.lastIndexOf("\""));
2057                        name = where.substring(startIndex, endIndex);
2058                        table = computeTableForSetting(uri, name);
2059                        return;
2060                    } else if (supportAll && where == null && whereArgs == null) {
2061                        name = null;
2062                        table = computeTableForSetting(uri, null);
2063                        return;
2064                    }
2065                } break;
2066
2067                case 2: {
2068                    if (where == null && whereArgs == null) {
2069                        name = uri.getPathSegments().get(1);
2070                        table = computeTableForSetting(uri, name);
2071                        return;
2072                    }
2073                } break;
2074            }
2075
2076            EventLogTags.writeUnsupportedSettingsQuery(
2077                    uri.toSafeString(), where, Arrays.toString(whereArgs));
2078            String message = String.format( "Supported SQL:\n"
2079                    + "  uri content://some_table/some_property with null where and where args\n"
2080                    + "  uri content://some_table with query name=? and single name as arg\n"
2081                    + "  uri content://some_table with query name=some_name and null args\n"
2082                    + "  but got - uri:%1s, where:%2s whereArgs:%3s", uri, where,
2083                    Arrays.toString(whereArgs));
2084            throw new IllegalArgumentException(message);
2085        }
2086
2087        private static String computeTableForSetting(Uri uri, String name) {
2088            String table = getValidTableOrThrow(uri);
2089
2090            if (name != null) {
2091                if (sSystemMovedToSecureSettings.contains(name)) {
2092                    table = TABLE_SECURE;
2093                }
2094
2095                if (sSystemMovedToGlobalSettings.contains(name)) {
2096                    table = TABLE_GLOBAL;
2097                }
2098
2099                if (sSecureMovedToGlobalSettings.contains(name)) {
2100                    table = TABLE_GLOBAL;
2101                }
2102
2103                if (sGlobalMovedToSecureSettings.contains(name)) {
2104                    table = TABLE_SECURE;
2105                }
2106            }
2107
2108            return table;
2109        }
2110    }
2111
2112    final class SettingsRegistry {
2113        private static final String DROPBOX_TAG_USERLOG = "restricted_profile_ssaid";
2114
2115        private static final String SETTINGS_FILE_GLOBAL = "settings_global.xml";
2116        private static final String SETTINGS_FILE_SYSTEM = "settings_system.xml";
2117        private static final String SETTINGS_FILE_SECURE = "settings_secure.xml";
2118        private static final String SETTINGS_FILE_SSAID = "settings_ssaid.xml";
2119
2120        private static final String SSAID_USER_KEY = "userkey";
2121
2122        private final SparseArray<SettingsState> mSettingsStates = new SparseArray<>();
2123
2124        private GenerationRegistry mGenerationRegistry;
2125
2126        private final Handler mHandler;
2127
2128        private final BackupManager mBackupManager;
2129
2130        private String mSettingsCreationBuildId;
2131
2132        public SettingsRegistry() {
2133            mHandler = new MyHandler(getContext().getMainLooper());
2134            mGenerationRegistry = new GenerationRegistry(mLock);
2135            mBackupManager = new BackupManager(getContext());
2136            migrateAllLegacySettingsIfNeeded();
2137            syncSsaidTableOnStart();
2138        }
2139
2140        private void generateUserKeyLocked(int userId) {
2141            // Generate a random key for each user used for creating a new ssaid.
2142            final byte[] keyBytes = new byte[32];
2143            final SecureRandom rand = new SecureRandom();
2144            rand.nextBytes(keyBytes);
2145
2146            // Convert to string for storage in settings table.
2147            final String userKey = ByteStringUtils.toHexString(keyBytes);
2148
2149            // Store the key in the ssaid table.
2150            final SettingsState ssaidSettings = getSettingsLocked(SETTINGS_TYPE_SSAID, userId);
2151            final boolean success = ssaidSettings.insertSettingLocked(SSAID_USER_KEY, userKey, null,
2152                    true, SettingsState.SYSTEM_PACKAGE_NAME);
2153
2154            if (!success) {
2155                throw new IllegalStateException("Ssaid settings not accessible");
2156            }
2157        }
2158
2159        private byte[] getLengthPrefix(byte[] data) {
2160            return ByteBuffer.allocate(4).putInt(data.length).array();
2161        }
2162
2163        public Setting generateSsaidLocked(PackageInfo callingPkg, int userId) {
2164            // Read the user's key from the ssaid table.
2165            Setting userKeySetting = getSettingLocked(SETTINGS_TYPE_SSAID, userId, SSAID_USER_KEY);
2166            if (userKeySetting == null || userKeySetting.isNull()
2167                    || userKeySetting.getValue() == null) {
2168                // Lazy initialize and store the user key.
2169                generateUserKeyLocked(userId);
2170                userKeySetting = getSettingLocked(SETTINGS_TYPE_SSAID, userId, SSAID_USER_KEY);
2171                if (userKeySetting == null || userKeySetting.isNull()
2172                        || userKeySetting.getValue() == null) {
2173                    throw new IllegalStateException("User key not accessible");
2174                }
2175            }
2176            final String userKey = userKeySetting.getValue();
2177
2178            // Convert the user's key back to a byte array.
2179            final byte[] keyBytes = ByteStringUtils.fromHexToByteArray(userKey);
2180
2181            // Validate that the key is of expected length.
2182            // Keys are currently 32 bytes, but were once 16 bytes during Android O development.
2183            if (keyBytes == null || (keyBytes.length != 16 && keyBytes.length != 32)) {
2184                throw new IllegalStateException("User key invalid");
2185            }
2186
2187            final Mac m;
2188            try {
2189                m = Mac.getInstance("HmacSHA256");
2190                m.init(new SecretKeySpec(keyBytes, m.getAlgorithm()));
2191            } catch (NoSuchAlgorithmException e) {
2192                throw new IllegalStateException("HmacSHA256 is not available", e);
2193            } catch (InvalidKeyException e) {
2194                throw new IllegalStateException("Key is corrupted", e);
2195            }
2196
2197            // Mac each of the developer signatures.
2198            for (int i = 0; i < callingPkg.signatures.length; i++) {
2199                byte[] sig = callingPkg.signatures[i].toByteArray();
2200                m.update(getLengthPrefix(sig), 0, 4);
2201                m.update(sig);
2202            }
2203
2204            // Convert result to a string for storage in settings table. Only want first 64 bits.
2205            final String ssaid = ByteStringUtils.toHexString(m.doFinal()).substring(0, 16)
2206                    .toLowerCase(Locale.US);
2207
2208            // Save the ssaid in the ssaid table.
2209            final String uid = Integer.toString(callingPkg.applicationInfo.uid);
2210            final SettingsState ssaidSettings = getSettingsLocked(SETTINGS_TYPE_SSAID, userId);
2211            final boolean success = ssaidSettings.insertSettingLocked(uid, ssaid, null, true,
2212                callingPkg.packageName);
2213
2214            if (!success) {
2215                throw new IllegalStateException("Ssaid settings not accessible");
2216            }
2217
2218            return getSettingLocked(SETTINGS_TYPE_SSAID, userId, uid);
2219        }
2220
2221        public void syncSsaidTableOnStart() {
2222            synchronized (mLock) {
2223                // Verify that each user's packages and ssaid's are in sync.
2224                for (UserInfo user : mUserManager.getUsers(true)) {
2225                    // Get all uids for the user's packages.
2226                    final List<PackageInfo> packages;
2227                    try {
2228                        packages = mPackageManager.getInstalledPackages(
2229                            PackageManager.MATCH_UNINSTALLED_PACKAGES,
2230                            user.id).getList();
2231                    } catch (RemoteException e) {
2232                        throw new IllegalStateException("Package manager not available");
2233                    }
2234                    final Set<String> appUids = new HashSet<>();
2235                    for (PackageInfo info : packages) {
2236                        appUids.add(Integer.toString(info.applicationInfo.uid));
2237                    }
2238
2239                    // Get all uids currently stored in the user's ssaid table.
2240                    final Set<String> ssaidUids = new HashSet<>(
2241                            getSettingsNamesLocked(SETTINGS_TYPE_SSAID, user.id));
2242                    ssaidUids.remove(SSAID_USER_KEY);
2243
2244                    // Perform a set difference for the appUids and ssaidUids.
2245                    ssaidUids.removeAll(appUids);
2246
2247                    // If there are ssaidUids left over they need to be removed from the table.
2248                    final SettingsState ssaidSettings = getSettingsLocked(SETTINGS_TYPE_SSAID,
2249                            user.id);
2250                    for (String uid : ssaidUids) {
2251                        ssaidSettings.deleteSettingLocked(uid);
2252                    }
2253                }
2254            }
2255        }
2256
2257        public List<String> getSettingsNamesLocked(int type, int userId) {
2258            final int key = makeKey(type, userId);
2259            SettingsState settingsState = peekSettingsStateLocked(key);
2260            if (settingsState == null) {
2261                return new ArrayList<String>();
2262            }
2263            return settingsState.getSettingNamesLocked();
2264        }
2265
2266        public SparseBooleanArray getKnownUsersLocked() {
2267            SparseBooleanArray users = new SparseBooleanArray();
2268            for (int i = mSettingsStates.size()-1; i >= 0; i--) {
2269                users.put(getUserIdFromKey(mSettingsStates.keyAt(i)), true);
2270            }
2271            return users;
2272        }
2273
2274        @Nullable
2275        public SettingsState getSettingsLocked(int type, int userId) {
2276            final int key = makeKey(type, userId);
2277            return peekSettingsStateLocked(key);
2278        }
2279
2280        public boolean ensureSettingsForUserLocked(int userId) {
2281            // First make sure this user actually exists.
2282            if (mUserManager.getUserInfo(userId) == null) {
2283                Slog.wtf(LOG_TAG, "Requested user " + userId + " does not exist");
2284                return false;
2285            }
2286
2287            // Migrate the setting for this user if needed.
2288            migrateLegacySettingsForUserIfNeededLocked(userId);
2289
2290            // Ensure global settings loaded if owner.
2291            if (userId == UserHandle.USER_SYSTEM) {
2292                final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
2293                ensureSettingsStateLocked(globalKey);
2294            }
2295
2296            // Ensure secure settings loaded.
2297            final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
2298            ensureSettingsStateLocked(secureKey);
2299
2300            // Make sure the secure settings have an Android id set.
2301            SettingsState secureSettings = getSettingsLocked(SETTINGS_TYPE_SECURE, userId);
2302            ensureSecureSettingAndroidIdSetLocked(secureSettings);
2303
2304            // Ensure system settings loaded.
2305            final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
2306            ensureSettingsStateLocked(systemKey);
2307
2308            // Ensure secure settings loaded.
2309            final int ssaidKey = makeKey(SETTINGS_TYPE_SSAID, userId);
2310            ensureSettingsStateLocked(ssaidKey);
2311
2312            // Upgrade the settings to the latest version.
2313            UpgradeController upgrader = new UpgradeController(userId);
2314            upgrader.upgradeIfNeededLocked();
2315            return true;
2316        }
2317
2318        private void ensureSettingsStateLocked(int key) {
2319            if (mSettingsStates.get(key) == null) {
2320                final int maxBytesPerPackage = getMaxBytesPerPackageForType(getTypeFromKey(key));
2321                SettingsState settingsState = new SettingsState(getContext(), mLock,
2322                        getSettingsFile(key), key, maxBytesPerPackage, mHandlerThread.getLooper());
2323                mSettingsStates.put(key, settingsState);
2324            }
2325        }
2326
2327        public void removeUserStateLocked(int userId, boolean permanently) {
2328            // We always keep the global settings in memory.
2329
2330            // Nuke system settings.
2331            final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
2332            final SettingsState systemSettingsState = mSettingsStates.get(systemKey);
2333            if (systemSettingsState != null) {
2334                if (permanently) {
2335                    mSettingsStates.remove(systemKey);
2336                    systemSettingsState.destroyLocked(null);
2337                } else {
2338                    systemSettingsState.destroyLocked(new Runnable() {
2339                        @Override
2340                        public void run() {
2341                            mSettingsStates.remove(systemKey);
2342                        }
2343                    });
2344                }
2345            }
2346
2347            // Nuke secure settings.
2348            final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
2349            final SettingsState secureSettingsState = mSettingsStates.get(secureKey);
2350            if (secureSettingsState != null) {
2351                if (permanently) {
2352                    mSettingsStates.remove(secureKey);
2353                    secureSettingsState.destroyLocked(null);
2354                } else {
2355                    secureSettingsState.destroyLocked(new Runnable() {
2356                        @Override
2357                        public void run() {
2358                            mSettingsStates.remove(secureKey);
2359                        }
2360                    });
2361                }
2362            }
2363
2364            // Nuke ssaid settings.
2365            final int ssaidKey = makeKey(SETTINGS_TYPE_SSAID, userId);
2366            final SettingsState ssaidSettingsState = mSettingsStates.get(ssaidKey);
2367            if (ssaidSettingsState != null) {
2368                if (permanently) {
2369                    mSettingsStates.remove(ssaidKey);
2370                    ssaidSettingsState.destroyLocked(null);
2371                } else {
2372                    ssaidSettingsState.destroyLocked(new Runnable() {
2373                        @Override
2374                        public void run() {
2375                            mSettingsStates.remove(ssaidKey);
2376                        }
2377                    });
2378                }
2379            }
2380
2381            // Nuke generation tracking data
2382            mGenerationRegistry.onUserRemoved(userId);
2383        }
2384
2385        public boolean insertSettingLocked(int type, int userId, String name, String value,
2386                String tag, boolean makeDefault, String packageName, boolean forceNotify,
2387                Set<String> criticalSettings) {
2388            final int key = makeKey(type, userId);
2389
2390            boolean success = false;
2391            SettingsState settingsState = peekSettingsStateLocked(key);
2392            if (settingsState != null) {
2393                success = settingsState.insertSettingLocked(name, value,
2394                        tag, makeDefault, packageName);
2395            }
2396
2397            if (success && criticalSettings != null && criticalSettings.contains(name)) {
2398                settingsState.persistSyncLocked();
2399            }
2400
2401            if (forceNotify || success) {
2402                notifyForSettingsChange(key, name);
2403            }
2404            return success;
2405        }
2406
2407        public boolean deleteSettingLocked(int type, int userId, String name, boolean forceNotify,
2408                Set<String> criticalSettings) {
2409            final int key = makeKey(type, userId);
2410
2411            boolean success = false;
2412            SettingsState settingsState = peekSettingsStateLocked(key);
2413            if (settingsState != null) {
2414                success = settingsState.deleteSettingLocked(name);
2415            }
2416
2417            if (success && criticalSettings != null && criticalSettings.contains(name)) {
2418                settingsState.persistSyncLocked();
2419            }
2420
2421            if (forceNotify || success) {
2422                notifyForSettingsChange(key, name);
2423            }
2424            return success;
2425        }
2426
2427        public boolean updateSettingLocked(int type, int userId, String name, String value,
2428                String tag, boolean makeDefault, String packageName, boolean forceNotify,
2429                Set<String> criticalSettings) {
2430            final int key = makeKey(type, userId);
2431
2432            boolean success = false;
2433            SettingsState settingsState = peekSettingsStateLocked(key);
2434            if (settingsState != null) {
2435                success = settingsState.updateSettingLocked(name, value, tag,
2436                        makeDefault, packageName);
2437            }
2438
2439            if (success && criticalSettings != null && criticalSettings.contains(name)) {
2440                settingsState.persistSyncLocked();
2441            }
2442
2443            if (forceNotify || success) {
2444                notifyForSettingsChange(key, name);
2445            }
2446
2447            return success;
2448        }
2449
2450        public Setting getSettingLocked(int type, int userId, String name) {
2451            final int key = makeKey(type, userId);
2452
2453            SettingsState settingsState = peekSettingsStateLocked(key);
2454            if (settingsState == null) {
2455                return null;
2456            }
2457
2458            // getSettingLocked will return non-null result
2459            return settingsState.getSettingLocked(name);
2460        }
2461
2462        public void resetSettingsLocked(int type, int userId, String packageName, int mode,
2463                String tag) {
2464            final int key = makeKey(type, userId);
2465            SettingsState settingsState = peekSettingsStateLocked(key);
2466            if (settingsState == null) {
2467                return;
2468            }
2469
2470            switch (mode) {
2471                case Settings.RESET_MODE_PACKAGE_DEFAULTS: {
2472                    for (String name : settingsState.getSettingNamesLocked()) {
2473                        boolean someSettingChanged = false;
2474                        Setting setting = settingsState.getSettingLocked(name);
2475                        if (packageName.equals(setting.getPackageName())) {
2476                            if (tag != null && !tag.equals(setting.getTag())) {
2477                                continue;
2478                            }
2479                            if (settingsState.resetSettingLocked(name)) {
2480                                someSettingChanged = true;
2481                                notifyForSettingsChange(key, name);
2482                            }
2483                        }
2484                        if (someSettingChanged) {
2485                            settingsState.persistSyncLocked();
2486                        }
2487                    }
2488                } break;
2489
2490                case Settings.RESET_MODE_UNTRUSTED_DEFAULTS: {
2491                    for (String name : settingsState.getSettingNamesLocked()) {
2492                        boolean someSettingChanged = false;
2493                        Setting setting = settingsState.getSettingLocked(name);
2494                        if (!SettingsState.isSystemPackage(getContext(),
2495                                setting.getPackageName())) {
2496                            if (settingsState.resetSettingLocked(name)) {
2497                                someSettingChanged = true;
2498                                notifyForSettingsChange(key, name);
2499                            }
2500                        }
2501                        if (someSettingChanged) {
2502                            settingsState.persistSyncLocked();
2503                        }
2504                    }
2505                } break;
2506
2507                case Settings.RESET_MODE_UNTRUSTED_CHANGES: {
2508                    for (String name : settingsState.getSettingNamesLocked()) {
2509                        boolean someSettingChanged = false;
2510                        Setting setting = settingsState.getSettingLocked(name);
2511                        if (!SettingsState.isSystemPackage(getContext(),
2512                                setting.getPackageName())) {
2513                            if (setting.isDefaultFromSystem()) {
2514                                if (settingsState.resetSettingLocked(name)) {
2515                                    someSettingChanged = true;
2516                                    notifyForSettingsChange(key, name);
2517                                }
2518                            } else if (settingsState.deleteSettingLocked(name)) {
2519                                someSettingChanged = true;
2520                                notifyForSettingsChange(key, name);
2521                            }
2522                        }
2523                        if (someSettingChanged) {
2524                            settingsState.persistSyncLocked();
2525                        }
2526                    }
2527                } break;
2528
2529                case Settings.RESET_MODE_TRUSTED_DEFAULTS: {
2530                    for (String name : settingsState.getSettingNamesLocked()) {
2531                        Setting setting = settingsState.getSettingLocked(name);
2532                        boolean someSettingChanged = false;
2533                        if (setting.isDefaultFromSystem()) {
2534                            if (settingsState.resetSettingLocked(name)) {
2535                                someSettingChanged = true;
2536                                notifyForSettingsChange(key, name);
2537                            }
2538                        } else if (settingsState.deleteSettingLocked(name)) {
2539                            someSettingChanged = true;
2540                            notifyForSettingsChange(key, name);
2541                        }
2542                        if (someSettingChanged) {
2543                            settingsState.persistSyncLocked();
2544                        }
2545                    }
2546                } break;
2547            }
2548        }
2549
2550        public void onPackageRemovedLocked(String packageName, int userId) {
2551            // Global and secure settings are signature protected. Apps signed
2552            // by the platform certificate are generally not uninstalled  and
2553            // the main exception is tests. We trust components signed
2554            // by the platform certificate and do not do a clean up after them.
2555
2556            final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
2557            SettingsState systemSettings = mSettingsStates.get(systemKey);
2558            if (systemSettings != null) {
2559                systemSettings.onPackageRemovedLocked(packageName);
2560            }
2561        }
2562
2563        public void onUidRemovedLocked(int uid) {
2564            final SettingsState ssaidSettings = getSettingsLocked(SETTINGS_TYPE_SSAID,
2565                    UserHandle.getUserId(uid));
2566            if (ssaidSettings != null) {
2567                ssaidSettings.deleteSettingLocked(Integer.toString(uid));
2568            }
2569        }
2570
2571        @Nullable
2572        private SettingsState peekSettingsStateLocked(int key) {
2573            SettingsState settingsState = mSettingsStates.get(key);
2574            if (settingsState != null) {
2575                return settingsState;
2576            }
2577
2578            if (!ensureSettingsForUserLocked(getUserIdFromKey(key))) {
2579                return null;
2580            }
2581            return mSettingsStates.get(key);
2582        }
2583
2584        private void migrateAllLegacySettingsIfNeeded() {
2585            synchronized (mLock) {
2586                final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
2587                File globalFile = getSettingsFile(key);
2588                if (SettingsState.stateFileExists(globalFile)) {
2589                    return;
2590                }
2591
2592                mSettingsCreationBuildId = Build.ID;
2593
2594                final long identity = Binder.clearCallingIdentity();
2595                try {
2596                    List<UserInfo> users = mUserManager.getUsers(true);
2597
2598                    final int userCount = users.size();
2599                    for (int i = 0; i < userCount; i++) {
2600                        final int userId = users.get(i).id;
2601
2602                        DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId);
2603                        SQLiteDatabase database = dbHelper.getWritableDatabase();
2604                        migrateLegacySettingsForUserLocked(dbHelper, database, userId);
2605
2606                        // Upgrade to the latest version.
2607                        UpgradeController upgrader = new UpgradeController(userId);
2608                        upgrader.upgradeIfNeededLocked();
2609
2610                        // Drop from memory if not a running user.
2611                        if (!mUserManager.isUserRunning(new UserHandle(userId))) {
2612                            removeUserStateLocked(userId, false);
2613                        }
2614                    }
2615                } finally {
2616                    Binder.restoreCallingIdentity(identity);
2617                }
2618            }
2619        }
2620
2621        private void migrateLegacySettingsForUserIfNeededLocked(int userId) {
2622            // Every user has secure settings and if no file we need to migrate.
2623            final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
2624            File secureFile = getSettingsFile(secureKey);
2625            if (SettingsState.stateFileExists(secureFile)) {
2626                return;
2627            }
2628
2629            DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId);
2630            SQLiteDatabase database = dbHelper.getWritableDatabase();
2631
2632            migrateLegacySettingsForUserLocked(dbHelper, database, userId);
2633        }
2634
2635        private void migrateLegacySettingsForUserLocked(DatabaseHelper dbHelper,
2636                SQLiteDatabase database, int userId) {
2637            // Move over the system settings.
2638            final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
2639            ensureSettingsStateLocked(systemKey);
2640            SettingsState systemSettings = mSettingsStates.get(systemKey);
2641            migrateLegacySettingsLocked(systemSettings, database, TABLE_SYSTEM);
2642            systemSettings.persistSyncLocked();
2643
2644            // Move over the secure settings.
2645            // Do this after System settings, since this is the first thing we check when deciding
2646            // to skip over migration from db to xml for a secondary user.
2647            final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
2648            ensureSettingsStateLocked(secureKey);
2649            SettingsState secureSettings = mSettingsStates.get(secureKey);
2650            migrateLegacySettingsLocked(secureSettings, database, TABLE_SECURE);
2651            ensureSecureSettingAndroidIdSetLocked(secureSettings);
2652            secureSettings.persistSyncLocked();
2653
2654            // Move over the global settings if owner.
2655            // Do this last, since this is the first thing we check when deciding
2656            // to skip over migration from db to xml for owner user.
2657            if (userId == UserHandle.USER_SYSTEM) {
2658                final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, userId);
2659                ensureSettingsStateLocked(globalKey);
2660                SettingsState globalSettings = mSettingsStates.get(globalKey);
2661                migrateLegacySettingsLocked(globalSettings, database, TABLE_GLOBAL);
2662                // If this was just created
2663                if (mSettingsCreationBuildId != null) {
2664                    globalSettings.insertSettingLocked(Settings.Global.DATABASE_CREATION_BUILDID,
2665                            mSettingsCreationBuildId, null, true,
2666                            SettingsState.SYSTEM_PACKAGE_NAME);
2667                }
2668                globalSettings.persistSyncLocked();
2669            }
2670
2671            // Drop the database as now all is moved and persisted.
2672            if (DROP_DATABASE_ON_MIGRATION) {
2673                dbHelper.dropDatabase();
2674            } else {
2675                dbHelper.backupDatabase();
2676            }
2677        }
2678
2679        private void migrateLegacySettingsLocked(SettingsState settingsState,
2680                SQLiteDatabase database, String table) {
2681            SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
2682            queryBuilder.setTables(table);
2683
2684            Cursor cursor = queryBuilder.query(database, ALL_COLUMNS,
2685                    null, null, null, null, null);
2686
2687            if (cursor == null) {
2688                return;
2689            }
2690
2691            try {
2692                if (!cursor.moveToFirst()) {
2693                    return;
2694                }
2695
2696                final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME);
2697                final int valueColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.VALUE);
2698
2699                settingsState.setVersionLocked(database.getVersion());
2700
2701                while (!cursor.isAfterLast()) {
2702                    String name = cursor.getString(nameColumnIdx);
2703                    String value = cursor.getString(valueColumnIdx);
2704                    settingsState.insertSettingLocked(name, value, null, true,
2705                            SettingsState.SYSTEM_PACKAGE_NAME);
2706                    cursor.moveToNext();
2707                }
2708            } finally {
2709                cursor.close();
2710            }
2711        }
2712
2713        private void ensureSecureSettingAndroidIdSetLocked(SettingsState secureSettings) {
2714            Setting value = secureSettings.getSettingLocked(Settings.Secure.ANDROID_ID);
2715
2716            if (!value.isNull()) {
2717                return;
2718            }
2719
2720            final int userId = getUserIdFromKey(secureSettings.mKey);
2721
2722            final UserInfo user;
2723            final long identity = Binder.clearCallingIdentity();
2724            try {
2725                user = mUserManager.getUserInfo(userId);
2726            } finally {
2727                Binder.restoreCallingIdentity(identity);
2728            }
2729            if (user == null) {
2730                // Can happen due to races when deleting users - treat as benign.
2731                return;
2732            }
2733
2734            String androidId = Long.toHexString(new SecureRandom().nextLong());
2735            secureSettings.insertSettingLocked(Settings.Secure.ANDROID_ID, androidId,
2736                    null, true, SettingsState.SYSTEM_PACKAGE_NAME);
2737
2738            Slog.d(LOG_TAG, "Generated and saved new ANDROID_ID [" + androidId
2739                    + "] for user " + userId);
2740
2741            // Write a drop box entry if it's a restricted profile
2742            if (user.isRestricted()) {
2743                DropBoxManager dbm = (DropBoxManager) getContext().getSystemService(
2744                        Context.DROPBOX_SERVICE);
2745                if (dbm != null && dbm.isTagEnabled(DROPBOX_TAG_USERLOG)) {
2746                    dbm.addText(DROPBOX_TAG_USERLOG, System.currentTimeMillis()
2747                            + "," + DROPBOX_TAG_USERLOG + "," + androidId + "\n");
2748                }
2749            }
2750        }
2751
2752        private void notifyForSettingsChange(int key, String name) {
2753            // Increment the generation first, so observers always see the new value
2754            mGenerationRegistry.incrementGeneration(key);
2755
2756            if (isGlobalSettingsKey(key)) {
2757                final long token = Binder.clearCallingIdentity();
2758                try {
2759                    if (Global.LOCATION_GLOBAL_KILL_SWITCH.equals(name)) {
2760                        // When the global kill switch is updated, send the
2761                        // change notification for the location setting.
2762                        notifyLocationChangeForRunningUsers();
2763                    }
2764                    notifyGlobalSettingChangeForRunningUsers(key, name);
2765                } finally {
2766                    Binder.restoreCallingIdentity(token);
2767                }
2768            } else {
2769                final int userId = getUserIdFromKey(key);
2770                final Uri uri = getNotificationUriFor(key, name);
2771                mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
2772                        userId, 0, uri).sendToTarget();
2773                if (isSecureSettingsKey(key)) {
2774                    maybeNotifyProfiles(getTypeFromKey(key), userId, uri, name,
2775                            sSecureCloneToManagedSettings);
2776                    maybeNotifyProfiles(SETTINGS_TYPE_SYSTEM, userId, uri, name,
2777                            sSystemCloneFromParentOnDependency.values());
2778                } else if (isSystemSettingsKey(key)) {
2779                    maybeNotifyProfiles(getTypeFromKey(key), userId, uri, name,
2780                            sSystemCloneToManagedSettings);
2781                }
2782            }
2783
2784            // Always notify that our data changed
2785            mHandler.obtainMessage(MyHandler.MSG_NOTIFY_DATA_CHANGED).sendToTarget();
2786        }
2787
2788        private void maybeNotifyProfiles(int type, int userId, Uri uri, String name,
2789                Collection<String> keysCloned) {
2790            if (keysCloned.contains(name)) {
2791                for (int profileId : mUserManager.getProfileIdsWithDisabled(userId)) {
2792                    // the notification for userId has already been sent.
2793                    if (profileId != userId) {
2794                        final int key = makeKey(type, profileId);
2795                        // Increment the generation first, so observers always see the new value
2796                        mGenerationRegistry.incrementGeneration(key);
2797                        mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
2798                                profileId, 0, uri).sendToTarget();
2799                    }
2800                }
2801            }
2802        }
2803
2804        private void notifyGlobalSettingChangeForRunningUsers(int key, String name) {
2805            // Important: No need to update generation for each user as there
2806            // is a singleton generation entry for the global settings which
2807            // is already incremented be the caller.
2808            final Uri uri = getNotificationUriFor(key, name);
2809            final List<UserInfo> users = mUserManager.getUsers(/*excludeDying*/ true);
2810            for (int i = 0; i < users.size(); i++) {
2811                final int userId = users.get(i).id;
2812                if (mUserManager.isUserRunning(UserHandle.of(userId))) {
2813                    mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
2814                            userId, 0, uri).sendToTarget();
2815                }
2816            }
2817        }
2818
2819        private void notifyLocationChangeForRunningUsers() {
2820            final List<UserInfo> users = mUserManager.getUsers(/*excludeDying=*/ true);
2821
2822            for (int i = 0; i < users.size(); i++) {
2823                final int userId = users.get(i).id;
2824
2825                if (!mUserManager.isUserRunning(UserHandle.of(userId))) {
2826                    continue;
2827                }
2828
2829                // Increment the generation first, so observers always see the new value
2830                final int key = makeKey(SETTINGS_TYPE_SECURE, userId);
2831                mGenerationRegistry.incrementGeneration(key);
2832
2833                final Uri uri = getNotificationUriFor(key, Secure.LOCATION_PROVIDERS_ALLOWED);
2834                mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
2835                        userId, 0, uri).sendToTarget();
2836            }
2837        }
2838
2839        private boolean isGlobalSettingsKey(int key) {
2840            return getTypeFromKey(key) == SETTINGS_TYPE_GLOBAL;
2841        }
2842
2843        private boolean isSystemSettingsKey(int key) {
2844            return getTypeFromKey(key) == SETTINGS_TYPE_SYSTEM;
2845        }
2846
2847        private boolean isSecureSettingsKey(int key) {
2848            return getTypeFromKey(key) == SETTINGS_TYPE_SECURE;
2849        }
2850
2851        private boolean isSsaidSettingsKey(int key) {
2852            return getTypeFromKey(key) == SETTINGS_TYPE_SSAID;
2853        }
2854
2855        private File getSettingsFile(int key) {
2856            if (isGlobalSettingsKey(key)) {
2857                final int userId = getUserIdFromKey(key);
2858                return new File(Environment.getUserSystemDirectory(userId),
2859                        SETTINGS_FILE_GLOBAL);
2860            } else if (isSystemSettingsKey(key)) {
2861                final int userId = getUserIdFromKey(key);
2862                return new File(Environment.getUserSystemDirectory(userId),
2863                        SETTINGS_FILE_SYSTEM);
2864            } else if (isSecureSettingsKey(key)) {
2865                final int userId = getUserIdFromKey(key);
2866                return new File(Environment.getUserSystemDirectory(userId),
2867                        SETTINGS_FILE_SECURE);
2868            } else if (isSsaidSettingsKey(key)) {
2869                final int userId = getUserIdFromKey(key);
2870                return new File(Environment.getUserSystemDirectory(userId),
2871                        SETTINGS_FILE_SSAID);
2872            } else {
2873                throw new IllegalArgumentException("Invalid settings key:" + key);
2874            }
2875        }
2876
2877        private Uri getNotificationUriFor(int key, String name) {
2878            if (isGlobalSettingsKey(key)) {
2879                return (name != null) ? Uri.withAppendedPath(Settings.Global.CONTENT_URI, name)
2880                        : Settings.Global.CONTENT_URI;
2881            } else if (isSecureSettingsKey(key)) {
2882                return (name != null) ? Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name)
2883                        : Settings.Secure.CONTENT_URI;
2884            } else if (isSystemSettingsKey(key)) {
2885                return (name != null) ? Uri.withAppendedPath(Settings.System.CONTENT_URI, name)
2886                        : Settings.System.CONTENT_URI;
2887            } else {
2888                throw new IllegalArgumentException("Invalid settings key:" + key);
2889            }
2890        }
2891
2892        private int getMaxBytesPerPackageForType(int type) {
2893            switch (type) {
2894                case SETTINGS_TYPE_GLOBAL:
2895                case SETTINGS_TYPE_SECURE:
2896                case SETTINGS_TYPE_SSAID: {
2897                    return SettingsState.MAX_BYTES_PER_APP_PACKAGE_UNLIMITED;
2898                }
2899
2900                default: {
2901                    return SettingsState.MAX_BYTES_PER_APP_PACKAGE_LIMITED;
2902                }
2903            }
2904        }
2905
2906        private final class MyHandler extends Handler {
2907            private static final int MSG_NOTIFY_URI_CHANGED = 1;
2908            private static final int MSG_NOTIFY_DATA_CHANGED = 2;
2909
2910            public MyHandler(Looper looper) {
2911                super(looper);
2912            }
2913
2914            @Override
2915            public void handleMessage(Message msg) {
2916                switch (msg.what) {
2917                    case MSG_NOTIFY_URI_CHANGED: {
2918                        final int userId = msg.arg1;
2919                        Uri uri = (Uri) msg.obj;
2920                        try {
2921                            getContext().getContentResolver().notifyChange(uri, null, true, userId);
2922                        } catch (SecurityException e) {
2923                            Slog.w(LOG_TAG, "Failed to notify for " + userId + ": " + uri, e);
2924                        }
2925                        if (DEBUG || true) {
2926                            Slog.v(LOG_TAG, "Notifying for " + userId + ": " + uri);
2927                        }
2928                    } break;
2929
2930                    case MSG_NOTIFY_DATA_CHANGED: {
2931                        mBackupManager.dataChanged();
2932                    } break;
2933                }
2934            }
2935        }
2936
2937        private final class UpgradeController {
2938            private static final int SETTINGS_VERSION = 169;
2939
2940            private final int mUserId;
2941
2942            public UpgradeController(int userId) {
2943                mUserId = userId;
2944            }
2945
2946            public void upgradeIfNeededLocked() {
2947                // The version of all settings for a user is the same (all users have secure).
2948                SettingsState secureSettings = getSettingsLocked(
2949                        SETTINGS_TYPE_SECURE, mUserId);
2950
2951                // Try an update from the current state.
2952                final int oldVersion = secureSettings.getVersionLocked();
2953                final int newVersion = SETTINGS_VERSION;
2954
2955                // If up do date - done.
2956                if (oldVersion == newVersion) {
2957                    return;
2958                }
2959
2960                // Try to upgrade.
2961                final int curVersion = onUpgradeLocked(mUserId, oldVersion, newVersion);
2962
2963                // If upgrade failed start from scratch and upgrade.
2964                if (curVersion != newVersion) {
2965                    // Drop state we have for this user.
2966                    removeUserStateLocked(mUserId, true);
2967
2968                    // Recreate the database.
2969                    DatabaseHelper dbHelper = new DatabaseHelper(getContext(), mUserId);
2970                    SQLiteDatabase database = dbHelper.getWritableDatabase();
2971                    dbHelper.recreateDatabase(database, newVersion, curVersion, oldVersion);
2972
2973                    // Migrate the settings for this user.
2974                    migrateLegacySettingsForUserLocked(dbHelper, database, mUserId);
2975
2976                    // Now upgrade should work fine.
2977                    onUpgradeLocked(mUserId, oldVersion, newVersion);
2978
2979                    // Make a note what happened, so we don't wonder why data was lost
2980                    String reason = "Settings rebuilt! Current version: "
2981                            + curVersion + " while expected: " + newVersion;
2982                    getGlobalSettingsLocked().insertSettingLocked(
2983                            Settings.Global.DATABASE_DOWNGRADE_REASON,
2984                            reason, null, true, SettingsState.SYSTEM_PACKAGE_NAME);
2985                }
2986
2987                // Set the global settings version if owner.
2988                if (mUserId == UserHandle.USER_SYSTEM) {
2989                    SettingsState globalSettings = getSettingsLocked(
2990                            SETTINGS_TYPE_GLOBAL, mUserId);
2991                    globalSettings.setVersionLocked(newVersion);
2992                }
2993
2994                // Set the secure settings version.
2995                secureSettings.setVersionLocked(newVersion);
2996
2997                // Set the system settings version.
2998                SettingsState systemSettings = getSettingsLocked(
2999                        SETTINGS_TYPE_SYSTEM, mUserId);
3000                systemSettings.setVersionLocked(newVersion);
3001            }
3002
3003            private SettingsState getGlobalSettingsLocked() {
3004                return getSettingsLocked(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
3005            }
3006
3007            private SettingsState getSecureSettingsLocked(int userId) {
3008                return getSettingsLocked(SETTINGS_TYPE_SECURE, userId);
3009            }
3010
3011            private SettingsState getSsaidSettingsLocked(int userId) {
3012                return getSettingsLocked(SETTINGS_TYPE_SSAID, userId);
3013            }
3014
3015            private SettingsState getSystemSettingsLocked(int userId) {
3016                return getSettingsLocked(SETTINGS_TYPE_SYSTEM, userId);
3017            }
3018
3019            /**
3020             * You must perform all necessary mutations to bring the settings
3021             * for this user from the old to the new version. When you add a new
3022             * upgrade step you *must* update SETTINGS_VERSION.
3023             *
3024             * This is an example of moving a setting from secure to global.
3025             *
3026             * // v119: Example settings changes.
3027             * if (currentVersion == 118) {
3028             *     if (userId == UserHandle.USER_OWNER) {
3029             *         // Remove from the secure settings.
3030             *         SettingsState secureSettings = getSecureSettingsLocked(userId);
3031             *         String name = "example_setting_to_move";
3032             *         String value = secureSettings.getSetting(name);
3033             *         secureSettings.deleteSetting(name);
3034             *
3035             *         // Add to the global settings.
3036             *         SettingsState globalSettings = getGlobalSettingsLocked();
3037             *         globalSettings.insertSetting(name, value, SettingsState.SYSTEM_PACKAGE_NAME);
3038             *     }
3039             *
3040             *     // Update the current version.
3041             *     currentVersion = 119;
3042             * }
3043             */
3044            private int onUpgradeLocked(int userId, int oldVersion, int newVersion) {
3045                if (DEBUG) {
3046                    Slog.w(LOG_TAG, "Upgrading settings for user: " + userId + " from version: "
3047                            + oldVersion + " to version: " + newVersion);
3048                }
3049
3050                int currentVersion = oldVersion;
3051
3052                // v119: Reset zen + ringer mode.
3053                if (currentVersion == 118) {
3054                    if (userId == UserHandle.USER_SYSTEM) {
3055                        final SettingsState globalSettings = getGlobalSettingsLocked();
3056                        globalSettings.updateSettingLocked(Settings.Global.ZEN_MODE,
3057                                Integer.toString(Settings.Global.ZEN_MODE_OFF), null,
3058                                true, SettingsState.SYSTEM_PACKAGE_NAME);
3059                        globalSettings.updateSettingLocked(Settings.Global.MODE_RINGER,
3060                                Integer.toString(AudioManager.RINGER_MODE_NORMAL), null,
3061                                true, SettingsState.SYSTEM_PACKAGE_NAME);
3062                    }
3063                    currentVersion = 119;
3064                }
3065
3066                // v120: Add double tap to wake setting.
3067                if (currentVersion == 119) {
3068                    SettingsState secureSettings = getSecureSettingsLocked(userId);
3069                    secureSettings.insertSettingLocked(Settings.Secure.DOUBLE_TAP_TO_WAKE,
3070                            getContext().getResources().getBoolean(
3071                                    R.bool.def_double_tap_to_wake) ? "1" : "0", null, true,
3072                            SettingsState.SYSTEM_PACKAGE_NAME);
3073
3074                    currentVersion = 120;
3075                }
3076
3077                if (currentVersion == 120) {
3078                    // Before 121, we used a different string encoding logic.  We just bump the
3079                    // version here; SettingsState knows how to handle pre-version 120 files.
3080                    currentVersion = 121;
3081                }
3082
3083                if (currentVersion == 121) {
3084                    // Version 122: allow OEMs to set a default payment component in resources.
3085                    // Note that we only write the default if no default has been set;
3086                    // if there is, we just leave the default at whatever it currently is.
3087                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
3088                    String defaultComponent = (getContext().getResources().getString(
3089                            R.string.def_nfc_payment_component));
3090                    Setting currentSetting = secureSettings.getSettingLocked(
3091                            Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT);
3092                    if (defaultComponent != null && !defaultComponent.isEmpty() &&
3093                        currentSetting.isNull()) {
3094                        secureSettings.insertSettingLocked(
3095                                Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT,
3096                                defaultComponent, null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3097                    }
3098                    currentVersion = 122;
3099                }
3100
3101                if (currentVersion == 122) {
3102                    // Version 123: Adding a default value for the ability to add a user from
3103                    // the lock screen.
3104                    if (userId == UserHandle.USER_SYSTEM) {
3105                        final SettingsState globalSettings = getGlobalSettingsLocked();
3106                        Setting currentSetting = globalSettings.getSettingLocked(
3107                                Settings.Global.ADD_USERS_WHEN_LOCKED);
3108                        if (currentSetting.isNull()) {
3109                            globalSettings.insertSettingLocked(
3110                                    Settings.Global.ADD_USERS_WHEN_LOCKED,
3111                                    getContext().getResources().getBoolean(
3112                                            R.bool.def_add_users_from_lockscreen) ? "1" : "0",
3113                                    null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3114                        }
3115                    }
3116                    currentVersion = 123;
3117                }
3118
3119                if (currentVersion == 123) {
3120                    final SettingsState globalSettings = getGlobalSettingsLocked();
3121                    String defaultDisabledProfiles = (getContext().getResources().getString(
3122                            R.string.def_bluetooth_disabled_profiles));
3123                    globalSettings.insertSettingLocked(Settings.Global.BLUETOOTH_DISABLED_PROFILES,
3124                            defaultDisabledProfiles, null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3125                    currentVersion = 124;
3126                }
3127
3128                if (currentVersion == 124) {
3129                    // Version 124: allow OEMs to set a default value for whether IME should be
3130                    // shown when a physical keyboard is connected.
3131                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
3132                    Setting currentSetting = secureSettings.getSettingLocked(
3133                            Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
3134                    if (currentSetting.isNull()) {
3135                        secureSettings.insertSettingLocked(
3136                                Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
3137                                getContext().getResources().getBoolean(
3138                                        R.bool.def_show_ime_with_hard_keyboard) ? "1" : "0",
3139                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3140                    }
3141                    currentVersion = 125;
3142                }
3143
3144                if (currentVersion == 125) {
3145                    // Version 125: Allow OEMs to set the default VR service.
3146                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
3147
3148                    Setting currentSetting = secureSettings.getSettingLocked(
3149                            Settings.Secure.ENABLED_VR_LISTENERS);
3150                    if (currentSetting.isNull()) {
3151                        ArraySet<ComponentName> l =
3152                                SystemConfig.getInstance().getDefaultVrComponents();
3153
3154                        if (l != null && !l.isEmpty()) {
3155                            StringBuilder b = new StringBuilder();
3156                            boolean start = true;
3157                            for (ComponentName c : l) {
3158                                if (!start) {
3159                                    b.append(':');
3160                                }
3161                                b.append(c.flattenToString());
3162                                start = false;
3163                            }
3164                            secureSettings.insertSettingLocked(
3165                                    Settings.Secure.ENABLED_VR_LISTENERS, b.toString(),
3166                                    null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3167                        }
3168
3169                    }
3170                    currentVersion = 126;
3171                }
3172
3173                if (currentVersion == 126) {
3174                    // Version 126: copy the primary values of LOCK_SCREEN_SHOW_NOTIFICATIONS and
3175                    // LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS into managed profile.
3176                    if (mUserManager.isManagedProfile(userId)) {
3177                        final SettingsState systemSecureSettings =
3178                                getSecureSettingsLocked(UserHandle.USER_SYSTEM);
3179
3180                        final Setting showNotifications = systemSecureSettings.getSettingLocked(
3181                                Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS);
3182                        if (!showNotifications.isNull()) {
3183                            final SettingsState secureSettings = getSecureSettingsLocked(userId);
3184                            secureSettings.insertSettingLocked(
3185                                    Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
3186                                    showNotifications.getValue(), null, true,
3187                                    SettingsState.SYSTEM_PACKAGE_NAME);
3188                        }
3189
3190                        final Setting allowPrivate = systemSecureSettings.getSettingLocked(
3191                                Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
3192                        if (!allowPrivate.isNull()) {
3193                            final SettingsState secureSettings = getSecureSettingsLocked(userId);
3194                            secureSettings.insertSettingLocked(
3195                                    Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
3196                                    allowPrivate.getValue(), null, true,
3197                                    SettingsState.SYSTEM_PACKAGE_NAME);
3198                        }
3199                    }
3200                    currentVersion = 127;
3201                }
3202
3203                if (currentVersion == 127) {
3204                    // version 127 is no longer used.
3205                    currentVersion = 128;
3206                }
3207
3208                if (currentVersion == 128) {
3209                    // Version 128: Removed
3210                    currentVersion = 129;
3211                }
3212
3213                if (currentVersion == 129) {
3214                    // default longpress timeout changed from 500 to 400. If unchanged from the old
3215                    // default, update to the new default.
3216                    final SettingsState systemSecureSettings =
3217                            getSecureSettingsLocked(userId);
3218                    final String oldValue = systemSecureSettings.getSettingLocked(
3219                            Settings.Secure.LONG_PRESS_TIMEOUT).getValue();
3220                    if (TextUtils.equals("500", oldValue)) {
3221                        systemSecureSettings.insertSettingLocked(
3222                                Settings.Secure.LONG_PRESS_TIMEOUT,
3223                                String.valueOf(getContext().getResources().getInteger(
3224                                        R.integer.def_long_press_timeout_millis)),
3225                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3226                    }
3227                    currentVersion = 130;
3228                }
3229
3230                if (currentVersion == 130) {
3231                    // Split Ambient settings
3232                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
3233                    boolean dozeExplicitlyDisabled = "0".equals(secureSettings.
3234                            getSettingLocked(Settings.Secure.DOZE_ENABLED).getValue());
3235
3236                    if (dozeExplicitlyDisabled) {
3237                        secureSettings.insertSettingLocked(Settings.Secure.DOZE_PULSE_ON_PICK_UP,
3238                                "0", null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3239                        secureSettings.insertSettingLocked(Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP,
3240                                "0", null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3241                    }
3242                    currentVersion = 131;
3243                }
3244
3245                if (currentVersion == 131) {
3246                    // Initialize new multi-press timeout to default value
3247                    final SettingsState systemSecureSettings = getSecureSettingsLocked(userId);
3248                    final String oldValue = systemSecureSettings.getSettingLocked(
3249                            Settings.Secure.MULTI_PRESS_TIMEOUT).getValue();
3250                    if (TextUtils.equals(null, oldValue)) {
3251                        systemSecureSettings.insertSettingLocked(
3252                                Settings.Secure.MULTI_PRESS_TIMEOUT,
3253                                String.valueOf(getContext().getResources().getInteger(
3254                                        R.integer.def_multi_press_timeout_millis)),
3255                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3256                    }
3257
3258                    currentVersion = 132;
3259                }
3260
3261                if (currentVersion == 132) {
3262                    // Version 132: Allow managed profile to optionally use the parent's ringtones
3263                    final SettingsState systemSecureSettings = getSecureSettingsLocked(userId);
3264                    String defaultSyncParentSounds = (getContext().getResources()
3265                            .getBoolean(R.bool.def_sync_parent_sounds) ? "1" : "0");
3266                    systemSecureSettings.insertSettingLocked(
3267                            Settings.Secure.SYNC_PARENT_SOUNDS, defaultSyncParentSounds,
3268                            null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3269                    currentVersion = 133;
3270                }
3271
3272                if (currentVersion == 133) {
3273                    // Version 133: Add default end button behavior
3274                    final SettingsState systemSettings = getSystemSettingsLocked(userId);
3275                    if (systemSettings.getSettingLocked(Settings.System.END_BUTTON_BEHAVIOR) ==
3276                            null) {
3277                        String defaultEndButtonBehavior = Integer.toString(getContext()
3278                                .getResources().getInteger(R.integer.def_end_button_behavior));
3279                        systemSettings.insertSettingLocked(Settings.System.END_BUTTON_BEHAVIOR,
3280                                defaultEndButtonBehavior, null, true,
3281                                SettingsState.SYSTEM_PACKAGE_NAME);
3282                    }
3283                    currentVersion = 134;
3284                }
3285
3286                if (currentVersion == 134) {
3287                    // Remove setting that specifies if magnification values should be preserved.
3288                    // This setting defaulted to true and never has a UI.
3289                    getSecureSettingsLocked(userId).deleteSettingLocked(
3290                            Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE);
3291                    currentVersion = 135;
3292                }
3293
3294                if (currentVersion == 135) {
3295                    // Version 135 no longer used.
3296                    currentVersion = 136;
3297                }
3298
3299                if (currentVersion == 136) {
3300                    // Version 136: Store legacy SSAID for all apps currently installed on the
3301                    // device as first step in migrating SSAID to be unique per application.
3302
3303                    final boolean isUpgrade;
3304                    try {
3305                        isUpgrade = mPackageManager.isUpgrade();
3306                    } catch (RemoteException e) {
3307                        throw new IllegalStateException("Package manager not available");
3308                    }
3309                    // Only retain legacy ssaid if the device is performing an OTA. After wiping
3310                    // user data or first boot on a new device should use new ssaid generation.
3311                    if (isUpgrade) {
3312                        // Retrieve the legacy ssaid from the secure settings table.
3313                        final Setting legacySsaidSetting = getSettingLocked(SETTINGS_TYPE_SECURE,
3314                                userId, Settings.Secure.ANDROID_ID);
3315                        if (legacySsaidSetting == null || legacySsaidSetting.isNull()
3316                                || legacySsaidSetting.getValue() == null) {
3317                            throw new IllegalStateException("Legacy ssaid not accessible");
3318                        }
3319                        final String legacySsaid = legacySsaidSetting.getValue();
3320
3321                        // Fill each uid with the legacy ssaid to be backwards compatible.
3322                        final List<PackageInfo> packages;
3323                        try {
3324                            packages = mPackageManager.getInstalledPackages(
3325                                PackageManager.MATCH_UNINSTALLED_PACKAGES,
3326                                userId).getList();
3327                        } catch (RemoteException e) {
3328                            throw new IllegalStateException("Package manager not available");
3329                        }
3330
3331                        final SettingsState ssaidSettings = getSsaidSettingsLocked(userId);
3332                        for (PackageInfo info : packages) {
3333                            // Check if the UID already has an entry in the table.
3334                            final String uid = Integer.toString(info.applicationInfo.uid);
3335                            final Setting ssaid = ssaidSettings.getSettingLocked(uid);
3336
3337                            if (ssaid.isNull() || ssaid.getValue() == null) {
3338                                // Android Id doesn't exist for this package so create it.
3339                                ssaidSettings.insertSettingLocked(uid, legacySsaid, null, true,
3340                                        info.packageName);
3341                                if (DEBUG) {
3342                                    Slog.d(LOG_TAG, "Keep the legacy ssaid for uid=" + uid);
3343                                }
3344                            }
3345                        }
3346                    }
3347
3348                    currentVersion = 137;
3349                }
3350                if (currentVersion == 137) {
3351                    // Version 138: Settings.Secure#INSTALL_NON_MARKET_APPS is deprecated and its
3352                    // default value set to 1. The user can no longer change the value of this
3353                    // setting through the UI.
3354                    final SettingsState secureSetting = getSecureSettingsLocked(userId);
3355                    if (!mUserManager.hasUserRestriction(
3356                            UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, UserHandle.of(userId))
3357                            && secureSetting.getSettingLocked(
3358                            Settings.Secure.INSTALL_NON_MARKET_APPS).getValue().equals("0")) {
3359
3360                        secureSetting.insertSettingLocked(Settings.Secure.INSTALL_NON_MARKET_APPS,
3361                                "1", null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3362                        // For managed profiles with profile owners, DevicePolicyManagerService
3363                        // may want to set the user restriction in this case
3364                        secureSetting.insertSettingLocked(
3365                                Settings.Secure.UNKNOWN_SOURCES_DEFAULT_REVERSED, "1", null, true,
3366                                SettingsState.SYSTEM_PACKAGE_NAME);
3367                    }
3368                    currentVersion = 138;
3369                }
3370
3371                if (currentVersion == 138) {
3372                    // Version 139: Removed.
3373                    currentVersion = 139;
3374                }
3375
3376                if (currentVersion == 139) {
3377                    // Version 140: Settings.Secure#ACCESSIBILITY_SPEAK_PASSWORD is deprecated and
3378                    // the user can no longer change the value of this setting through the UI.
3379                    // Force to true.
3380                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
3381                    secureSettings.updateSettingLocked(Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD,
3382                            "1", null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3383                    currentVersion = 140;
3384                }
3385
3386                if (currentVersion == 140) {
3387                    // Version 141: Removed
3388                    currentVersion = 141;
3389                }
3390
3391                if (currentVersion == 141) {
3392                    // This implementation was incorrectly setting the current value of
3393                    // settings changed by non-system packages as the default which default
3394                    // is set by the system. We add a new upgrade step at the end to properly
3395                    // handle this case which would also fix incorrect changes made by the
3396                    // old implementation of this step.
3397                    currentVersion = 142;
3398                }
3399
3400                if (currentVersion == 142) {
3401                    // Version 143: Set a default value for Wi-Fi wakeup feature.
3402                    if (userId == UserHandle.USER_SYSTEM) {
3403                        final SettingsState globalSettings = getGlobalSettingsLocked();
3404                        Setting currentSetting = globalSettings.getSettingLocked(
3405                                Settings.Global.WIFI_WAKEUP_ENABLED);
3406                        if (currentSetting.isNull()) {
3407                            globalSettings.insertSettingLocked(
3408                                    Settings.Global.WIFI_WAKEUP_ENABLED,
3409                                    getContext().getResources().getBoolean(
3410                                            R.bool.def_wifi_wakeup_enabled) ? "1" : "0",
3411                                    null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3412                        }
3413                    }
3414
3415                    currentVersion = 143;
3416                }
3417
3418                if (currentVersion == 143) {
3419                    // Version 144: Set a default value for Autofill service.
3420                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
3421                    final Setting currentSetting = secureSettings
3422                            .getSettingLocked(Settings.Secure.AUTOFILL_SERVICE);
3423                    if (currentSetting.isNull()) {
3424                        final String defaultValue = getContext().getResources().getString(
3425                                com.android.internal.R.string.config_defaultAutofillService);
3426                        if (defaultValue != null) {
3427                            Slog.d(LOG_TAG, "Setting [" + defaultValue + "] as Autofill Service "
3428                                    + "for user " + userId);
3429                            secureSettings.insertSettingLocked(Settings.Secure.AUTOFILL_SERVICE,
3430                                    defaultValue, null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3431                        }
3432                    }
3433
3434                    currentVersion = 144;
3435                }
3436
3437                if (currentVersion == 144) {
3438                    // Version 145: Removed
3439                    currentVersion = 145;
3440                }
3441
3442                if (currentVersion == 145) {
3443                    // Version 146: In step 142 we had a bug where incorrectly
3444                    // some settings were considered system set and as a result
3445                    // made the default and marked as the default being set by
3446                    // the system. Here reevaluate the default and default system
3447                    // set flags. This would both fix corruption by the old impl
3448                    // of step 142 and also properly handle devices which never
3449                    // run 142.
3450                    if (userId == UserHandle.USER_SYSTEM) {
3451                        SettingsState globalSettings = getGlobalSettingsLocked();
3452                        ensureLegacyDefaultValueAndSystemSetUpdatedLocked(globalSettings, userId);
3453                        globalSettings.persistSyncLocked();
3454                    }
3455
3456                    SettingsState secureSettings = getSecureSettingsLocked(mUserId);
3457                    ensureLegacyDefaultValueAndSystemSetUpdatedLocked(secureSettings, userId);
3458                    secureSettings.persistSyncLocked();
3459
3460                    SettingsState systemSettings = getSystemSettingsLocked(mUserId);
3461                    ensureLegacyDefaultValueAndSystemSetUpdatedLocked(systemSettings, userId);
3462                    systemSettings.persistSyncLocked();
3463
3464                    currentVersion = 146;
3465                }
3466
3467                if (currentVersion == 146) {
3468                    // Version 147: Removed. (This version previously allowed showing the
3469                    // "wifi_wakeup_available" setting).
3470                    // The setting that was added here is deleted in 153.
3471                    currentVersion = 147;
3472                }
3473
3474                if (currentVersion == 147) {
3475                    // Version 148: Set the default value for DEFAULT_RESTRICT_BACKGROUND_DATA.
3476                    if (userId == UserHandle.USER_SYSTEM) {
3477                        final SettingsState globalSettings = getGlobalSettingsLocked();
3478                        final Setting currentSetting = globalSettings.getSettingLocked(
3479                                Global.DEFAULT_RESTRICT_BACKGROUND_DATA);
3480                        if (currentSetting.isNull()) {
3481                            globalSettings.insertSettingLocked(
3482                                    Global.DEFAULT_RESTRICT_BACKGROUND_DATA,
3483                                    getContext().getResources().getBoolean(
3484                                            R.bool.def_restrict_background_data) ? "1" : "0",
3485                                    null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3486                        }
3487                    }
3488                    currentVersion = 148;
3489                }
3490
3491                if (currentVersion == 148) {
3492                    // Version 149: Set the default value for BACKUP_MANAGER_CONSTANTS.
3493                    final SettingsState systemSecureSettings = getSecureSettingsLocked(userId);
3494                    final String oldValue = systemSecureSettings.getSettingLocked(
3495                            Settings.Secure.BACKUP_MANAGER_CONSTANTS).getValue();
3496                    if (TextUtils.equals(null, oldValue)) {
3497                        final String defaultValue = getContext().getResources().getString(
3498                                R.string.def_backup_manager_constants);
3499                        if (!TextUtils.isEmpty(defaultValue)) {
3500                            systemSecureSettings.insertSettingLocked(
3501                                    Settings.Secure.BACKUP_MANAGER_CONSTANTS, defaultValue, null,
3502                                    true, SettingsState.SYSTEM_PACKAGE_NAME);
3503                        }
3504                    }
3505                    currentVersion = 149;
3506                }
3507
3508                if (currentVersion == 149) {
3509                    // Version 150: Set a default value for mobile data always on
3510                    final SettingsState globalSettings = getGlobalSettingsLocked();
3511                    final Setting currentSetting = globalSettings.getSettingLocked(
3512                            Settings.Global.MOBILE_DATA_ALWAYS_ON);
3513                    if (currentSetting.isNull()) {
3514                        globalSettings.insertSettingLocked(
3515                                Settings.Global.MOBILE_DATA_ALWAYS_ON,
3516                                getContext().getResources().getBoolean(
3517                                        R.bool.def_mobile_data_always_on) ? "1" : "0",
3518                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3519                    }
3520
3521                    currentVersion = 150;
3522                }
3523
3524                if (currentVersion == 150) {
3525                    // Version 151: Removed.
3526                    currentVersion = 151;
3527                }
3528
3529                if (currentVersion == 151) {
3530                    // Version 152: Removed. (This version made the setting for wifi_wakeup enabled
3531                    // by default but it is now no longer configurable).
3532                    // The setting updated here is deleted in 153.
3533                    currentVersion = 152;
3534                }
3535
3536                if (currentVersion == 152) {
3537                    getGlobalSettingsLocked().deleteSettingLocked("wifi_wakeup_available");
3538                    currentVersion = 153;
3539                }
3540
3541                if (currentVersion == 153) {
3542                    // Version 154: Read notification badge configuration from config.
3543                    // If user has already set the value, don't do anything.
3544                    final SettingsState systemSecureSettings = getSecureSettingsLocked(userId);
3545                    final Setting showNotificationBadges = systemSecureSettings.getSettingLocked(
3546                            Settings.Secure.NOTIFICATION_BADGING);
3547                    if (showNotificationBadges.isNull()) {
3548                        final boolean defaultValue = getContext().getResources().getBoolean(
3549                                com.android.internal.R.bool.config_notificationBadging);
3550                        systemSecureSettings.insertSettingLocked(
3551                                Secure.NOTIFICATION_BADGING,
3552                                defaultValue ? "1" : "0",
3553                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3554                    }
3555                    currentVersion = 154;
3556                }
3557
3558                if (currentVersion == 154) {
3559                    // Version 155: Set the default value for BACKUP_LOCAL_TRANSPORT_PARAMETERS.
3560                    final SettingsState systemSecureSettings = getSecureSettingsLocked(userId);
3561                    final String oldValue = systemSecureSettings.getSettingLocked(
3562                            Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS).getValue();
3563                    if (TextUtils.equals(null, oldValue)) {
3564                        final String defaultValue = getContext().getResources().getString(
3565                                R.string.def_backup_local_transport_parameters);
3566                        if (!TextUtils.isEmpty(defaultValue)) {
3567                            systemSecureSettings.insertSettingLocked(
3568                                    Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS, defaultValue,
3569                                    null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3570                        }
3571
3572                    }
3573                    currentVersion = 155;
3574                }
3575
3576                if (currentVersion == 155) {
3577                    // Version 156: Set the default value for CHARGING_STARTED_SOUND.
3578                    final SettingsState globalSettings = getGlobalSettingsLocked();
3579                    final String oldValue = globalSettings.getSettingLocked(
3580                            Global.CHARGING_STARTED_SOUND).getValue();
3581                    final String oldDefault = getContext().getResources().getString(
3582                            R.string.def_wireless_charging_started_sound);
3583                    if (TextUtils.equals(null, oldValue)
3584                            || TextUtils.equals(oldValue, oldDefault)) {
3585                        final String defaultValue = getContext().getResources().getString(
3586                                R.string.def_charging_started_sound);
3587                        if (!TextUtils.isEmpty(defaultValue)) {
3588                            globalSettings.insertSettingLocked(
3589                                    Settings.Global.CHARGING_STARTED_SOUND, defaultValue,
3590                                    null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3591                        }
3592
3593                    }
3594                    currentVersion = 156;
3595                }
3596
3597                if (currentVersion == 156) {
3598                    // Version 157: Set a default value for zen duration
3599                    final SettingsState globalSettings = getGlobalSettingsLocked();
3600                    final Setting currentSetting = globalSettings.getSettingLocked(
3601                            Global.ZEN_DURATION);
3602                    if (currentSetting.isNull()) {
3603                        String defaultZenDuration = Integer.toString(getContext()
3604                                .getResources().getInteger(R.integer.def_zen_duration));
3605                        globalSettings.insertSettingLocked(
3606                                Global.ZEN_DURATION, defaultZenDuration,
3607                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3608                    }
3609                    currentVersion = 157;
3610                }
3611
3612                if (currentVersion == 157) {
3613                    // Version 158: Set default value for BACKUP_AGENT_TIMEOUT_PARAMETERS.
3614                    final SettingsState globalSettings = getGlobalSettingsLocked();
3615                    final String oldValue = globalSettings.getSettingLocked(
3616                            Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS).getValue();
3617                    if (TextUtils.equals(null, oldValue)) {
3618                        final String defaultValue = getContext().getResources().getString(
3619                                R.string.def_backup_agent_timeout_parameters);
3620                        if (!TextUtils.isEmpty(defaultValue)) {
3621                            globalSettings.insertSettingLocked(
3622                                    Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS, defaultValue,
3623                                    null, true,
3624                                    SettingsState.SYSTEM_PACKAGE_NAME);
3625                        }
3626                    }
3627                    currentVersion = 158;
3628                }
3629
3630                if (currentVersion == 158) {
3631                    // Remove setting that specifies wifi bgscan throttling params
3632                    getGlobalSettingsLocked().deleteSettingLocked(
3633                        "wifi_scan_background_throttle_interval_ms");
3634                    getGlobalSettingsLocked().deleteSettingLocked(
3635                        "wifi_scan_background_throttle_package_whitelist");
3636                    currentVersion = 159;
3637                }
3638
3639                if (currentVersion == 159) {
3640                    // Version 160: Hiding notifications from the lockscreen is only available as
3641                    // primary user option, profiles can only make them redacted. If a profile was
3642                    // configured to not show lockscreen notifications, ensure that at the very
3643                    // least these will be come hidden.
3644                    if (mUserManager.isManagedProfile(userId)) {
3645                        final SettingsState secureSettings = getSecureSettingsLocked(userId);
3646                        Setting showNotifications = secureSettings.getSettingLocked(
3647                            Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS);
3648                        // The default value is "1", check if user has turned it off.
3649                        if ("0".equals(showNotifications.getValue())) {
3650                            secureSettings.insertSettingLocked(
3651                                Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, "0",
3652                                null /* tag */, false /* makeDefault */,
3653                                SettingsState.SYSTEM_PACKAGE_NAME);
3654                        }
3655                        // The setting is no longer valid for managed profiles, it should be
3656                        // treated as if it was set to "1".
3657                        secureSettings.deleteSettingLocked(Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS);
3658                    }
3659                    currentVersion = 160;
3660                }
3661
3662                if (currentVersion == 160) {
3663                    // Version 161: Set the default value for
3664                    // MAX_SOUND_TRIGGER_DETECTION_SERVICE_OPS_PER_DAY and
3665                    // SOUND_TRIGGER_DETECTION_SERVICE_OP_TIMEOUT
3666                    final SettingsState globalSettings = getGlobalSettingsLocked();
3667
3668                    String oldValue = globalSettings.getSettingLocked(
3669                            Global.MAX_SOUND_TRIGGER_DETECTION_SERVICE_OPS_PER_DAY).getValue();
3670                    if (TextUtils.equals(null, oldValue)) {
3671                        globalSettings.insertSettingLocked(
3672                                Settings.Global.MAX_SOUND_TRIGGER_DETECTION_SERVICE_OPS_PER_DAY,
3673                                Integer.toString(getContext().getResources().getInteger(
3674                                        R.integer.def_max_sound_trigger_detection_service_ops_per_day)),
3675                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3676                    }
3677
3678                    oldValue = globalSettings.getSettingLocked(
3679                            Global.SOUND_TRIGGER_DETECTION_SERVICE_OP_TIMEOUT).getValue();
3680                    if (TextUtils.equals(null, oldValue)) {
3681                        globalSettings.insertSettingLocked(
3682                                Settings.Global.SOUND_TRIGGER_DETECTION_SERVICE_OP_TIMEOUT,
3683                                Integer.toString(getContext().getResources().getInteger(
3684                                        R.integer.def_sound_trigger_detection_service_op_timeout)),
3685                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3686                    }
3687                    currentVersion = 161;
3688                }
3689
3690                if (currentVersion == 161) {
3691                    // Version 161: Add a gesture for silencing phones
3692                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
3693                    final Setting currentSetting = secureSettings.getSettingLocked(
3694                            Secure.VOLUME_HUSH_GESTURE);
3695                    if (currentSetting.isNull()) {
3696                        secureSettings.insertSettingLocked(
3697                                Secure.VOLUME_HUSH_GESTURE,
3698                                Integer.toString(Secure.VOLUME_HUSH_VIBRATE),
3699                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3700                    }
3701
3702                    currentVersion = 162;
3703                }
3704
3705                if (currentVersion == 162) {
3706                    // Version 162: REMOVED: Add a gesture for silencing phones
3707                    currentVersion = 163;
3708                }
3709
3710                if (currentVersion == 163) {
3711                    // Version 163: Update default value of
3712                    // MAX_SOUND_TRIGGER_DETECTION_SERVICE_OPS_PER_DAY from old to new default
3713                    final SettingsState settings = getGlobalSettingsLocked();
3714                    final Setting currentSetting = settings.getSettingLocked(
3715                            Global.MAX_SOUND_TRIGGER_DETECTION_SERVICE_OPS_PER_DAY);
3716                    if (currentSetting.isDefaultFromSystem()) {
3717                        settings.insertSettingLocked(
3718                                Settings.Global.MAX_SOUND_TRIGGER_DETECTION_SERVICE_OPS_PER_DAY,
3719                                Integer.toString(getContext().getResources().getInteger(
3720                                        R.integer
3721                                        .def_max_sound_trigger_detection_service_ops_per_day)),
3722                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3723                    }
3724
3725                    currentVersion = 164;
3726                }
3727
3728                if (currentVersion == 164) {
3729                    // Version 164: show zen upgrade notification
3730                    final SettingsState settings = getGlobalSettingsLocked();
3731                    final Setting currentSetting = settings.getSettingLocked(
3732                            Global.SHOW_ZEN_UPGRADE_NOTIFICATION);
3733                    if (!currentSetting.isNull()
3734                            && TextUtils.equals("0", currentSetting.getValue())) {
3735                        settings.insertSettingLocked(
3736                                Global.SHOW_ZEN_UPGRADE_NOTIFICATION, "1",
3737                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3738                    }
3739
3740                    currentVersion = 165;
3741                }
3742
3743                if (currentVersion == 165) {
3744                    // Version 165: Show zen settings suggestion and zen updated
3745                    final SettingsState settings = getGlobalSettingsLocked();
3746                    final Setting currentSetting = settings.getSettingLocked(
3747                            Global.SHOW_ZEN_SETTINGS_SUGGESTION);
3748                    if (currentSetting.isNull()) {
3749                        settings.insertSettingLocked(
3750                                Global.SHOW_ZEN_SETTINGS_SUGGESTION, "1",
3751                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3752                    }
3753
3754                    final Setting currentUpdatedSetting = settings.getSettingLocked(
3755                            Global.ZEN_SETTINGS_UPDATED);
3756                    if (currentUpdatedSetting.isNull()) {
3757                        settings.insertSettingLocked(
3758                                Global.ZEN_SETTINGS_UPDATED, "0",
3759                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3760                    }
3761
3762                    final Setting currentSettingSuggestionViewed = settings.getSettingLocked(
3763                            Global.ZEN_SETTINGS_SUGGESTION_VIEWED);
3764                    if (currentSettingSuggestionViewed.isNull()) {
3765                        settings.insertSettingLocked(
3766                                Global.ZEN_SETTINGS_SUGGESTION_VIEWED, "0",
3767                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3768                    }
3769
3770                    currentVersion = 166;
3771                }
3772
3773                if (currentVersion == 166) {
3774                    // Version 166: add default values for hush gesture used and manual ringer
3775                    // toggle
3776                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
3777                    Setting currentHushUsedSetting = secureSettings.getSettingLocked(
3778                            Secure.HUSH_GESTURE_USED);
3779                    if (currentHushUsedSetting.isNull()) {
3780                        secureSettings.insertSettingLocked(
3781                                Settings.Secure.HUSH_GESTURE_USED, "0", null, true,
3782                                SettingsState.SYSTEM_PACKAGE_NAME);
3783                    }
3784
3785                    Setting currentRingerToggleCountSetting = secureSettings.getSettingLocked(
3786                            Secure.MANUAL_RINGER_TOGGLE_COUNT);
3787                    if (currentRingerToggleCountSetting.isNull()) {
3788                        secureSettings.insertSettingLocked(
3789                                Settings.Secure.MANUAL_RINGER_TOGGLE_COUNT, "0", null, true,
3790                                SettingsState.SYSTEM_PACKAGE_NAME);
3791                    }
3792                    currentVersion = 167;
3793                }
3794
3795                if (currentVersion == 167) {
3796                    // Version 167: by default, vibrate for wireless charging
3797                    final SettingsState globalSettings = getGlobalSettingsLocked();
3798                    final Setting currentSetting = globalSettings.getSettingLocked(
3799                            Global.CHARGING_VIBRATION_ENABLED);
3800                    if (currentSetting.isNull()) {
3801                        globalSettings.insertSettingLocked(
3802                                Global.CHARGING_VIBRATION_ENABLED, "1",
3803                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3804                    }
3805                    currentVersion = 168;
3806                }
3807
3808                if (currentVersion == 168) {
3809                    // Version 168: by default, vibrate for phone calls
3810                    final SettingsState systemSettings = getSystemSettingsLocked(userId);
3811                    final Setting currentSetting = systemSettings.getSettingLocked(
3812                            Settings.System.VIBRATE_WHEN_RINGING);
3813                    if (currentSetting.isNull()) {
3814                        systemSettings.insertSettingLocked(
3815                                Settings.System.VIBRATE_WHEN_RINGING,
3816                                getContext().getResources().getBoolean(
3817                                        R.bool.def_vibrate_when_ringing) ? "1" : "0",
3818                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
3819                    }
3820                    currentVersion = 169;
3821                }
3822
3823                // vXXX: Add new settings above this point.
3824
3825                if (currentVersion != newVersion) {
3826                    Slog.wtf("SettingsProvider", "warning: upgrading settings database to version "
3827                            + newVersion + " left it at "
3828                            + currentVersion +
3829                            " instead; this is probably a bug. Did you update SETTINGS_VERSION?",
3830                            new Throwable());
3831                    if (DEBUG) {
3832                        throw new RuntimeException("db upgrade error");
3833                    }
3834                }
3835
3836                // Return the current version.
3837                return currentVersion;
3838            }
3839        }
3840
3841        private void ensureLegacyDefaultValueAndSystemSetUpdatedLocked(SettingsState settings,
3842                int userId) {
3843            List<String> names = settings.getSettingNamesLocked();
3844            final int nameCount = names.size();
3845            for (int i = 0; i < nameCount; i++) {
3846                String name = names.get(i);
3847                Setting setting = settings.getSettingLocked(name);
3848
3849                // In the upgrade case we pretend the call is made from the app
3850                // that made the last change to the setting to properly determine
3851                // whether the call has been made by a system component.
3852                int callingUid = -1;
3853                try {
3854                    callingUid = mPackageManager.getPackageUid(setting.getPackageName(), 0, userId);
3855                } catch (RemoteException e) {
3856                    /* ignore - handled below */
3857                }
3858                if (callingUid < 0) {
3859                    Slog.e(LOG_TAG, "Unknown package: " + setting.getPackageName());
3860                    continue;
3861                }
3862                try {
3863                    final boolean systemSet = SettingsState.isSystemPackage(getContext(),
3864                            setting.getPackageName(), callingUid);
3865                    if (systemSet) {
3866                        settings.insertSettingLocked(name, setting.getValue(),
3867                                setting.getTag(), true, setting.getPackageName());
3868                    } else if (setting.getDefaultValue() != null && setting.isDefaultFromSystem()) {
3869                        // We had a bug where changes by non-system packages were marked
3870                        // as system made and as a result set as the default. Therefore, if
3871                        // the package changed the setting last is not a system one but the
3872                        // setting is marked as its default coming from the system we clear
3873                        // the default and clear the system set flag.
3874                        settings.resetSettingDefaultValueLocked(name);
3875                    }
3876                } catch (IllegalStateException e) {
3877                    // If the package goes over its quota during the upgrade, don't
3878                    // crash but just log the error as the system does the upgrade.
3879                    Slog.e(LOG_TAG, "Error upgrading setting: " + setting.getName(), e);
3880
3881                }
3882            }
3883        }
3884    }
3885}
3886