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