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