1 /* 2 * Copyright (C) 2008 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.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.UserIdInt; 22 import android.app.backup.BackupAgentHelper; 23 import android.app.backup.BackupDataInput; 24 import android.app.backup.BackupDataOutput; 25 import android.app.backup.FullBackupDataOutput; 26 import android.content.ContentResolver; 27 import android.content.ContentValues; 28 import android.content.Context; 29 import android.content.pm.PackageManager; 30 import android.database.Cursor; 31 import android.net.NetworkPolicy; 32 import android.net.NetworkPolicyManager; 33 import android.net.Uri; 34 import android.net.wifi.SoftApConfiguration; 35 import android.net.wifi.WifiManager; 36 import android.os.Build; 37 import android.os.ParcelFileDescriptor; 38 import android.os.UserHandle; 39 import android.provider.Settings; 40 import android.provider.settings.backup.DeviceSpecificSettings; 41 import android.provider.settings.backup.GlobalSettings; 42 import android.provider.settings.backup.LargeScreenSettings; 43 import android.provider.settings.backup.SecureSettings; 44 import android.provider.settings.backup.SystemSettings; 45 import android.provider.settings.validators.GlobalSettingsValidators; 46 import android.provider.settings.validators.SecureSettingsValidators; 47 import android.provider.settings.validators.SystemSettingsValidators; 48 import android.provider.settings.validators.Validator; 49 import android.telephony.SubscriptionManager; 50 import android.util.ArrayMap; 51 import android.util.ArraySet; 52 import android.util.BackupUtils; 53 import android.util.FeatureFlagUtils; 54 import android.util.Log; 55 import android.util.Slog; 56 import android.view.Display; 57 58 import com.android.internal.annotations.VisibleForTesting; 59 import com.android.internal.util.ArrayUtils; 60 import com.android.internal.widget.LockPatternUtils; 61 import com.android.settingslib.display.DisplayDensityConfiguration; 62 import com.android.window.flags.Flags; 63 64 import java.io.BufferedOutputStream; 65 import java.io.ByteArrayInputStream; 66 import java.io.ByteArrayOutputStream; 67 import java.io.DataInputStream; 68 import java.io.DataOutputStream; 69 import java.io.EOFException; 70 import java.io.FileInputStream; 71 import java.io.FileOutputStream; 72 import java.io.IOException; 73 import java.io.OutputStream; 74 import java.time.DateTimeException; 75 import java.util.Arrays; 76 import java.util.Collections; 77 import java.util.HashSet; 78 import java.util.Map; 79 import java.util.Objects; 80 import java.util.Set; 81 import java.util.concurrent.CountDownLatch; 82 import java.util.concurrent.TimeUnit; 83 import java.util.concurrent.atomic.AtomicInteger; 84 import java.util.function.Consumer; 85 import java.util.zip.CRC32; 86 87 /** 88 * Performs backup and restore of the System and Secure settings. 89 * List of settings that are backed up are stored in the Settings.java file 90 */ 91 public class SettingsBackupAgent extends BackupAgentHelper { 92 private static final boolean DEBUG = false; 93 private static final boolean DEBUG_BACKUP = DEBUG || false; 94 95 private static final byte[] NULL_VALUE = new byte[0]; 96 private static final int NULL_SIZE = -1; 97 private static final float FONT_SCALE_DEF_VALUE = 1.0f; 98 99 private static final String KEY_SYSTEM = "system"; 100 private static final String KEY_SECURE = "secure"; 101 private static final String KEY_GLOBAL = "global"; 102 private static final String KEY_LOCALE = "locale"; 103 private static final String KEY_LOCK_SETTINGS = "lock_settings"; 104 private static final String KEY_SOFTAP_CONFIG = "softap_config"; 105 private static final String KEY_NETWORK_POLICIES = "network_policies"; 106 private static final String KEY_WIFI_NEW_CONFIG = "wifi_new_config"; 107 private static final String KEY_DEVICE_SPECIFIC_CONFIG = "device_specific_config"; 108 private static final String KEY_SIM_SPECIFIC_SETTINGS = "sim_specific_settings"; 109 // Restoring sim-specific data backed up from newer Android version to Android 12 was causing a 110 // fatal crash. Creating a backup with a different key will prevent Android 12 versions from 111 // restoring this data. 112 private static final String KEY_SIM_SPECIFIC_SETTINGS_2 = "sim_specific_settings_2"; 113 private static final String KEY_WIFI_SETTINGS_BACKUP_DATA = "wifi_settings_backup_data"; 114 115 // Versioning of the state file. Increment this version 116 // number any time the set of state items is altered. 117 private static final int STATE_VERSION = 9; 118 119 // Versioning of the Network Policies backup payload. 120 private static final int NETWORK_POLICIES_BACKUP_VERSION = 1; 121 122 // Slots in the checksum array. Never insert new items in the middle 123 // of this array; new slots must be appended. 124 private static final int STATE_SYSTEM = 0; 125 private static final int STATE_SECURE = 1; 126 private static final int STATE_LOCALE = 2; 127 private static final int STATE_WIFI_SUPPLICANT = 3; 128 private static final int STATE_WIFI_CONFIG = 4; 129 private static final int STATE_GLOBAL = 5; 130 private static final int STATE_LOCK_SETTINGS = 6; 131 private static final int STATE_SOFTAP_CONFIG = 7; 132 private static final int STATE_NETWORK_POLICIES = 8; 133 private static final int STATE_WIFI_NEW_CONFIG = 9; 134 private static final int STATE_DEVICE_CONFIG = 10; 135 private static final int STATE_SIM_SPECIFIC_SETTINGS = 11; 136 private static final int STATE_WIFI_SETTINGS = 12; 137 138 private static final int STATE_SIZE = 13; // The current number of state items 139 140 // Number of entries in the checksum array at various version numbers 141 private static final int STATE_SIZES[] = { 142 0, 143 4, // version 1 144 5, // version 2 added STATE_WIFI_CONFIG 145 6, // version 3 added STATE_GLOBAL 146 7, // version 4 added STATE_LOCK_SETTINGS 147 8, // version 5 added STATE_SOFTAP_CONFIG 148 9, // version 6 added STATE_NETWORK_POLICIES 149 10, // version 7 added STATE_WIFI_NEW_CONFIG 150 11, // version 8 added STATE_DEVICE_CONFIG 151 12, // version 9 added STATE_SIM_SPECIFIC_SETTINGS 152 STATE_SIZE // version 10 added STATE_WIFI_SETTINGS 153 }; 154 155 private static final int FULL_BACKUP_ADDED_GLOBAL = 2; // added the "global" entry 156 private static final int FULL_BACKUP_ADDED_LOCK_SETTINGS = 3; // added the "lock_settings" entry 157 private static final int FULL_BACKUP_ADDED_SOFTAP_CONF = 4; //added the "softap_config" entry 158 private static final int FULL_BACKUP_ADDED_NETWORK_POLICIES = 5; //added "network_policies" 159 private static final int FULL_BACKUP_ADDED_WIFI_NEW = 6; // added "wifi_new_config" entry 160 private static final int FULL_BACKUP_ADDED_DEVICE_SPECIFIC = 7; // added "device specific" entry 161 // Versioning of the 'full backup' format 162 // Increment this version any time a new item is added 163 private static final int FULL_BACKUP_VERSION = FULL_BACKUP_ADDED_DEVICE_SPECIFIC; 164 165 private static final int INTEGER_BYTE_COUNT = Integer.SIZE / Byte.SIZE; 166 167 private static final byte[] EMPTY_DATA = new byte[0]; 168 169 private static final String TAG = "SettingsBackupAgent"; 170 171 @VisibleForTesting 172 static final String[] PROJECTION = { 173 Settings.NameValueTable.NAME, 174 Settings.NameValueTable.VALUE 175 }; 176 177 // Versioning of the 'device specific' section of a backup 178 // Increment this any time the format is changed or data added. 179 @VisibleForTesting 180 static final int DEVICE_SPECIFIC_VERSION = 1; 181 182 // the key to store the WIFI data under, should be sorted as last, so restore happens last. 183 // use very late unicode character to quasi-guarantee last sort position. 184 private static final String KEY_WIFI_SUPPLICANT = "\uffedWIFI"; 185 private static final String KEY_WIFI_CONFIG = "\uffedCONFIG_WIFI"; 186 187 // Keys within the lock settings section 188 private static final String KEY_LOCK_SETTINGS_OWNER_INFO_ENABLED = "owner_info_enabled"; 189 private static final String KEY_LOCK_SETTINGS_OWNER_INFO = "owner_info"; 190 private static final String KEY_LOCK_SETTINGS_VISIBLE_PATTERN_ENABLED = 191 "visible_pattern_enabled"; 192 private static final String KEY_LOCK_SETTINGS_POWER_BUTTON_INSTANTLY_LOCKS = 193 "power_button_instantly_locks"; 194 private static final String KEY_LOCK_SETTINGS_PIN_ENHANCED_PRIVACY = 195 "pin_enhanced_privacy"; 196 197 // Name of the temporary file we use during full backup/restore. This is 198 // stored in the full-backup tarfile as well, so should not be changed. 199 private static final String STAGE_FILE = "flattened-data"; 200 201 // List of keys that support restore to lower version of the SDK, introduced in Android P 202 private static final ArraySet<String> RESTORE_FROM_HIGHER_SDK_INT_SUPPORTED_KEYS = 203 new ArraySet<String>(Arrays.asList(new String[] { 204 KEY_NETWORK_POLICIES, 205 KEY_WIFI_NEW_CONFIG, 206 KEY_SYSTEM, 207 KEY_SECURE, 208 KEY_GLOBAL, 209 })); 210 211 @VisibleForTesting 212 SettingsHelper mSettingsHelper; 213 214 private WifiManager mWifiManager; 215 216 // Version of the SDK that com.android.providers.settings package has been restored from. 217 // Populated in onRestore(). 218 private int mRestoredFromSdkInt; 219 220 // The available font scale for the current device 221 @Nullable 222 private String[] mAvailableFontScales; 223 224 // The font_scale default value for this device. 225 private float mDefaultFontScale; 226 227 @Override onCreate()228 public void onCreate() { 229 if (DEBUG_BACKUP) Log.d(TAG, "onCreate() invoked"); 230 mDefaultFontScale = getBaseContext().getResources().getFloat(R.dimen.def_device_font_scale); 231 mAvailableFontScales = getBaseContext().getResources() 232 .getStringArray(R.array.entryvalues_font_size); 233 mSettingsHelper = new SettingsHelper(this); 234 mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); 235 super.onCreate(); 236 } 237 238 @Override onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState)239 public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, 240 ParcelFileDescriptor newState) throws IOException { 241 byte[] systemSettingsData = getSystemSettings(); 242 byte[] secureSettingsData = getSecureSettings(); 243 byte[] globalSettingsData = getGlobalSettings(); 244 byte[] lockSettingsData = getLockSettings(UserHandle.myUserId()); 245 byte[] locale = mSettingsHelper.getLocaleData(); 246 byte[] softApConfigData = getSoftAPConfiguration(); 247 byte[] netPoliciesData = getNetworkPolicies(); 248 byte[] wifiFullConfigData = getNewWifiConfigData(); 249 byte[] deviceSpecificInformation = getDeviceSpecificConfiguration(); 250 byte[] simSpecificSettingsData = getSimSpecificSettingsData(); 251 byte[] wifiSettingsData = getWifiSettingsBackupData(); 252 253 long[] stateChecksums = readOldChecksums(oldState); 254 255 stateChecksums[STATE_SYSTEM] = 256 writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data); 257 stateChecksums[STATE_SECURE] = 258 writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data); 259 stateChecksums[STATE_GLOBAL] = 260 writeIfChanged(stateChecksums[STATE_GLOBAL], KEY_GLOBAL, globalSettingsData, data); 261 stateChecksums[STATE_LOCALE] = 262 writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data); 263 stateChecksums[STATE_WIFI_SUPPLICANT] = 0; 264 stateChecksums[STATE_WIFI_CONFIG] = 0; 265 stateChecksums[STATE_LOCK_SETTINGS] = 266 writeIfChanged(stateChecksums[STATE_LOCK_SETTINGS], KEY_LOCK_SETTINGS, 267 lockSettingsData, data); 268 if (isWatch()) { 269 stateChecksums[STATE_SOFTAP_CONFIG] = 0; 270 } else { 271 stateChecksums[STATE_SOFTAP_CONFIG] = 272 writeIfChanged(stateChecksums[STATE_SOFTAP_CONFIG], KEY_SOFTAP_CONFIG, 273 softApConfigData, data); 274 } 275 stateChecksums[STATE_NETWORK_POLICIES] = 276 writeIfChanged(stateChecksums[STATE_NETWORK_POLICIES], KEY_NETWORK_POLICIES, 277 netPoliciesData, data); 278 stateChecksums[STATE_WIFI_NEW_CONFIG] = 279 writeIfChanged(stateChecksums[STATE_WIFI_NEW_CONFIG], KEY_WIFI_NEW_CONFIG, 280 wifiFullConfigData, data); 281 stateChecksums[STATE_DEVICE_CONFIG] = 282 writeIfChanged(stateChecksums[STATE_DEVICE_CONFIG], KEY_DEVICE_SPECIFIC_CONFIG, 283 deviceSpecificInformation, data); 284 stateChecksums[STATE_SIM_SPECIFIC_SETTINGS] = 285 writeIfChanged(stateChecksums[STATE_SIM_SPECIFIC_SETTINGS], 286 KEY_SIM_SPECIFIC_SETTINGS_2, simSpecificSettingsData, data); 287 stateChecksums[STATE_WIFI_SETTINGS] = 288 writeIfChanged(stateChecksums[STATE_WIFI_SETTINGS], 289 KEY_WIFI_SETTINGS_BACKUP_DATA, wifiSettingsData, data); 290 291 writeNewChecksums(stateChecksums, newState); 292 } 293 isWatch()294 private boolean isWatch() { 295 return getBaseContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH); 296 } 297 298 @Override onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)299 public void onRestore(BackupDataInput data, int appVersionCode, 300 ParcelFileDescriptor newState) { 301 throw new RuntimeException("SettingsBackupAgent has been migrated to use key exclusion"); 302 } 303 304 @Override onRestore(BackupDataInput data, long appVersionCode, ParcelFileDescriptor newState, Set<String> dynamicBlockList)305 public void onRestore(BackupDataInput data, long appVersionCode, 306 ParcelFileDescriptor newState, Set<String> dynamicBlockList) throws IOException { 307 308 if (DEBUG) { 309 Log.d(TAG, "onRestore(): appVersionCode: " + appVersionCode 310 + "; Build.VERSION.SDK_INT: " + Build.VERSION.SDK_INT); 311 } 312 313 boolean overrideRestoreAnyVersion = Settings.Global.getInt(getContentResolver(), 314 Settings.Global.OVERRIDE_SETTINGS_PROVIDER_RESTORE_ANY_VERSION, 0) == 1; 315 if ((appVersionCode > Build.VERSION.SDK_INT) && overrideRestoreAnyVersion) { 316 Log.w(TAG, "Ignoring restore from API" + appVersionCode + " to API" 317 + Build.VERSION.SDK_INT + " due to settings flag override."); 318 return; 319 } 320 321 // versionCode of com.android.providers.settings corresponds to SDK_INT 322 mRestoredFromSdkInt = (int) appVersionCode; 323 324 Set<String> movedToGlobal = getMovedToGlobalSettings(); 325 Set<String> movedToSecure = getMovedToSecureSettings(); 326 Set<String> movedToSystem = getMovedToSystemSettings(); 327 328 Set<String> preservedGlobalSettings = getSettingsToPreserveInRestore( 329 Settings.Global.CONTENT_URI); 330 Set<String> preservedSecureSettings = getSettingsToPreserveInRestore( 331 Settings.Secure.CONTENT_URI); 332 Set<String> preservedSystemSettings = getSettingsToPreserveInRestore( 333 Settings.System.CONTENT_URI); 334 Set<String> preservedSettings = new HashSet<>(preservedGlobalSettings); 335 preservedSettings.addAll(preservedSecureSettings); 336 preservedSettings.addAll(preservedSystemSettings); 337 338 byte[] restoredWifiSupplicantData = null; 339 byte[] restoredWifiIpConfigData = null; 340 341 while (data.readNextHeader()) { 342 final String key = data.getKey(); 343 final int size = data.getDataSize(); 344 345 // bail out of restoring from higher SDK_INT version for unsupported keys 346 if (appVersionCode > Build.VERSION.SDK_INT 347 && !RESTORE_FROM_HIGHER_SDK_INT_SUPPORTED_KEYS.contains(key)) { 348 Log.w(TAG, "Not restoring unrecognized key '" 349 + key + "' from future version " + appVersionCode); 350 data.skipEntityData(); 351 continue; 352 } 353 354 switch (key) { 355 case KEY_SYSTEM : 356 restoreSettings(data, Settings.System.CONTENT_URI, movedToGlobal, 357 movedToSecure, /* movedToSystem= */ null, 358 R.array.restore_blocked_system_settings, dynamicBlockList, 359 preservedSystemSettings); 360 mSettingsHelper.applyAudioSettings(); 361 break; 362 363 case KEY_SECURE : 364 restoreSettings(data, Settings.Secure.CONTENT_URI, movedToGlobal, 365 /* movedToSecure= */ null, movedToSystem, 366 R.array.restore_blocked_secure_settings, dynamicBlockList, 367 preservedSecureSettings); 368 break; 369 370 case KEY_GLOBAL : 371 restoreSettings(data, Settings.Global.CONTENT_URI, /* movedToGlobal= */ null, 372 movedToSecure, movedToSystem, R.array.restore_blocked_global_settings, 373 dynamicBlockList, preservedGlobalSettings); 374 break; 375 376 case KEY_WIFI_SUPPLICANT : 377 restoredWifiSupplicantData = new byte[size]; 378 data.readEntityData(restoredWifiSupplicantData, 0, size); 379 break; 380 381 case KEY_LOCALE : 382 byte[] localeData = new byte[size]; 383 data.readEntityData(localeData, 0, size); 384 mSettingsHelper.setLocaleData(localeData, size); 385 break; 386 387 case KEY_WIFI_CONFIG : 388 restoredWifiIpConfigData = new byte[size]; 389 data.readEntityData(restoredWifiIpConfigData, 0, size); 390 break; 391 392 case KEY_LOCK_SETTINGS : 393 restoreLockSettings(UserHandle.myUserId(), data); 394 break; 395 396 case KEY_SOFTAP_CONFIG : 397 byte[] softapData = new byte[size]; 398 data.readEntityData(softapData, 0, size); 399 if (!isWatch()) { 400 restoreSoftApConfiguration(softapData); 401 } 402 break; 403 404 case KEY_NETWORK_POLICIES: 405 byte[] netPoliciesData = new byte[size]; 406 data.readEntityData(netPoliciesData, 0, size); 407 if (!isWatch()) { 408 restoreNetworkPolicies(netPoliciesData); 409 } 410 break; 411 412 case KEY_WIFI_NEW_CONFIG: 413 byte[] restoredWifiNewConfigData = new byte[size]; 414 data.readEntityData(restoredWifiNewConfigData, 0, size); 415 if (!isWatch()) { 416 restoreNewWifiConfigData(restoredWifiNewConfigData); 417 } 418 break; 419 420 case KEY_DEVICE_SPECIFIC_CONFIG: 421 byte[] restoredDeviceSpecificConfig = new byte[size]; 422 data.readEntityData(restoredDeviceSpecificConfig, 0, size); 423 restoreDeviceSpecificConfig( 424 restoredDeviceSpecificConfig, 425 R.array.restore_blocked_device_specific_settings, 426 dynamicBlockList, 427 preservedSettings); 428 break; 429 430 case KEY_SIM_SPECIFIC_SETTINGS: 431 // Intentional fall through so that sim-specific backups from Android 12 will 432 // also be restored on newer Android versions. 433 case KEY_SIM_SPECIFIC_SETTINGS_2: 434 byte[] restoredSimSpecificSettings = new byte[size]; 435 data.readEntityData(restoredSimSpecificSettings, 0, size); 436 restoreSimSpecificSettings(restoredSimSpecificSettings); 437 break; 438 case KEY_WIFI_SETTINGS_BACKUP_DATA: 439 byte[] restoredWifiData = new byte[size]; 440 data.readEntityData(restoredWifiData, 0, size); 441 if (!isWatch()) { 442 restoreWifiData(restoredWifiData); 443 } 444 break; 445 default : 446 data.skipEntityData(); 447 448 } 449 } 450 451 // Do this at the end so that we also pull in the ipconfig data. 452 if (restoredWifiSupplicantData != null && !isWatch()) { 453 restoreSupplicantWifiConfigData( 454 restoredWifiSupplicantData, restoredWifiIpConfigData); 455 } 456 } 457 458 @Override onFullBackup(FullBackupDataOutput data)459 public void onFullBackup(FullBackupDataOutput data) throws IOException { 460 // Full backup of SettingsBackupAgent support was removed in Android P. If you want to adb 461 // backup com.android.providers.settings package use \"-keyvalue\" flag. 462 // Full restore of SettingsBackupAgent is still available for backwards compatibility. 463 } 464 465 @Override onRestoreFile(ParcelFileDescriptor data, long size, int type, String domain, String relpath, long mode, long mtime)466 public void onRestoreFile(ParcelFileDescriptor data, long size, 467 int type, String domain, String relpath, long mode, long mtime) 468 throws IOException { 469 if (DEBUG_BACKUP) Log.d(TAG, "onRestoreFile() invoked"); 470 // Our data is actually a blob of flattened settings data identical to that 471 // produced during incremental backups. Just unpack and apply it all in 472 // turn. 473 FileInputStream instream = new FileInputStream(data.getFileDescriptor()); 474 DataInputStream in = new DataInputStream(instream); 475 476 int version = in.readInt(); 477 if (DEBUG_BACKUP) Log.d(TAG, "Flattened data version " + version); 478 if (version <= FULL_BACKUP_VERSION) { 479 // Generate the moved-to-global lookup table 480 Set<String> movedToGlobal = getMovedToGlobalSettings(); 481 Set<String> movedToSecure = getMovedToSecureSettings(); 482 Set<String> movedToSystem = getMovedToSystemSettings(); 483 484 // system settings data first 485 int nBytes = in.readInt(); 486 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of settings data"); 487 byte[] buffer = new byte[nBytes]; 488 in.readFully(buffer, 0, nBytes); 489 restoreSettings(buffer, nBytes, Settings.System.CONTENT_URI, movedToGlobal, 490 movedToSecure, /* movedToSystem= */ null, 491 R.array.restore_blocked_system_settings, Collections.emptySet(), 492 Collections.emptySet()); 493 494 // secure settings 495 nBytes = in.readInt(); 496 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of secure settings data"); 497 if (nBytes > buffer.length) buffer = new byte[nBytes]; 498 in.readFully(buffer, 0, nBytes); 499 restoreSettings(buffer, nBytes, Settings.Secure.CONTENT_URI, movedToGlobal, 500 /* movedToSecure= */ null, movedToSystem, 501 R.array.restore_blocked_secure_settings, Collections.emptySet(), 502 Collections.emptySet()); 503 504 // Global only if sufficiently new 505 if (version >= FULL_BACKUP_ADDED_GLOBAL) { 506 nBytes = in.readInt(); 507 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of global settings data"); 508 if (nBytes > buffer.length) buffer = new byte[nBytes]; 509 in.readFully(buffer, 0, nBytes); 510 restoreSettings(buffer, nBytes, Settings.Global.CONTENT_URI, 511 /* movedToGlobal= */ null, movedToSecure, movedToSystem, 512 R.array.restore_blocked_global_settings, Collections.emptySet(), 513 Collections.emptySet()); 514 } 515 516 // locale 517 nBytes = in.readInt(); 518 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of locale data"); 519 if (nBytes > buffer.length) buffer = new byte[nBytes]; 520 in.readFully(buffer, 0, nBytes); 521 mSettingsHelper.setLocaleData(buffer, nBytes); 522 523 // Restore older backups performing the necessary migrations. 524 if (version < FULL_BACKUP_ADDED_WIFI_NEW) { 525 // wifi supplicant 526 int supplicant_size = in.readInt(); 527 if (DEBUG_BACKUP) Log.d(TAG, supplicant_size + " bytes of wifi supplicant data"); 528 byte[] supplicant_buffer = new byte[supplicant_size]; 529 in.readFully(supplicant_buffer, 0, supplicant_size); 530 531 // ip config 532 int ipconfig_size = in.readInt(); 533 if (DEBUG_BACKUP) Log.d(TAG, ipconfig_size + " bytes of ip config data"); 534 byte[] ipconfig_buffer = new byte[ipconfig_size]; 535 in.readFully(ipconfig_buffer, 0, nBytes); 536 if (!isWatch()) { 537 restoreSupplicantWifiConfigData(supplicant_buffer, ipconfig_buffer); 538 } 539 } 540 541 if (version >= FULL_BACKUP_ADDED_LOCK_SETTINGS) { 542 nBytes = in.readInt(); 543 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of lock settings data"); 544 if (nBytes > buffer.length) buffer = new byte[nBytes]; 545 if (nBytes > 0) { 546 in.readFully(buffer, 0, nBytes); 547 restoreLockSettings(UserHandle.myUserId(), buffer, nBytes); 548 } 549 } 550 // softap config 551 if (version >= FULL_BACKUP_ADDED_SOFTAP_CONF) { 552 nBytes = in.readInt(); 553 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of softap config data"); 554 if (nBytes > buffer.length) buffer = new byte[nBytes]; 555 if (nBytes > 0) { 556 in.readFully(buffer, 0, nBytes); 557 if (!isWatch()) { 558 restoreSoftApConfiguration(buffer); 559 } 560 } 561 } 562 // network policies 563 if (version >= FULL_BACKUP_ADDED_NETWORK_POLICIES) { 564 nBytes = in.readInt(); 565 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of network policies data"); 566 if (nBytes > buffer.length) buffer = new byte[nBytes]; 567 if (nBytes > 0) { 568 in.readFully(buffer, 0, nBytes); 569 if (!isWatch()) { 570 restoreNetworkPolicies(buffer); 571 } 572 } 573 } 574 // Restore full wifi config data 575 if (version >= FULL_BACKUP_ADDED_WIFI_NEW) { 576 nBytes = in.readInt(); 577 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of full wifi config data"); 578 if (nBytes > buffer.length) buffer = new byte[nBytes]; 579 in.readFully(buffer, 0, nBytes); 580 if (!isWatch()) { 581 restoreNewWifiConfigData(buffer); 582 } 583 } 584 585 if (DEBUG_BACKUP) Log.d(TAG, "Full restore complete."); 586 } else { 587 data.close(); 588 throw new IOException("Invalid file schema"); 589 } 590 } 591 getMovedToGlobalSettings()592 private Set<String> getMovedToGlobalSettings() { 593 HashSet<String> movedToGlobalSettings = new HashSet<String>(); 594 Settings.System.getMovedToGlobalSettings(movedToGlobalSettings); 595 Settings.Secure.getMovedToGlobalSettings(movedToGlobalSettings); 596 return movedToGlobalSettings; 597 } 598 getMovedToSecureSettings()599 private Set<String> getMovedToSecureSettings() { 600 Set<String> movedToSecureSettings = new HashSet<>(); 601 Settings.Global.getMovedToSecureSettings(movedToSecureSettings); 602 Settings.System.getMovedToSecureSettings(movedToSecureSettings); 603 return movedToSecureSettings; 604 } 605 getMovedToSystemSettings()606 private Set<String> getMovedToSystemSettings() { 607 Set<String> movedToSystemSettings = new HashSet<>(); 608 Settings.Global.getMovedToSystemSettings(movedToSystemSettings); 609 Settings.Secure.getMovedToSystemSettings(movedToSystemSettings); 610 return movedToSystemSettings; 611 } 612 readOldChecksums(ParcelFileDescriptor oldState)613 private long[] readOldChecksums(ParcelFileDescriptor oldState) throws IOException { 614 long[] stateChecksums = new long[STATE_SIZE]; 615 616 DataInputStream dataInput = new DataInputStream( 617 new FileInputStream(oldState.getFileDescriptor())); 618 619 try { 620 int stateVersion = dataInput.readInt(); 621 if (stateVersion > STATE_VERSION) { 622 // Constrain the maximum state version this backup agent 623 // can handle in case a newer or corrupt backup set existed 624 stateVersion = STATE_VERSION; 625 } 626 for (int i = 0; i < STATE_SIZES[stateVersion]; i++) { 627 stateChecksums[i] = dataInput.readLong(); 628 } 629 } catch (EOFException eof) { 630 // With the default 0 checksum we'll wind up forcing a backup of 631 // any unhandled data sets, which is appropriate. 632 } 633 dataInput.close(); 634 return stateChecksums; 635 } 636 writeNewChecksums(long[] checksums, ParcelFileDescriptor newState)637 private void writeNewChecksums(long[] checksums, ParcelFileDescriptor newState) 638 throws IOException { 639 DataOutputStream dataOutput = new DataOutputStream( 640 new BufferedOutputStream(new FileOutputStream(newState.getFileDescriptor()))); 641 642 dataOutput.writeInt(STATE_VERSION); 643 for (int i = 0; i < STATE_SIZE; i++) { 644 dataOutput.writeLong(checksums[i]); 645 } 646 dataOutput.close(); 647 } 648 writeIfChanged(long oldChecksum, String key, byte[] data, BackupDataOutput output)649 private long writeIfChanged(long oldChecksum, String key, byte[] data, 650 BackupDataOutput output) { 651 CRC32 checkSummer = new CRC32(); 652 checkSummer.update(data); 653 long newChecksum = checkSummer.getValue(); 654 if (oldChecksum == newChecksum) { 655 return oldChecksum; 656 } 657 try { 658 if (DEBUG_BACKUP) { 659 Log.v(TAG, "Writing entity " + key + " of size " + data.length); 660 } 661 output.writeEntityHeader(key, data.length); 662 output.writeEntityData(data, data.length); 663 } catch (IOException ioe) { 664 // Bail 665 } 666 return newChecksum; 667 } 668 getSystemSettings()669 private byte[] getSystemSettings() { 670 Cursor cursor = getContentResolver().query(Settings.System.CONTENT_URI, PROJECTION, null, 671 null, null); 672 try { 673 return extractRelevantValues(cursor, SystemSettings.SETTINGS_TO_BACKUP); 674 } finally { 675 cursor.close(); 676 } 677 } 678 getSecureSettings()679 private byte[] getSecureSettings() { 680 Cursor cursor = getContentResolver().query(Settings.Secure.CONTENT_URI, PROJECTION, null, 681 null, null); 682 try { 683 return extractRelevantValues(cursor, SecureSettings.SETTINGS_TO_BACKUP); 684 } finally { 685 cursor.close(); 686 } 687 } 688 getGlobalSettings()689 private byte[] getGlobalSettings() { 690 Cursor cursor = getContentResolver().query(Settings.Global.CONTENT_URI, PROJECTION, null, 691 null, null); 692 try { 693 return extractRelevantValues(cursor, GlobalSettings.SETTINGS_TO_BACKUP); 694 } finally { 695 cursor.close(); 696 } 697 } 698 699 /** 700 * Get names of the settings for which the current value should be preserved during restore. 701 */ getSettingsToPreserveInRestore(Uri settingsUri)702 private Set<String> getSettingsToPreserveInRestore(Uri settingsUri) { 703 if (!FeatureFlagUtils.isEnabled(getBaseContext(), 704 FeatureFlagUtils.SETTINGS_DO_NOT_RESTORE_PRESERVED)) { 705 return Collections.emptySet(); 706 } 707 708 try (Cursor cursor = getContentResolver().query(settingsUri, new String[]{ 709 Settings.NameValueTable.NAME, 710 Settings.NameValueTable.IS_PRESERVED_IN_RESTORE}, 711 /* selection */ null, /* selectionArgs */ null, /* sortOrder */ null)) { 712 713 if (!cursor.moveToFirst()) { 714 Slog.i(TAG, "No settings to be preserved in restore"); 715 return Collections.emptySet(); 716 } 717 718 int nameIndex = cursor.getColumnIndex(Settings.NameValueTable.NAME); 719 int isPreservedIndex = cursor.getColumnIndex( 720 Settings.NameValueTable.IS_PRESERVED_IN_RESTORE); 721 722 Set<String> preservedSettings = new HashSet<>(); 723 while (!cursor.isAfterLast()) { 724 if (Boolean.parseBoolean(cursor.getString(isPreservedIndex))) { 725 preservedSettings.add(getQualifiedKeyForSetting(cursor.getString(nameIndex), 726 settingsUri)); 727 } 728 cursor.moveToNext(); 729 } 730 731 return preservedSettings; 732 } 733 } 734 735 /** 736 * Serialize the owner info and other lock settings 737 */ getLockSettings(@serIdInt int userId)738 private byte[] getLockSettings(@UserIdInt int userId) { 739 final LockPatternUtils lockPatternUtils = new LockPatternUtils(this); 740 final boolean ownerInfoEnabled = lockPatternUtils.isOwnerInfoEnabled(userId); 741 final String ownerInfo = lockPatternUtils.getOwnerInfo(userId); 742 final boolean lockPatternEnabled = lockPatternUtils.isLockPatternEnabled(userId); 743 final boolean visiblePatternEnabled = lockPatternUtils.isVisiblePatternEnabled(userId); 744 final boolean powerButtonInstantlyLocks = 745 lockPatternUtils.getPowerButtonInstantlyLocks(userId); 746 747 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 748 DataOutputStream out = new DataOutputStream(baos); 749 try { 750 out.writeUTF(KEY_LOCK_SETTINGS_OWNER_INFO_ENABLED); 751 out.writeUTF(ownerInfoEnabled ? "1" : "0"); 752 if (ownerInfo != null) { 753 out.writeUTF(KEY_LOCK_SETTINGS_OWNER_INFO); 754 out.writeUTF(ownerInfo != null ? ownerInfo : ""); 755 } 756 if (lockPatternUtils.isVisiblePatternEverChosen(userId)) { 757 out.writeUTF(KEY_LOCK_SETTINGS_VISIBLE_PATTERN_ENABLED); 758 out.writeUTF(visiblePatternEnabled ? "1" : "0"); 759 } 760 if (lockPatternUtils.isPowerButtonInstantlyLocksEverChosen(userId)) { 761 out.writeUTF(KEY_LOCK_SETTINGS_POWER_BUTTON_INSTANTLY_LOCKS); 762 out.writeUTF(powerButtonInstantlyLocks ? "1" : "0"); 763 } 764 if (lockPatternUtils.isPinEnhancedPrivacyEverChosen(userId)) { 765 out.writeUTF(KEY_LOCK_SETTINGS_PIN_ENHANCED_PRIVACY); 766 out.writeUTF(lockPatternUtils.isPinEnhancedPrivacyEnabled(userId) ? "1" : "0"); 767 } 768 // End marker 769 out.writeUTF(""); 770 out.flush(); 771 } catch (IOException ioe) { 772 } 773 return baos.toByteArray(); 774 } 775 restoreSettings( BackupDataInput data, Uri contentUri, Set<String> movedToGlobal, Set<String> movedToSecure, Set<String> movedToSystem, int blockedSettingsArrayId, Set<String> dynamicBlockList, Set<String> settingsToPreserve)776 private void restoreSettings( 777 BackupDataInput data, 778 Uri contentUri, 779 Set<String> movedToGlobal, 780 Set<String> movedToSecure, 781 Set<String> movedToSystem, 782 int blockedSettingsArrayId, 783 Set<String> dynamicBlockList, 784 Set<String> settingsToPreserve) { 785 byte[] settings = new byte[data.getDataSize()]; 786 try { 787 data.readEntityData(settings, 0, settings.length); 788 } catch (IOException ioe) { 789 Log.e(TAG, "Couldn't read entity data"); 790 return; 791 } 792 restoreSettings( 793 settings, 794 settings.length, 795 contentUri, 796 movedToGlobal, 797 movedToSecure, 798 movedToSystem, 799 blockedSettingsArrayId, 800 dynamicBlockList, 801 settingsToPreserve); 802 } 803 restoreSettings( byte[] settings, int bytes, Uri contentUri, Set<String> movedToGlobal, Set<String> movedToSecure, Set<String> movedToSystem, int blockedSettingsArrayId, Set<String> dynamicBlockList, Set<String> settingsToPreserve)804 private void restoreSettings( 805 byte[] settings, 806 int bytes, 807 Uri contentUri, 808 Set<String> movedToGlobal, 809 Set<String> movedToSecure, 810 Set<String> movedToSystem, 811 int blockedSettingsArrayId, 812 Set<String> dynamicBlockList, 813 Set<String> settingsToPreserve) { 814 restoreSettings( 815 settings, 816 0, 817 bytes, 818 contentUri, 819 movedToGlobal, 820 movedToSecure, 821 movedToSystem, 822 blockedSettingsArrayId, 823 dynamicBlockList, 824 settingsToPreserve); 825 } 826 827 @VisibleForTesting restoreSettings( byte[] settings, int pos, int bytes, Uri contentUri, Set<String> movedToGlobal, Set<String> movedToSecure, Set<String> movedToSystem, int blockedSettingsArrayId, Set<String> dynamicBlockList, Set<String> settingsToPreserve)828 void restoreSettings( 829 byte[] settings, 830 int pos, 831 int bytes, 832 Uri contentUri, 833 Set<String> movedToGlobal, 834 Set<String> movedToSecure, 835 Set<String> movedToSystem, 836 int blockedSettingsArrayId, 837 Set<String> dynamicBlockList, 838 Set<String> settingsToPreserve) { 839 if (DEBUG) { 840 Log.i(TAG, "restoreSettings: " + contentUri); 841 } 842 843 SettingsBackupWhitelist whitelist = getBackupWhitelist(contentUri); 844 845 // Restore only the white list data. 846 final ArrayMap<String, String> cachedEntries = new ArrayMap<>(); 847 ContentValues contentValues = new ContentValues(2); 848 SettingsHelper settingsHelper = mSettingsHelper; 849 ContentResolver cr = getContentResolver(); 850 851 Set<String> blockedSettings = getBlockedSettings(blockedSettingsArrayId); 852 853 for (String key : whitelist.mSettingsWhitelist) { 854 boolean isBlockedBySystem = blockedSettings != null && blockedSettings.contains(key); 855 if (isBlockedBySystem || isBlockedByDynamicList(dynamicBlockList, contentUri, key)) { 856 Log.i( 857 TAG, 858 "Key " 859 + key 860 + " removed from restore by " 861 + (isBlockedBySystem ? "system" : "dynamic") 862 + " block list"); 863 continue; 864 } 865 866 // Filter out Settings.Secure.NAVIGATION_MODE from modified preserve settings. 867 // Let it take part in restore process. See also b/244532342. 868 boolean isSettingPreserved = settingsToPreserve.contains( 869 getQualifiedKeyForSetting(key, contentUri)); 870 if (isSettingPreserved && !Settings.Secure.NAVIGATION_MODE.equals(key)) { 871 Log.i(TAG, "Skipping restore for setting " + key + " as it is marked as " 872 + "preserved"); 873 continue; 874 } 875 876 if (LargeScreenSettings.doNotRestoreIfLargeScreenSetting(key, getBaseContext())) { 877 Log.i(TAG, "Skipping restore for setting " + key + " as the target device " 878 + "is a large screen (i.e tablet or foldable in unfolded state)"); 879 continue; 880 } 881 882 String value = null; 883 boolean hasValueToRestore = false; 884 if (cachedEntries.indexOfKey(key) >= 0) { 885 value = cachedEntries.remove(key); 886 hasValueToRestore = true; 887 } else { 888 // If the value not cached, let us look it up. 889 while (pos < bytes) { 890 int length = readInt(settings, pos); 891 pos += INTEGER_BYTE_COUNT; 892 String dataKey = length >= 0 ? new String(settings, pos, length) : null; 893 pos += length; 894 length = readInt(settings, pos); 895 pos += INTEGER_BYTE_COUNT; 896 String dataValue = null; 897 if (length >= 0) { 898 dataValue = new String(settings, pos, length); 899 pos += length; 900 } 901 if (key.equals(dataKey)) { 902 value = dataValue; 903 hasValueToRestore = true; 904 break; 905 } 906 cachedEntries.put(dataKey, dataValue); 907 } 908 } 909 910 if (!hasValueToRestore) { 911 continue; 912 } 913 914 // only restore the settings that have valid values 915 if (!isValidSettingValue(key, value, whitelist.mSettingsValidators)) { 916 Log.w(TAG, "Attempted restore of " + key + " setting, but its value didn't pass" 917 + " validation, value: " + value); 918 continue; 919 } 920 921 final Uri destination; 922 if (movedToGlobal != null && movedToGlobal.contains(key)) { 923 destination = Settings.Global.CONTENT_URI; 924 } else if (movedToSecure != null && movedToSecure.contains(key)) { 925 destination = Settings.Secure.CONTENT_URI; 926 } else if (movedToSystem != null && movedToSystem.contains(key)) { 927 destination = Settings.System.CONTENT_URI; 928 } else { 929 destination = contentUri; 930 } 931 932 // Value is written to NAVIGATION_MODE_RESTORE to mark navigation mode 933 // has been set before on source device. 934 // See also: b/244532342. 935 if (Settings.Secure.NAVIGATION_MODE.equals(key)) { 936 contentValues.clear(); 937 contentValues.put(Settings.NameValueTable.NAME, 938 Settings.Secure.NAVIGATION_MODE_RESTORE); 939 contentValues.put(Settings.NameValueTable.VALUE, value); 940 cr.insert(destination, contentValues); 941 // Avoid restore original setting if it has been preserved. 942 if (isSettingPreserved) { 943 Log.i(TAG, "Skipping restore for setting navigation_mode " 944 + "as it is marked as preserved"); 945 continue; 946 } 947 } 948 949 if (Settings.System.FONT_SCALE.equals(key)) { 950 // If the current value is different from the default it means that it's been 951 // already changed for a11y reason. In that case we don't need to restore 952 // the new value. 953 final float currentValue = Settings.System.getFloat(cr, Settings.System.FONT_SCALE, 954 mDefaultFontScale); 955 if (currentValue != mDefaultFontScale) { 956 Log.d(TAG, "Font scale not restored because changed for a11y reason."); 957 continue; 958 } 959 final String toRestore = value; 960 value = findClosestAllowedFontScale(value, mAvailableFontScales); 961 Log.d(TAG, "Restored font scale from: " + toRestore + " to " + value); 962 } 963 964 965 settingsHelper.restoreValue(this, cr, contentValues, destination, key, value, 966 mRestoredFromSdkInt); 967 968 Log.d(TAG, "Restored setting: " + destination + " : " + key + "=" + value); 969 } 970 } 971 972 973 @VisibleForTesting findClosestAllowedFontScale(@onNull String requestedFontScale, @NonNull String[] availableFontScales)974 static String findClosestAllowedFontScale(@NonNull String requestedFontScale, 975 @NonNull String[] availableFontScales) { 976 if (Flags.configurableFontScaleDefault()) { 977 final float requestedValue = Float.parseFloat(requestedFontScale); 978 // Whatever is the requested value, we search the closest allowed value which is 979 // equals or larger. Note that if the requested value is the previous default, 980 // and this is still available, the value will be preserved. 981 float candidate = 0.0f; 982 boolean fontScaleFound = false; 983 for (int i = 0; !fontScaleFound && i < availableFontScales.length; i++) { 984 final float fontScale = Float.parseFloat(availableFontScales[i]); 985 if (fontScale >= requestedValue) { 986 candidate = fontScale; 987 fontScaleFound = true; 988 } 989 } 990 // If the current value is greater than all the allowed ones, we return the 991 // largest possible. 992 return fontScaleFound ? String.valueOf(candidate) : String.valueOf( 993 availableFontScales[availableFontScales.length - 1]); 994 } 995 return requestedFontScale; 996 } 997 998 @VisibleForTesting getBackupWhitelist(Uri contentUri)999 SettingsBackupWhitelist getBackupWhitelist(Uri contentUri) { 1000 // Figure out the white list and redirects to the global table. We restore anything 1001 // in either the backup allowlist or the legacy-restore allowlist for this table. 1002 String[] whitelist; 1003 Map<String, Validator> validators = null; 1004 if (contentUri.equals(Settings.Secure.CONTENT_URI)) { 1005 whitelist = ArrayUtils.concat(String.class, SecureSettings.SETTINGS_TO_BACKUP, 1006 Settings.Secure.LEGACY_RESTORE_SETTINGS, 1007 DeviceSpecificSettings.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP); 1008 validators = SecureSettingsValidators.VALIDATORS; 1009 } else if (contentUri.equals(Settings.System.CONTENT_URI)) { 1010 whitelist = ArrayUtils.concat(String.class, SystemSettings.SETTINGS_TO_BACKUP, 1011 Settings.System.LEGACY_RESTORE_SETTINGS); 1012 validators = SystemSettingsValidators.VALIDATORS; 1013 } else if (contentUri.equals(Settings.Global.CONTENT_URI)) { 1014 whitelist = ArrayUtils.concat(String.class, GlobalSettings.SETTINGS_TO_BACKUP, 1015 Settings.Global.LEGACY_RESTORE_SETTINGS); 1016 validators = GlobalSettingsValidators.VALIDATORS; 1017 } else { 1018 throw new IllegalArgumentException("Unknown URI: " + contentUri); 1019 } 1020 1021 return new SettingsBackupWhitelist(whitelist, validators); 1022 } 1023 isBlockedByDynamicList(Set<String> dynamicBlockList, Uri areaUri, String key)1024 private boolean isBlockedByDynamicList(Set<String> dynamicBlockList, Uri areaUri, String key) { 1025 String contentKey = Uri.withAppendedPath(areaUri, key).toString(); 1026 return dynamicBlockList.contains(contentKey); 1027 } 1028 1029 @VisibleForTesting getQualifiedKeyForSetting(String settingName, Uri settingUri)1030 static String getQualifiedKeyForSetting(String settingName, Uri settingUri) { 1031 return Uri.withAppendedPath(settingUri, settingName).toString(); 1032 } 1033 1034 // There may be other sources of blocked settings, so I'm separating out this 1035 // code to make it easy to modify in the future. 1036 @VisibleForTesting getBlockedSettings(int blockedSettingsArrayId)1037 protected Set<String> getBlockedSettings(int blockedSettingsArrayId) { 1038 String[] blockedSettings = getResources().getStringArray(blockedSettingsArrayId); 1039 return new HashSet<>(Arrays.asList(blockedSettings)); 1040 } 1041 isValidSettingValue(String key, String value, Map<String, Validator> validators)1042 private boolean isValidSettingValue(String key, String value, 1043 Map<String, Validator> validators) { 1044 if (key == null || validators == null) { 1045 return false; 1046 } 1047 Validator validator = validators.get(key); 1048 return (validator != null) && validator.validate(value); 1049 } 1050 1051 /** 1052 * Restores the owner info enabled and other settings in LockSettings. 1053 * 1054 * @param buffer 1055 * @param nBytes 1056 */ restoreLockSettings(@serIdInt int userId, byte[] buffer, int nBytes)1057 private void restoreLockSettings(@UserIdInt int userId, byte[] buffer, int nBytes) { 1058 final LockPatternUtils lockPatternUtils = new LockPatternUtils(this); 1059 1060 ByteArrayInputStream bais = new ByteArrayInputStream(buffer, 0, nBytes); 1061 DataInputStream in = new DataInputStream(bais); 1062 try { 1063 String key; 1064 // Read until empty string marker 1065 while ((key = in.readUTF()).length() > 0) { 1066 final String value = in.readUTF(); 1067 if (DEBUG_BACKUP) { 1068 Log.v(TAG, "Restoring lock_settings " + key + " = " + value); 1069 } 1070 switch (key) { 1071 case KEY_LOCK_SETTINGS_OWNER_INFO_ENABLED: 1072 lockPatternUtils.setOwnerInfoEnabled("1".equals(value), userId); 1073 break; 1074 case KEY_LOCK_SETTINGS_OWNER_INFO: 1075 lockPatternUtils.setOwnerInfo(value, userId); 1076 break; 1077 case KEY_LOCK_SETTINGS_VISIBLE_PATTERN_ENABLED: 1078 lockPatternUtils.setVisiblePatternEnabled("1".equals(value), userId); 1079 break; 1080 case KEY_LOCK_SETTINGS_POWER_BUTTON_INSTANTLY_LOCKS: 1081 lockPatternUtils.setPowerButtonInstantlyLocks("1".equals(value), userId); 1082 break; 1083 case KEY_LOCK_SETTINGS_PIN_ENHANCED_PRIVACY: 1084 lockPatternUtils.setPinEnhancedPrivacyEnabled("1".equals(value), userId); 1085 break; 1086 } 1087 } 1088 in.close(); 1089 } catch (IOException ioe) { 1090 } 1091 } 1092 restoreLockSettings(@serIdInt int userId, BackupDataInput data)1093 private void restoreLockSettings(@UserIdInt int userId, BackupDataInput data) { 1094 final byte[] settings = new byte[data.getDataSize()]; 1095 try { 1096 data.readEntityData(settings, 0, settings.length); 1097 } catch (IOException ioe) { 1098 Log.e(TAG, "Couldn't read entity data"); 1099 return; 1100 } 1101 restoreLockSettings(userId, settings, settings.length); 1102 } 1103 1104 /** 1105 * Given a cursor and a set of keys, extract the required keys and 1106 * values and write them to a byte array. 1107 * 1108 * @param cursor A cursor with settings data. 1109 * @param settings The settings to extract. 1110 * @return The byte array of extracted values. 1111 */ extractRelevantValues(Cursor cursor, String[] settings)1112 private byte[] extractRelevantValues(Cursor cursor, String[] settings) { 1113 if (!cursor.moveToFirst()) { 1114 Log.e(TAG, "Couldn't read from the cursor"); 1115 return new byte[0]; 1116 } 1117 1118 final int nameColumnIndex = cursor.getColumnIndex(Settings.NameValueTable.NAME); 1119 final int valueColumnIndex = cursor.getColumnIndex(Settings.NameValueTable.VALUE); 1120 1121 // Obtain the relevant data in a temporary array. 1122 int totalSize = 0; 1123 int backedUpSettingIndex = 0; 1124 final int settingsCount = settings.length; 1125 final byte[][] values = new byte[settingsCount * 2][]; // keys and values 1126 final ArrayMap<String, String> cachedEntries = new ArrayMap<>(); 1127 for (int i = 0; i < settingsCount; i++) { 1128 final String key = settings[i]; 1129 1130 // If the value not cached, let us look it up. 1131 String value = null; 1132 boolean hasValueToBackup = false; 1133 if (cachedEntries.indexOfKey(key) >= 0) { 1134 value = cachedEntries.remove(key); 1135 hasValueToBackup = true; 1136 } else { 1137 while (!cursor.isAfterLast()) { 1138 final String cursorKey = cursor.getString(nameColumnIndex); 1139 final String cursorValue = cursor.getString(valueColumnIndex); 1140 cursor.moveToNext(); 1141 if (key.equals(cursorKey)) { 1142 value = cursorValue; 1143 hasValueToBackup = true; 1144 break; 1145 } 1146 cachedEntries.put(cursorKey, cursorValue); 1147 } 1148 } 1149 1150 if (!hasValueToBackup) { 1151 continue; 1152 } 1153 1154 // Intercept the keys and see if they need special handling 1155 value = mSettingsHelper.onBackupValue(key, value); 1156 1157 // Write the key and value in the intermediary array. 1158 final byte[] keyBytes = key.getBytes(); 1159 totalSize += INTEGER_BYTE_COUNT + keyBytes.length; 1160 values[backedUpSettingIndex * 2] = keyBytes; 1161 1162 final byte[] valueBytes = (value != null) ? value.getBytes() : NULL_VALUE; 1163 totalSize += INTEGER_BYTE_COUNT + valueBytes.length; 1164 values[backedUpSettingIndex * 2 + 1] = valueBytes; 1165 1166 backedUpSettingIndex++; 1167 1168 if (DEBUG) { 1169 Log.d(TAG, "Backed up setting: " + key + "=" + value); 1170 } 1171 } 1172 1173 // Aggregate the result. 1174 byte[] result = new byte[totalSize]; 1175 int pos = 0; 1176 final int keyValuePairCount = backedUpSettingIndex * 2; 1177 for (int i = 0; i < keyValuePairCount; i++) { 1178 final byte[] value = values[i]; 1179 if (value != NULL_VALUE) { 1180 pos = writeInt(result, pos, value.length); 1181 pos = writeBytes(result, pos, value); 1182 } else { 1183 pos = writeInt(result, pos, NULL_SIZE); 1184 } 1185 } 1186 return result; 1187 } 1188 restoreSupplicantWifiConfigData(byte[] supplicant_bytes, byte[] ipconfig_bytes)1189 private void restoreSupplicantWifiConfigData(byte[] supplicant_bytes, byte[] ipconfig_bytes) { 1190 if (DEBUG_BACKUP) { 1191 Log.v(TAG, "Applying restored supplicant wifi data"); 1192 } 1193 mWifiManager.restoreSupplicantBackupData(supplicant_bytes, ipconfig_bytes); 1194 } 1195 getSoftAPConfiguration()1196 private byte[] getSoftAPConfiguration() { 1197 return mWifiManager.retrieveSoftApBackupData(); 1198 } 1199 restoreSoftApConfiguration(byte[] data)1200 private void restoreSoftApConfiguration(byte[] data) { 1201 SoftApConfiguration configInCloud = mWifiManager.restoreSoftApBackupData(data); 1202 if (configInCloud != null) { 1203 if (DEBUG) Log.d(TAG, "Successfully unMarshaled SoftApConfiguration "); 1204 // Depending on device hardware, we may need to notify the user of a setting change 1205 SoftApConfiguration storedConfig = mWifiManager.getSoftApConfiguration(); 1206 1207 if (isConfigurationHasChanged(configInCloud, storedConfig)) { 1208 Log.d(TAG, "restored ap configuration requires a conversion: " 1209 + ", configInCloud is " + configInCloud + " but storedConfig is " 1210 + storedConfig); 1211 } 1212 } 1213 } 1214 isConfigurationHasChanged(SoftApConfiguration configInCloud, SoftApConfiguration storedConfig)1215 private boolean isConfigurationHasChanged(SoftApConfiguration configInCloud, 1216 SoftApConfiguration storedConfig) { 1217 // Check if the cloud configuration was modified when restored to the device. 1218 // All elements of the configuration are compared except: 1219 // 1. Persistent randomized MAC address (which is per device) 1220 // 2. The flag indicating whether the configuration is "user modified" 1221 return !(Objects.equals(configInCloud.getWifiSsid(), storedConfig.getWifiSsid()) 1222 && Objects.equals(configInCloud.getBssid(), storedConfig.getBssid()) 1223 && Objects.equals(configInCloud.getPassphrase(), storedConfig.getPassphrase()) 1224 && configInCloud.isHiddenSsid() == storedConfig.isHiddenSsid() 1225 && configInCloud.getChannels().toString().equals( 1226 storedConfig.getChannels().toString()) 1227 && configInCloud.getSecurityType() == storedConfig.getSecurityType() 1228 && configInCloud.getMaxNumberOfClients() == storedConfig.getMaxNumberOfClients() 1229 && configInCloud.isAutoShutdownEnabled() == storedConfig.isAutoShutdownEnabled() 1230 && configInCloud.getShutdownTimeoutMillis() 1231 == storedConfig.getShutdownTimeoutMillis() 1232 && configInCloud.isClientControlByUserEnabled() 1233 == storedConfig.isClientControlByUserEnabled() 1234 && Objects.equals(configInCloud.getBlockedClientList(), 1235 storedConfig.getBlockedClientList()) 1236 && Objects.equals(configInCloud.getAllowedClientList(), 1237 storedConfig.getAllowedClientList()) 1238 && configInCloud.getMacRandomizationSetting() 1239 == storedConfig.getMacRandomizationSetting() 1240 && configInCloud.isBridgedModeOpportunisticShutdownEnabled() 1241 == storedConfig.isBridgedModeOpportunisticShutdownEnabled() 1242 && configInCloud.isIeee80211axEnabled() == storedConfig.isIeee80211axEnabled() 1243 && configInCloud.isIeee80211beEnabled() == storedConfig.isIeee80211beEnabled() 1244 && configInCloud.getBridgedModeOpportunisticShutdownTimeoutMillis() 1245 == storedConfig.getBridgedModeOpportunisticShutdownTimeoutMillis() 1246 && Objects.equals(configInCloud.getVendorElements(), 1247 storedConfig.getVendorElements()) 1248 && Arrays.equals(configInCloud.getAllowedAcsChannels( 1249 SoftApConfiguration.BAND_2GHZ), 1250 storedConfig.getAllowedAcsChannels(SoftApConfiguration.BAND_2GHZ)) 1251 && Arrays.equals(configInCloud.getAllowedAcsChannels( 1252 SoftApConfiguration.BAND_5GHZ), 1253 storedConfig.getAllowedAcsChannels(SoftApConfiguration.BAND_5GHZ)) 1254 && Arrays.equals(configInCloud.getAllowedAcsChannels( 1255 SoftApConfiguration.BAND_6GHZ), 1256 storedConfig.getAllowedAcsChannels(SoftApConfiguration.BAND_6GHZ)) 1257 && configInCloud.getMaxChannelBandwidth() == storedConfig.getMaxChannelBandwidth() 1258 ); 1259 } 1260 getNetworkPolicies()1261 private byte[] getNetworkPolicies() { 1262 NetworkPolicyManager networkPolicyManager = 1263 (NetworkPolicyManager) getSystemService(NETWORK_POLICY_SERVICE); 1264 NetworkPolicy[] policies = networkPolicyManager.getNetworkPolicies(); 1265 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 1266 if (policies != null && policies.length != 0) { 1267 DataOutputStream out = new DataOutputStream(baos); 1268 try { 1269 out.writeInt(NETWORK_POLICIES_BACKUP_VERSION); 1270 out.writeInt(policies.length); 1271 for (NetworkPolicy policy : policies) { 1272 // We purposefully only backup policies that the user has 1273 // defined; any inferred policies might include 1274 // carrier-protected data that we can't export. 1275 if (policy != null && !policy.inferred) { 1276 byte[] marshaledPolicy = policy.getBytesForBackup(); 1277 out.writeByte(BackupUtils.NOT_NULL); 1278 out.writeInt(marshaledPolicy.length); 1279 out.write(marshaledPolicy); 1280 } else { 1281 out.writeByte(BackupUtils.NULL); 1282 } 1283 } 1284 } catch (IOException ioe) { 1285 Log.e(TAG, "Failed to convert NetworkPolicies to byte array " + ioe.getMessage()); 1286 baos.reset(); 1287 } 1288 } 1289 return baos.toByteArray(); 1290 } 1291 getNewWifiConfigData()1292 private byte[] getNewWifiConfigData() { 1293 return mWifiManager.retrieveBackupData(); 1294 } 1295 restoreNewWifiConfigData(byte[] bytes)1296 private void restoreNewWifiConfigData(byte[] bytes) { 1297 if (DEBUG_BACKUP) { 1298 Log.v(TAG, "Applying restored wifi data"); 1299 } 1300 mWifiManager.restoreBackupData(bytes); 1301 } 1302 restoreNetworkPolicies(byte[] data)1303 private void restoreNetworkPolicies(byte[] data) { 1304 NetworkPolicyManager networkPolicyManager = 1305 (NetworkPolicyManager) getSystemService(NETWORK_POLICY_SERVICE); 1306 if (data != null && data.length != 0) { 1307 DataInputStream in = new DataInputStream(new ByteArrayInputStream(data)); 1308 try { 1309 int version = in.readInt(); 1310 if (version < 1 || version > NETWORK_POLICIES_BACKUP_VERSION) { 1311 throw new BackupUtils.BadVersionException( 1312 "Unknown Backup Serialization Version"); 1313 } 1314 int length = in.readInt(); 1315 NetworkPolicy[] policies = new NetworkPolicy[length]; 1316 for (int i = 0; i < length; i++) { 1317 byte isNull = in.readByte(); 1318 if (isNull == BackupUtils.NULL) continue; 1319 int byteLength = in.readInt(); 1320 byte[] policyData = new byte[byteLength]; 1321 in.read(policyData, 0, byteLength); 1322 policies[i] = NetworkPolicy.getNetworkPolicyFromBackup( 1323 new DataInputStream(new ByteArrayInputStream(policyData))); 1324 } 1325 // Only set the policies if there was no error in the restore operation 1326 networkPolicyManager.setNetworkPolicies(policies); 1327 } catch (NullPointerException | IOException | BackupUtils.BadVersionException 1328 | DateTimeException e) { 1329 // NPE can be thrown when trying to instantiate a NetworkPolicy 1330 Log.e(TAG, "Failed to convert byte array to NetworkPolicies " + e.getMessage()); 1331 } 1332 } 1333 } 1334 1335 @VisibleForTesting getDeviceSpecificConfiguration()1336 byte[] getDeviceSpecificConfiguration() throws IOException { 1337 try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { 1338 writeHeader(os); 1339 os.write(getDeviceSpecificSettings()); 1340 return os.toByteArray(); 1341 } 1342 } 1343 1344 @VisibleForTesting writeHeader(OutputStream os)1345 void writeHeader(OutputStream os) throws IOException { 1346 os.write(toByteArray(DEVICE_SPECIFIC_VERSION)); 1347 os.write(toByteArray(Build.MANUFACTURER)); 1348 os.write(toByteArray(Build.PRODUCT)); 1349 } 1350 getDeviceSpecificSettings()1351 private byte[] getDeviceSpecificSettings() { 1352 try (Cursor cursor = 1353 getContentResolver() 1354 .query(Settings.Secure.CONTENT_URI, PROJECTION, null, null, null)) { 1355 return extractRelevantValues( 1356 cursor, DeviceSpecificSettings.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP); 1357 } 1358 } 1359 1360 /** 1361 * Restore the device specific settings. 1362 * 1363 * @param data The byte array holding a backed up version of another devices settings. 1364 * @param blockedSettingsArrayId The string array resource holding the settings not to restore. 1365 * @param dynamicBlocklist The dynamic list of settings not to restore fed into this agent. 1366 * @return true if the restore succeeded, false if it was stopped. 1367 */ 1368 @VisibleForTesting restoreDeviceSpecificConfig(byte[] data, int blockedSettingsArrayId, Set<String> dynamicBlocklist, Set<String> preservedSettings)1369 boolean restoreDeviceSpecificConfig(byte[] data, int blockedSettingsArrayId, 1370 Set<String> dynamicBlocklist, Set<String> preservedSettings) { 1371 // We're using an AtomicInteger to wrap the position int and allow called methods to 1372 // modify it. 1373 AtomicInteger pos = new AtomicInteger(0); 1374 if (!isSourceAcceptable(data, pos)) { 1375 return false; 1376 } 1377 1378 Integer originalDensity = getPreviousDensity(); 1379 1380 int dataStart = pos.get(); 1381 restoreSettings( 1382 data, 1383 dataStart, 1384 data.length, 1385 Settings.Secure.CONTENT_URI, 1386 null, 1387 null, 1388 null, 1389 blockedSettingsArrayId, 1390 dynamicBlocklist, 1391 preservedSettings); 1392 1393 updateWindowManagerIfNeeded(originalDensity); 1394 1395 return true; 1396 } 1397 getSimSpecificSettingsData()1398 private byte[] getSimSpecificSettingsData() { 1399 byte[] simSpecificData = new byte[0]; 1400 PackageManager packageManager = getBaseContext().getPackageManager(); 1401 if (packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) { 1402 SubscriptionManager subManager = SubscriptionManager.from(getBaseContext()); 1403 simSpecificData = subManager.getAllSimSpecificSettingsForBackup(); 1404 Log.i(TAG, "sim specific data of length + " + simSpecificData.length 1405 + " successfully retrieved"); 1406 } 1407 1408 return simSpecificData; 1409 } 1410 restoreSimSpecificSettings(byte[] data)1411 private void restoreSimSpecificSettings(byte[] data) { 1412 PackageManager packageManager = getBaseContext().getPackageManager(); 1413 boolean hasTelephony = packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY); 1414 if (hasTelephony) { 1415 SubscriptionManager subManager = SubscriptionManager.from(getBaseContext()); 1416 subManager.restoreAllSimSpecificSettingsFromBackup(data); 1417 } 1418 } 1419 1420 private static final class Mutable<E> { 1421 public volatile E value; 1422 Mutable()1423 Mutable() { 1424 value = null; 1425 } 1426 } 1427 getWifiSettingsBackupData()1428 private byte[] getWifiSettingsBackupData() { 1429 final CountDownLatch latch = new CountDownLatch(1); 1430 final Mutable<byte[]> backupWifiData = new Mutable<byte[]>(); 1431 1432 try { 1433 mWifiManager.retrieveWifiBackupData(getBaseContext().getMainExecutor(), 1434 new Consumer<byte[]>() { 1435 @Override 1436 public void accept(byte[] value) { 1437 backupWifiData.value = value; 1438 latch.countDown(); 1439 } 1440 }); 1441 // cts requires B&R with 10 seconds 1442 if (latch.await(10, TimeUnit.SECONDS) && backupWifiData.value != null) { 1443 return backupWifiData.value; 1444 } 1445 } catch (InterruptedException ie) { 1446 Log.e(TAG, "fail to retrieveWifiBackupData, " + ie); 1447 } 1448 Log.e(TAG, "fail to retrieveWifiBackupData"); 1449 return new byte[0]; 1450 } 1451 restoreWifiData(byte[] data)1452 private void restoreWifiData(byte[] data) { 1453 if (DEBUG_BACKUP) { 1454 Log.v(TAG, "Applying restored all wifi data"); 1455 } 1456 mWifiManager.restoreWifiBackupData(data); 1457 } 1458 updateWindowManagerIfNeeded(Integer previousDensity)1459 private void updateWindowManagerIfNeeded(Integer previousDensity) { 1460 int newDensity; 1461 try { 1462 newDensity = getForcedDensity(); 1463 } catch (Settings.SettingNotFoundException e) { 1464 // If there's not density setting we can't perform a change. 1465 return; 1466 } 1467 1468 if (previousDensity == null || previousDensity != newDensity) { 1469 // From nothing to something is a change. 1470 DisplayDensityConfiguration.setForcedDisplayDensity( 1471 Display.DEFAULT_DISPLAY, newDensity); 1472 } 1473 } 1474 getPreviousDensity()1475 private Integer getPreviousDensity() { 1476 try { 1477 return getForcedDensity(); 1478 } catch (Settings.SettingNotFoundException e) { 1479 return null; 1480 } 1481 } 1482 getForcedDensity()1483 private int getForcedDensity() throws Settings.SettingNotFoundException { 1484 return Settings.Secure.getInt(getContentResolver(), Settings.Secure.DISPLAY_DENSITY_FORCED); 1485 } 1486 1487 @VisibleForTesting isSourceAcceptable(byte[] data, AtomicInteger pos)1488 boolean isSourceAcceptable(byte[] data, AtomicInteger pos) { 1489 int version = readInt(data, pos); 1490 if (version > DEVICE_SPECIFIC_VERSION) { 1491 Slog.w(TAG, "Unable to restore device specific information; Backup is too new"); 1492 return false; 1493 } 1494 1495 String sourceManufacturer = readString(data, pos); 1496 if (!Objects.equals(Build.MANUFACTURER, sourceManufacturer)) { 1497 Log.w( 1498 TAG, 1499 "Unable to restore device specific information; Manufacturer mismatch " 1500 + "(\'" 1501 + Build.MANUFACTURER 1502 + "\' and \'" 1503 + sourceManufacturer 1504 + "\')"); 1505 return false; 1506 } 1507 1508 String sourceProduct = readString(data, pos); 1509 if (!Objects.equals(Build.PRODUCT, sourceProduct)) { 1510 Log.w( 1511 TAG, 1512 "Unable to restore device specific information; Product mismatch (\'" 1513 + Build.PRODUCT 1514 + "\' and \'" 1515 + sourceProduct 1516 + "\')"); 1517 return false; 1518 } 1519 1520 return true; 1521 } 1522 1523 @VisibleForTesting toByteArray(String value)1524 static byte[] toByteArray(String value) { 1525 if (value == null) { 1526 return toByteArray(NULL_SIZE); 1527 } 1528 1529 byte[] stringBytes = value.getBytes(); 1530 byte[] sizeAndString = new byte[stringBytes.length + INTEGER_BYTE_COUNT]; 1531 writeInt(sizeAndString, 0, stringBytes.length); 1532 writeBytes(sizeAndString, INTEGER_BYTE_COUNT, stringBytes); 1533 return sizeAndString; 1534 } 1535 1536 @VisibleForTesting toByteArray(int value)1537 static byte[] toByteArray(int value) { 1538 byte[] result = new byte[INTEGER_BYTE_COUNT]; 1539 writeInt(result, 0, value); 1540 return result; 1541 } 1542 readString(byte[] data, AtomicInteger pos)1543 private String readString(byte[] data, AtomicInteger pos) { 1544 int byteCount = readInt(data, pos); 1545 if (byteCount == NULL_SIZE) { 1546 return null; 1547 } 1548 1549 int stringStart = pos.getAndAdd(byteCount); 1550 return new String(data, stringStart, byteCount); 1551 } 1552 1553 /** 1554 * Write an int in BigEndian into the byte array. 1555 * @param out byte array 1556 * @param pos current pos in array 1557 * @param value integer to write 1558 * @return the index after adding the size of an int (4) in bytes. 1559 */ writeInt(byte[] out, int pos, int value)1560 private static int writeInt(byte[] out, int pos, int value) { 1561 out[pos + 0] = (byte) ((value >> 24) & 0xFF); 1562 out[pos + 1] = (byte) ((value >> 16) & 0xFF); 1563 out[pos + 2] = (byte) ((value >> 8) & 0xFF); 1564 out[pos + 3] = (byte) ((value >> 0) & 0xFF); 1565 return pos + INTEGER_BYTE_COUNT; 1566 } 1567 writeBytes(byte[] out, int pos, byte[] value)1568 private static int writeBytes(byte[] out, int pos, byte[] value) { 1569 System.arraycopy(value, 0, out, pos, value.length); 1570 return pos + value.length; 1571 } 1572 readInt(byte[] in, AtomicInteger pos)1573 private int readInt(byte[] in, AtomicInteger pos) { 1574 return readInt(in, pos.getAndAdd(INTEGER_BYTE_COUNT)); 1575 } 1576 readInt(byte[] in, int pos)1577 private int readInt(byte[] in, int pos) { 1578 int result = ((in[pos] & 0xFF) << 24) 1579 | ((in[pos + 1] & 0xFF) << 16) 1580 | ((in[pos + 2] & 0xFF) << 8) 1581 | ((in[pos + 3] & 0xFF) << 0); 1582 return result; 1583 } 1584 1585 /** 1586 * Store the allowlist of settings to be backed up and validators for them. 1587 */ 1588 @VisibleForTesting 1589 static class SettingsBackupWhitelist { 1590 final String[] mSettingsWhitelist; 1591 final Map<String, Validator> mSettingsValidators; 1592 1593 SettingsBackupWhitelist(String[] settingsWhitelist, Map<String, Validator> settingsValidators)1594 SettingsBackupWhitelist(String[] settingsWhitelist, 1595 Map<String, Validator> settingsValidators) { 1596 mSettingsWhitelist = settingsWhitelist; 1597 mSettingsValidators = settingsValidators; 1598 } 1599 } 1600 } 1601