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 17 package com.android.providers.settings; 18 19 import android.Manifest; 20 import android.app.ActivityManager; 21 import android.app.AppGlobals; 22 import android.app.backup.BackupManager; 23 import android.content.BroadcastReceiver; 24 import android.content.ComponentName; 25 import android.content.ContentProvider; 26 import android.content.ContentValues; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.IntentFilter; 30 import android.content.pm.ApplicationInfo; 31 import android.content.pm.IPackageManager; 32 import android.content.pm.PackageInfo; 33 import android.content.pm.PackageManager; 34 import android.content.pm.UserInfo; 35 import android.database.Cursor; 36 import android.database.MatrixCursor; 37 import android.database.sqlite.SQLiteDatabase; 38 import android.database.sqlite.SQLiteQueryBuilder; 39 import android.hardware.camera2.utils.ArrayUtils; 40 import android.media.AudioManager; 41 import android.net.Uri; 42 import android.os.Binder; 43 import android.os.Build; 44 import android.os.Bundle; 45 import android.os.Debug; 46 import android.os.DropBoxManager; 47 import android.os.Environment; 48 import android.os.Handler; 49 import android.os.HandlerThread; 50 import android.os.Looper; 51 import android.os.Message; 52 import android.os.ParcelFileDescriptor; 53 import android.os.Process; 54 import android.os.RemoteException; 55 import android.os.SELinux; 56 import android.os.UserHandle; 57 import android.os.UserManager; 58 import android.os.UserManagerInternal; 59 import android.provider.Settings; 60 import android.text.TextUtils; 61 import android.util.ArraySet; 62 import android.util.Slog; 63 import android.util.SparseArray; 64 65 import com.android.internal.annotations.GuardedBy; 66 import com.android.internal.content.PackageMonitor; 67 import com.android.internal.os.BackgroundThread; 68 import com.android.providers.settings.SettingsState.Setting; 69 import com.android.server.LocalServices; 70 import com.android.server.SystemConfig; 71 72 import java.io.File; 73 import java.io.FileDescriptor; 74 import java.io.FileNotFoundException; 75 import java.io.PrintWriter; 76 import java.security.SecureRandom; 77 import java.util.Arrays; 78 import java.util.List; 79 import java.util.Set; 80 import java.util.regex.Pattern; 81 82 /** 83 * <p> 84 * This class is a content provider that publishes the system settings. 85 * It can be accessed via the content provider APIs or via custom call 86 * commands. The latter is a bit faster and is the preferred way to access 87 * the platform settings. 88 * </p> 89 * <p> 90 * There are three settings types, global (with signature level protection 91 * and shared across users), secure (with signature permission level 92 * protection and per user), and system (with dangerous permission level 93 * protection and per user). Global settings are stored under the device owner. 94 * Each of these settings is represented by a {@link 95 * com.android.providers.settings.SettingsState} object mapped to an integer 96 * key derived from the setting type in the most significant bits and user 97 * id in the least significant bits. Settings are synchronously loaded on 98 * instantiation of a SettingsState and asynchronously persisted on mutation. 99 * Settings are stored in the user specific system directory. 100 * </p> 101 * <p> 102 * Apps targeting APIs Lollipop MR1 and lower can add custom settings entries 103 * and get a warning. Targeting higher API version prohibits this as the 104 * system settings are not a place for apps to save their state. When a package 105 * is removed the settings it added are deleted. Apps cannot delete system 106 * settings added by the platform. System settings values are validated to 107 * ensure the clients do not put bad values. Global and secure settings are 108 * changed only by trusted parties, therefore no validation is performed. Also 109 * there is a limit on the amount of app specific settings that can be added 110 * to prevent unlimited growth of the system process memory footprint. 111 * </p> 112 */ 113 @SuppressWarnings("deprecation") 114 public class SettingsProvider extends ContentProvider { 115 private static final boolean DEBUG = false; 116 117 private static final boolean DROP_DATABASE_ON_MIGRATION = !Build.IS_DEBUGGABLE; 118 119 private static final String LOG_TAG = "SettingsProvider"; 120 121 private static final String TABLE_SYSTEM = "system"; 122 private static final String TABLE_SECURE = "secure"; 123 private static final String TABLE_GLOBAL = "global"; 124 125 // Old tables no longer exist. 126 private static final String TABLE_FAVORITES = "favorites"; 127 private static final String TABLE_OLD_FAVORITES = "old_favorites"; 128 private static final String TABLE_BLUETOOTH_DEVICES = "bluetooth_devices"; 129 private static final String TABLE_BOOKMARKS = "bookmarks"; 130 private static final String TABLE_ANDROID_METADATA = "android_metadata"; 131 132 // The set of removed legacy tables. 133 private static final Set<String> REMOVED_LEGACY_TABLES = new ArraySet<>(); 134 static { 135 REMOVED_LEGACY_TABLES.add(TABLE_FAVORITES); 136 REMOVED_LEGACY_TABLES.add(TABLE_OLD_FAVORITES); 137 REMOVED_LEGACY_TABLES.add(TABLE_BLUETOOTH_DEVICES); 138 REMOVED_LEGACY_TABLES.add(TABLE_BOOKMARKS); 139 REMOVED_LEGACY_TABLES.add(TABLE_ANDROID_METADATA); 140 } 141 142 private static final int MUTATION_OPERATION_INSERT = 1; 143 private static final int MUTATION_OPERATION_DELETE = 2; 144 private static final int MUTATION_OPERATION_UPDATE = 3; 145 146 private static final String[] ALL_COLUMNS = new String[] { 147 Settings.NameValueTable._ID, 148 Settings.NameValueTable.NAME, 149 Settings.NameValueTable.VALUE 150 }; 151 152 public static final int SETTINGS_TYPE_GLOBAL = 0; 153 public static final int SETTINGS_TYPE_SYSTEM = 1; 154 public static final int SETTINGS_TYPE_SECURE = 2; 155 156 public static final int SETTINGS_TYPE_MASK = 0xF0000000; 157 public static final int SETTINGS_TYPE_SHIFT = 28; 158 159 private static final Bundle NULL_SETTING_BUNDLE = Bundle.forPair( 160 Settings.NameValueTable.VALUE, null); 161 162 // Per user secure settings that moved to the for all users global settings. 163 static final Set<String> sSecureMovedToGlobalSettings = new ArraySet<>(); 164 static { 165 Settings.Secure.getMovedToGlobalSettings(sSecureMovedToGlobalSettings); 166 } 167 168 // Per user system settings that moved to the for all users global settings. 169 static final Set<String> sSystemMovedToGlobalSettings = new ArraySet<>(); 170 static { 171 Settings.System.getMovedToGlobalSettings(sSystemMovedToGlobalSettings); 172 } 173 174 // Per user system settings that moved to the per user secure settings. 175 static final Set<String> sSystemMovedToSecureSettings = new ArraySet<>(); 176 static { 177 Settings.System.getMovedToSecureSettings(sSystemMovedToSecureSettings); 178 } 179 180 // Per all users global settings that moved to the per user secure settings. 181 static final Set<String> sGlobalMovedToSecureSettings = new ArraySet<>(); 182 static { 183 Settings.Global.getMovedToSecureSettings(sGlobalMovedToSecureSettings); 184 } 185 186 // Per user secure settings that are cloned for the managed profiles of the user. 187 private static final Set<String> sSecureCloneToManagedSettings = new ArraySet<>(); 188 static { 189 Settings.Secure.getCloneToManagedProfileSettings(sSecureCloneToManagedSettings); 190 } 191 192 // Per user system settings that are cloned for the managed profiles of the user. 193 private static final Set<String> sSystemCloneToManagedSettings = new ArraySet<>(); 194 static { 195 Settings.System.getCloneToManagedProfileSettings(sSystemCloneToManagedSettings); 196 } 197 198 private final Object mLock = new Object(); 199 200 @GuardedBy("mLock") 201 private SettingsRegistry mSettingsRegistry; 202 203 @GuardedBy("mLock") 204 private HandlerThread mHandlerThread; 205 206 // We have to call in the user manager with no lock held, 207 private volatile UserManager mUserManager; 208 209 // We have to call in the package manager with no lock held, 210 private volatile IPackageManager mPackageManager; 211 212 public static int makeKey(int type, int userId) { 213 return (type << SETTINGS_TYPE_SHIFT) | userId; 214 } 215 216 public static int getTypeFromKey(int key) { 217 return key >>> SETTINGS_TYPE_SHIFT; 218 } 219 220 public static int getUserIdFromKey(int key) { 221 return key & ~SETTINGS_TYPE_MASK; 222 } 223 224 public static String settingTypeToString(int type) { 225 switch (type) { 226 case SETTINGS_TYPE_GLOBAL: { 227 return "SETTINGS_GLOBAL"; 228 } 229 case SETTINGS_TYPE_SECURE: { 230 return "SETTINGS_SECURE"; 231 } 232 case SETTINGS_TYPE_SYSTEM: { 233 return "SETTINGS_SYSTEM"; 234 } 235 default: { 236 return "UNKNOWN"; 237 } 238 } 239 } 240 241 public static String keyToString(int key) { 242 return "Key[user=" + getUserIdFromKey(key) + ";type=" 243 + settingTypeToString(getTypeFromKey(key)) + "]"; 244 } 245 246 @Override 247 public boolean onCreate() { 248 synchronized (mLock) { 249 mUserManager = UserManager.get(getContext()); 250 mPackageManager = AppGlobals.getPackageManager(); 251 mHandlerThread = new HandlerThread(LOG_TAG, 252 Process.THREAD_PRIORITY_BACKGROUND); 253 mHandlerThread.start(); 254 mSettingsRegistry = new SettingsRegistry(); 255 } 256 registerBroadcastReceivers(); 257 startWatchingUserRestrictionChanges(); 258 return true; 259 } 260 261 @Override 262 public Bundle call(String method, String name, Bundle args) { 263 final int requestingUserId = getRequestingUserId(args); 264 switch (method) { 265 case Settings.CALL_METHOD_GET_GLOBAL: { 266 Setting setting = getGlobalSetting(name); 267 return packageValueForCallResult(setting, isTrackingGeneration(args)); 268 } 269 270 case Settings.CALL_METHOD_GET_SECURE: { 271 Setting setting = getSecureSetting(name, requestingUserId); 272 return packageValueForCallResult(setting, isTrackingGeneration(args)); 273 } 274 275 case Settings.CALL_METHOD_GET_SYSTEM: { 276 Setting setting = getSystemSetting(name, requestingUserId); 277 return packageValueForCallResult(setting, isTrackingGeneration(args)); 278 } 279 280 case Settings.CALL_METHOD_PUT_GLOBAL: { 281 String value = getSettingValue(args); 282 insertGlobalSetting(name, value, requestingUserId, false); 283 break; 284 } 285 286 case Settings.CALL_METHOD_PUT_SECURE: { 287 String value = getSettingValue(args); 288 insertSecureSetting(name, value, requestingUserId, false); 289 break; 290 } 291 292 case Settings.CALL_METHOD_PUT_SYSTEM: { 293 String value = getSettingValue(args); 294 insertSystemSetting(name, value, requestingUserId); 295 break; 296 } 297 298 default: { 299 Slog.w(LOG_TAG, "call() with invalid method: " + method); 300 } break; 301 } 302 303 return null; 304 } 305 306 @Override 307 public String getType(Uri uri) { 308 Arguments args = new Arguments(uri, null, null, true); 309 if (TextUtils.isEmpty(args.name)) { 310 return "vnd.android.cursor.dir/" + args.table; 311 } else { 312 return "vnd.android.cursor.item/" + args.table; 313 } 314 } 315 316 @Override 317 public Cursor query(Uri uri, String[] projection, String where, String[] whereArgs, 318 String order) { 319 if (DEBUG) { 320 Slog.v(LOG_TAG, "query() for user: " + UserHandle.getCallingUserId()); 321 } 322 323 Arguments args = new Arguments(uri, where, whereArgs, true); 324 String[] normalizedProjection = normalizeProjection(projection); 325 326 // If a legacy table that is gone, done. 327 if (REMOVED_LEGACY_TABLES.contains(args.table)) { 328 return new MatrixCursor(normalizedProjection, 0); 329 } 330 331 switch (args.table) { 332 case TABLE_GLOBAL: { 333 if (args.name != null) { 334 Setting setting = getGlobalSetting(args.name); 335 return packageSettingForQuery(setting, normalizedProjection); 336 } else { 337 return getAllGlobalSettings(projection); 338 } 339 } 340 341 case TABLE_SECURE: { 342 final int userId = UserHandle.getCallingUserId(); 343 if (args.name != null) { 344 Setting setting = getSecureSetting(args.name, userId); 345 return packageSettingForQuery(setting, normalizedProjection); 346 } else { 347 return getAllSecureSettings(userId, projection); 348 } 349 } 350 351 case TABLE_SYSTEM: { 352 final int userId = UserHandle.getCallingUserId(); 353 if (args.name != null) { 354 Setting setting = getSystemSetting(args.name, userId); 355 return packageSettingForQuery(setting, normalizedProjection); 356 } else { 357 return getAllSystemSettings(userId, projection); 358 } 359 } 360 361 default: { 362 throw new IllegalArgumentException("Invalid Uri path:" + uri); 363 } 364 } 365 } 366 367 @Override 368 public Uri insert(Uri uri, ContentValues values) { 369 if (DEBUG) { 370 Slog.v(LOG_TAG, "insert() for user: " + UserHandle.getCallingUserId()); 371 } 372 373 String table = getValidTableOrThrow(uri); 374 375 // If a legacy table that is gone, done. 376 if (REMOVED_LEGACY_TABLES.contains(table)) { 377 return null; 378 } 379 380 String name = values.getAsString(Settings.Secure.NAME); 381 if (!isKeyValid(name)) { 382 return null; 383 } 384 385 String value = values.getAsString(Settings.Secure.VALUE); 386 387 switch (table) { 388 case TABLE_GLOBAL: { 389 if (insertGlobalSetting(name, value, UserHandle.getCallingUserId(), false)) { 390 return Uri.withAppendedPath(Settings.Global.CONTENT_URI, name); 391 } 392 } break; 393 394 case TABLE_SECURE: { 395 if (insertSecureSetting(name, value, UserHandle.getCallingUserId(), false)) { 396 return Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name); 397 } 398 } break; 399 400 case TABLE_SYSTEM: { 401 if (insertSystemSetting(name, value, UserHandle.getCallingUserId())) { 402 return Uri.withAppendedPath(Settings.System.CONTENT_URI, name); 403 } 404 } break; 405 406 default: { 407 throw new IllegalArgumentException("Bad Uri path:" + uri); 408 } 409 } 410 411 return null; 412 } 413 414 @Override 415 public int bulkInsert(Uri uri, ContentValues[] allValues) { 416 if (DEBUG) { 417 Slog.v(LOG_TAG, "bulkInsert() for user: " + UserHandle.getCallingUserId()); 418 } 419 420 int insertionCount = 0; 421 final int valuesCount = allValues.length; 422 for (int i = 0; i < valuesCount; i++) { 423 ContentValues values = allValues[i]; 424 if (insert(uri, values) != null) { 425 insertionCount++; 426 } 427 } 428 429 return insertionCount; 430 } 431 432 @Override 433 public int delete(Uri uri, String where, String[] whereArgs) { 434 if (DEBUG) { 435 Slog.v(LOG_TAG, "delete() for user: " + UserHandle.getCallingUserId()); 436 } 437 438 Arguments args = new Arguments(uri, where, whereArgs, false); 439 440 // If a legacy table that is gone, done. 441 if (REMOVED_LEGACY_TABLES.contains(args.table)) { 442 return 0; 443 } 444 445 if (!isKeyValid(args.name)) { 446 return 0; 447 } 448 449 switch (args.table) { 450 case TABLE_GLOBAL: { 451 final int userId = UserHandle.getCallingUserId(); 452 return deleteGlobalSetting(args.name, userId, false) ? 1 : 0; 453 } 454 455 case TABLE_SECURE: { 456 final int userId = UserHandle.getCallingUserId(); 457 return deleteSecureSetting(args.name, userId, false) ? 1 : 0; 458 } 459 460 case TABLE_SYSTEM: { 461 final int userId = UserHandle.getCallingUserId(); 462 return deleteSystemSetting(args.name, userId) ? 1 : 0; 463 } 464 465 default: { 466 throw new IllegalArgumentException("Bad Uri path:" + uri); 467 } 468 } 469 } 470 471 @Override 472 public int update(Uri uri, ContentValues values, String where, String[] whereArgs) { 473 if (DEBUG) { 474 Slog.v(LOG_TAG, "update() for user: " + UserHandle.getCallingUserId()); 475 } 476 477 Arguments args = new Arguments(uri, where, whereArgs, false); 478 479 // If a legacy table that is gone, done. 480 if (REMOVED_LEGACY_TABLES.contains(args.table)) { 481 return 0; 482 } 483 484 String name = values.getAsString(Settings.Secure.NAME); 485 if (!isKeyValid(name)) { 486 return 0; 487 } 488 String value = values.getAsString(Settings.Secure.VALUE); 489 490 switch (args.table) { 491 case TABLE_GLOBAL: { 492 final int userId = UserHandle.getCallingUserId(); 493 return updateGlobalSetting(args.name, value, userId, false) ? 1 : 0; 494 } 495 496 case TABLE_SECURE: { 497 final int userId = UserHandle.getCallingUserId(); 498 return updateSecureSetting(args.name, value, userId, false) ? 1 : 0; 499 } 500 501 case TABLE_SYSTEM: { 502 final int userId = UserHandle.getCallingUserId(); 503 return updateSystemSetting(args.name, value, userId) ? 1 : 0; 504 } 505 506 default: { 507 throw new IllegalArgumentException("Invalid Uri path:" + uri); 508 } 509 } 510 } 511 512 @Override 513 public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { 514 final String cacheName; 515 if (Settings.System.RINGTONE_CACHE_URI.equals(uri)) { 516 cacheName = Settings.System.RINGTONE_CACHE; 517 } else if (Settings.System.NOTIFICATION_SOUND_CACHE_URI.equals(uri)) { 518 cacheName = Settings.System.NOTIFICATION_SOUND_CACHE; 519 } else if (Settings.System.ALARM_ALERT_CACHE_URI.equals(uri)) { 520 cacheName = Settings.System.ALARM_ALERT_CACHE; 521 } else { 522 throw new FileNotFoundException("Direct file access no longer supported; " 523 + "ringtone playback is available through android.media.Ringtone"); 524 } 525 526 final File cacheFile = new File( 527 getRingtoneCacheDir(UserHandle.getCallingUserId()), cacheName); 528 return ParcelFileDescriptor.open(cacheFile, ParcelFileDescriptor.parseMode(mode)); 529 } 530 531 private File getRingtoneCacheDir(int userId) { 532 final File cacheDir = new File(Environment.getDataSystemDeDirectory(userId), "ringtones"); 533 cacheDir.mkdir(); 534 SELinux.restorecon(cacheDir); 535 return cacheDir; 536 } 537 538 @Override 539 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 540 synchronized (mLock) { 541 final long identity = Binder.clearCallingIdentity(); 542 try { 543 List<UserInfo> users = mUserManager.getUsers(true); 544 final int userCount = users.size(); 545 for (int i = 0; i < userCount; i++) { 546 UserInfo user = users.get(i); 547 dumpForUserLocked(user.id, pw); 548 } 549 } finally { 550 Binder.restoreCallingIdentity(identity); 551 } 552 } 553 } 554 555 private void dumpForUserLocked(int userId, PrintWriter pw) { 556 if (userId == UserHandle.USER_SYSTEM) { 557 pw.println("GLOBAL SETTINGS (user " + userId + ")"); 558 Cursor globalCursor = getAllGlobalSettings(ALL_COLUMNS); 559 dumpSettings(globalCursor, pw); 560 pw.println(); 561 562 SettingsState globalSettings = mSettingsRegistry.getSettingsLocked( 563 SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM); 564 globalSettings.dumpHistoricalOperations(pw); 565 } 566 567 pw.println("SECURE SETTINGS (user " + userId + ")"); 568 Cursor secureCursor = getAllSecureSettings(userId, ALL_COLUMNS); 569 dumpSettings(secureCursor, pw); 570 pw.println(); 571 572 SettingsState secureSettings = mSettingsRegistry.getSettingsLocked( 573 SETTINGS_TYPE_SECURE, userId); 574 secureSettings.dumpHistoricalOperations(pw); 575 576 pw.println("SYSTEM SETTINGS (user " + userId + ")"); 577 Cursor systemCursor = getAllSystemSettings(userId, ALL_COLUMNS); 578 dumpSettings(systemCursor, pw); 579 pw.println(); 580 581 SettingsState systemSettings = mSettingsRegistry.getSettingsLocked( 582 SETTINGS_TYPE_SYSTEM, userId); 583 systemSettings.dumpHistoricalOperations(pw); 584 } 585 586 private void dumpSettings(Cursor cursor, PrintWriter pw) { 587 if (cursor == null || !cursor.moveToFirst()) { 588 return; 589 } 590 591 final int idColumnIdx = cursor.getColumnIndex(Settings.NameValueTable._ID); 592 final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME); 593 final int valueColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.VALUE); 594 595 do { 596 pw.append("_id:").append(toDumpString(cursor.getString(idColumnIdx))); 597 pw.append(" name:").append(toDumpString(cursor.getString(nameColumnIdx))); 598 pw.append(" value:").append(toDumpString(cursor.getString(valueColumnIdx))); 599 pw.println(); 600 } while (cursor.moveToNext()); 601 } 602 603 private static String toDumpString(String s) { 604 if (s != null) { 605 return s; 606 } 607 return "{null}"; 608 } 609 610 private void registerBroadcastReceivers() { 611 IntentFilter userFilter = new IntentFilter(); 612 userFilter.addAction(Intent.ACTION_USER_REMOVED); 613 userFilter.addAction(Intent.ACTION_USER_STOPPED); 614 615 getContext().registerReceiver(new BroadcastReceiver() { 616 @Override 617 public void onReceive(Context context, Intent intent) { 618 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 619 UserHandle.USER_SYSTEM); 620 621 switch (intent.getAction()) { 622 case Intent.ACTION_USER_REMOVED: { 623 synchronized (mLock) { 624 mSettingsRegistry.removeUserStateLocked(userId, true); 625 } 626 } break; 627 628 case Intent.ACTION_USER_STOPPED: { 629 synchronized (mLock) { 630 mSettingsRegistry.removeUserStateLocked(userId, false); 631 } 632 } break; 633 } 634 } 635 }, userFilter); 636 637 PackageMonitor monitor = new PackageMonitor() { 638 @Override 639 public void onPackageRemoved(String packageName, int uid) { 640 synchronized (mLock) { 641 mSettingsRegistry.onPackageRemovedLocked(packageName, 642 UserHandle.getUserId(uid)); 643 } 644 } 645 }; 646 647 // package changes 648 monitor.register(getContext(), BackgroundThread.getHandler().getLooper(), 649 UserHandle.ALL, true); 650 } 651 652 private void startWatchingUserRestrictionChanges() { 653 // TODO: The current design of settings looking different based on user restrictions 654 // should be reworked to keep them separate and system code should check the setting 655 // first followed by checking the user restriction before performing an operation. 656 UserManagerInternal userManager = LocalServices.getService(UserManagerInternal.class); 657 userManager.addUserRestrictionsListener((int userId, Bundle newRestrictions, 658 Bundle prevRestrictions) -> { 659 // We are changing the settings affected by restrictions to their current 660 // value with a forced update to ensure that all cross profile dependencies 661 // are taken into account. Also make sure the settings update to.. the same 662 // value passes the security checks, so clear binder calling id. 663 if (newRestrictions.containsKey(UserManager.DISALLOW_SHARE_LOCATION) 664 != prevRestrictions.containsKey(UserManager.DISALLOW_SHARE_LOCATION)) { 665 final long identity = Binder.clearCallingIdentity(); 666 try { 667 synchronized (mLock) { 668 Setting setting = getSecureSetting( 669 Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId); 670 updateSecureSetting(Settings.Secure.LOCATION_PROVIDERS_ALLOWED, 671 setting != null ? setting.getValue() : null, userId, true); 672 } 673 } finally { 674 Binder.restoreCallingIdentity(identity); 675 } 676 } 677 if (newRestrictions.containsKey(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES) 678 != prevRestrictions.containsKey(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)) { 679 final long identity = Binder.clearCallingIdentity(); 680 try { 681 synchronized (mLock) { 682 Setting setting = getGlobalSetting(Settings.Global.INSTALL_NON_MARKET_APPS); 683 updateGlobalSetting(Settings.Global.INSTALL_NON_MARKET_APPS, 684 setting != null ? setting.getValue() : null, userId, true); 685 } 686 } finally { 687 Binder.restoreCallingIdentity(identity); 688 } 689 } 690 if (newRestrictions.containsKey(UserManager.DISALLOW_DEBUGGING_FEATURES) 691 != prevRestrictions.containsKey(UserManager.DISALLOW_DEBUGGING_FEATURES)) { 692 final long identity = Binder.clearCallingIdentity(); 693 try { 694 synchronized (mLock) { 695 Setting setting = getGlobalSetting(Settings.Global.ADB_ENABLED); 696 updateGlobalSetting(Settings.Global.ADB_ENABLED, 697 setting != null ? setting.getValue() : null, userId, true); 698 } 699 } finally { 700 Binder.restoreCallingIdentity(identity); 701 } 702 } 703 if (newRestrictions.containsKey(UserManager.ENSURE_VERIFY_APPS) 704 != prevRestrictions.containsKey(UserManager.ENSURE_VERIFY_APPS)) { 705 final long identity = Binder.clearCallingIdentity(); 706 try { 707 synchronized (mLock) { 708 Setting enable = getGlobalSetting( 709 Settings.Global.PACKAGE_VERIFIER_ENABLE); 710 updateGlobalSetting(Settings.Global.PACKAGE_VERIFIER_ENABLE, 711 enable != null ? enable.getValue() : null, userId, true); 712 Setting include = getGlobalSetting( 713 Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB); 714 updateGlobalSetting(Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 715 include != null ? include.getValue() : null, userId, true); 716 } 717 } finally { 718 Binder.restoreCallingIdentity(identity); 719 } 720 } 721 if (newRestrictions.containsKey(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS) 722 != prevRestrictions.containsKey(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) { 723 final long identity = Binder.clearCallingIdentity(); 724 try { 725 synchronized (mLock) { 726 Setting setting = getGlobalSetting( 727 Settings.Global.PREFERRED_NETWORK_MODE); 728 updateGlobalSetting(Settings.Global.PREFERRED_NETWORK_MODE, 729 setting != null ? setting.getValue() : null, userId, true); 730 } 731 } finally { 732 Binder.restoreCallingIdentity(identity); 733 } 734 } 735 }); 736 } 737 738 private Cursor getAllGlobalSettings(String[] projection) { 739 if (DEBUG) { 740 Slog.v(LOG_TAG, "getAllGlobalSettings()"); 741 } 742 743 synchronized (mLock) { 744 // Get the settings. 745 SettingsState settingsState = mSettingsRegistry.getSettingsLocked( 746 SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM); 747 748 List<String> names = settingsState.getSettingNamesLocked(); 749 750 final int nameCount = names.size(); 751 752 String[] normalizedProjection = normalizeProjection(projection); 753 MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount); 754 755 // Anyone can get the global settings, so no security checks. 756 for (int i = 0; i < nameCount; i++) { 757 String name = names.get(i); 758 Setting setting = settingsState.getSettingLocked(name); 759 appendSettingToCursor(result, setting); 760 } 761 762 return result; 763 } 764 } 765 766 private Setting getGlobalSetting(String name) { 767 if (DEBUG) { 768 Slog.v(LOG_TAG, "getGlobalSetting(" + name + ")"); 769 } 770 771 // Get the value. 772 synchronized (mLock) { 773 return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_GLOBAL, 774 UserHandle.USER_SYSTEM, name); 775 } 776 } 777 778 private boolean updateGlobalSetting(String name, String value, int requestingUserId, 779 boolean forceNotify) { 780 if (DEBUG) { 781 Slog.v(LOG_TAG, "updateGlobalSetting(" + name + ", " + value + ")"); 782 } 783 return mutateGlobalSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE, 784 forceNotify); 785 } 786 787 private boolean insertGlobalSetting(String name, String value, int requestingUserId, 788 boolean forceNotify) { 789 if (DEBUG) { 790 Slog.v(LOG_TAG, "insertGlobalSetting(" + name + ", " + value + ")"); 791 } 792 return mutateGlobalSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT, 793 forceNotify); 794 } 795 796 private boolean deleteGlobalSetting(String name, int requestingUserId, boolean forceNotify) { 797 if (DEBUG) { 798 Slog.v(LOG_TAG, "deleteGlobalSettingLocked(" + name + ")"); 799 } 800 return mutateGlobalSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE, 801 forceNotify); 802 } 803 804 private boolean mutateGlobalSetting(String name, String value, int requestingUserId, 805 int operation, boolean forceNotify) { 806 // Make sure the caller can change the settings - treated as secure. 807 enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS); 808 809 // Resolve the userId on whose behalf the call is made. 810 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); 811 812 // If this is a setting that is currently restricted for this user, do not allow 813 // unrestricting changes. 814 if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value, 815 Binder.getCallingUid())) { 816 return false; 817 } 818 819 // Perform the mutation. 820 synchronized (mLock) { 821 switch (operation) { 822 case MUTATION_OPERATION_INSERT: { 823 return mSettingsRegistry 824 .insertSettingLocked(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM, 825 name, value, getCallingPackage(), forceNotify); 826 } 827 828 case MUTATION_OPERATION_DELETE: { 829 return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_GLOBAL, 830 UserHandle.USER_SYSTEM, name, forceNotify); 831 } 832 833 case MUTATION_OPERATION_UPDATE: { 834 return mSettingsRegistry 835 .updateSettingLocked(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM, 836 name, value, getCallingPackage(), forceNotify); 837 } 838 } 839 } 840 841 return false; 842 } 843 844 private Cursor getAllSecureSettings(int userId, String[] projection) { 845 if (DEBUG) { 846 Slog.v(LOG_TAG, "getAllSecureSettings(" + userId + ")"); 847 } 848 849 // Resolve the userId on whose behalf the call is made. 850 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId); 851 852 synchronized (mLock) { 853 List<String> names = mSettingsRegistry.getSettingsNamesLocked( 854 SETTINGS_TYPE_SECURE, callingUserId); 855 856 final int nameCount = names.size(); 857 858 String[] normalizedProjection = normalizeProjection(projection); 859 MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount); 860 861 for (int i = 0; i < nameCount; i++) { 862 String name = names.get(i); 863 // Determine the owning user as some profile settings are cloned from the parent. 864 final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, 865 name); 866 867 // Special case for location (sigh). 868 if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) { 869 continue; 870 } 871 872 Setting setting = mSettingsRegistry.getSettingLocked( 873 SETTINGS_TYPE_SECURE, owningUserId, name); 874 appendSettingToCursor(result, setting); 875 } 876 877 return result; 878 } 879 } 880 881 private Setting getSecureSetting(String name, int requestingUserId) { 882 if (DEBUG) { 883 Slog.v(LOG_TAG, "getSecureSetting(" + name + ", " + requestingUserId + ")"); 884 } 885 886 // Resolve the userId on whose behalf the call is made. 887 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); 888 889 // Determine the owning user as some profile settings are cloned from the parent. 890 final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name); 891 892 // Special case for location (sigh). 893 if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) { 894 return mSettingsRegistry.getSettingsLocked(SETTINGS_TYPE_SECURE, 895 owningUserId).getNullSetting(); 896 } 897 898 // Get the value. 899 synchronized (mLock) { 900 return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SECURE, 901 owningUserId, name); 902 } 903 } 904 905 private boolean insertSecureSetting(String name, String value, int requestingUserId, 906 boolean forceNotify) { 907 if (DEBUG) { 908 Slog.v(LOG_TAG, "insertSecureSetting(" + name + ", " + value + ", " 909 + requestingUserId + ")"); 910 } 911 912 return mutateSecureSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT, 913 forceNotify); 914 } 915 916 private boolean deleteSecureSetting(String name, int requestingUserId, boolean forceNotify) { 917 if (DEBUG) { 918 Slog.v(LOG_TAG, "deleteSecureSetting(" + name + ", " + requestingUserId + ")"); 919 } 920 921 return mutateSecureSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE, 922 forceNotify); 923 } 924 925 private boolean updateSecureSetting(String name, String value, int requestingUserId, 926 boolean forceNotify) { 927 if (DEBUG) { 928 Slog.v(LOG_TAG, "updateSecureSetting(" + name + ", " + value + ", " 929 + requestingUserId + ")"); 930 } 931 932 return mutateSecureSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE, 933 forceNotify); 934 } 935 936 private boolean mutateSecureSetting(String name, String value, int requestingUserId, 937 int operation, boolean forceNotify) { 938 // Make sure the caller can change the settings. 939 enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS); 940 941 // Resolve the userId on whose behalf the call is made. 942 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); 943 944 // If this is a setting that is currently restricted for this user, do not allow 945 // unrestricting changes. 946 if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value, 947 Binder.getCallingUid())) { 948 return false; 949 } 950 951 // Determine the owning user as some profile settings are cloned from the parent. 952 final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name); 953 954 // Only the owning user can change the setting. 955 if (owningUserId != callingUserId) { 956 return false; 957 } 958 959 // Special cases for location providers (sigh). 960 if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) { 961 return updateLocationProvidersAllowedLocked(value, owningUserId, forceNotify); 962 } 963 964 // Mutate the value. 965 synchronized (mLock) { 966 switch (operation) { 967 case MUTATION_OPERATION_INSERT: { 968 return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SECURE, 969 owningUserId, name, value, getCallingPackage(), forceNotify); 970 } 971 972 case MUTATION_OPERATION_DELETE: { 973 return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_SECURE, 974 owningUserId, name, forceNotify); 975 } 976 977 case MUTATION_OPERATION_UPDATE: { 978 return mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_SECURE, 979 owningUserId, name, value, getCallingPackage(), forceNotify); 980 } 981 } 982 } 983 984 return false; 985 } 986 987 private Cursor getAllSystemSettings(int userId, String[] projection) { 988 if (DEBUG) { 989 Slog.v(LOG_TAG, "getAllSecureSystem(" + userId + ")"); 990 } 991 992 // Resolve the userId on whose behalf the call is made. 993 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId); 994 995 synchronized (mLock) { 996 List<String> names = mSettingsRegistry.getSettingsNamesLocked( 997 SETTINGS_TYPE_SYSTEM, callingUserId); 998 999 final int nameCount = names.size(); 1000 1001 String[] normalizedProjection = normalizeProjection(projection); 1002 MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount); 1003 1004 for (int i = 0; i < nameCount; i++) { 1005 String name = names.get(i); 1006 1007 // Determine the owning user as some profile settings are cloned from the parent. 1008 final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, 1009 name); 1010 1011 Setting setting = mSettingsRegistry.getSettingLocked( 1012 SETTINGS_TYPE_SYSTEM, owningUserId, name); 1013 appendSettingToCursor(result, setting); 1014 } 1015 1016 return result; 1017 } 1018 } 1019 1020 private Setting getSystemSetting(String name, int requestingUserId) { 1021 if (DEBUG) { 1022 Slog.v(LOG_TAG, "getSystemSetting(" + name + ", " + requestingUserId + ")"); 1023 } 1024 1025 // Resolve the userId on whose behalf the call is made. 1026 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId); 1027 1028 // Determine the owning user as some profile settings are cloned from the parent. 1029 final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name); 1030 1031 // Get the value. 1032 synchronized (mLock) { 1033 return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SYSTEM, owningUserId, name); 1034 } 1035 } 1036 1037 private boolean insertSystemSetting(String name, String value, int requestingUserId) { 1038 if (DEBUG) { 1039 Slog.v(LOG_TAG, "insertSystemSetting(" + name + ", " + value + ", " 1040 + requestingUserId + ")"); 1041 } 1042 1043 return mutateSystemSetting(name, value, requestingUserId, MUTATION_OPERATION_INSERT); 1044 } 1045 1046 private boolean deleteSystemSetting(String name, int requestingUserId) { 1047 if (DEBUG) { 1048 Slog.v(LOG_TAG, "deleteSystemSetting(" + name + ", " + requestingUserId + ")"); 1049 } 1050 1051 return mutateSystemSetting(name, null, requestingUserId, MUTATION_OPERATION_DELETE); 1052 } 1053 1054 private boolean updateSystemSetting(String name, String value, int requestingUserId) { 1055 if (DEBUG) { 1056 Slog.v(LOG_TAG, "updateSystemSetting(" + name + ", " + value + ", " 1057 + requestingUserId + ")"); 1058 } 1059 1060 return mutateSystemSetting(name, value, requestingUserId, MUTATION_OPERATION_UPDATE); 1061 } 1062 1063 private boolean mutateSystemSetting(String name, String value, int runAsUserId, 1064 int operation) { 1065 if (!hasWriteSecureSettingsPermission()) { 1066 // If the caller doesn't hold WRITE_SECURE_SETTINGS, we verify whether this 1067 // operation is allowed for the calling package through appops. 1068 if (!Settings.checkAndNoteWriteSettingsOperation(getContext(), 1069 Binder.getCallingUid(), getCallingPackage(), true)) { 1070 return false; 1071 } 1072 } 1073 1074 // Resolve the userId on whose behalf the call is made. 1075 final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(runAsUserId); 1076 1077 // Enforce what the calling package can mutate the system settings. 1078 enforceRestrictedSystemSettingsMutationForCallingPackage(operation, name, callingUserId); 1079 1080 // Determine the owning user as some profile settings are cloned from the parent. 1081 final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name); 1082 1083 // Only the owning user id can change the setting. 1084 if (owningUserId != callingUserId) { 1085 return false; 1086 } 1087 1088 // Invalidate any relevant cache files 1089 String cacheName = null; 1090 if (Settings.System.RINGTONE.equals(name)) { 1091 cacheName = Settings.System.RINGTONE_CACHE; 1092 } else if (Settings.System.NOTIFICATION_SOUND.equals(name)) { 1093 cacheName = Settings.System.NOTIFICATION_SOUND_CACHE; 1094 } else if (Settings.System.ALARM_ALERT.equals(name)) { 1095 cacheName = Settings.System.ALARM_ALERT_CACHE; 1096 } 1097 if (cacheName != null) { 1098 final File cacheFile = new File( 1099 getRingtoneCacheDir(UserHandle.getCallingUserId()), cacheName); 1100 cacheFile.delete(); 1101 } 1102 1103 // Mutate the value. 1104 synchronized (mLock) { 1105 switch (operation) { 1106 case MUTATION_OPERATION_INSERT: { 1107 validateSystemSettingValue(name, value); 1108 return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SYSTEM, 1109 owningUserId, name, value, getCallingPackage(), false); 1110 } 1111 1112 case MUTATION_OPERATION_DELETE: { 1113 return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_SYSTEM, 1114 owningUserId, name, false); 1115 } 1116 1117 case MUTATION_OPERATION_UPDATE: { 1118 validateSystemSettingValue(name, value); 1119 return mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_SYSTEM, 1120 owningUserId, name, value, getCallingPackage(), false); 1121 } 1122 } 1123 1124 return false; 1125 } 1126 } 1127 1128 private boolean hasWriteSecureSettingsPermission() { 1129 // Write secure settings is a more protected permission. If caller has it we are good. 1130 if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS) 1131 == PackageManager.PERMISSION_GRANTED) { 1132 return true; 1133 } 1134 1135 return false; 1136 } 1137 1138 private void validateSystemSettingValue(String name, String value) { 1139 Settings.System.Validator validator = Settings.System.VALIDATORS.get(name); 1140 if (validator != null && !validator.validate(value)) { 1141 throw new IllegalArgumentException("Invalid value: " + value 1142 + " for setting: " + name); 1143 } 1144 } 1145 1146 private boolean isLocationProvidersAllowedRestricted(String name, int callingUserId, 1147 int owningUserId) { 1148 // Optimization - location providers are restricted only for managed profiles. 1149 if (callingUserId == owningUserId) { 1150 return false; 1151 } 1152 if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name) 1153 && mUserManager.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, 1154 new UserHandle(callingUserId))) { 1155 return true; 1156 } 1157 return false; 1158 } 1159 1160 /** 1161 * Checks whether changing a setting to a value is prohibited by the corresponding user 1162 * restriction. 1163 * 1164 * <p>See also {@link com.android.server.pm.UserRestrictionsUtils#applyUserRestriction( 1165 * Context, int, String, boolean)}, which should be in sync with this method. 1166 * 1167 * @return true if the change is prohibited, false if the change is allowed. 1168 */ 1169 private boolean isGlobalOrSecureSettingRestrictedForUser(String setting, int userId, 1170 String value, int callingUid) { 1171 String restriction; 1172 switch (setting) { 1173 case Settings.Secure.LOCATION_MODE: 1174 // Note LOCATION_MODE will be converted into LOCATION_PROVIDERS_ALLOWED 1175 // in android.provider.Settings.Secure.putStringForUser(), so we shouldn't come 1176 // here normally, but we still protect it here from a direct provider write. 1177 if (String.valueOf(Settings.Secure.LOCATION_MODE_OFF).equals(value)) return false; 1178 restriction = UserManager.DISALLOW_SHARE_LOCATION; 1179 break; 1180 1181 case Settings.Secure.LOCATION_PROVIDERS_ALLOWED: 1182 // See SettingsProvider.updateLocationProvidersAllowedLocked. "-" is to disable 1183 // a provider, which should be allowed even if the user restriction is set. 1184 if (value != null && value.startsWith("-")) return false; 1185 restriction = UserManager.DISALLOW_SHARE_LOCATION; 1186 break; 1187 1188 case Settings.Secure.INSTALL_NON_MARKET_APPS: 1189 if ("0".equals(value)) return false; 1190 restriction = UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES; 1191 break; 1192 1193 case Settings.Global.ADB_ENABLED: 1194 if ("0".equals(value)) return false; 1195 restriction = UserManager.DISALLOW_DEBUGGING_FEATURES; 1196 break; 1197 1198 case Settings.Global.PACKAGE_VERIFIER_ENABLE: 1199 case Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB: 1200 if ("1".equals(value)) return false; 1201 restriction = UserManager.ENSURE_VERIFY_APPS; 1202 break; 1203 1204 case Settings.Global.PREFERRED_NETWORK_MODE: 1205 restriction = UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS; 1206 break; 1207 1208 case Settings.Secure.ALWAYS_ON_VPN_APP: 1209 case Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN: 1210 // Whitelist system uid (ConnectivityService) and root uid to change always-on vpn 1211 if (callingUid == Process.SYSTEM_UID || callingUid == Process.ROOT_UID) { 1212 return false; 1213 } 1214 restriction = UserManager.DISALLOW_CONFIG_VPN; 1215 break; 1216 1217 case Settings.Global.SAFE_BOOT_DISALLOWED: 1218 if ("1".equals(value)) return false; 1219 restriction = UserManager.DISALLOW_SAFE_BOOT; 1220 break; 1221 1222 default: 1223 if (setting != null && setting.startsWith(Settings.Global.DATA_ROAMING)) { 1224 if ("0".equals(value)) return false; 1225 restriction = UserManager.DISALLOW_DATA_ROAMING; 1226 break; 1227 } 1228 return false; 1229 } 1230 1231 return mUserManager.hasUserRestriction(restriction, UserHandle.of(userId)); 1232 } 1233 1234 private int resolveOwningUserIdForSecureSettingLocked(int userId, String setting) { 1235 return resolveOwningUserIdLocked(userId, sSecureCloneToManagedSettings, setting); 1236 } 1237 1238 private int resolveOwningUserIdForSystemSettingLocked(int userId, String setting) { 1239 return resolveOwningUserIdLocked(userId, sSystemCloneToManagedSettings, setting); 1240 } 1241 1242 private int resolveOwningUserIdLocked(int userId, Set<String> keys, String name) { 1243 final int parentId = getGroupParentLocked(userId); 1244 if (parentId != userId && keys.contains(name)) { 1245 return parentId; 1246 } 1247 return userId; 1248 } 1249 1250 private void enforceRestrictedSystemSettingsMutationForCallingPackage(int operation, 1251 String name, int userId) { 1252 // System/root/shell can mutate whatever secure settings they want. 1253 final int callingUid = Binder.getCallingUid(); 1254 if (callingUid == android.os.Process.SYSTEM_UID 1255 || callingUid == Process.SHELL_UID 1256 || callingUid == Process.ROOT_UID) { 1257 return; 1258 } 1259 1260 switch (operation) { 1261 case MUTATION_OPERATION_INSERT: 1262 // Insert updates. 1263 case MUTATION_OPERATION_UPDATE: { 1264 if (Settings.System.PUBLIC_SETTINGS.contains(name)) { 1265 return; 1266 } 1267 1268 // The calling package is already verified. 1269 PackageInfo packageInfo = getCallingPackageInfoOrThrow(userId); 1270 1271 // Privileged apps can do whatever they want. 1272 if ((packageInfo.applicationInfo.privateFlags 1273 & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) { 1274 return; 1275 } 1276 1277 warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk( 1278 packageInfo.applicationInfo.targetSdkVersion, name); 1279 } break; 1280 1281 case MUTATION_OPERATION_DELETE: { 1282 if (Settings.System.PUBLIC_SETTINGS.contains(name) 1283 || Settings.System.PRIVATE_SETTINGS.contains(name)) { 1284 throw new IllegalArgumentException("You cannot delete system defined" 1285 + " secure settings."); 1286 } 1287 1288 // The calling package is already verified. 1289 PackageInfo packageInfo = getCallingPackageInfoOrThrow(userId); 1290 1291 // Privileged apps can do whatever they want. 1292 if ((packageInfo.applicationInfo.privateFlags & 1293 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) { 1294 return; 1295 } 1296 1297 warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk( 1298 packageInfo.applicationInfo.targetSdkVersion, name); 1299 } break; 1300 } 1301 } 1302 1303 private PackageInfo getCallingPackageInfoOrThrow(int userId) { 1304 try { 1305 PackageInfo packageInfo = mPackageManager.getPackageInfo( 1306 getCallingPackage(), 0, userId); 1307 if (packageInfo != null) { 1308 return packageInfo; 1309 } 1310 } catch (RemoteException e) { 1311 /* ignore */ 1312 } 1313 throw new IllegalStateException("Calling package doesn't exist"); 1314 } 1315 1316 private int getGroupParentLocked(int userId) { 1317 // Most frequent use case. 1318 if (userId == UserHandle.USER_SYSTEM) { 1319 return userId; 1320 } 1321 // We are in the same process with the user manager and the returned 1322 // user info is a cached instance, so just look up instead of cache. 1323 final long identity = Binder.clearCallingIdentity(); 1324 try { 1325 // Just a lookup and not reentrant, so holding a lock is fine. 1326 UserInfo userInfo = mUserManager.getProfileParent(userId); 1327 return (userInfo != null) ? userInfo.id : userId; 1328 } finally { 1329 Binder.restoreCallingIdentity(identity); 1330 } 1331 } 1332 1333 private void enforceWritePermission(String permission) { 1334 if (getContext().checkCallingOrSelfPermission(permission) 1335 != PackageManager.PERMISSION_GRANTED) { 1336 throw new SecurityException("Permission denial: writing to settings requires:" 1337 + permission); 1338 } 1339 } 1340 1341 /* 1342 * Used to parse changes to the value of Settings.Secure.LOCATION_PROVIDERS_ALLOWED. 1343 * This setting contains a list of the currently enabled location providers. 1344 * But helper functions in android.providers.Settings can enable or disable 1345 * a single provider by using a "+" or "-" prefix before the provider name. 1346 * 1347 * <p>See also {@link #isGlobalOrSecureSettingRestrictedForUser()}. If DISALLOW_SHARE_LOCATION 1348 * is set, the said method will only allow values with the "-" prefix. 1349 * 1350 * @returns whether the enabled location providers changed. 1351 */ 1352 private boolean updateLocationProvidersAllowedLocked(String value, int owningUserId, 1353 boolean forceNotify) { 1354 if (TextUtils.isEmpty(value)) { 1355 return false; 1356 } 1357 1358 final char prefix = value.charAt(0); 1359 if (prefix != '+' && prefix != '-') { 1360 if (forceNotify) { 1361 final int key = makeKey(SETTINGS_TYPE_SECURE, owningUserId); 1362 mSettingsRegistry.notifyForSettingsChange(key, 1363 Settings.Secure.LOCATION_PROVIDERS_ALLOWED); 1364 } 1365 return false; 1366 } 1367 1368 // skip prefix 1369 value = value.substring(1); 1370 1371 Setting settingValue = getSecureSetting( 1372 Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId); 1373 1374 String oldProviders = (settingValue != null) ? settingValue.getValue() : ""; 1375 1376 int index = oldProviders.indexOf(value); 1377 int end = index + value.length(); 1378 1379 // check for commas to avoid matching on partial string 1380 if (index > 0 && oldProviders.charAt(index - 1) != ',') { 1381 index = -1; 1382 } 1383 1384 // check for commas to avoid matching on partial string 1385 if (end < oldProviders.length() && oldProviders.charAt(end) != ',') { 1386 index = -1; 1387 } 1388 1389 String newProviders; 1390 1391 if (prefix == '+' && index < 0) { 1392 // append the provider to the list if not present 1393 if (oldProviders.length() == 0) { 1394 newProviders = value; 1395 } else { 1396 newProviders = oldProviders + ',' + value; 1397 } 1398 } else if (prefix == '-' && index >= 0) { 1399 // remove the provider from the list if present 1400 // remove leading or trailing comma 1401 if (index > 0) { 1402 index--; 1403 } else if (end < oldProviders.length()) { 1404 end++; 1405 } 1406 1407 newProviders = oldProviders.substring(0, index); 1408 if (end < oldProviders.length()) { 1409 newProviders += oldProviders.substring(end); 1410 } 1411 } else { 1412 // nothing changed, so no need to update the database 1413 if (forceNotify) { 1414 final int key = makeKey(SETTINGS_TYPE_SECURE, owningUserId); 1415 mSettingsRegistry.notifyForSettingsChange(key, 1416 Settings.Secure.LOCATION_PROVIDERS_ALLOWED); 1417 } 1418 return false; 1419 } 1420 1421 return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SECURE, 1422 owningUserId, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, newProviders, 1423 getCallingPackage(), forceNotify); 1424 } 1425 1426 private static void warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk( 1427 int targetSdkVersion, String name) { 1428 // If the app targets Lollipop MR1 or older SDK we warn, otherwise crash. 1429 if (targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1) { 1430 if (Settings.System.PRIVATE_SETTINGS.contains(name)) { 1431 Slog.w(LOG_TAG, "You shouldn't not change private system settings." 1432 + " This will soon become an error."); 1433 } else { 1434 Slog.w(LOG_TAG, "You shouldn't keep your settings in the secure settings." 1435 + " This will soon become an error."); 1436 } 1437 } else { 1438 if (Settings.System.PRIVATE_SETTINGS.contains(name)) { 1439 throw new IllegalArgumentException("You cannot change private secure settings."); 1440 } else { 1441 throw new IllegalArgumentException("You cannot keep your settings in" 1442 + " the secure settings."); 1443 } 1444 } 1445 } 1446 1447 private static int resolveCallingUserIdEnforcingPermissionsLocked(int requestingUserId) { 1448 if (requestingUserId == UserHandle.getCallingUserId()) { 1449 return requestingUserId; 1450 } 1451 return ActivityManager.handleIncomingUser(Binder.getCallingPid(), 1452 Binder.getCallingUid(), requestingUserId, false, true, 1453 "get/set setting for user", null); 1454 } 1455 1456 private Bundle packageValueForCallResult(Setting setting, 1457 boolean trackingGeneration) { 1458 if (!trackingGeneration) { 1459 if (setting.isNull()) { 1460 return NULL_SETTING_BUNDLE; 1461 } 1462 return Bundle.forPair(Settings.NameValueTable.VALUE, setting.getValue()); 1463 } 1464 Bundle result = new Bundle(); 1465 result.putString(Settings.NameValueTable.VALUE, 1466 !setting.isNull() ? setting.getValue() : null); 1467 mSettingsRegistry.mGenerationRegistry.addGenerationData(result, setting.getkey()); 1468 return result; 1469 } 1470 1471 private static int getRequestingUserId(Bundle args) { 1472 final int callingUserId = UserHandle.getCallingUserId(); 1473 return (args != null) ? args.getInt(Settings.CALL_METHOD_USER_KEY, callingUserId) 1474 : callingUserId; 1475 } 1476 1477 private boolean isTrackingGeneration(Bundle args) { 1478 return args != null && args.containsKey(Settings.CALL_METHOD_TRACK_GENERATION_KEY); 1479 } 1480 1481 private static String getSettingValue(Bundle args) { 1482 return (args != null) ? args.getString(Settings.NameValueTable.VALUE) : null; 1483 } 1484 1485 private static String getValidTableOrThrow(Uri uri) { 1486 if (uri.getPathSegments().size() > 0) { 1487 String table = uri.getPathSegments().get(0); 1488 if (DatabaseHelper.isValidTable(table)) { 1489 return table; 1490 } 1491 throw new IllegalArgumentException("Bad root path: " + table); 1492 } 1493 throw new IllegalArgumentException("Invalid URI:" + uri); 1494 } 1495 1496 private static MatrixCursor packageSettingForQuery(Setting setting, String[] projection) { 1497 if (setting.isNull()) { 1498 return new MatrixCursor(projection, 0); 1499 } 1500 MatrixCursor cursor = new MatrixCursor(projection, 1); 1501 appendSettingToCursor(cursor, setting); 1502 return cursor; 1503 } 1504 1505 private static String[] normalizeProjection(String[] projection) { 1506 if (projection == null) { 1507 return ALL_COLUMNS; 1508 } 1509 1510 final int columnCount = projection.length; 1511 for (int i = 0; i < columnCount; i++) { 1512 String column = projection[i]; 1513 if (!ArrayUtils.contains(ALL_COLUMNS, column)) { 1514 throw new IllegalArgumentException("Invalid column: " + column); 1515 } 1516 } 1517 1518 return projection; 1519 } 1520 1521 private static void appendSettingToCursor(MatrixCursor cursor, Setting setting) { 1522 if (setting.isNull()) { 1523 return; 1524 } 1525 final int columnCount = cursor.getColumnCount(); 1526 1527 String[] values = new String[columnCount]; 1528 1529 for (int i = 0; i < columnCount; i++) { 1530 String column = cursor.getColumnName(i); 1531 1532 switch (column) { 1533 case Settings.NameValueTable._ID: { 1534 values[i] = setting.getId(); 1535 } break; 1536 1537 case Settings.NameValueTable.NAME: { 1538 values[i] = setting.getName(); 1539 } break; 1540 1541 case Settings.NameValueTable.VALUE: { 1542 values[i] = setting.getValue(); 1543 } break; 1544 } 1545 } 1546 1547 cursor.addRow(values); 1548 } 1549 1550 private static boolean isKeyValid(String key) { 1551 return !(TextUtils.isEmpty(key) || SettingsState.isBinary(key)); 1552 } 1553 1554 private static final class Arguments { 1555 private static final Pattern WHERE_PATTERN_WITH_PARAM_NO_BRACKETS = 1556 Pattern.compile("[\\s]*name[\\s]*=[\\s]*\\?[\\s]*"); 1557 1558 private static final Pattern WHERE_PATTERN_WITH_PARAM_IN_BRACKETS = 1559 Pattern.compile("[\\s]*\\([\\s]*name[\\s]*=[\\s]*\\?[\\s]*\\)[\\s]*"); 1560 1561 private static final Pattern WHERE_PATTERN_NO_PARAM_IN_BRACKETS = 1562 Pattern.compile("[\\s]*\\([\\s]*name[\\s]*=[\\s]*['\"].*['\"][\\s]*\\)[\\s]*"); 1563 1564 private static final Pattern WHERE_PATTERN_NO_PARAM_NO_BRACKETS = 1565 Pattern.compile("[\\s]*name[\\s]*=[\\s]*['\"].*['\"][\\s]*"); 1566 1567 public final String table; 1568 public final String name; 1569 1570 public Arguments(Uri uri, String where, String[] whereArgs, boolean supportAll) { 1571 final int segmentSize = uri.getPathSegments().size(); 1572 switch (segmentSize) { 1573 case 1: { 1574 if (where != null 1575 && (WHERE_PATTERN_WITH_PARAM_NO_BRACKETS.matcher(where).matches() 1576 || WHERE_PATTERN_WITH_PARAM_IN_BRACKETS.matcher(where).matches()) 1577 && whereArgs.length == 1) { 1578 name = whereArgs[0]; 1579 table = computeTableForSetting(uri, name); 1580 return; 1581 } else if (where != null 1582 && (WHERE_PATTERN_NO_PARAM_NO_BRACKETS.matcher(where).matches() 1583 || WHERE_PATTERN_NO_PARAM_IN_BRACKETS.matcher(where).matches())) { 1584 final int startIndex = Math.max(where.indexOf("'"), 1585 where.indexOf("\"")) + 1; 1586 final int endIndex = Math.max(where.lastIndexOf("'"), 1587 where.lastIndexOf("\"")); 1588 name = where.substring(startIndex, endIndex); 1589 table = computeTableForSetting(uri, name); 1590 return; 1591 } else if (supportAll && where == null && whereArgs == null) { 1592 name = null; 1593 table = computeTableForSetting(uri, null); 1594 return; 1595 } 1596 } break; 1597 1598 case 2: { 1599 if (where == null && whereArgs == null) { 1600 name = uri.getPathSegments().get(1); 1601 table = computeTableForSetting(uri, name); 1602 return; 1603 } 1604 } break; 1605 } 1606 1607 EventLogTags.writeUnsupportedSettingsQuery( 1608 uri.toSafeString(), where, Arrays.toString(whereArgs)); 1609 String message = String.format( "Supported SQL:\n" 1610 + " uri content://some_table/some_property with null where and where args\n" 1611 + " uri content://some_table with query name=? and single name as arg\n" 1612 + " uri content://some_table with query name=some_name and null args\n" 1613 + " but got - uri:%1s, where:%2s whereArgs:%3s", uri, where, 1614 Arrays.toString(whereArgs)); 1615 throw new IllegalArgumentException(message); 1616 } 1617 1618 private static String computeTableForSetting(Uri uri, String name) { 1619 String table = getValidTableOrThrow(uri); 1620 1621 if (name != null) { 1622 if (sSystemMovedToSecureSettings.contains(name)) { 1623 table = TABLE_SECURE; 1624 } 1625 1626 if (sSystemMovedToGlobalSettings.contains(name)) { 1627 table = TABLE_GLOBAL; 1628 } 1629 1630 if (sSecureMovedToGlobalSettings.contains(name)) { 1631 table = TABLE_GLOBAL; 1632 } 1633 1634 if (sGlobalMovedToSecureSettings.contains(name)) { 1635 table = TABLE_SECURE; 1636 } 1637 } 1638 1639 return table; 1640 } 1641 } 1642 1643 final class SettingsRegistry { 1644 private static final String DROPBOX_TAG_USERLOG = "restricted_profile_ssaid"; 1645 1646 private static final String SETTINGS_FILE_GLOBAL = "settings_global.xml"; 1647 private static final String SETTINGS_FILE_SYSTEM = "settings_system.xml"; 1648 private static final String SETTINGS_FILE_SECURE = "settings_secure.xml"; 1649 1650 private final SparseArray<SettingsState> mSettingsStates = new SparseArray<>(); 1651 1652 private GenerationRegistry mGenerationRegistry; 1653 1654 private final Handler mHandler; 1655 1656 private final BackupManager mBackupManager; 1657 1658 public SettingsRegistry() { 1659 mHandler = new MyHandler(getContext().getMainLooper()); 1660 mGenerationRegistry = new GenerationRegistry(mLock); 1661 mBackupManager = new BackupManager(getContext()); 1662 migrateAllLegacySettingsIfNeeded(); 1663 } 1664 1665 public List<String> getSettingsNamesLocked(int type, int userId) { 1666 final int key = makeKey(type, userId); 1667 SettingsState settingsState = peekSettingsStateLocked(key); 1668 return settingsState.getSettingNamesLocked(); 1669 } 1670 1671 public SettingsState getSettingsLocked(int type, int userId) { 1672 final int key = makeKey(type, userId); 1673 return peekSettingsStateLocked(key); 1674 } 1675 1676 public void ensureSettingsForUserLocked(int userId) { 1677 // Migrate the setting for this user if needed. 1678 migrateLegacySettingsForUserIfNeededLocked(userId); 1679 1680 // Ensure global settings loaded if owner. 1681 if (userId == UserHandle.USER_SYSTEM) { 1682 final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM); 1683 ensureSettingsStateLocked(globalKey); 1684 } 1685 1686 // Ensure secure settings loaded. 1687 final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId); 1688 ensureSettingsStateLocked(secureKey); 1689 1690 // Make sure the secure settings have an Android id set. 1691 SettingsState secureSettings = getSettingsLocked(SETTINGS_TYPE_SECURE, userId); 1692 ensureSecureSettingAndroidIdSetLocked(secureSettings); 1693 1694 // Ensure system settings loaded. 1695 final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId); 1696 ensureSettingsStateLocked(systemKey); 1697 1698 // Upgrade the settings to the latest version. 1699 UpgradeController upgrader = new UpgradeController(userId); 1700 upgrader.upgradeIfNeededLocked(); 1701 } 1702 1703 private void ensureSettingsStateLocked(int key) { 1704 if (mSettingsStates.get(key) == null) { 1705 final int maxBytesPerPackage = getMaxBytesPerPackageForType(getTypeFromKey(key)); 1706 SettingsState settingsState = new SettingsState(mLock, getSettingsFile(key), key, 1707 maxBytesPerPackage, mHandlerThread.getLooper()); 1708 mSettingsStates.put(key, settingsState); 1709 } 1710 } 1711 1712 public void removeUserStateLocked(int userId, boolean permanently) { 1713 // We always keep the global settings in memory. 1714 1715 // Nuke system settings. 1716 final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId); 1717 final SettingsState systemSettingsState = mSettingsStates.get(systemKey); 1718 if (systemSettingsState != null) { 1719 if (permanently) { 1720 mSettingsStates.remove(systemKey); 1721 systemSettingsState.destroyLocked(null); 1722 } else { 1723 systemSettingsState.destroyLocked(new Runnable() { 1724 @Override 1725 public void run() { 1726 mSettingsStates.remove(systemKey); 1727 } 1728 }); 1729 } 1730 } 1731 1732 // Nuke secure settings. 1733 final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId); 1734 final SettingsState secureSettingsState = mSettingsStates.get(secureKey); 1735 if (secureSettingsState != null) { 1736 if (permanently) { 1737 mSettingsStates.remove(secureKey); 1738 secureSettingsState.destroyLocked(null); 1739 } else { 1740 secureSettingsState.destroyLocked(new Runnable() { 1741 @Override 1742 public void run() { 1743 mSettingsStates.remove(secureKey); 1744 } 1745 }); 1746 } 1747 } 1748 1749 // Nuke generation tracking data 1750 mGenerationRegistry.onUserRemoved(userId); 1751 } 1752 1753 public boolean insertSettingLocked(int type, int userId, String name, String value, 1754 String packageName, boolean forceNotify) { 1755 final int key = makeKey(type, userId); 1756 1757 SettingsState settingsState = peekSettingsStateLocked(key); 1758 final boolean success = settingsState.insertSettingLocked(name, value, packageName); 1759 1760 if (forceNotify || success) { 1761 notifyForSettingsChange(key, name); 1762 } 1763 return success; 1764 } 1765 1766 public boolean deleteSettingLocked(int type, int userId, String name, boolean forceNotify) { 1767 final int key = makeKey(type, userId); 1768 1769 SettingsState settingsState = peekSettingsStateLocked(key); 1770 final boolean success = settingsState.deleteSettingLocked(name); 1771 1772 if (forceNotify || success) { 1773 notifyForSettingsChange(key, name); 1774 } 1775 return success; 1776 } 1777 1778 public Setting getSettingLocked(int type, int userId, String name) { 1779 final int key = makeKey(type, userId); 1780 1781 SettingsState settingsState = peekSettingsStateLocked(key); 1782 return settingsState.getSettingLocked(name); 1783 } 1784 1785 public boolean updateSettingLocked(int type, int userId, String name, String value, 1786 String packageName, boolean forceNotify) { 1787 final int key = makeKey(type, userId); 1788 1789 SettingsState settingsState = peekSettingsStateLocked(key); 1790 final boolean success = settingsState.updateSettingLocked(name, value, packageName); 1791 1792 if (forceNotify || success) { 1793 notifyForSettingsChange(key, name); 1794 } 1795 1796 return success; 1797 } 1798 1799 public void onPackageRemovedLocked(String packageName, int userId) { 1800 // Global and secure settings are signature protected. Apps signed 1801 // by the platform certificate are generally not uninstalled and 1802 // the main exception is tests. We trust components signed 1803 // by the platform certificate and do not do a clean up after them. 1804 1805 final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId); 1806 SettingsState systemSettings = mSettingsStates.get(systemKey); 1807 if (systemSettings != null) { 1808 systemSettings.onPackageRemovedLocked(packageName); 1809 } 1810 } 1811 1812 private SettingsState peekSettingsStateLocked(int key) { 1813 SettingsState settingsState = mSettingsStates.get(key); 1814 if (settingsState != null) { 1815 return settingsState; 1816 } 1817 1818 ensureSettingsForUserLocked(getUserIdFromKey(key)); 1819 return mSettingsStates.get(key); 1820 } 1821 1822 private void migrateAllLegacySettingsIfNeeded() { 1823 synchronized (mLock) { 1824 final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM); 1825 File globalFile = getSettingsFile(key); 1826 if (globalFile.exists()) { 1827 return; 1828 } 1829 1830 final long identity = Binder.clearCallingIdentity(); 1831 try { 1832 List<UserInfo> users = mUserManager.getUsers(true); 1833 1834 final int userCount = users.size(); 1835 for (int i = 0; i < userCount; i++) { 1836 final int userId = users.get(i).id; 1837 1838 DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId); 1839 SQLiteDatabase database = dbHelper.getWritableDatabase(); 1840 migrateLegacySettingsForUserLocked(dbHelper, database, userId); 1841 1842 // Upgrade to the latest version. 1843 UpgradeController upgrader = new UpgradeController(userId); 1844 upgrader.upgradeIfNeededLocked(); 1845 1846 // Drop from memory if not a running user. 1847 if (!mUserManager.isUserRunning(new UserHandle(userId))) { 1848 removeUserStateLocked(userId, false); 1849 } 1850 } 1851 } finally { 1852 Binder.restoreCallingIdentity(identity); 1853 } 1854 } 1855 } 1856 1857 private void migrateLegacySettingsForUserIfNeededLocked(int userId) { 1858 // Every user has secure settings and if no file we need to migrate. 1859 final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId); 1860 File secureFile = getSettingsFile(secureKey); 1861 if (secureFile.exists()) { 1862 return; 1863 } 1864 1865 DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId); 1866 SQLiteDatabase database = dbHelper.getWritableDatabase(); 1867 1868 migrateLegacySettingsForUserLocked(dbHelper, database, userId); 1869 } 1870 1871 private void migrateLegacySettingsForUserLocked(DatabaseHelper dbHelper, 1872 SQLiteDatabase database, int userId) { 1873 // Move over the system settings. 1874 final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId); 1875 ensureSettingsStateLocked(systemKey); 1876 SettingsState systemSettings = mSettingsStates.get(systemKey); 1877 migrateLegacySettingsLocked(systemSettings, database, TABLE_SYSTEM); 1878 systemSettings.persistSyncLocked(); 1879 1880 // Move over the secure settings. 1881 // Do this after System settings, since this is the first thing we check when deciding 1882 // to skip over migration from db to xml for a secondary user. 1883 final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId); 1884 ensureSettingsStateLocked(secureKey); 1885 SettingsState secureSettings = mSettingsStates.get(secureKey); 1886 migrateLegacySettingsLocked(secureSettings, database, TABLE_SECURE); 1887 ensureSecureSettingAndroidIdSetLocked(secureSettings); 1888 secureSettings.persistSyncLocked(); 1889 1890 // Move over the global settings if owner. 1891 // Do this last, since this is the first thing we check when deciding 1892 // to skip over migration from db to xml for owner user. 1893 if (userId == UserHandle.USER_SYSTEM) { 1894 final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, userId); 1895 ensureSettingsStateLocked(globalKey); 1896 SettingsState globalSettings = mSettingsStates.get(globalKey); 1897 migrateLegacySettingsLocked(globalSettings, database, TABLE_GLOBAL); 1898 globalSettings.persistSyncLocked(); 1899 } 1900 1901 // Drop the database as now all is moved and persisted. 1902 if (DROP_DATABASE_ON_MIGRATION) { 1903 dbHelper.dropDatabase(); 1904 } else { 1905 dbHelper.backupDatabase(); 1906 } 1907 } 1908 1909 private void migrateLegacySettingsLocked(SettingsState settingsState, 1910 SQLiteDatabase database, String table) { 1911 SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); 1912 queryBuilder.setTables(table); 1913 1914 Cursor cursor = queryBuilder.query(database, ALL_COLUMNS, 1915 null, null, null, null, null); 1916 1917 if (cursor == null) { 1918 return; 1919 } 1920 1921 try { 1922 if (!cursor.moveToFirst()) { 1923 return; 1924 } 1925 1926 final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME); 1927 final int valueColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.VALUE); 1928 1929 settingsState.setVersionLocked(database.getVersion()); 1930 1931 while (!cursor.isAfterLast()) { 1932 String name = cursor.getString(nameColumnIdx); 1933 String value = cursor.getString(valueColumnIdx); 1934 settingsState.insertSettingLocked(name, value, 1935 SettingsState.SYSTEM_PACKAGE_NAME); 1936 cursor.moveToNext(); 1937 } 1938 } finally { 1939 cursor.close(); 1940 } 1941 } 1942 1943 private void ensureSecureSettingAndroidIdSetLocked(SettingsState secureSettings) { 1944 Setting value = secureSettings.getSettingLocked(Settings.Secure.ANDROID_ID); 1945 1946 if (!value.isNull()) { 1947 return; 1948 } 1949 1950 final int userId = getUserIdFromKey(secureSettings.mKey); 1951 1952 final UserInfo user; 1953 final long identity = Binder.clearCallingIdentity(); 1954 try { 1955 user = mUserManager.getUserInfo(userId); 1956 } finally { 1957 Binder.restoreCallingIdentity(identity); 1958 } 1959 if (user == null) { 1960 // Can happen due to races when deleting users - treat as benign. 1961 return; 1962 } 1963 1964 String androidId = Long.toHexString(new SecureRandom().nextLong()); 1965 secureSettings.insertSettingLocked(Settings.Secure.ANDROID_ID, androidId, 1966 SettingsState.SYSTEM_PACKAGE_NAME); 1967 1968 Slog.d(LOG_TAG, "Generated and saved new ANDROID_ID [" + androidId 1969 + "] for user " + userId); 1970 1971 // Write a drop box entry if it's a restricted profile 1972 if (user.isRestricted()) { 1973 DropBoxManager dbm = (DropBoxManager) getContext().getSystemService( 1974 Context.DROPBOX_SERVICE); 1975 if (dbm != null && dbm.isTagEnabled(DROPBOX_TAG_USERLOG)) { 1976 dbm.addText(DROPBOX_TAG_USERLOG, System.currentTimeMillis() 1977 + "," + DROPBOX_TAG_USERLOG + "," + androidId + "\n"); 1978 } 1979 } 1980 } 1981 1982 private void notifyForSettingsChange(int key, String name) { 1983 final int userId = getUserIdFromKey(key); 1984 Uri uri = getNotificationUriFor(key, name); 1985 1986 mGenerationRegistry.incrementGeneration(key); 1987 1988 mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED, 1989 userId, 0, uri).sendToTarget(); 1990 1991 if (isSecureSettingsKey(key)) { 1992 maybeNotifyProfiles(getTypeFromKey(key), userId, uri, name, 1993 sSecureCloneToManagedSettings); 1994 } else if (isSystemSettingsKey(key)) { 1995 maybeNotifyProfiles(getTypeFromKey(key), userId, uri, name, 1996 sSystemCloneToManagedSettings); 1997 } 1998 1999 mHandler.obtainMessage(MyHandler.MSG_NOTIFY_DATA_CHANGED).sendToTarget(); 2000 } 2001 2002 private void maybeNotifyProfiles(int type, int userId, Uri uri, String name, 2003 Set<String> keysCloned) { 2004 if (keysCloned.contains(name)) { 2005 for (int profileId : mUserManager.getProfileIdsWithDisabled(userId)) { 2006 // the notification for userId has already been sent. 2007 if (profileId != userId) { 2008 mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED, 2009 profileId, 0, uri).sendToTarget(); 2010 final int key = makeKey(type, profileId); 2011 mGenerationRegistry.incrementGeneration(key); 2012 2013 mHandler.obtainMessage(MyHandler.MSG_NOTIFY_DATA_CHANGED).sendToTarget(); 2014 } 2015 } 2016 } 2017 } 2018 2019 private boolean isGlobalSettingsKey(int key) { 2020 return getTypeFromKey(key) == SETTINGS_TYPE_GLOBAL; 2021 } 2022 2023 private boolean isSystemSettingsKey(int key) { 2024 return getTypeFromKey(key) == SETTINGS_TYPE_SYSTEM; 2025 } 2026 2027 private boolean isSecureSettingsKey(int key) { 2028 return getTypeFromKey(key) == SETTINGS_TYPE_SECURE; 2029 } 2030 2031 private File getSettingsFile(int key) { 2032 if (isGlobalSettingsKey(key)) { 2033 final int userId = getUserIdFromKey(key); 2034 return new File(Environment.getUserSystemDirectory(userId), 2035 SETTINGS_FILE_GLOBAL); 2036 } else if (isSystemSettingsKey(key)) { 2037 final int userId = getUserIdFromKey(key); 2038 return new File(Environment.getUserSystemDirectory(userId), 2039 SETTINGS_FILE_SYSTEM); 2040 } else if (isSecureSettingsKey(key)) { 2041 final int userId = getUserIdFromKey(key); 2042 return new File(Environment.getUserSystemDirectory(userId), 2043 SETTINGS_FILE_SECURE); 2044 } else { 2045 throw new IllegalArgumentException("Invalid settings key:" + key); 2046 } 2047 } 2048 2049 private Uri getNotificationUriFor(int key, String name) { 2050 if (isGlobalSettingsKey(key)) { 2051 return (name != null) ? Uri.withAppendedPath(Settings.Global.CONTENT_URI, name) 2052 : Settings.Global.CONTENT_URI; 2053 } else if (isSecureSettingsKey(key)) { 2054 return (name != null) ? Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name) 2055 : Settings.Secure.CONTENT_URI; 2056 } else if (isSystemSettingsKey(key)) { 2057 return (name != null) ? Uri.withAppendedPath(Settings.System.CONTENT_URI, name) 2058 : Settings.System.CONTENT_URI; 2059 } else { 2060 throw new IllegalArgumentException("Invalid settings key:" + key); 2061 } 2062 } 2063 2064 private int getMaxBytesPerPackageForType(int type) { 2065 switch (type) { 2066 case SETTINGS_TYPE_GLOBAL: 2067 case SETTINGS_TYPE_SECURE: { 2068 return SettingsState.MAX_BYTES_PER_APP_PACKAGE_UNLIMITED; 2069 } 2070 2071 default: { 2072 return SettingsState.MAX_BYTES_PER_APP_PACKAGE_LIMITED; 2073 } 2074 } 2075 } 2076 2077 private final class MyHandler extends Handler { 2078 private static final int MSG_NOTIFY_URI_CHANGED = 1; 2079 private static final int MSG_NOTIFY_DATA_CHANGED = 2; 2080 2081 public MyHandler(Looper looper) { 2082 super(looper); 2083 } 2084 2085 @Override 2086 public void handleMessage(Message msg) { 2087 switch (msg.what) { 2088 case MSG_NOTIFY_URI_CHANGED: { 2089 final int userId = msg.arg1; 2090 Uri uri = (Uri) msg.obj; 2091 getContext().getContentResolver().notifyChange(uri, null, true, userId); 2092 if (DEBUG) { 2093 Slog.v(LOG_TAG, "Notifying for " + userId + ": " + uri); 2094 } 2095 } break; 2096 2097 case MSG_NOTIFY_DATA_CHANGED: { 2098 mBackupManager.dataChanged(); 2099 } break; 2100 } 2101 } 2102 } 2103 2104 private final class UpgradeController { 2105 private static final int SETTINGS_VERSION = 130; 2106 2107 private final int mUserId; 2108 2109 public UpgradeController(int userId) { 2110 mUserId = userId; 2111 } 2112 2113 public void upgradeIfNeededLocked() { 2114 // The version of all settings for a user is the same (all users have secure). 2115 SettingsState secureSettings = getSettingsLocked( 2116 SETTINGS_TYPE_SECURE, mUserId); 2117 2118 // Try an update from the current state. 2119 final int oldVersion = secureSettings.getVersionLocked(); 2120 final int newVersion = SETTINGS_VERSION; 2121 2122 // If up do date - done. 2123 if (oldVersion == newVersion) { 2124 return; 2125 } 2126 2127 // Try to upgrade. 2128 final int curVersion = onUpgradeLocked(mUserId, oldVersion, newVersion); 2129 2130 // If upgrade failed start from scratch and upgrade. 2131 if (curVersion != newVersion) { 2132 // Drop state we have for this user. 2133 removeUserStateLocked(mUserId, true); 2134 2135 // Recreate the database. 2136 DatabaseHelper dbHelper = new DatabaseHelper(getContext(), mUserId); 2137 SQLiteDatabase database = dbHelper.getWritableDatabase(); 2138 dbHelper.recreateDatabase(database, newVersion, curVersion, oldVersion); 2139 2140 // Migrate the settings for this user. 2141 migrateLegacySettingsForUserLocked(dbHelper, database, mUserId); 2142 2143 // Now upgrade should work fine. 2144 onUpgradeLocked(mUserId, oldVersion, newVersion); 2145 } 2146 2147 // Set the global settings version if owner. 2148 if (mUserId == UserHandle.USER_SYSTEM) { 2149 SettingsState globalSettings = getSettingsLocked( 2150 SETTINGS_TYPE_GLOBAL, mUserId); 2151 globalSettings.setVersionLocked(newVersion); 2152 } 2153 2154 // Set the secure settings version. 2155 secureSettings.setVersionLocked(newVersion); 2156 2157 // Set the system settings version. 2158 SettingsState systemSettings = getSettingsLocked( 2159 SETTINGS_TYPE_SYSTEM, mUserId); 2160 systemSettings.setVersionLocked(newVersion); 2161 } 2162 2163 private SettingsState getGlobalSettingsLocked() { 2164 return getSettingsLocked(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM); 2165 } 2166 2167 private SettingsState getSecureSettingsLocked(int userId) { 2168 return getSettingsLocked(SETTINGS_TYPE_SECURE, userId); 2169 } 2170 2171 private SettingsState getSystemSettingsLocked(int userId) { 2172 return getSettingsLocked(SETTINGS_TYPE_SYSTEM, userId); 2173 } 2174 2175 /** 2176 * You must perform all necessary mutations to bring the settings 2177 * for this user from the old to the new version. When you add a new 2178 * upgrade step you *must* update SETTINGS_VERSION. 2179 * 2180 * This is an example of moving a setting from secure to global. 2181 * 2182 * // v119: Example settings changes. 2183 * if (currentVersion == 118) { 2184 * if (userId == UserHandle.USER_OWNER) { 2185 * // Remove from the secure settings. 2186 * SettingsState secureSettings = getSecureSettingsLocked(userId); 2187 * String name = "example_setting_to_move"; 2188 * String value = secureSettings.getSetting(name); 2189 * secureSettings.deleteSetting(name); 2190 * 2191 * // Add to the global settings. 2192 * SettingsState globalSettings = getGlobalSettingsLocked(); 2193 * globalSettings.insertSetting(name, value, SettingsState.SYSTEM_PACKAGE_NAME); 2194 * } 2195 * 2196 * // Update the current version. 2197 * currentVersion = 119; 2198 * } 2199 */ 2200 private int onUpgradeLocked(int userId, int oldVersion, int newVersion) { 2201 if (DEBUG) { 2202 Slog.w(LOG_TAG, "Upgrading settings for user: " + userId + " from version: " 2203 + oldVersion + " to version: " + newVersion); 2204 } 2205 2206 int currentVersion = oldVersion; 2207 2208 // v119: Reset zen + ringer mode. 2209 if (currentVersion == 118) { 2210 if (userId == UserHandle.USER_SYSTEM) { 2211 final SettingsState globalSettings = getGlobalSettingsLocked(); 2212 globalSettings.updateSettingLocked(Settings.Global.ZEN_MODE, 2213 Integer.toString(Settings.Global.ZEN_MODE_OFF), 2214 SettingsState.SYSTEM_PACKAGE_NAME); 2215 globalSettings.updateSettingLocked(Settings.Global.MODE_RINGER, 2216 Integer.toString(AudioManager.RINGER_MODE_NORMAL), 2217 SettingsState.SYSTEM_PACKAGE_NAME); 2218 } 2219 currentVersion = 119; 2220 } 2221 2222 // v120: Add double tap to wake setting. 2223 if (currentVersion == 119) { 2224 SettingsState secureSettings = getSecureSettingsLocked(userId); 2225 secureSettings.insertSettingLocked(Settings.Secure.DOUBLE_TAP_TO_WAKE, 2226 getContext().getResources().getBoolean( 2227 R.bool.def_double_tap_to_wake) ? "1" : "0", 2228 SettingsState.SYSTEM_PACKAGE_NAME); 2229 2230 currentVersion = 120; 2231 } 2232 2233 if (currentVersion == 120) { 2234 // Before 121, we used a different string encoding logic. We just bump the 2235 // version here; SettingsState knows how to handle pre-version 120 files. 2236 currentVersion = 121; 2237 } 2238 2239 if (currentVersion == 121) { 2240 // Version 122: allow OEMs to set a default payment component in resources. 2241 // Note that we only write the default if no default has been set; 2242 // if there is, we just leave the default at whatever it currently is. 2243 final SettingsState secureSettings = getSecureSettingsLocked(userId); 2244 String defaultComponent = (getContext().getResources().getString( 2245 R.string.def_nfc_payment_component)); 2246 Setting currentSetting = secureSettings.getSettingLocked( 2247 Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT); 2248 if (defaultComponent != null && !defaultComponent.isEmpty() && 2249 currentSetting.isNull()) { 2250 secureSettings.insertSettingLocked( 2251 Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT, 2252 defaultComponent, 2253 SettingsState.SYSTEM_PACKAGE_NAME); 2254 } 2255 currentVersion = 122; 2256 } 2257 2258 if (currentVersion == 122) { 2259 // Version 123: Adding a default value for the ability to add a user from 2260 // the lock screen. 2261 if (userId == UserHandle.USER_SYSTEM) { 2262 final SettingsState globalSettings = getGlobalSettingsLocked(); 2263 Setting currentSetting = globalSettings.getSettingLocked( 2264 Settings.Global.ADD_USERS_WHEN_LOCKED); 2265 if (currentSetting.isNull()) { 2266 globalSettings.insertSettingLocked( 2267 Settings.Global.ADD_USERS_WHEN_LOCKED, 2268 getContext().getResources().getBoolean( 2269 R.bool.def_add_users_from_lockscreen) ? "1" : "0", 2270 SettingsState.SYSTEM_PACKAGE_NAME); 2271 } 2272 } 2273 currentVersion = 123; 2274 } 2275 2276 if (currentVersion == 123) { 2277 final SettingsState globalSettings = getGlobalSettingsLocked(); 2278 String defaultDisabledProfiles = (getContext().getResources().getString( 2279 R.string.def_bluetooth_disabled_profiles)); 2280 globalSettings.insertSettingLocked(Settings.Global.BLUETOOTH_DISABLED_PROFILES, 2281 defaultDisabledProfiles, SettingsState.SYSTEM_PACKAGE_NAME); 2282 currentVersion = 124; 2283 } 2284 2285 if (currentVersion == 124) { 2286 // Version 124: allow OEMs to set a default value for whether IME should be 2287 // shown when a physical keyboard is connected. 2288 final SettingsState secureSettings = getSecureSettingsLocked(userId); 2289 Setting currentSetting = secureSettings.getSettingLocked( 2290 Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD); 2291 if (currentSetting.isNull()) { 2292 secureSettings.insertSettingLocked( 2293 Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 2294 getContext().getResources().getBoolean( 2295 R.bool.def_show_ime_with_hard_keyboard) ? "1" : "0", 2296 SettingsState.SYSTEM_PACKAGE_NAME); 2297 } 2298 currentVersion = 125; 2299 } 2300 2301 if (currentVersion == 125) { 2302 // Version 125: Allow OEMs to set the default VR service. 2303 final SettingsState secureSettings = getSecureSettingsLocked(userId); 2304 2305 Setting currentSetting = secureSettings.getSettingLocked( 2306 Settings.Secure.ENABLED_VR_LISTENERS); 2307 if (currentSetting.isNull()) { 2308 ArraySet<ComponentName> l = 2309 SystemConfig.getInstance().getDefaultVrComponents(); 2310 2311 if (l != null && !l.isEmpty()) { 2312 StringBuilder b = new StringBuilder(); 2313 boolean start = true; 2314 for (ComponentName c : l) { 2315 if (!start) { 2316 b.append(':'); 2317 } 2318 b.append(c.flattenToString()); 2319 start = false; 2320 } 2321 secureSettings.insertSettingLocked( 2322 Settings.Secure.ENABLED_VR_LISTENERS, b.toString(), 2323 SettingsState.SYSTEM_PACKAGE_NAME); 2324 } 2325 2326 } 2327 currentVersion = 126; 2328 } 2329 2330 if (currentVersion == 126) { 2331 // Version 126: copy the primary values of LOCK_SCREEN_SHOW_NOTIFICATIONS and 2332 // LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS into managed profile. 2333 if (mUserManager.isManagedProfile(userId)) { 2334 final SettingsState systemSecureSettings = 2335 getSecureSettingsLocked(UserHandle.USER_SYSTEM); 2336 2337 final Setting showNotifications = systemSecureSettings.getSettingLocked( 2338 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS); 2339 if (!showNotifications.isNull()) { 2340 final SettingsState secureSettings = getSecureSettingsLocked(userId); 2341 secureSettings.insertSettingLocked( 2342 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 2343 showNotifications.getValue(), 2344 SettingsState.SYSTEM_PACKAGE_NAME); 2345 } 2346 2347 final Setting allowPrivate = systemSecureSettings.getSettingLocked( 2348 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS); 2349 if (!allowPrivate.isNull()) { 2350 final SettingsState secureSettings = getSecureSettingsLocked(userId); 2351 secureSettings.insertSettingLocked( 2352 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 2353 allowPrivate.getValue(), 2354 SettingsState.SYSTEM_PACKAGE_NAME); 2355 } 2356 } 2357 currentVersion = 127; 2358 } 2359 2360 if (currentVersion == 127) { 2361 // version 127 is no longer used. 2362 currentVersion = 128; 2363 } 2364 2365 if (currentVersion == 128) { 2366 // Version 128: Allow OEMs to grant DND access to default apps. Note that 2367 // the new apps are appended to the list of already approved apps. 2368 final SettingsState systemSecureSettings = 2369 getSecureSettingsLocked(userId); 2370 2371 final Setting policyAccess = systemSecureSettings.getSettingLocked( 2372 Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES); 2373 String defaultPolicyAccess = getContext().getResources().getString( 2374 com.android.internal.R.string.config_defaultDndAccessPackages); 2375 if (!TextUtils.isEmpty(defaultPolicyAccess)) { 2376 if (policyAccess.isNull()) { 2377 systemSecureSettings.insertSettingLocked( 2378 Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES, 2379 defaultPolicyAccess, 2380 SettingsState.SYSTEM_PACKAGE_NAME); 2381 } else { 2382 StringBuilder currentSetting = 2383 new StringBuilder(policyAccess.getValue()); 2384 currentSetting.append(":"); 2385 currentSetting.append(defaultPolicyAccess); 2386 systemSecureSettings.updateSettingLocked( 2387 Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES, 2388 currentSetting.toString(), 2389 SettingsState.SYSTEM_PACKAGE_NAME); 2390 } 2391 } 2392 2393 currentVersion = 129; 2394 } 2395 2396 if (currentVersion == 129) { 2397 // default longpress timeout changed from 500 to 400. If unchanged from the old 2398 // default, update to the new default. 2399 final SettingsState systemSecureSettings = 2400 getSecureSettingsLocked(userId); 2401 final String oldValue = systemSecureSettings.getSettingLocked( 2402 Settings.Secure.LONG_PRESS_TIMEOUT).getValue(); 2403 if (TextUtils.equals("500", oldValue)) { 2404 systemSecureSettings.insertSettingLocked( 2405 Settings.Secure.LONG_PRESS_TIMEOUT, 2406 String.valueOf(getContext().getResources().getInteger( 2407 R.integer.def_long_press_timeout_millis)), 2408 SettingsState.SYSTEM_PACKAGE_NAME); 2409 } 2410 currentVersion = 130; 2411 } 2412 2413 if (currentVersion != newVersion) { 2414 Slog.w("SettingsProvider", "warning: upgrading settings database to version " 2415 + newVersion + " left it at " 2416 + currentVersion + " instead; this is probably a bug", new Throwable()); 2417 if (DEBUG) { 2418 throw new RuntimeException("db upgrade error"); 2419 } 2420 } 2421 2422 // vXXX: Add new settings above this point. 2423 2424 // Return the current version. 2425 return currentVersion; 2426 } 2427 } 2428 } 2429 } 2430