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