SettingsProvider.java revision 310e1eeb352e6e65e83a108c66bbea9f441ba58d
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 (!isKeyValid(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 (!isKeyValid(args.name)) { 410 return 0; 411 } 412 413 switch (args.table) { 414 case TABLE_GLOBAL: { 415 final int userId = UserHandle.getCallingUserId(); 416 return deleteGlobalSetting(args.name, userId) ? 1 : 0; 417 } 418 419 case TABLE_SECURE: { 420 final int userId = UserHandle.getCallingUserId(); 421 return deleteSecureSetting(args.name, userId) ? 1 : 0; 422 } 423 424 case TABLE_SYSTEM: { 425 final int userId = UserHandle.getCallingUserId(); 426 return deleteSystemSetting(args.name, userId) ? 1 : 0; 427 } 428 429 default: { 430 throw new IllegalArgumentException("Bad Uri path:" + uri); 431 } 432 } 433 } 434 435 @Override 436 public int update(Uri uri, ContentValues values, String where, String[] whereArgs) { 437 if (DEBUG) { 438 Slog.v(LOG_TAG, "update() for user: " + UserHandle.getCallingUserId()); 439 } 440 441 Arguments args = new Arguments(uri, where, whereArgs, false); 442 443 // If a legacy table that is gone, done. 444 if (REMOVED_LEGACY_TABLES.contains(args.table)) { 445 return 0; 446 } 447 448 String name = values.getAsString(Settings.Secure.NAME); 449 if (!isKeyValid(name)) { 450 return 0; 451 } 452 String value = values.getAsString(Settings.Secure.VALUE); 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(toDumpString(cursor.getString(idColumnIdx))); 529 pw.append(" name:").append(toDumpString(cursor.getString(nameColumnIdx))); 530 pw.append(" value:").append(toDumpString(cursor.getString(valueColumnIdx))); 531 pw.println(); 532 } while (cursor.moveToNext()); 533 } 534 535 private static final String toDumpString(String s) { 536 if (s != null) { 537 return s; 538 } 539 return "{null}"; 540 } 541 542 private void registerBroadcastReceivers() { 543 IntentFilter userFilter = new IntentFilter(); 544 userFilter.addAction(Intent.ACTION_USER_REMOVED); 545 userFilter.addAction(Intent.ACTION_USER_STOPPED); 546 547 getContext().registerReceiver(new BroadcastReceiver() { 548 @Override 549 public void onReceive(Context context, Intent intent) { 550 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 551 UserHandle.USER_OWNER); 552 553 switch (intent.getAction()) { 554 case Intent.ACTION_USER_REMOVED: { 555 mSettingsRegistry.removeUserStateLocked(userId, true); 556 } break; 557 558 case Intent.ACTION_USER_STOPPED: { 559 mSettingsRegistry.removeUserStateLocked(userId, false); 560 } break; 561 } 562 } 563 }, userFilter); 564 565 PackageMonitor monitor = new PackageMonitor() { 566 @Override 567 public void onPackageRemoved(String packageName, int uid) { 568 synchronized (mLock) { 569 mSettingsRegistry.onPackageRemovedLocked(packageName, 570 UserHandle.getUserId(uid)); 571 } 572 } 573 }; 574 575 // package changes 576 monitor.register(getContext(), BackgroundThread.getHandler().getLooper(), 577 UserHandle.ALL, true); 578 } 579 580 private Cursor getAllGlobalSettings(String[] projection) { 581 if (DEBUG) { 582 Slog.v(LOG_TAG, "getAllGlobalSettings()"); 583 } 584 585 synchronized (mLock) { 586 // Get the settings. 587 SettingsState settingsState = mSettingsRegistry.getSettingsLocked( 588 SettingsRegistry.SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER); 589 590 List<String> names = settingsState.getSettingNamesLocked(); 591 592 final int nameCount = names.size(); 593 594 String[] normalizedProjection = normalizeProjection(projection); 595 MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount); 596 597 // Anyone can get the global settings, so no security checks. 598 for (int i = 0; i < nameCount; i++) { 599 String name = names.get(i); 600 Setting setting = settingsState.getSettingLocked(name); 601 appendSettingToCursor(result, setting); 602 } 603 604 return result; 605 } 606 } 607 608 private Setting getGlobalSetting(String name) { 609 if (DEBUG) { 610 Slog.v(LOG_TAG, "getGlobalSetting(" + name + ")"); 611 } 612 613 // Get the value. 614 synchronized (mLock) { 615 return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL, 616 UserHandle.USER_OWNER, name); 617 } 618 } 619 620 private boolean updateGlobalSetting(String name, String value, int requestingUserId) { 621 if (DEBUG) { 622 Slog.v(LOG_TAG, "updateGlobalSetting(" + name + ", " + value + ")"); 623 } 624 return mutateGlobalSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE); 625 } 626 627 private boolean insertGlobalSetting(String name, String value, int requestingUserId) { 628 if (DEBUG) { 629 Slog.v(LOG_TAG, "insertGlobalSetting(" + name + ", " + value + ")"); 630 } 631 return mutateGlobalSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT); 632 } 633 634 private boolean deleteGlobalSetting(String name, int requestingUserId) { 635 if (DEBUG) { 636 Slog.v(LOG_TAG, "deleteGlobalSettingLocked(" + name + ")"); 637 } 638 return mutateGlobalSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE); 639 } 640 641 private boolean mutateGlobalSetting(String name, String value, int requestingUserId, 642 int operation) { 643 // Make sure the caller can change the settings - treated as secure. 644 enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS); 645 646 // Verify whether this operation is allowed for the calling package. 647 if (!isAppOpWriteSettingsAllowedForCallingPackage()) { 648 return false; 649 } 650 651 // Resolve the userId on whose behalf the call is made. 652 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); 653 654 // If this is a setting that is currently restricted for this user, done. 655 if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId)) { 656 return false; 657 } 658 659 // Perform the mutation. 660 synchronized (mLock) { 661 switch (operation) { 662 case MUTATION_OPERATION_INSERT: { 663 return mSettingsRegistry 664 .insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL, 665 UserHandle.USER_OWNER, name, value, getCallingPackage()); 666 } 667 668 case MUTATION_OPERATION_DELETE: { 669 return mSettingsRegistry.deleteSettingLocked( 670 SettingsRegistry.SETTINGS_TYPE_GLOBAL, 671 UserHandle.USER_OWNER, name); 672 } 673 674 case MUTATION_OPERATION_UPDATE: { 675 return mSettingsRegistry 676 .updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL, 677 UserHandle.USER_OWNER, name, value, getCallingPackage()); 678 } 679 } 680 } 681 682 return false; 683 } 684 685 private Cursor getAllSecureSettings(int userId, String[] projection) { 686 if (DEBUG) { 687 Slog.v(LOG_TAG, "getAllSecureSettings(" + userId + ")"); 688 } 689 690 // Resolve the userId on whose behalf the call is made. 691 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId); 692 693 synchronized (mLock) { 694 List<String> names = mSettingsRegistry.getSettingsNamesLocked( 695 SettingsRegistry.SETTINGS_TYPE_SECURE, callingUserId); 696 697 final int nameCount = names.size(); 698 699 String[] normalizedProjection = normalizeProjection(projection); 700 MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount); 701 702 for (int i = 0; i < nameCount; i++) { 703 String name = names.get(i); 704 // Determine the owning user as some profile settings are cloned from the parent. 705 final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, 706 name); 707 708 // Special case for location (sigh). 709 if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) { 710 return null; 711 } 712 713 Setting setting = mSettingsRegistry.getSettingLocked( 714 SettingsRegistry.SETTINGS_TYPE_SECURE, owningUserId, name); 715 appendSettingToCursor(result, setting); 716 } 717 718 return result; 719 } 720 } 721 722 private Setting getSecureSetting(String name, int requestingUserId) { 723 if (DEBUG) { 724 Slog.v(LOG_TAG, "getSecureSetting(" + name + ", " + requestingUserId + ")"); 725 } 726 727 // Resolve the userId on whose behalf the call is made. 728 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); 729 730 // Determine the owning user as some profile settings are cloned from the parent. 731 final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name); 732 733 // Special case for location (sigh). 734 if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) { 735 return null; 736 } 737 738 // Get the value. 739 synchronized (mLock) { 740 return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE, 741 owningUserId, name); 742 } 743 } 744 745 private boolean insertSecureSetting(String name, String value, int requestingUserId) { 746 if (DEBUG) { 747 Slog.v(LOG_TAG, "insertSecureSetting(" + name + ", " + value + ", " 748 + requestingUserId + ")"); 749 } 750 751 return mutateSecureSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT); 752 } 753 754 private boolean deleteSecureSetting(String name, int requestingUserId) { 755 if (DEBUG) { 756 Slog.v(LOG_TAG, "deleteSecureSetting(" + name + ", " + requestingUserId + ")"); 757 } 758 759 return mutateSecureSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE); 760 } 761 762 private boolean updateSecureSetting(String name, String value, int requestingUserId) { 763 if (DEBUG) { 764 Slog.v(LOG_TAG, "updateSecureSetting(" + name + ", " + value + ", " 765 + requestingUserId + ")"); 766 } 767 768 return mutateSecureSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE); 769 } 770 771 private boolean mutateSecureSetting(String name, String value, int requestingUserId, 772 int operation) { 773 // Make sure the caller can change the settings. 774 enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS); 775 776 // Verify whether this operation is allowed for the calling package. 777 if (!isAppOpWriteSettingsAllowedForCallingPackage()) { 778 return false; 779 } 780 781 // Resolve the userId on whose behalf the call is made. 782 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); 783 784 // If this is a setting that is currently restricted for this user, done. 785 if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId)) { 786 return false; 787 } 788 789 // Determine the owning user as some profile settings are cloned from the parent. 790 final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name); 791 792 // Only the owning user can change the setting. 793 if (owningUserId != callingUserId) { 794 return false; 795 } 796 797 // Special cases for location providers (sigh). 798 if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) { 799 return updateLocationProvidersAllowedLocked(value, owningUserId); 800 } 801 802 // Mutate the value. 803 synchronized (mLock) { 804 switch (operation) { 805 case MUTATION_OPERATION_INSERT: { 806 return mSettingsRegistry 807 .insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE, 808 owningUserId, name, value, getCallingPackage()); 809 } 810 811 case MUTATION_OPERATION_DELETE: { 812 return mSettingsRegistry.deleteSettingLocked( 813 SettingsRegistry.SETTINGS_TYPE_SECURE, 814 owningUserId, name); 815 } 816 817 case MUTATION_OPERATION_UPDATE: { 818 return mSettingsRegistry 819 .updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE, 820 owningUserId, name, value, getCallingPackage()); 821 } 822 } 823 } 824 825 return false; 826 } 827 828 private Cursor getAllSystemSettings(int userId, String[] projection) { 829 if (DEBUG) { 830 Slog.v(LOG_TAG, "getAllSecureSystem(" + userId + ")"); 831 } 832 833 // Resolve the userId on whose behalf the call is made. 834 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId); 835 836 synchronized (mLock) { 837 List<String> names = mSettingsRegistry.getSettingsNamesLocked( 838 SettingsRegistry.SETTINGS_TYPE_SYSTEM, callingUserId); 839 840 final int nameCount = names.size(); 841 842 String[] normalizedProjection = normalizeProjection(projection); 843 MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount); 844 845 for (int i = 0; i < nameCount; i++) { 846 String name = names.get(i); 847 848 // Determine the owning user as some profile settings are cloned from the parent. 849 final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, 850 name); 851 852 Setting setting = mSettingsRegistry.getSettingLocked( 853 SettingsRegistry.SETTINGS_TYPE_SYSTEM, owningUserId, name); 854 appendSettingToCursor(result, setting); 855 } 856 857 return result; 858 } 859 } 860 861 private Setting getSystemSetting(String name, int requestingUserId) { 862 if (DEBUG) { 863 Slog.v(LOG_TAG, "getSystemSetting(" + name + ", " + requestingUserId + ")"); 864 } 865 866 // Resolve the userId on whose behalf the call is made. 867 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); 868 869 // Determine the owning user as some profile settings are cloned from the parent. 870 final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name); 871 872 // Get the value. 873 synchronized (mLock) { 874 return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM, 875 owningUserId, name); 876 } 877 } 878 879 private boolean insertSystemSetting(String name, String value, int requestingUserId) { 880 if (DEBUG) { 881 Slog.v(LOG_TAG, "insertSystemSetting(" + name + ", " + value + ", " 882 + requestingUserId + ")"); 883 } 884 885 return mutateSystemSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT); 886 } 887 888 private boolean deleteSystemSetting(String name, int requestingUserId) { 889 if (DEBUG) { 890 Slog.v(LOG_TAG, "deleteSystemSetting(" + name + ", " + requestingUserId + ")"); 891 } 892 893 return mutateSystemSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE); 894 } 895 896 private boolean updateSystemSetting(String name, String value, int requestingUserId) { 897 if (DEBUG) { 898 Slog.v(LOG_TAG, "updateSystemSetting(" + name + ", " + value + ", " 899 + requestingUserId + ")"); 900 } 901 902 return mutateSystemSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE); 903 } 904 905 private boolean mutateSystemSetting(String name, String value, int runAsUserId, 906 int operation) { 907 // Check for permissions first. 908 if (!hasPermissionsToMutateSystemSettings()) { 909 return false; 910 } 911 912 // Verify whether this operation is allowed for the calling package. 913 if (!isAppOpWriteSettingsAllowedForCallingPackage()) { 914 return false; 915 } 916 917 // Enforce what the calling package can mutate the system settings. 918 enforceRestrictedSystemSettingsMutationForCallingPackage(operation, name); 919 920 // Resolve the userId on whose behalf the call is made. 921 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(runAsUserId); 922 923 // Determine the owning user as some profile settings are cloned from the parent. 924 final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name); 925 926 // Only the owning user id can change the setting. 927 if (owningUserId != callingUserId) { 928 return false; 929 } 930 931 // Mutate the value. 932 synchronized (mLock) { 933 switch (operation) { 934 case MUTATION_OPERATION_INSERT: { 935 validateSystemSettingValue(name, value); 936 return mSettingsRegistry 937 .insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM, 938 owningUserId, name, value, getCallingPackage()); 939 } 940 941 case MUTATION_OPERATION_DELETE: { 942 return mSettingsRegistry.deleteSettingLocked( 943 SettingsRegistry.SETTINGS_TYPE_SYSTEM, 944 owningUserId, name); 945 } 946 947 case MUTATION_OPERATION_UPDATE: { 948 validateSystemSettingValue(name, value); 949 return mSettingsRegistry 950 .updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM, 951 owningUserId, name, value, getCallingPackage()); 952 } 953 } 954 955 return false; 956 } 957 } 958 959 private boolean hasPermissionsToMutateSystemSettings() { 960 // Write secure settings is a more protected permission. If caller has it we are good. 961 if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS) 962 == PackageManager.PERMISSION_GRANTED) { 963 return true; 964 } 965 966 // The write settings permission gates mutation of system settings. 967 if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SETTINGS) 968 == PackageManager.PERMISSION_GRANTED) { 969 return true; 970 } 971 972 // Excpet we let system apps change system settings without the permission. 973 PackageInfo packageInfo = getCallingPackageInfoOrThrow(); 974 if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { 975 return true; 976 } 977 978 return false; 979 } 980 981 private void validateSystemSettingValue(String name, String value) { 982 Settings.System.Validator validator = Settings.System.VALIDATORS.get(name); 983 if (validator != null && !validator.validate(value)) { 984 throw new IllegalArgumentException("Invalid value: " + value 985 + " for setting: " + name); 986 } 987 } 988 989 private boolean isLocationProvidersAllowedRestricted(String name, int callingUserId, 990 int owningUserId) { 991 // Optimization - location providers are restricted only for managed profiles. 992 if (callingUserId == owningUserId) { 993 return false; 994 } 995 if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name) 996 && mUserManager.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, 997 new UserHandle(callingUserId))) { 998 return true; 999 } 1000 return false; 1001 } 1002 1003 private boolean isGlobalOrSecureSettingRestrictedForUser(String setting, int userId) { 1004 String restriction = sSettingToUserRestrictionMap.get(setting); 1005 if (restriction == null) { 1006 return false; 1007 } 1008 return mUserManager.hasUserRestriction(restriction, new UserHandle(userId)); 1009 } 1010 1011 private int resolveOwningUserIdForSecureSettingLocked(int userId, String setting) { 1012 return resolveOwningUserIdLocked(userId, sSecureCloneToManagedSettings, setting); 1013 } 1014 1015 private int resolveOwningUserIdForSystemSettingLocked(int userId, String setting) { 1016 return resolveOwningUserIdLocked(userId, sSystemCloneToManagedSettings, setting); 1017 } 1018 1019 private int resolveOwningUserIdLocked(int userId, Set<String> keys, String name) { 1020 final int parentId = getGroupParentLocked(userId); 1021 if (parentId != userId && keys.contains(name)) { 1022 return parentId; 1023 } 1024 return userId; 1025 } 1026 1027 private void enforceRestrictedSystemSettingsMutationForCallingPackage(int operation, 1028 String name) { 1029 // System/root/shell can mutate whatever secure settings they want. 1030 final int callingUid = Binder.getCallingUid(); 1031 if (callingUid == android.os.Process.SYSTEM_UID 1032 || callingUid == Process.SHELL_UID 1033 || callingUid == Process.ROOT_UID) { 1034 return; 1035 } 1036 1037 switch (operation) { 1038 case MUTATION_OPERATION_INSERT: 1039 // Insert updates. 1040 case MUTATION_OPERATION_UPDATE: { 1041 if (Settings.System.PUBLIC_SETTINGS.contains(name)) { 1042 return; 1043 } 1044 1045 // The calling package is already verified. 1046 PackageInfo packageInfo = getCallingPackageInfoOrThrow(); 1047 1048 // Privileged apps can do whatever they want. 1049 if ((packageInfo.applicationInfo.privateFlags 1050 & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) { 1051 return; 1052 } 1053 1054 warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk( 1055 packageInfo.applicationInfo.targetSdkVersion, name); 1056 } break; 1057 1058 case MUTATION_OPERATION_DELETE: { 1059 if (Settings.System.PUBLIC_SETTINGS.contains(name) 1060 || Settings.System.PRIVATE_SETTINGS.contains(name)) { 1061 throw new IllegalArgumentException("You cannot delete system defined" 1062 + " secure settings."); 1063 } 1064 1065 // The calling package is already verified. 1066 PackageInfo packageInfo = getCallingPackageInfoOrThrow(); 1067 1068 // Privileged apps can do whatever they want. 1069 if ((packageInfo.applicationInfo.privateFlags & 1070 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) { 1071 return; 1072 } 1073 1074 warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk( 1075 packageInfo.applicationInfo.targetSdkVersion, name); 1076 } break; 1077 } 1078 } 1079 1080 private PackageInfo getCallingPackageInfoOrThrow() { 1081 try { 1082 return mPackageManager.getPackageInfo(getCallingPackage(), 0); 1083 } catch (PackageManager.NameNotFoundException e) { 1084 throw new IllegalStateException("Calling package doesn't exist"); 1085 } 1086 } 1087 1088 private int getGroupParentLocked(int userId) { 1089 // Most frequent use case. 1090 if (userId == UserHandle.USER_OWNER) { 1091 return userId; 1092 } 1093 // We are in the same process with the user manager and the returned 1094 // user info is a cached instance, so just look up instead of cache. 1095 final long identity = Binder.clearCallingIdentity(); 1096 try { 1097 // Just a lookup and not reentrant, so holding a lock is fine. 1098 UserInfo userInfo = mUserManager.getProfileParent(userId); 1099 return (userInfo != null) ? userInfo.id : userId; 1100 } finally { 1101 Binder.restoreCallingIdentity(identity); 1102 } 1103 } 1104 1105 private boolean isAppOpWriteSettingsAllowedForCallingPackage() { 1106 final int callingUid = Binder.getCallingUid(); 1107 1108 mAppOpsManager.checkPackage(Binder.getCallingUid(), getCallingPackage()); 1109 1110 return mAppOpsManager.noteOp(AppOpsManager.OP_WRITE_SETTINGS, callingUid, 1111 getCallingPackage()) == AppOpsManager.MODE_ALLOWED; 1112 } 1113 1114 private void enforceWritePermission(String permission) { 1115 if (getContext().checkCallingOrSelfPermission(permission) 1116 != PackageManager.PERMISSION_GRANTED) { 1117 throw new SecurityException("Permission denial: writing to settings requires:" 1118 + permission); 1119 } 1120 } 1121 1122 /* 1123 * Used to parse changes to the value of Settings.Secure.LOCATION_PROVIDERS_ALLOWED. 1124 * This setting contains a list of the currently enabled location providers. 1125 * But helper functions in android.providers.Settings can enable or disable 1126 * a single provider by using a "+" or "-" prefix before the provider name. 1127 * 1128 * @returns whether the enabled location providers changed. 1129 */ 1130 private boolean updateLocationProvidersAllowedLocked(String value, int owningUserId) { 1131 if (TextUtils.isEmpty(value)) { 1132 return false; 1133 } 1134 1135 final char prefix = value.charAt(0); 1136 if (prefix != '+' && prefix != '-') { 1137 return false; 1138 } 1139 1140 // skip prefix 1141 value = value.substring(1); 1142 1143 Setting settingValue = getSecureSetting( 1144 Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId); 1145 1146 String oldProviders = (settingValue != null) ? settingValue.getValue() : ""; 1147 1148 int index = oldProviders.indexOf(value); 1149 int end = index + value.length(); 1150 1151 // check for commas to avoid matching on partial string 1152 if (index > 0 && oldProviders.charAt(index - 1) != ',') { 1153 index = -1; 1154 } 1155 1156 // check for commas to avoid matching on partial string 1157 if (end < oldProviders.length() && oldProviders.charAt(end) != ',') { 1158 index = -1; 1159 } 1160 1161 String newProviders; 1162 1163 if (prefix == '+' && index < 0) { 1164 // append the provider to the list if not present 1165 if (oldProviders.length() == 0) { 1166 newProviders = value; 1167 } else { 1168 newProviders = oldProviders + ',' + value; 1169 } 1170 } else if (prefix == '-' && index >= 0) { 1171 // remove the provider from the list if present 1172 // remove leading or trailing comma 1173 if (index > 0) { 1174 index--; 1175 } else if (end < oldProviders.length()) { 1176 end++; 1177 } 1178 1179 newProviders = oldProviders.substring(0, index); 1180 if (end < oldProviders.length()) { 1181 newProviders += oldProviders.substring(end); 1182 } 1183 } else { 1184 // nothing changed, so no need to update the database 1185 return false; 1186 } 1187 1188 return mSettingsRegistry.insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE, 1189 owningUserId, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, newProviders, 1190 getCallingPackage()); 1191 } 1192 1193 private void sendNotify(Uri uri, int userId) { 1194 final long identity = Binder.clearCallingIdentity(); 1195 try { 1196 getContext().getContentResolver().notifyChange(uri, null, true, userId); 1197 if (DEBUG) { 1198 Slog.v(LOG_TAG, "Notifying for " + userId + ": " + uri); 1199 } 1200 } finally { 1201 Binder.restoreCallingIdentity(identity); 1202 } 1203 } 1204 1205 private static void warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk( 1206 int targetSdkVersion, String name) { 1207 // If the app targets Lollipop MR1 or older SDK we warn, otherwise crash. 1208 if (targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1) { 1209 if (Settings.System.PRIVATE_SETTINGS.contains(name)) { 1210 Slog.w(LOG_TAG, "You shouldn't not change private system settings." 1211 + " This will soon become an error."); 1212 } else { 1213 Slog.w(LOG_TAG, "You shouldn't keep your settings in the secure settings." 1214 + " This will soon become an error."); 1215 } 1216 } else { 1217 if (Settings.System.PRIVATE_SETTINGS.contains(name)) { 1218 throw new IllegalArgumentException("You cannot change private secure settings."); 1219 } else { 1220 throw new IllegalArgumentException("You cannot keep your settings in" 1221 + " the secure settings."); 1222 } 1223 } 1224 } 1225 1226 private static int resolveCallingUserIdEnforcingPermissionsLocked(int requestingUserId) { 1227 if (requestingUserId == UserHandle.getCallingUserId()) { 1228 return requestingUserId; 1229 } 1230 return ActivityManager.handleIncomingUser(Binder.getCallingPid(), 1231 Binder.getCallingUid(), requestingUserId, false, true, 1232 "get/set setting for user", null); 1233 } 1234 1235 private static Bundle packageValueForCallResult(Setting setting) { 1236 if (setting == null) { 1237 return NULL_SETTING; 1238 } 1239 return Bundle.forPair(Settings.NameValueTable.VALUE, setting.getValue()); 1240 } 1241 1242 private static int getRequestingUserId(Bundle args) { 1243 final int callingUserId = UserHandle.getCallingUserId(); 1244 return (args != null) ? args.getInt(Settings.CALL_METHOD_USER_KEY, callingUserId) 1245 : callingUserId; 1246 } 1247 1248 private static String getSettingValue(Bundle args) { 1249 return (args != null) ? args.getString(Settings.NameValueTable.VALUE) : null; 1250 } 1251 1252 private static String getValidTableOrThrow(Uri uri) { 1253 if (uri.getPathSegments().size() > 0) { 1254 String table = uri.getPathSegments().get(0); 1255 if (DatabaseHelper.isValidTable(table)) { 1256 return table; 1257 } 1258 throw new IllegalArgumentException("Bad root path: " + table); 1259 } 1260 throw new IllegalArgumentException("Invalid URI:" + uri); 1261 } 1262 1263 private static MatrixCursor packageSettingForQuery(Setting setting, String[] projection) { 1264 if (setting == null) { 1265 return new MatrixCursor(projection, 0); 1266 } 1267 MatrixCursor cursor = new MatrixCursor(projection, 1); 1268 appendSettingToCursor(cursor, setting); 1269 return cursor; 1270 } 1271 1272 private static String[] normalizeProjection(String[] projection) { 1273 if (projection == null) { 1274 return ALL_COLUMNS; 1275 } 1276 1277 final int columnCount = projection.length; 1278 for (int i = 0; i < columnCount; i++) { 1279 String column = projection[i]; 1280 if (!ArrayUtils.contains(ALL_COLUMNS, column)) { 1281 throw new IllegalArgumentException("Invalid column: " + column); 1282 } 1283 } 1284 1285 return projection; 1286 } 1287 1288 private static void appendSettingToCursor(MatrixCursor cursor, Setting setting) { 1289 final int columnCount = cursor.getColumnCount(); 1290 1291 String[] values = new String[columnCount]; 1292 1293 for (int i = 0; i < columnCount; i++) { 1294 String column = cursor.getColumnName(i); 1295 1296 switch (column) { 1297 case Settings.NameValueTable._ID: { 1298 values[i] = setting.getId(); 1299 } break; 1300 1301 case Settings.NameValueTable.NAME: { 1302 values[i] = setting.getName(); 1303 } break; 1304 1305 case Settings.NameValueTable.VALUE: { 1306 values[i] = setting.getValue(); 1307 } break; 1308 } 1309 } 1310 1311 cursor.addRow(values); 1312 } 1313 1314 private static boolean isKeyValid(String key) { 1315 return !(TextUtils.isEmpty(key) || SettingsState.isBinary(key)); 1316 } 1317 1318 private static final class Arguments { 1319 private static final Pattern WHERE_PATTERN_WITH_PARAM_NO_BRACKETS = 1320 Pattern.compile("[\\s]*name[\\s]*=[\\s]*\\?[\\s]*"); 1321 1322 private static final Pattern WHERE_PATTERN_WITH_PARAM_IN_BRACKETS = 1323 Pattern.compile("[\\s]*\\([\\s]*name[\\s]*=[\\s]*\\?[\\s]*\\)[\\s]*"); 1324 1325 private static final Pattern WHERE_PATTERN_NO_PARAM_IN_BRACKETS = 1326 Pattern.compile("[\\s]*\\([\\s]*name[\\s]*=[\\s]*['\"].*['\"][\\s]*\\)[\\s]*"); 1327 1328 private static final Pattern WHERE_PATTERN_NO_PARAM_NO_BRACKETS = 1329 Pattern.compile("[\\s]*name[\\s]*=[\\s]*['\"].*['\"][\\s]*"); 1330 1331 public final String table; 1332 public final String name; 1333 1334 public Arguments(Uri uri, String where, String[] whereArgs, boolean supportAll) { 1335 final int segmentSize = uri.getPathSegments().size(); 1336 switch (segmentSize) { 1337 case 1: { 1338 if (where != null 1339 && (WHERE_PATTERN_WITH_PARAM_NO_BRACKETS.matcher(where).matches() 1340 || WHERE_PATTERN_WITH_PARAM_IN_BRACKETS.matcher(where).matches()) 1341 && whereArgs.length == 1) { 1342 name = whereArgs[0]; 1343 table = computeTableForSetting(uri, name); 1344 return; 1345 } else if (where != null 1346 && (WHERE_PATTERN_NO_PARAM_NO_BRACKETS.matcher(where).matches() 1347 || WHERE_PATTERN_NO_PARAM_IN_BRACKETS.matcher(where).matches())) { 1348 final int startIndex = Math.max(where.indexOf("'"), 1349 where.indexOf("\"")) + 1; 1350 final int endIndex = Math.max(where.lastIndexOf("'"), 1351 where.lastIndexOf("\"")); 1352 name = where.substring(startIndex, endIndex); 1353 table = computeTableForSetting(uri, name); 1354 return; 1355 } else if (supportAll && where == null && whereArgs == null) { 1356 name = null; 1357 table = computeTableForSetting(uri, null); 1358 return; 1359 } 1360 } break; 1361 1362 case 2: { 1363 if (where == null && whereArgs == null) { 1364 name = uri.getPathSegments().get(1); 1365 table = computeTableForSetting(uri, name); 1366 return; 1367 } 1368 } break; 1369 } 1370 1371 EventLogTags.writeUnsupportedSettingsQuery( 1372 uri.toSafeString(), where, Arrays.toString(whereArgs)); 1373 String message = String.format( "Supported SQL:\n" 1374 + " uri content://some_table/some_property with null where and where args\n" 1375 + " uri content://some_table with query name=? and single name as arg\n" 1376 + " uri content://some_table with query name=some_name and null args\n" 1377 + " but got - uri:%1s, where:%2s whereArgs:%3s", uri, where, 1378 Arrays.toString(whereArgs)); 1379 throw new IllegalArgumentException(message); 1380 } 1381 1382 private static String computeTableForSetting(Uri uri, String name) { 1383 String table = getValidTableOrThrow(uri); 1384 1385 if (name != null) { 1386 if (sSystemMovedToSecureSettings.contains(name)) { 1387 table = TABLE_SECURE; 1388 } 1389 1390 if (sSystemMovedToGlobalSettings.contains(name)) { 1391 table = TABLE_GLOBAL; 1392 } 1393 1394 if (sSecureMovedToGlobalSettings.contains(name)) { 1395 table = TABLE_GLOBAL; 1396 } 1397 1398 if (sGlobalMovedToSecureSettings.contains(name)) { 1399 table = TABLE_SECURE; 1400 } 1401 } 1402 1403 return table; 1404 } 1405 } 1406 1407 final class SettingsRegistry { 1408 private static final String DROPBOX_TAG_USERLOG = "restricted_profile_ssaid"; 1409 1410 private static final int SETTINGS_TYPE_GLOBAL = 0; 1411 private static final int SETTINGS_TYPE_SYSTEM = 1; 1412 private static final int SETTINGS_TYPE_SECURE = 2; 1413 1414 private static final int SETTINGS_TYPE_MASK = 0xF0000000; 1415 private static final int SETTINGS_TYPE_SHIFT = 28; 1416 1417 private static final String SETTINGS_FILE_GLOBAL = "settings_global.xml"; 1418 private static final String SETTINGS_FILE_SYSTEM = "settings_system.xml"; 1419 private static final String SETTINGS_FILE_SECURE = "settings_secure.xml"; 1420 1421 private final SparseArray<SettingsState> mSettingsStates = new SparseArray<>(); 1422 1423 private final BackupManager mBackupManager; 1424 1425 public SettingsRegistry() { 1426 mBackupManager = new BackupManager(getContext()); 1427 migrateAllLegacySettingsIfNeeded(); 1428 } 1429 1430 public List<String> getSettingsNamesLocked(int type, int userId) { 1431 final int key = makeKey(type, userId); 1432 SettingsState settingsState = peekSettingsStateLocked(key); 1433 return settingsState.getSettingNamesLocked(); 1434 } 1435 1436 public SettingsState getSettingsLocked(int type, int userId) { 1437 final int key = makeKey(type, userId); 1438 return peekSettingsStateLocked(key); 1439 } 1440 1441 public void ensureSettingsForUserLocked(int userId) { 1442 // Migrate the setting for this user if needed. 1443 migrateLegacySettingsForUserIfNeededLocked(userId); 1444 1445 // Ensure global settings loaded if owner. 1446 if (userId == UserHandle.USER_OWNER) { 1447 final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER); 1448 ensureSettingsStateLocked(globalKey); 1449 } 1450 1451 // Ensure secure settings loaded. 1452 final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId); 1453 ensureSettingsStateLocked(secureKey); 1454 1455 // Make sure the secure settings have an Android id set. 1456 SettingsState secureSettings = getSettingsLocked(SETTINGS_TYPE_SECURE, userId); 1457 ensureSecureSettingAndroidIdSetLocked(secureSettings); 1458 1459 // Ensure system settings loaded. 1460 final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId); 1461 ensureSettingsStateLocked(systemKey); 1462 1463 // Upgrade the settings to the latest version. 1464 UpgradeController upgrader = new UpgradeController(userId); 1465 upgrader.upgradeIfNeededLocked(); 1466 } 1467 1468 private void ensureSettingsStateLocked(int key) { 1469 if (mSettingsStates.get(key) == null) { 1470 final int maxBytesPerPackage = getMaxBytesPerPackageForType(getTypeFromKey(key)); 1471 SettingsState settingsState = new SettingsState(mLock, getSettingsFile(key), key, 1472 maxBytesPerPackage); 1473 mSettingsStates.put(key, settingsState); 1474 } 1475 } 1476 1477 public void removeUserStateLocked(int userId, boolean permanently) { 1478 // We always keep the global settings in memory. 1479 1480 // Nuke system settings. 1481 final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId); 1482 final SettingsState systemSettingsState = mSettingsStates.get(systemKey); 1483 if (systemSettingsState != null) { 1484 if (permanently) { 1485 mSettingsStates.remove(systemKey); 1486 systemSettingsState.destroyLocked(null); 1487 } else { 1488 systemSettingsState.destroyLocked(new Runnable() { 1489 @Override 1490 public void run() { 1491 mSettingsStates.remove(systemKey); 1492 } 1493 }); 1494 } 1495 } 1496 1497 // Nuke secure settings. 1498 final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId); 1499 final SettingsState secureSettingsState = mSettingsStates.get(secureKey); 1500 if (secureSettingsState != null) { 1501 if (permanently) { 1502 mSettingsStates.remove(secureKey); 1503 secureSettingsState.destroyLocked(null); 1504 } else { 1505 secureSettingsState.destroyLocked(new Runnable() { 1506 @Override 1507 public void run() { 1508 mSettingsStates.remove(secureKey); 1509 } 1510 }); 1511 } 1512 } 1513 } 1514 1515 public boolean insertSettingLocked(int type, int userId, String name, String value, 1516 String packageName) { 1517 final int key = makeKey(type, userId); 1518 1519 SettingsState settingsState = peekSettingsStateLocked(key); 1520 final boolean success = settingsState.insertSettingLocked(name, value, packageName); 1521 1522 if (success) { 1523 notifyForSettingsChange(key, name); 1524 } 1525 return success; 1526 } 1527 1528 public boolean deleteSettingLocked(int type, int userId, String name) { 1529 final int key = makeKey(type, userId); 1530 1531 SettingsState settingsState = peekSettingsStateLocked(key); 1532 final boolean success = settingsState.deleteSettingLocked(name); 1533 1534 if (success) { 1535 notifyForSettingsChange(key, name); 1536 } 1537 return success; 1538 } 1539 1540 public Setting getSettingLocked(int type, int userId, String name) { 1541 final int key = makeKey(type, userId); 1542 1543 SettingsState settingsState = peekSettingsStateLocked(key); 1544 return settingsState.getSettingLocked(name); 1545 } 1546 1547 public boolean updateSettingLocked(int type, int userId, String name, String value, 1548 String packageName) { 1549 final int key = makeKey(type, userId); 1550 1551 SettingsState settingsState = peekSettingsStateLocked(key); 1552 final boolean success = settingsState.updateSettingLocked(name, value, packageName); 1553 1554 if (success) { 1555 notifyForSettingsChange(key, name); 1556 } 1557 1558 return success; 1559 } 1560 1561 public void onPackageRemovedLocked(String packageName, int userId) { 1562 // Global and secure settings are signature protected. Apps signed 1563 // by the platform certificate are generally not uninstalled and 1564 // the main exception is tests. We trust components signed 1565 // by the platform certificate and do not do a clean up after them. 1566 1567 final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId); 1568 SettingsState systemSettings = mSettingsStates.get(systemKey); 1569 if (systemSettings != null) { 1570 systemSettings.onPackageRemovedLocked(packageName); 1571 } 1572 } 1573 1574 private SettingsState peekSettingsStateLocked(int key) { 1575 SettingsState settingsState = mSettingsStates.get(key); 1576 if (settingsState != null) { 1577 return settingsState; 1578 } 1579 1580 ensureSettingsForUserLocked(getUserIdFromKey(key)); 1581 return mSettingsStates.get(key); 1582 } 1583 1584 private void migrateAllLegacySettingsIfNeeded() { 1585 synchronized (mLock) { 1586 final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER); 1587 File globalFile = getSettingsFile(key); 1588 if (globalFile.exists()) { 1589 return; 1590 } 1591 1592 final long identity = Binder.clearCallingIdentity(); 1593 try { 1594 List<UserInfo> users = mUserManager.getUsers(true); 1595 1596 final int userCount = users.size(); 1597 for (int i = 0; i < userCount; i++) { 1598 final int userId = users.get(i).id; 1599 1600 DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId); 1601 SQLiteDatabase database = dbHelper.getWritableDatabase(); 1602 migrateLegacySettingsForUserLocked(dbHelper, database, userId); 1603 1604 // Upgrade to the latest version. 1605 UpgradeController upgrader = new UpgradeController(userId); 1606 upgrader.upgradeIfNeededLocked(); 1607 1608 // Drop from memory if not a running user. 1609 if (!mUserManager.isUserRunning(new UserHandle(userId))) { 1610 removeUserStateLocked(userId, false); 1611 } 1612 } 1613 } finally { 1614 Binder.restoreCallingIdentity(identity); 1615 } 1616 } 1617 } 1618 1619 private void migrateLegacySettingsForUserIfNeededLocked(int userId) { 1620 // Every user has secure settings and if no file we need to migrate. 1621 final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId); 1622 File secureFile = getSettingsFile(secureKey); 1623 if (secureFile.exists()) { 1624 return; 1625 } 1626 1627 DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId); 1628 SQLiteDatabase database = dbHelper.getWritableDatabase(); 1629 1630 migrateLegacySettingsForUserLocked(dbHelper, database, userId); 1631 } 1632 1633 private void migrateLegacySettingsForUserLocked(DatabaseHelper dbHelper, 1634 SQLiteDatabase database, int userId) { 1635 // Move over the global settings if owner. 1636 if (userId == UserHandle.USER_OWNER) { 1637 final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, userId); 1638 ensureSettingsStateLocked(globalKey); 1639 SettingsState globalSettings = mSettingsStates.get(globalKey); 1640 migrateLegacySettingsLocked(globalSettings, database, TABLE_GLOBAL); 1641 globalSettings.persistSyncLocked(); 1642 } 1643 1644 // Move over the secure settings. 1645 final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId); 1646 ensureSettingsStateLocked(secureKey); 1647 SettingsState secureSettings = mSettingsStates.get(secureKey); 1648 migrateLegacySettingsLocked(secureSettings, database, TABLE_SECURE); 1649 ensureSecureSettingAndroidIdSetLocked(secureSettings); 1650 secureSettings.persistSyncLocked(); 1651 1652 // Move over the system settings. 1653 final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId); 1654 ensureSettingsStateLocked(systemKey); 1655 SettingsState systemSettings = mSettingsStates.get(systemKey); 1656 migrateLegacySettingsLocked(systemSettings, database, TABLE_SYSTEM); 1657 systemSettings.persistSyncLocked(); 1658 1659 // Drop the database as now all is moved and persisted. 1660 if (DROP_DATABASE_ON_MIGRATION) { 1661 dbHelper.dropDatabase(); 1662 } else { 1663 dbHelper.backupDatabase(); 1664 } 1665 } 1666 1667 private void migrateLegacySettingsLocked(SettingsState settingsState, 1668 SQLiteDatabase database, String table) { 1669 SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); 1670 queryBuilder.setTables(table); 1671 1672 Cursor cursor = queryBuilder.query(database, ALL_COLUMNS, 1673 null, null, null, null, null); 1674 1675 if (cursor == null) { 1676 return; 1677 } 1678 1679 try { 1680 if (!cursor.moveToFirst()) { 1681 return; 1682 } 1683 1684 final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME); 1685 final int valueColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.VALUE); 1686 1687 settingsState.setVersionLocked(database.getVersion()); 1688 1689 while (!cursor.isAfterLast()) { 1690 String name = cursor.getString(nameColumnIdx); 1691 String value = cursor.getString(valueColumnIdx); 1692 settingsState.insertSettingLocked(name, value, 1693 SettingsState.SYSTEM_PACKAGE_NAME); 1694 cursor.moveToNext(); 1695 } 1696 } finally { 1697 cursor.close(); 1698 } 1699 } 1700 1701 private void ensureSecureSettingAndroidIdSetLocked(SettingsState secureSettings) { 1702 Setting value = secureSettings.getSettingLocked(Settings.Secure.ANDROID_ID); 1703 1704 if (value != null) { 1705 return; 1706 } 1707 1708 final int userId = getUserIdFromKey(secureSettings.mKey); 1709 1710 final UserInfo user; 1711 final long identity = Binder.clearCallingIdentity(); 1712 try { 1713 user = mUserManager.getUserInfo(userId); 1714 } finally { 1715 Binder.restoreCallingIdentity(identity); 1716 } 1717 if (user == null) { 1718 // Can happen due to races when deleting users - treat as benign. 1719 return; 1720 } 1721 1722 String androidId = Long.toHexString(new SecureRandom().nextLong()); 1723 secureSettings.insertSettingLocked(Settings.Secure.ANDROID_ID, androidId, 1724 SettingsState.SYSTEM_PACKAGE_NAME); 1725 1726 Slog.d(LOG_TAG, "Generated and saved new ANDROID_ID [" + androidId 1727 + "] for user " + userId); 1728 1729 // Write a drop box entry if it's a restricted profile 1730 if (user.isRestricted()) { 1731 DropBoxManager dbm = (DropBoxManager) getContext().getSystemService( 1732 Context.DROPBOX_SERVICE); 1733 if (dbm != null && dbm.isTagEnabled(DROPBOX_TAG_USERLOG)) { 1734 dbm.addText(DROPBOX_TAG_USERLOG, System.currentTimeMillis() 1735 + "," + DROPBOX_TAG_USERLOG + "," + androidId + "\n"); 1736 } 1737 } 1738 } 1739 1740 private void notifyForSettingsChange(int key, String name) { 1741 // Update the system property *first*, so if someone is listening for 1742 // a notification and then using the contract class to get their data, 1743 // the system property will be updated and they'll get the new data. 1744 1745 boolean backedUpDataChanged = false; 1746 String property = null; 1747 if (isGlobalSettingsKey(key)) { 1748 property = Settings.Global.SYS_PROP_SETTING_VERSION; 1749 backedUpDataChanged = true; 1750 } else if (isSecureSettingsKey(key)) { 1751 property = Settings.Secure.SYS_PROP_SETTING_VERSION; 1752 backedUpDataChanged = true; 1753 } else if (isSystemSettingsKey(key)) { 1754 property = Settings.System.SYS_PROP_SETTING_VERSION; 1755 backedUpDataChanged = true; 1756 } 1757 1758 if (property != null) { 1759 final long version = SystemProperties.getLong(property, 0) + 1; 1760 SystemProperties.set(property, Long.toString(version)); 1761 if (DEBUG) { 1762 Slog.v(LOG_TAG, "System property " + property + "=" + version); 1763 } 1764 } 1765 1766 // Inform the backup manager about a data change 1767 if (backedUpDataChanged) { 1768 mBackupManager.dataChanged(); 1769 } 1770 1771 // Now send the notification through the content framework. 1772 1773 final int userId = getUserIdFromKey(key); 1774 Uri uri = getNotificationUriFor(key, name); 1775 1776 sendNotify(uri, userId); 1777 if (isSecureSettingsKey(key)) { 1778 maybeNotifyProfiles(userId, uri, name, sSecureCloneToManagedSettings); 1779 } else if (isSystemSettingsKey(key)) { 1780 maybeNotifyProfiles(userId, uri, name, sSystemCloneToManagedSettings); 1781 } 1782 } 1783 1784 private void maybeNotifyProfiles(int userId, Uri uri, String name, 1785 Set<String> keysCloned) { 1786 if (keysCloned.contains(name)) { 1787 List<UserInfo> profiles = mUserManager.getProfiles(userId); 1788 int size = profiles.size(); 1789 for (int i = 0; i < size; i++) { 1790 UserInfo profile = profiles.get(i); 1791 // the notification for userId has already been sent. 1792 if (profile.id != userId) { 1793 sendNotify(uri, profile.id); 1794 } 1795 } 1796 } 1797 } 1798 1799 private int makeKey(int type, int userId) { 1800 return (type << SETTINGS_TYPE_SHIFT) | userId; 1801 } 1802 1803 private int getTypeFromKey(int key) { 1804 return key >> SETTINGS_TYPE_SHIFT; 1805 } 1806 1807 private int getUserIdFromKey(int key) { 1808 return key & ~SETTINGS_TYPE_MASK; 1809 } 1810 1811 private boolean isGlobalSettingsKey(int key) { 1812 return getTypeFromKey(key) == SETTINGS_TYPE_GLOBAL; 1813 } 1814 1815 private boolean isSystemSettingsKey(int key) { 1816 return getTypeFromKey(key) == SETTINGS_TYPE_SYSTEM; 1817 } 1818 1819 private boolean isSecureSettingsKey(int key) { 1820 return getTypeFromKey(key) == SETTINGS_TYPE_SECURE; 1821 } 1822 1823 private File getSettingsFile(int key) { 1824 if (isGlobalSettingsKey(key)) { 1825 final int userId = getUserIdFromKey(key); 1826 return new File(Environment.getUserSystemDirectory(userId), 1827 SETTINGS_FILE_GLOBAL); 1828 } else if (isSystemSettingsKey(key)) { 1829 final int userId = getUserIdFromKey(key); 1830 return new File(Environment.getUserSystemDirectory(userId), 1831 SETTINGS_FILE_SYSTEM); 1832 } else if (isSecureSettingsKey(key)) { 1833 final int userId = getUserIdFromKey(key); 1834 return new File(Environment.getUserSystemDirectory(userId), 1835 SETTINGS_FILE_SECURE); 1836 } else { 1837 throw new IllegalArgumentException("Invalid settings key:" + key); 1838 } 1839 } 1840 1841 private Uri getNotificationUriFor(int key, String name) { 1842 if (isGlobalSettingsKey(key)) { 1843 return (name != null) ? Uri.withAppendedPath(Settings.Global.CONTENT_URI, name) 1844 : Settings.Global.CONTENT_URI; 1845 } else if (isSecureSettingsKey(key)) { 1846 return (name != null) ? Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name) 1847 : Settings.Secure.CONTENT_URI; 1848 } else if (isSystemSettingsKey(key)) { 1849 return (name != null) ? Uri.withAppendedPath(Settings.System.CONTENT_URI, name) 1850 : Settings.System.CONTENT_URI; 1851 } else { 1852 throw new IllegalArgumentException("Invalid settings key:" + key); 1853 } 1854 } 1855 1856 private int getMaxBytesPerPackageForType(int type) { 1857 switch (type) { 1858 case SETTINGS_TYPE_GLOBAL: 1859 case SETTINGS_TYPE_SECURE: { 1860 return SettingsState.MAX_BYTES_PER_APP_PACKAGE_UNLIMITED; 1861 } 1862 1863 default: { 1864 return SettingsState.MAX_BYTES_PER_APP_PACKAGE_LIMITED; 1865 } 1866 } 1867 } 1868 1869 private final class UpgradeController { 1870 private static final int SETTINGS_VERSION = 121; 1871 1872 private final int mUserId; 1873 1874 public UpgradeController(int userId) { 1875 mUserId = userId; 1876 } 1877 1878 public void upgradeIfNeededLocked() { 1879 // The version of all settings for a user is the same (all users have secure). 1880 SettingsState secureSettings = getSettingsLocked( 1881 SettingsRegistry.SETTINGS_TYPE_SECURE, mUserId); 1882 1883 // Try an update from the current state. 1884 final int oldVersion = secureSettings.getVersionLocked(); 1885 final int newVersion = SETTINGS_VERSION; 1886 1887 // If up do date - done. 1888 if (oldVersion == newVersion) { 1889 return; 1890 } 1891 1892 // Try to upgrade. 1893 final int curVersion = onUpgradeLocked(mUserId, oldVersion, newVersion); 1894 1895 // If upgrade failed start from scratch and upgrade. 1896 if (curVersion != newVersion) { 1897 // Drop state we have for this user. 1898 removeUserStateLocked(mUserId, true); 1899 1900 // Recreate the database. 1901 DatabaseHelper dbHelper = new DatabaseHelper(getContext(), mUserId); 1902 SQLiteDatabase database = dbHelper.getWritableDatabase(); 1903 dbHelper.recreateDatabase(database, newVersion, curVersion, oldVersion); 1904 1905 // Migrate the settings for this user. 1906 migrateLegacySettingsForUserLocked(dbHelper, database, mUserId); 1907 1908 // Now upgrade should work fine. 1909 onUpgradeLocked(mUserId, oldVersion, newVersion); 1910 } 1911 1912 // Set the global settings version if owner. 1913 if (mUserId == UserHandle.USER_OWNER) { 1914 SettingsState globalSettings = getSettingsLocked( 1915 SettingsRegistry.SETTINGS_TYPE_GLOBAL, mUserId); 1916 globalSettings.setVersionLocked(newVersion); 1917 } 1918 1919 // Set the secure settings version. 1920 secureSettings.setVersionLocked(newVersion); 1921 1922 // Set the system settings version. 1923 SettingsState systemSettings = getSettingsLocked( 1924 SettingsRegistry.SETTINGS_TYPE_SYSTEM, mUserId); 1925 systemSettings.setVersionLocked(newVersion); 1926 } 1927 1928 private SettingsState getGlobalSettingsLocked() { 1929 return getSettingsLocked(SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER); 1930 } 1931 1932 private SettingsState getSecureSettingsLocked(int userId) { 1933 return getSettingsLocked(SETTINGS_TYPE_SECURE, userId); 1934 } 1935 1936 private SettingsState getSystemSettingsLocked(int userId) { 1937 return getSettingsLocked(SETTINGS_TYPE_SYSTEM, userId); 1938 } 1939 1940 /** 1941 * You must perform all necessary mutations to bring the settings 1942 * for this user from the old to the new version. When you add a new 1943 * upgrade step you *must* update SETTINGS_VERSION. 1944 * 1945 * This is an example of moving a setting from secure to global. 1946 * 1947 * // v119: Example settings changes. 1948 * if (currentVersion == 118) { 1949 * if (userId == UserHandle.USER_OWNER) { 1950 * // Remove from the secure settings. 1951 * SettingsState secureSettings = getSecureSettingsLocked(userId); 1952 * String name = "example_setting_to_move"; 1953 * String value = secureSettings.getSetting(name); 1954 * secureSettings.deleteSetting(name); 1955 * 1956 * // Add to the global settings. 1957 * SettingsState globalSettings = getGlobalSettingsLocked(); 1958 * globalSettings.insertSetting(name, value, SettingsState.SYSTEM_PACKAGE_NAME); 1959 * } 1960 * 1961 * // Update the current version. 1962 * currentVersion = 119; 1963 * } 1964 */ 1965 private int onUpgradeLocked(int userId, int oldVersion, int newVersion) { 1966 if (DEBUG) { 1967 Slog.w(LOG_TAG, "Upgrading settings for user: " + userId + " from version: " 1968 + oldVersion + " to version: " + newVersion); 1969 } 1970 1971 int currentVersion = oldVersion; 1972 1973 // v119: Reset zen + ringer mode. 1974 if (currentVersion == 118) { 1975 if (userId == UserHandle.USER_OWNER) { 1976 final SettingsState globalSettings = getGlobalSettingsLocked(); 1977 globalSettings.updateSettingLocked(Settings.Global.ZEN_MODE, 1978 Integer.toString(Settings.Global.ZEN_MODE_OFF), 1979 SettingsState.SYSTEM_PACKAGE_NAME); 1980 globalSettings.updateSettingLocked(Settings.Global.MODE_RINGER, 1981 Integer.toString(AudioManager.RINGER_MODE_NORMAL), 1982 SettingsState.SYSTEM_PACKAGE_NAME); 1983 } 1984 currentVersion = 119; 1985 } 1986 1987 // v120: Add double tap to wake setting. 1988 if (currentVersion == 119) { 1989 SettingsState secureSettings = getSecureSettingsLocked(userId); 1990 secureSettings.insertSettingLocked(Settings.Secure.DOUBLE_TAP_TO_WAKE, 1991 getContext().getResources().getBoolean( 1992 R.bool.def_double_tap_to_wake) ? "1" : "0", 1993 SettingsState.SYSTEM_PACKAGE_NAME); 1994 1995 currentVersion = 120; 1996 } 1997 1998 // Before 121, we used a different string encoding logic. We just bump the version 1999 // here; SettingsState knows how to handle pre-version 120 files. 2000 currentVersion = 121; 2001 2002 // vXXX: Add new settings above this point. 2003 2004 // Return the current version. 2005 return currentVersion; 2006 } 2007 } 2008 } 2009} 2010