blob: 920df2e30aae8449370af7c6d92394859747657f [file] [log] [blame]
Amith Yamasani220f4d62009-07-02 02:34:14 -07001/*
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
17package com.android.providers.settings;
18
Svetoslav Ganova571a582011-09-20 18:32:20 -070019import android.app.backup.BackupAgentHelper;
20import android.app.backup.BackupDataInput;
21import android.app.backup.BackupDataOutput;
22import android.app.backup.FullBackupDataOutput;
Christopher Tate87bc7e72013-06-10 16:55:02 -070023import android.content.ContentResolver;
Svetoslav Ganova571a582011-09-20 18:32:20 -070024import android.content.ContentValues;
25import android.content.Context;
26import android.database.Cursor;
Ritesh Reddyadca34a2016-02-04 18:33:30 +000027import android.net.NetworkPolicy;
28import android.net.NetworkPolicyManager;
Svetoslav Ganova571a582011-09-20 18:32:20 -070029import android.net.Uri;
Christopher Tatecab915a2015-01-08 12:50:00 -080030import android.net.wifi.WifiConfiguration;
Svetoslav Ganova571a582011-09-20 18:32:20 -070031import android.net.wifi.WifiManager;
Christopher Tated488bc02012-10-09 14:06:30 -070032import android.os.Handler;
Svetoslav Ganova571a582011-09-20 18:32:20 -070033import android.os.ParcelFileDescriptor;
Amith Yamasani072543f2015-02-13 11:09:45 -080034import android.os.UserHandle;
Svetoslav Ganova571a582011-09-20 18:32:20 -070035import android.provider.Settings;
Ritesh Reddyaeb4c062016-01-26 19:40:48 +000036import android.util.BackupUtils;
Svetoslav Ganova571a582011-09-20 18:32:20 -070037import android.util.Log;
38
Amith Yamasani072543f2015-02-13 11:09:45 -080039import com.android.internal.widget.LockPatternUtils;
40
Brad Fitzpatrick70787892010-11-17 11:31:12 -080041import java.io.BufferedOutputStream;
Amith Yamasani072543f2015-02-13 11:09:45 -080042import java.io.ByteArrayInputStream;
Christopher Tatecab915a2015-01-08 12:50:00 -080043import java.io.ByteArrayOutputStream;
Amith Yamasanid1582142009-07-08 20:04:55 -070044import java.io.DataInputStream;
45import java.io.DataOutputStream;
Amith Yamasani2cfab842009-09-09 18:27:31 -070046import java.io.EOFException;
Amith Yamasani220f4d62009-07-02 02:34:14 -070047import java.io.File;
48import java.io.FileInputStream;
49import java.io.FileOutputStream;
50import java.io.IOException;
Svetoslav Ganova571a582011-09-20 18:32:20 -070051import java.util.HashMap;
Christopher Tate8dfe2b92012-05-15 15:05:04 -070052import java.util.HashSet;
Svetoslav Ganova571a582011-09-20 18:32:20 -070053import java.util.Map;
Amith Yamasanid1582142009-07-08 20:04:55 -070054import java.util.zip.CRC32;
Amith Yamasani220f4d62009-07-02 02:34:14 -070055
Amith Yamasani220f4d62009-07-02 02:34:14 -070056/**
57 * Performs backup and restore of the System and Secure settings.
58 * List of settings that are backed up are stored in the Settings.java file
59 */
Christopher Tatecc84c692010-03-29 14:54:02 -070060public class SettingsBackupAgent extends BackupAgentHelper {
Christopher Tate436344a2009-09-30 16:17:37 -070061 private static final boolean DEBUG = false;
Christopher Tate8dfe2b92012-05-15 15:05:04 -070062 private static final boolean DEBUG_BACKUP = DEBUG || false;
Amith Yamasani220f4d62009-07-02 02:34:14 -070063
64 private static final String KEY_SYSTEM = "system";
65 private static final String KEY_SECURE = "secure";
Christopher Tate66488d62012-10-02 11:58:01 -070066 private static final String KEY_GLOBAL = "global";
Amith Yamasani8823c0a82009-07-07 14:30:17 -070067 private static final String KEY_LOCALE = "locale";
Amith Yamasani072543f2015-02-13 11:09:45 -080068 private static final String KEY_LOCK_SETTINGS = "lock_settings";
Ritesh Reddyaeb4c062016-01-26 19:40:48 +000069 private static final String KEY_SOFTAP_CONFIG = "softap_config";
Ritesh Reddyadca34a2016-02-04 18:33:30 +000070 private static final String KEY_NETWORK_POLICIES = "network_policies";
Roshan Pius1bf86982016-06-02 09:22:55 -070071 private static final String KEY_WIFI_NEW_CONFIG = "wifi_new_config";
Amith Yamasani220f4d62009-07-02 02:34:14 -070072
Christopher Tatea286f412009-09-18 15:51:15 -070073 // Versioning of the state file. Increment this version
74 // number any time the set of state items is altered.
Roshan Pius1bf86982016-06-02 09:22:55 -070075 private static final int STATE_VERSION = 7;
Ritesh Reddyadca34a2016-02-04 18:33:30 +000076
77 // Versioning of the Network Policies backup payload.
78 private static final int NETWORK_POLICIES_BACKUP_VERSION = 1;
79
Christopher Tatea286f412009-09-18 15:51:15 -070080
Christopher Tate66488d62012-10-02 11:58:01 -070081 // Slots in the checksum array. Never insert new items in the middle
82 // of this array; new slots must be appended.
Ritesh Reddyadca34a2016-02-04 18:33:30 +000083 private static final int STATE_SYSTEM = 0;
84 private static final int STATE_SECURE = 1;
85 private static final int STATE_LOCALE = 2;
86 private static final int STATE_WIFI_SUPPLICANT = 3;
87 private static final int STATE_WIFI_CONFIG = 4;
88 private static final int STATE_GLOBAL = 5;
89 private static final int STATE_LOCK_SETTINGS = 6;
90 private static final int STATE_SOFTAP_CONFIG = 7;
91 private static final int STATE_NETWORK_POLICIES = 8;
Roshan Pius1bf86982016-06-02 09:22:55 -070092 private static final int STATE_WIFI_NEW_CONFIG = 9;
Christopher Tate66488d62012-10-02 11:58:01 -070093
Roshan Pius1bf86982016-06-02 09:22:55 -070094 private static final int STATE_SIZE = 10; // The current number of state items
Christopher Tate66488d62012-10-02 11:58:01 -070095
96 // Number of entries in the checksum array at various version numbers
97 private static final int STATE_SIZES[] = {
Ritesh Reddyaeb4c062016-01-26 19:40:48 +000098 0,
99 4, // version 1
100 5, // version 2 added STATE_WIFI_CONFIG
101 6, // version 3 added STATE_GLOBAL
102 7, // version 4 added STATE_LOCK_SETTINGS
Ritesh Reddyadca34a2016-02-04 18:33:30 +0000103 8, // version 5 added STATE_SOFTAP_CONFIG
Roshan Pius1bf86982016-06-02 09:22:55 -0700104 9, // version 6 added STATE_NETWORK_POLICIES
105 STATE_SIZE // version 7 added STATE_WIFI_NEW_CONFIG
Christopher Tate66488d62012-10-02 11:58:01 -0700106 };
Amith Yamasanid1582142009-07-08 20:04:55 -0700107
Christopher Tate75a99702011-05-18 16:28:19 -0700108 // Versioning of the 'full backup' format
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000109 // Increment this version any time a new item is added
Roshan Pius1bf86982016-06-02 09:22:55 -0700110 private static final int FULL_BACKUP_VERSION = 6;
Christopher Tate66488d62012-10-02 11:58:01 -0700111 private static final int FULL_BACKUP_ADDED_GLOBAL = 2; // added the "global" entry
Amith Yamasani072543f2015-02-13 11:09:45 -0800112 private static final int FULL_BACKUP_ADDED_LOCK_SETTINGS = 3; // added the "lock_settings" entry
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000113 private static final int FULL_BACKUP_ADDED_SOFTAP_CONF = 4; //added the "softap_config" entry
Ritesh Reddyadca34a2016-02-04 18:33:30 +0000114 private static final int FULL_BACKUP_ADDED_NETWORK_POLICIES = 5; //added "network_policies"
Roshan Pius1bf86982016-06-02 09:22:55 -0700115 private static final int FULL_BACKUP_ADDED_WIFI_NEW = 6; // added "wifi_new_config" entry
Christopher Tate75a99702011-05-18 16:28:19 -0700116
Svetoslav Ganova571a582011-09-20 18:32:20 -0700117 private static final int INTEGER_BYTE_COUNT = Integer.SIZE / Byte.SIZE;
Amith Yamasani220f4d62009-07-02 02:34:14 -0700118
119 private static final byte[] EMPTY_DATA = new byte[0];
120
121 private static final String TAG = "SettingsBackupAgent";
122
Amith Yamasani220f4d62009-07-02 02:34:14 -0700123 private static final String[] PROJECTION = {
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000124 Settings.NameValueTable.NAME,
125 Settings.NameValueTable.VALUE
Amith Yamasani220f4d62009-07-02 02:34:14 -0700126 };
127
Christian Sonntag92c17522009-08-07 15:16:17 -0700128 // the key to store the WIFI data under, should be sorted as last, so restore happens last.
129 // use very late unicode character to quasi-guarantee last sort position.
Amith Yamasani2cfab842009-09-09 18:27:31 -0700130 private static final String KEY_WIFI_SUPPLICANT = "\uffedWIFI";
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -0800131 private static final String KEY_WIFI_CONFIG = "\uffedCONFIG_WIFI";
Amith Yamasani220f4d62009-07-02 02:34:14 -0700132
Amith Yamasani072543f2015-02-13 11:09:45 -0800133 // Keys within the lock settings section
134 private static final String KEY_LOCK_SETTINGS_OWNER_INFO_ENABLED = "owner_info_enabled";
135 private static final String KEY_LOCK_SETTINGS_OWNER_INFO = "owner_info";
136
Christopher Tate4a627c72011-04-01 14:43:32 -0700137 // Name of the temporary file we use during full backup/restore. This is
138 // stored in the full-backup tarfile as well, so should not be changed.
139 private static final String STAGE_FILE = "flattened-data";
140
Amith Yamasani220f4d62009-07-02 02:34:14 -0700141 private SettingsHelper mSettingsHelper;
142
Roshan Pius1bf86982016-06-02 09:22:55 -0700143 private WifiManager mWifiManager;
Christopher Tate8dfe2b92012-05-15 15:05:04 -0700144
Svetoslav Ganova571a582011-09-20 18:32:20 -0700145 @Override
Amith Yamasani220f4d62009-07-02 02:34:14 -0700146 public void onCreate() {
Christopher Tate75a99702011-05-18 16:28:19 -0700147 if (DEBUG_BACKUP) Log.d(TAG, "onCreate() invoked");
148
Amith Yamasani220f4d62009-07-02 02:34:14 -0700149 mSettingsHelper = new SettingsHelper(this);
Roshan Pius1bf86982016-06-02 09:22:55 -0700150 mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
Amith Yamasani220f4d62009-07-02 02:34:14 -0700151 super.onCreate();
152 }
153
154 @Override
155 public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
Ritesh Reddy33117fe2016-02-01 13:45:33 +0000156 ParcelFileDescriptor newState) throws IOException {
Amith Yamasani220f4d62009-07-02 02:34:14 -0700157
158 byte[] systemSettingsData = getSystemSettings();
159 byte[] secureSettingsData = getSecureSettings();
Christopher Tate66488d62012-10-02 11:58:01 -0700160 byte[] globalSettingsData = getGlobalSettings();
Amith Yamasani072543f2015-02-13 11:09:45 -0800161 byte[] lockSettingsData = getLockSettings();
Amith Yamasani8823c0a82009-07-07 14:30:17 -0700162 byte[] locale = mSettingsHelper.getLocaleData();
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000163 byte[] softApConfigData = getSoftAPConfiguration();
Ritesh Reddyadca34a2016-02-04 18:33:30 +0000164 byte[] netPoliciesData = getNetworkPolicies();
Roshan Pius1bf86982016-06-02 09:22:55 -0700165 byte[] wifiFullConfigData = getNewWifiConfigData();
Amith Yamasani220f4d62009-07-02 02:34:14 -0700166
Christopher Tate79ec80d2011-06-24 14:58:49 -0700167 long[] stateChecksums = readOldChecksums(oldState);
Amith Yamasani220f4d62009-07-02 02:34:14 -0700168
Christopher Tate79ec80d2011-06-24 14:58:49 -0700169 stateChecksums[STATE_SYSTEM] =
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000170 writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data);
Christopher Tate79ec80d2011-06-24 14:58:49 -0700171 stateChecksums[STATE_SECURE] =
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000172 writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data);
Christopher Tate66488d62012-10-02 11:58:01 -0700173 stateChecksums[STATE_GLOBAL] =
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000174 writeIfChanged(stateChecksums[STATE_GLOBAL], KEY_GLOBAL, globalSettingsData, data);
Christopher Tate79ec80d2011-06-24 14:58:49 -0700175 stateChecksums[STATE_LOCALE] =
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000176 writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data);
Roshan Pius1bf86982016-06-02 09:22:55 -0700177 stateChecksums[STATE_WIFI_SUPPLICANT] = 0;
178 stateChecksums[STATE_WIFI_CONFIG] = 0;
Amith Yamasani072543f2015-02-13 11:09:45 -0800179 stateChecksums[STATE_LOCK_SETTINGS] =
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000180 writeIfChanged(stateChecksums[STATE_LOCK_SETTINGS], KEY_LOCK_SETTINGS,
181 lockSettingsData, data);
182 stateChecksums[STATE_SOFTAP_CONFIG] =
183 writeIfChanged(stateChecksums[STATE_SOFTAP_CONFIG], KEY_SOFTAP_CONFIG,
184 softApConfigData, data);
Ritesh Reddyadca34a2016-02-04 18:33:30 +0000185 stateChecksums[STATE_NETWORK_POLICIES] =
186 writeIfChanged(stateChecksums[STATE_NETWORK_POLICIES], KEY_NETWORK_POLICIES,
187 netPoliciesData, data);
Roshan Pius1bf86982016-06-02 09:22:55 -0700188 stateChecksums[STATE_WIFI_NEW_CONFIG] =
189 writeIfChanged(stateChecksums[STATE_WIFI_NEW_CONFIG], KEY_WIFI_NEW_CONFIG,
190 wifiFullConfigData, data);
Amith Yamasani8823c0a82009-07-07 14:30:17 -0700191
Christopher Tate79ec80d2011-06-24 14:58:49 -0700192 writeNewChecksums(stateChecksums, newState);
Amith Yamasani220f4d62009-07-02 02:34:14 -0700193 }
194
195 @Override
196 public void onRestore(BackupDataInput data, int appVersionCode,
Ritesh Reddy33117fe2016-02-01 13:45:33 +0000197 ParcelFileDescriptor newState) throws IOException {
Amith Yamasani220f4d62009-07-02 02:34:14 -0700198
Christopher Tate66488d62012-10-02 11:58:01 -0700199 HashSet<String> movedToGlobal = new HashSet<String>();
Svetoslav683914b2015-01-15 14:22:26 -0800200 Settings.System.getMovedToGlobalSettings(movedToGlobal);
201 Settings.Secure.getMovedToGlobalSettings(movedToGlobal);
Roshan Pius1bf86982016-06-02 09:22:55 -0700202 byte[] restoredWifiSupplicantData = null;
203 byte[] restoredWifiIpConfigData = null;
Christopher Tate66488d62012-10-02 11:58:01 -0700204
Amith Yamasani220f4d62009-07-02 02:34:14 -0700205 while (data.readNextHeader()) {
206 final String key = data.getKey();
Amith Yamasani8823c0a82009-07-07 14:30:17 -0700207 final int size = data.getDataSize();
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000208 switch (key) {
209 case KEY_SYSTEM :
210 restoreSettings(data, Settings.System.CONTENT_URI, movedToGlobal);
211 mSettingsHelper.applyAudioSettings();
212 break;
213
214 case KEY_SECURE :
215 restoreSettings(data, Settings.Secure.CONTENT_URI, movedToGlobal);
216 break;
217
218 case KEY_GLOBAL :
219 restoreSettings(data, Settings.Global.CONTENT_URI, null);
220 break;
221
222 case KEY_WIFI_SUPPLICANT :
Roshan Pius1bf86982016-06-02 09:22:55 -0700223 restoredWifiSupplicantData = new byte[size];
224 data.readEntityData(restoredWifiSupplicantData, 0, size);
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000225 break;
226
227 case KEY_LOCALE :
228 byte[] localeData = new byte[size];
229 data.readEntityData(localeData, 0, size);
230 mSettingsHelper.setLocaleData(localeData, size);
231 break;
232
233 case KEY_WIFI_CONFIG :
Roshan Pius1bf86982016-06-02 09:22:55 -0700234 restoredWifiIpConfigData = new byte[size];
235 data.readEntityData(restoredWifiIpConfigData, 0, size);
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000236 break;
237
238 case KEY_LOCK_SETTINGS :
239 restoreLockSettings(data);
240 break;
241
242 case KEY_SOFTAP_CONFIG :
243 byte[] softapData = new byte[size];
244 data.readEntityData(softapData, 0, size);
245 restoreSoftApConfiguration(softapData);
246 break;
247
Ritesh Reddyadca34a2016-02-04 18:33:30 +0000248 case KEY_NETWORK_POLICIES:
249 byte[] netPoliciesData = new byte[size];
250 data.readEntityData(netPoliciesData, 0, size);
251 restoreNetworkPolicies(netPoliciesData);
252 break;
253
Roshan Pius1bf86982016-06-02 09:22:55 -0700254 case KEY_WIFI_NEW_CONFIG:
255 byte[] restoredWifiNewConfigData = new byte[size];
256 data.readEntityData(restoredWifiNewConfigData, 0, size);
Roshan Pius28be4fc2016-06-17 16:51:36 -0700257 restoreNewWifiConfigData(restoredWifiNewConfigData);
Roshan Pius1bf86982016-06-02 09:22:55 -0700258 break;
259
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000260 default :
261 data.skipEntityData();
262
Amith Yamasani220f4d62009-07-02 02:34:14 -0700263 }
264 }
Christopher Tated488bc02012-10-09 14:06:30 -0700265
Roshan Pius1bf86982016-06-02 09:22:55 -0700266 // Do this at the end so that we also pull in the ipconfig data.
267 if (restoredWifiSupplicantData != null) {
268 restoreSupplicantWifiConfigData(
Roshan Pius28be4fc2016-06-17 16:51:36 -0700269 restoredWifiSupplicantData, restoredWifiIpConfigData);
Christopher Tated488bc02012-10-09 14:06:30 -0700270 }
Amith Yamasani220f4d62009-07-02 02:34:14 -0700271 }
272
Christopher Tate75a99702011-05-18 16:28:19 -0700273 @Override
Christopher Tate79ec80d2011-06-24 14:58:49 -0700274 public void onFullBackup(FullBackupDataOutput data) throws IOException {
275 byte[] systemSettingsData = getSystemSettings();
276 byte[] secureSettingsData = getSecureSettings();
Christopher Tate66488d62012-10-02 11:58:01 -0700277 byte[] globalSettingsData = getGlobalSettings();
Amith Yamasani072543f2015-02-13 11:09:45 -0800278 byte[] lockSettingsData = getLockSettings();
Christopher Tate79ec80d2011-06-24 14:58:49 -0700279 byte[] locale = mSettingsHelper.getLocaleData();
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000280 byte[] softApConfigData = getSoftAPConfiguration();
Ritesh Reddyadca34a2016-02-04 18:33:30 +0000281 byte[] netPoliciesData = getNetworkPolicies();
Roshan Pius1bf86982016-06-02 09:22:55 -0700282 byte[] wifiFullConfigData = getNewWifiConfigData();
Christopher Tate79ec80d2011-06-24 14:58:49 -0700283
284 // Write the data to the staging file, then emit that as our tarfile
285 // representation of the backed-up settings.
286 String root = getFilesDir().getAbsolutePath();
287 File stage = new File(root, STAGE_FILE);
288 try {
289 FileOutputStream filestream = new FileOutputStream(stage);
290 BufferedOutputStream bufstream = new BufferedOutputStream(filestream);
291 DataOutputStream out = new DataOutputStream(bufstream);
292
Christopher Tate2efd2db2011-07-19 16:32:49 -0700293 if (DEBUG_BACKUP) Log.d(TAG, "Writing flattened data version " + FULL_BACKUP_VERSION);
Christopher Tate79ec80d2011-06-24 14:58:49 -0700294 out.writeInt(FULL_BACKUP_VERSION);
295
Christopher Tate2efd2db2011-07-19 16:32:49 -0700296 if (DEBUG_BACKUP) Log.d(TAG, systemSettingsData.length + " bytes of settings data");
Christopher Tate79ec80d2011-06-24 14:58:49 -0700297 out.writeInt(systemSettingsData.length);
298 out.write(systemSettingsData);
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000299 if (DEBUG_BACKUP) {
300 Log.d(TAG, secureSettingsData.length + " bytes of secure settings data");
301 }
Christopher Tate79ec80d2011-06-24 14:58:49 -0700302 out.writeInt(secureSettingsData.length);
303 out.write(secureSettingsData);
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000304 if (DEBUG_BACKUP) {
305 Log.d(TAG, globalSettingsData.length + " bytes of global settings data");
306 }
Christopher Tate66488d62012-10-02 11:58:01 -0700307 out.writeInt(globalSettingsData.length);
308 out.write(globalSettingsData);
Christopher Tate2efd2db2011-07-19 16:32:49 -0700309 if (DEBUG_BACKUP) Log.d(TAG, locale.length + " bytes of locale data");
Christopher Tate79ec80d2011-06-24 14:58:49 -0700310 out.writeInt(locale.length);
311 out.write(locale);
Amith Yamasani072543f2015-02-13 11:09:45 -0800312 if (DEBUG_BACKUP) Log.d(TAG, lockSettingsData.length + " bytes of lock settings data");
313 out.writeInt(lockSettingsData.length);
314 out.write(lockSettingsData);
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000315 if (DEBUG_BACKUP) Log.d(TAG, softApConfigData.length + " bytes of softap config data");
316 out.writeInt(softApConfigData.length);
317 out.write(softApConfigData);
Ritesh Reddyadca34a2016-02-04 18:33:30 +0000318 if (DEBUG_BACKUP) Log.d(TAG, netPoliciesData.length + " bytes of net policies data");
319 out.writeInt(netPoliciesData.length);
320 out.write(netPoliciesData);
Roshan Pius1bf86982016-06-02 09:22:55 -0700321 if (DEBUG_BACKUP) {
322 Log.d(TAG, wifiFullConfigData.length + " bytes of wifi config data");
323 }
324 out.writeInt(wifiFullConfigData.length);
325 out.write(wifiFullConfigData);
Christopher Tate79ec80d2011-06-24 14:58:49 -0700326
327 out.flush(); // also flushes downstream
328
329 // now we're set to emit the tar stream
330 fullBackupFile(stage, data);
331 } finally {
332 stage.delete();
333 }
334 }
335
336 @Override
Christopher Tate75a99702011-05-18 16:28:19 -0700337 public void onRestoreFile(ParcelFileDescriptor data, long size,
Ritesh Reddy33117fe2016-02-01 13:45:33 +0000338 int type, String domain, String relpath, long mode, long mtime)
Christopher Tate75a99702011-05-18 16:28:19 -0700339 throws IOException {
340 if (DEBUG_BACKUP) Log.d(TAG, "onRestoreFile() invoked");
341 // Our data is actually a blob of flattened settings data identical to that
342 // produced during incremental backups. Just unpack and apply it all in
343 // turn.
344 FileInputStream instream = new FileInputStream(data.getFileDescriptor());
345 DataInputStream in = new DataInputStream(instream);
346
347 int version = in.readInt();
348 if (DEBUG_BACKUP) Log.d(TAG, "Flattened data version " + version);
Christopher Tate66488d62012-10-02 11:58:01 -0700349 if (version <= FULL_BACKUP_VERSION) {
350 // Generate the moved-to-global lookup table
351 HashSet<String> movedToGlobal = new HashSet<String>();
Svetoslav683914b2015-01-15 14:22:26 -0800352 Settings.System.getMovedToGlobalSettings(movedToGlobal);
353 Settings.Secure.getMovedToGlobalSettings(movedToGlobal);
Christopher Tate66488d62012-10-02 11:58:01 -0700354
Christopher Tate75a99702011-05-18 16:28:19 -0700355 // system settings data first
356 int nBytes = in.readInt();
357 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of settings data");
358 byte[] buffer = new byte[nBytes];
Christopher Tate2efd2db2011-07-19 16:32:49 -0700359 in.readFully(buffer, 0, nBytes);
Christopher Tate66488d62012-10-02 11:58:01 -0700360 restoreSettings(buffer, nBytes, Settings.System.CONTENT_URI, movedToGlobal);
Christopher Tate75a99702011-05-18 16:28:19 -0700361
362 // secure settings
363 nBytes = in.readInt();
364 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of secure settings data");
365 if (nBytes > buffer.length) buffer = new byte[nBytes];
Christopher Tate2efd2db2011-07-19 16:32:49 -0700366 in.readFully(buffer, 0, nBytes);
Christopher Tate66488d62012-10-02 11:58:01 -0700367 restoreSettings(buffer, nBytes, Settings.Secure.CONTENT_URI, movedToGlobal);
368
369 // Global only if sufficiently new
370 if (version >= FULL_BACKUP_ADDED_GLOBAL) {
371 nBytes = in.readInt();
372 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of global settings data");
373 if (nBytes > buffer.length) buffer = new byte[nBytes];
374 in.readFully(buffer, 0, nBytes);
375 movedToGlobal.clear(); // no redirection; this *is* the global namespace
376 restoreSettings(buffer, nBytes, Settings.Global.CONTENT_URI, movedToGlobal);
377 }
Christopher Tate75a99702011-05-18 16:28:19 -0700378
379 // locale
380 nBytes = in.readInt();
381 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of locale data");
382 if (nBytes > buffer.length) buffer = new byte[nBytes];
Christopher Tate2efd2db2011-07-19 16:32:49 -0700383 in.readFully(buffer, 0, nBytes);
Christopher Tate75a99702011-05-18 16:28:19 -0700384 mSettingsHelper.setLocaleData(buffer, nBytes);
385
Roshan Pius1bf86982016-06-02 09:22:55 -0700386 // Restore older backups performing the necessary migrations.
387 if (version < FULL_BACKUP_ADDED_WIFI_NEW) {
388 // wifi supplicant
389 int supplicant_size = in.readInt();
390 if (DEBUG_BACKUP) Log.d(TAG, supplicant_size + " bytes of wifi supplicant data");
391 byte[] supplicant_buffer = new byte[supplicant_size];
392 in.readFully(supplicant_buffer, 0, supplicant_size);
Christopher Tate75a99702011-05-18 16:28:19 -0700393
Roshan Pius1bf86982016-06-02 09:22:55 -0700394 // ip config
395 int ipconfig_size = in.readInt();
396 if (DEBUG_BACKUP) Log.d(TAG, ipconfig_size + " bytes of ip config data");
397 byte[] ipconfig_buffer = new byte[ipconfig_size];
398 in.readFully(ipconfig_buffer, 0, nBytes);
Roshan Pius28be4fc2016-06-17 16:51:36 -0700399 restoreSupplicantWifiConfigData(supplicant_buffer, ipconfig_buffer);
Roshan Pius1bf86982016-06-02 09:22:55 -0700400 }
Christopher Tate75a99702011-05-18 16:28:19 -0700401
Amith Yamasani072543f2015-02-13 11:09:45 -0800402 if (version >= FULL_BACKUP_ADDED_LOCK_SETTINGS) {
403 nBytes = in.readInt();
404 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of lock settings data");
405 if (nBytes > buffer.length) buffer = new byte[nBytes];
406 if (nBytes > 0) {
407 in.readFully(buffer, 0, nBytes);
408 restoreLockSettings(buffer, nBytes);
409 }
410 }
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000411 // softap config
412 if (version >= FULL_BACKUP_ADDED_SOFTAP_CONF) {
413 nBytes = in.readInt();
414 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of softap config data");
415 if (nBytes > buffer.length) buffer = new byte[nBytes];
416 if (nBytes > 0) {
417 in.readFully(buffer, 0, nBytes);
418 restoreSoftApConfiguration(buffer);
419 }
420 }
Ritesh Reddyadca34a2016-02-04 18:33:30 +0000421 // network policies
422 if (version >= FULL_BACKUP_ADDED_NETWORK_POLICIES) {
423 nBytes = in.readInt();
424 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of network policies data");
425 if (nBytes > buffer.length) buffer = new byte[nBytes];
426 if (nBytes > 0) {
427 in.readFully(buffer, 0, nBytes);
428 restoreNetworkPolicies(buffer);
429 }
430 }
Roshan Pius1bf86982016-06-02 09:22:55 -0700431 // Restore full wifi config data
432 if (version >= FULL_BACKUP_ADDED_WIFI_NEW) {
433 nBytes = in.readInt();
434 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of full wifi config data");
435 if (nBytes > buffer.length) buffer = new byte[nBytes];
436 in.readFully(buffer, 0, nBytes);
Roshan Pius28be4fc2016-06-17 16:51:36 -0700437 restoreNewWifiConfigData(buffer);
Roshan Pius1bf86982016-06-02 09:22:55 -0700438 }
439
Christopher Tate75a99702011-05-18 16:28:19 -0700440 if (DEBUG_BACKUP) Log.d(TAG, "Full restore complete.");
441 } else {
442 data.close();
443 throw new IOException("Invalid file schema");
444 }
445 }
446
Amith Yamasanid1582142009-07-08 20:04:55 -0700447 private long[] readOldChecksums(ParcelFileDescriptor oldState) throws IOException {
448 long[] stateChecksums = new long[STATE_SIZE];
449
450 DataInputStream dataInput = new DataInputStream(
451 new FileInputStream(oldState.getFileDescriptor()));
Christopher Tatea286f412009-09-18 15:51:15 -0700452
453 try {
454 int stateVersion = dataInput.readInt();
Ritesh Reddy2400d272016-02-02 11:42:26 +0000455 if (stateVersion > STATE_VERSION) {
456 // Constrain the maximum state version this backup agent
457 // can handle in case a newer or corrupt backup set existed
458 stateVersion = STATE_VERSION;
459 }
Christopher Tate66488d62012-10-02 11:58:01 -0700460 for (int i = 0; i < STATE_SIZES[stateVersion]; i++) {
461 stateChecksums[i] = dataInput.readLong();
Amith Yamasanid1582142009-07-08 20:04:55 -0700462 }
Christopher Tatea286f412009-09-18 15:51:15 -0700463 } catch (EOFException eof) {
464 // With the default 0 checksum we'll wind up forcing a backup of
465 // any unhandled data sets, which is appropriate.
Amith Yamasanid1582142009-07-08 20:04:55 -0700466 }
467 dataInput.close();
468 return stateChecksums;
469 }
470
471 private void writeNewChecksums(long[] checksums, ParcelFileDescriptor newState)
472 throws IOException {
473 DataOutputStream dataOutput = new DataOutputStream(
Marvin Paul68795552014-12-16 14:12:33 -0800474 new BufferedOutputStream(new FileOutputStream(newState.getFileDescriptor())));
Christopher Tatea286f412009-09-18 15:51:15 -0700475
476 dataOutput.writeInt(STATE_VERSION);
Amith Yamasanid1582142009-07-08 20:04:55 -0700477 for (int i = 0; i < STATE_SIZE; i++) {
478 dataOutput.writeLong(checksums[i]);
479 }
480 dataOutput.close();
481 }
482
483 private long writeIfChanged(long oldChecksum, String key, byte[] data,
Ritesh Reddy33117fe2016-02-01 13:45:33 +0000484 BackupDataOutput output) {
Amith Yamasanid1582142009-07-08 20:04:55 -0700485 CRC32 checkSummer = new CRC32();
486 checkSummer.update(data);
487 long newChecksum = checkSummer.getValue();
488 if (oldChecksum == newChecksum) {
489 return oldChecksum;
490 }
491 try {
Amith Yamasani072543f2015-02-13 11:09:45 -0800492 if (DEBUG_BACKUP) {
493 Log.v(TAG, "Writing entity " + key + " of size " + data.length);
494 }
Amith Yamasanid1582142009-07-08 20:04:55 -0700495 output.writeEntityHeader(key, data.length);
496 output.writeEntityData(data, data.length);
497 } catch (IOException ioe) {
498 // Bail
499 }
500 return newChecksum;
501 }
502
Amith Yamasani220f4d62009-07-02 02:34:14 -0700503 private byte[] getSystemSettings() {
Svetoslav Ganova571a582011-09-20 18:32:20 -0700504 Cursor cursor = getContentResolver().query(Settings.System.CONTENT_URI, PROJECTION, null,
505 null, null);
Jeff Brown1d8e7d62011-10-09 15:24:53 -0700506 try {
507 return extractRelevantValues(cursor, Settings.System.SETTINGS_TO_BACKUP);
508 } finally {
509 cursor.close();
510 }
Amith Yamasani220f4d62009-07-02 02:34:14 -0700511 }
512
513 private byte[] getSecureSettings() {
Svetoslav Ganova571a582011-09-20 18:32:20 -0700514 Cursor cursor = getContentResolver().query(Settings.Secure.CONTENT_URI, PROJECTION, null,
515 null, null);
Jeff Brown1d8e7d62011-10-09 15:24:53 -0700516 try {
517 return extractRelevantValues(cursor, Settings.Secure.SETTINGS_TO_BACKUP);
518 } finally {
519 cursor.close();
520 }
Amith Yamasani220f4d62009-07-02 02:34:14 -0700521 }
522
Christopher Tate66488d62012-10-02 11:58:01 -0700523 private byte[] getGlobalSettings() {
524 Cursor cursor = getContentResolver().query(Settings.Global.CONTENT_URI, PROJECTION, null,
525 null, null);
526 try {
527 return extractRelevantValues(cursor, Settings.Global.SETTINGS_TO_BACKUP);
528 } finally {
529 cursor.close();
530 }
531 }
532
Amith Yamasani072543f2015-02-13 11:09:45 -0800533 /**
534 * Serialize the owner info settings
535 */
536 private byte[] getLockSettings() {
537 final LockPatternUtils lockPatternUtils = new LockPatternUtils(this);
Adrian Roos8150d2a2015-04-16 17:11:20 -0700538 final boolean ownerInfoEnabled = lockPatternUtils.isOwnerInfoEnabled(UserHandle.myUserId());
Amith Yamasani072543f2015-02-13 11:09:45 -0800539 final String ownerInfo = lockPatternUtils.getOwnerInfo(UserHandle.myUserId());
540
541 ByteArrayOutputStream baos = new ByteArrayOutputStream();
542 DataOutputStream out = new DataOutputStream(baos);
543 try {
544 out.writeUTF(KEY_LOCK_SETTINGS_OWNER_INFO_ENABLED);
545 out.writeUTF(ownerInfoEnabled ? "1" : "0");
546 if (ownerInfo != null) {
547 out.writeUTF(KEY_LOCK_SETTINGS_OWNER_INFO);
548 out.writeUTF(ownerInfo != null ? ownerInfo : "");
549 }
550 // End marker
551 out.writeUTF("");
552 out.flush();
553 } catch (IOException ioe) {
554 }
555 return baos.toByteArray();
556 }
557
Christopher Tate66488d62012-10-02 11:58:01 -0700558 private void restoreSettings(BackupDataInput data, Uri contentUri,
Ritesh Reddy33117fe2016-02-01 13:45:33 +0000559 HashSet<String> movedToGlobal) {
Christopher Tate75a99702011-05-18 16:28:19 -0700560 byte[] settings = new byte[data.getDataSize()];
561 try {
562 data.readEntityData(settings, 0, settings.length);
563 } catch (IOException ioe) {
564 Log.e(TAG, "Couldn't read entity data");
565 return;
566 }
Christopher Tate66488d62012-10-02 11:58:01 -0700567 restoreSettings(settings, settings.length, contentUri, movedToGlobal);
Christopher Tate75a99702011-05-18 16:28:19 -0700568 }
569
Christopher Tate66488d62012-10-02 11:58:01 -0700570 private void restoreSettings(byte[] settings, int bytes, Uri contentUri,
Ritesh Reddy33117fe2016-02-01 13:45:33 +0000571 HashSet<String> movedToGlobal) {
Svetoslav Ganova571a582011-09-20 18:32:20 -0700572 if (DEBUG) {
573 Log.i(TAG, "restoreSettings: " + contentUri);
574 }
575
Christopher Tate66488d62012-10-02 11:58:01 -0700576 // Figure out the white list and redirects to the global table.
Christopher Tate6597e342015-02-17 12:15:25 -0800577 final String[] whitelist;
Christopher Tate796e0f02009-09-22 11:57:58 -0700578 if (contentUri.equals(Settings.Secure.CONTENT_URI)) {
579 whitelist = Settings.Secure.SETTINGS_TO_BACKUP;
580 } else if (contentUri.equals(Settings.System.CONTENT_URI)) {
581 whitelist = Settings.System.SETTINGS_TO_BACKUP;
Christopher Tate66488d62012-10-02 11:58:01 -0700582 } else if (contentUri.equals(Settings.Global.CONTENT_URI)) {
583 whitelist = Settings.Global.SETTINGS_TO_BACKUP;
Svetoslav Ganova571a582011-09-20 18:32:20 -0700584 } else {
585 throw new IllegalArgumentException("Unknown URI: " + contentUri);
Christopher Tate796e0f02009-09-22 11:57:58 -0700586 }
587
Svetoslav Ganova571a582011-09-20 18:32:20 -0700588 // Restore only the white list data.
Amith Yamasani220f4d62009-07-02 02:34:14 -0700589 int pos = 0;
Svetoslav Ganova571a582011-09-20 18:32:20 -0700590 Map<String, String> cachedEntries = new HashMap<String, String>();
591 ContentValues contentValues = new ContentValues(2);
592 SettingsHelper settingsHelper = mSettingsHelper;
Christopher Tate6597e342015-02-17 12:15:25 -0800593 ContentResolver cr = getContentResolver();
Christopher Tate0738e882009-09-11 16:35:39 -0700594
Svetoslav Ganova571a582011-09-20 18:32:20 -0700595 final int whiteListSize = whitelist.length;
596 for (int i = 0; i < whiteListSize; i++) {
597 String key = whitelist[i];
598 String value = cachedEntries.remove(key);
Christopher Tate0738e882009-09-11 16:35:39 -0700599
Svetoslav Ganova571a582011-09-20 18:32:20 -0700600 // If the value not cached, let us look it up.
601 if (value == null) {
602 while (pos < bytes) {
603 int length = readInt(settings, pos);
604 pos += INTEGER_BYTE_COUNT;
605 String dataKey = length > 0 ? new String(settings, pos, length) : null;
606 pos += length;
607 length = readInt(settings, pos);
608 pos += INTEGER_BYTE_COUNT;
609 String dataValue = length > 0 ? new String(settings, pos, length) : null;
610 pos += length;
611 if (key.equals(dataKey)) {
612 value = dataValue;
613 break;
614 }
615 cachedEntries.put(dataKey, dataValue);
Amith Yamasani70c874b2009-07-06 14:53:25 -0700616 }
Amith Yamasani220f4d62009-07-02 02:34:14 -0700617 }
Amith Yamasani220f4d62009-07-02 02:34:14 -0700618
Svetoslav Ganova571a582011-09-20 18:32:20 -0700619 if (value == null) {
620 continue;
621 }
Christopher Tate796e0f02009-09-22 11:57:58 -0700622
Christopher Tate3543beb2012-10-05 13:35:12 -0700623 final Uri destination = (movedToGlobal != null && movedToGlobal.contains(key))
Christopher Tate66488d62012-10-02 11:58:01 -0700624 ? Settings.Global.CONTENT_URI
625 : contentUri;
Christopher Tate6597e342015-02-17 12:15:25 -0800626 settingsHelper.restoreValue(this, cr, contentValues, destination, key, value);
Svetoslav Ganova571a582011-09-20 18:32:20 -0700627
Christopher Tated488bc02012-10-09 14:06:30 -0700628 if (DEBUG) {
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000629 Log.d(TAG, "Restored setting: " + destination + " : " + key + "=" + value);
Christopher Tate0738e882009-09-11 16:35:39 -0700630 }
631 }
Amith Yamasani220f4d62009-07-02 02:34:14 -0700632 }
633
634 /**
Amith Yamasani072543f2015-02-13 11:09:45 -0800635 * Restores the owner info enabled and owner info settings in LockSettings.
636 *
637 * @param buffer
638 * @param nBytes
639 */
640 private void restoreLockSettings(byte[] buffer, int nBytes) {
641 final LockPatternUtils lockPatternUtils = new LockPatternUtils(this);
642
643 ByteArrayInputStream bais = new ByteArrayInputStream(buffer, 0, nBytes);
644 DataInputStream in = new DataInputStream(bais);
645 try {
646 String key;
647 // Read until empty string marker
648 while ((key = in.readUTF()).length() > 0) {
649 final String value = in.readUTF();
650 if (DEBUG_BACKUP) {
651 Log.v(TAG, "Restoring lock_settings " + key + " = " + value);
652 }
653 switch (key) {
654 case KEY_LOCK_SETTINGS_OWNER_INFO_ENABLED:
Adrian Roos8150d2a2015-04-16 17:11:20 -0700655 lockPatternUtils.setOwnerInfoEnabled("1".equals(value),
656 UserHandle.myUserId());
Amith Yamasani072543f2015-02-13 11:09:45 -0800657 break;
658 case KEY_LOCK_SETTINGS_OWNER_INFO:
659 lockPatternUtils.setOwnerInfo(value, UserHandle.myUserId());
660 break;
661 }
662 }
663 in.close();
664 } catch (IOException ioe) {
665 }
666 }
667
668 private void restoreLockSettings(BackupDataInput data) {
669 final byte[] settings = new byte[data.getDataSize()];
670 try {
671 data.readEntityData(settings, 0, settings.length);
672 } catch (IOException ioe) {
673 Log.e(TAG, "Couldn't read entity data");
674 return;
675 }
676 restoreLockSettings(settings, settings.length);
677 }
678
679 /**
Svetoslav Ganova571a582011-09-20 18:32:20 -0700680 * Given a cursor and a set of keys, extract the required keys and
681 * values and write them to a byte array.
682 *
683 * @param cursor A cursor with settings data.
684 * @param settings The settings to extract.
685 * @return The byte array of extracted values.
Amith Yamasani220f4d62009-07-02 02:34:14 -0700686 */
Svetoslav Ganova571a582011-09-20 18:32:20 -0700687 private byte[] extractRelevantValues(Cursor cursor, String[] settings) {
688 final int settingsCount = settings.length;
689 byte[][] values = new byte[settingsCount * 2][]; // keys and values
690 if (!cursor.moveToFirst()) {
Amith Yamasani220f4d62009-07-02 02:34:14 -0700691 Log.e(TAG, "Couldn't read from the cursor");
692 return new byte[0];
693 }
Svetoslav Ganova571a582011-09-20 18:32:20 -0700694
695 // Obtain the relevant data in a temporary array.
Amith Yamasani220f4d62009-07-02 02:34:14 -0700696 int totalSize = 0;
Svetoslav Ganova571a582011-09-20 18:32:20 -0700697 int backedUpSettingIndex = 0;
698 Map<String, String> cachedEntries = new HashMap<String, String>();
699 for (int i = 0; i < settingsCount; i++) {
700 String key = settings[i];
701 String value = cachedEntries.remove(key);
702
Svetoslav683914b2015-01-15 14:22:26 -0800703 final int nameColumnIndex = cursor.getColumnIndex(Settings.NameValueTable.NAME);
704 final int valueColumnIndex = cursor.getColumnIndex(Settings.NameValueTable.VALUE);
705
Svetoslav Ganova571a582011-09-20 18:32:20 -0700706 // If the value not cached, let us look it up.
707 if (value == null) {
708 while (!cursor.isAfterLast()) {
Svetoslav683914b2015-01-15 14:22:26 -0800709 String cursorKey = cursor.getString(nameColumnIndex);
710 String cursorValue = cursor.getString(valueColumnIndex);
Svetoslav Ganova571a582011-09-20 18:32:20 -0700711 cursor.moveToNext();
712 if (key.equals(cursorKey)) {
713 value = cursorValue;
714 break;
715 }
716 cachedEntries.put(cursorKey, cursorValue);
Amith Yamasani220f4d62009-07-02 02:34:14 -0700717 }
Amith Yamasani220f4d62009-07-02 02:34:14 -0700718 }
Svetoslav Ganova571a582011-09-20 18:32:20 -0700719
Amith Yamasani622bf2222013-09-06 13:54:28 -0700720 // Intercept the keys and see if they need special handling
721 value = mSettingsHelper.onBackupValue(key, value);
722
Svetoslav Ganova571a582011-09-20 18:32:20 -0700723 if (value == null) {
724 continue;
725 }
Svetoslav Ganova571a582011-09-20 18:32:20 -0700726 // Write the key and value in the intermediary array.
727 byte[] keyBytes = key.getBytes();
728 totalSize += INTEGER_BYTE_COUNT + keyBytes.length;
729 values[backedUpSettingIndex * 2] = keyBytes;
730
731 byte[] valueBytes = value.getBytes();
732 totalSize += INTEGER_BYTE_COUNT + valueBytes.length;
733 values[backedUpSettingIndex * 2 + 1] = valueBytes;
734
735 backedUpSettingIndex++;
736
737 if (DEBUG) {
738 Log.d(TAG, "Backed up setting: " + key + "=" + value);
Amith Yamasani220f4d62009-07-02 02:34:14 -0700739 }
740 }
741
Svetoslav Ganova571a582011-09-20 18:32:20 -0700742 // Aggregate the result.
Amith Yamasani220f4d62009-07-02 02:34:14 -0700743 byte[] result = new byte[totalSize];
744 int pos = 0;
Svetoslav Ganova571a582011-09-20 18:32:20 -0700745 final int keyValuePairCount = backedUpSettingIndex * 2;
746 for (int i = 0; i < keyValuePairCount; i++) {
747 pos = writeInt(result, pos, values[i].length);
748 pos = writeBytes(result, pos, values[i]);
Amith Yamasani220f4d62009-07-02 02:34:14 -0700749 }
750 return result;
751 }
752
Roshan Pius28be4fc2016-06-17 16:51:36 -0700753 private void restoreSupplicantWifiConfigData(byte[] supplicant_bytes, byte[] ipconfig_bytes) {
Roshan Pius1bf86982016-06-02 09:22:55 -0700754 if (DEBUG_BACKUP) {
755 Log.v(TAG, "Applying restored supplicant wifi data");
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -0800756 }
Roshan Pius1bf86982016-06-02 09:22:55 -0700757 mWifiManager.restoreSupplicantBackupData(supplicant_bytes, ipconfig_bytes);
Amith Yamasani2cfab842009-09-09 18:27:31 -0700758 }
759
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000760 private byte[] getSoftAPConfiguration() {
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000761 try {
Roshan Pius1bf86982016-06-02 09:22:55 -0700762 return mWifiManager.getWifiApConfiguration().getBytesForBackup();
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000763 } catch (IOException ioe) {
764 Log.e(TAG, "Failed to marshal SoftAPConfiguration" + ioe.getMessage());
765 return new byte[0];
766 }
767 }
768
769 private void restoreSoftApConfiguration(byte[] data) {
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000770 try {
771 WifiConfiguration config = WifiConfiguration
772 .getWifiConfigFromBackup(new DataInputStream(new ByteArrayInputStream(data)));
773 if (DEBUG) Log.d(TAG, "Successfully unMarshaled WifiConfiguration ");
Roshan Pius1bf86982016-06-02 09:22:55 -0700774 mWifiManager.setWifiApConfiguration(config);
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000775 } catch (IOException | BackupUtils.BadVersionException e) {
776 Log.e(TAG, "Failed to unMarshal SoftAPConfiguration " + e.getMessage());
777 }
778 }
779
Ritesh Reddyadca34a2016-02-04 18:33:30 +0000780 private byte[] getNetworkPolicies() {
781 NetworkPolicyManager networkPolicyManager =
782 (NetworkPolicyManager) getSystemService(NETWORK_POLICY_SERVICE);
783 NetworkPolicy[] policies = networkPolicyManager.getNetworkPolicies();
784 ByteArrayOutputStream baos = new ByteArrayOutputStream();
785 if (policies != null && policies.length != 0) {
786 DataOutputStream out = new DataOutputStream(baos);
787 try {
788 out.writeInt(NETWORK_POLICIES_BACKUP_VERSION);
789 out.writeInt(policies.length);
790 for (NetworkPolicy policy : policies) {
791 if (policy != null) {
792 byte[] marshaledPolicy = policy.getBytesForBackup();
793 out.writeByte(BackupUtils.NOT_NULL);
794 out.writeInt(marshaledPolicy.length);
795 out.write(marshaledPolicy);
796 } else {
797 out.writeByte(BackupUtils.NULL);
798 }
799 }
800 } catch (IOException ioe) {
801 Log.e(TAG, "Failed to convert NetworkPolicies to byte array " + ioe.getMessage());
802 baos.reset();
803 }
804 }
805 return baos.toByteArray();
806 }
807
Roshan Pius1bf86982016-06-02 09:22:55 -0700808 private byte[] getNewWifiConfigData() {
809 return mWifiManager.retrieveBackupData();
810 }
811
Roshan Pius28be4fc2016-06-17 16:51:36 -0700812 private void restoreNewWifiConfigData(byte[] bytes) {
Roshan Pius1bf86982016-06-02 09:22:55 -0700813 if (DEBUG_BACKUP) {
814 Log.v(TAG, "Applying restored wifi data");
815 }
816 mWifiManager.restoreBackupData(bytes);
817 }
818
Ritesh Reddyadca34a2016-02-04 18:33:30 +0000819 private void restoreNetworkPolicies(byte[] data) {
820 NetworkPolicyManager networkPolicyManager =
821 (NetworkPolicyManager) getSystemService(NETWORK_POLICY_SERVICE);
822 if (data != null && data.length != 0) {
823 DataInputStream in = new DataInputStream(new ByteArrayInputStream(data));
824 try {
825 int version = in.readInt();
826 if (version < 1 || version > NETWORK_POLICIES_BACKUP_VERSION) {
827 throw new BackupUtils.BadVersionException(
828 "Unknown Backup Serialization Version");
829 }
830 int length = in.readInt();
831 NetworkPolicy[] policies = new NetworkPolicy[length];
832 for (int i = 0; i < length; i++) {
833 byte isNull = in.readByte();
834 if (isNull == BackupUtils.NULL) continue;
835 int byteLength = in.readInt();
836 byte[] policyData = new byte[byteLength];
837 in.read(policyData, 0, byteLength);
838 policies[i] = NetworkPolicy.getNetworkPolicyFromBackup(
839 new DataInputStream(new ByteArrayInputStream(policyData)));
840 }
841 // Only set the policies if there was no error in the restore operation
842 networkPolicyManager.setNetworkPolicies(policies);
843 } catch (NullPointerException | IOException | BackupUtils.BadVersionException e) {
844 // NPE can be thrown when trying to instantiate a NetworkPolicy
845 Log.e(TAG, "Failed to convert byte array to NetworkPolicies " + e.getMessage());
846 }
847 }
848 }
849
Amith Yamasani220f4d62009-07-02 02:34:14 -0700850 /**
851 * Write an int in BigEndian into the byte array.
852 * @param out byte array
853 * @param pos current pos in array
854 * @param value integer to write
Svetoslav Ganova571a582011-09-20 18:32:20 -0700855 * @return the index after adding the size of an int (4) in bytes.
Amith Yamasani220f4d62009-07-02 02:34:14 -0700856 */
857 private int writeInt(byte[] out, int pos, int value) {
858 out[pos + 0] = (byte) ((value >> 24) & 0xFF);
859 out[pos + 1] = (byte) ((value >> 16) & 0xFF);
860 out[pos + 2] = (byte) ((value >> 8) & 0xFF);
861 out[pos + 3] = (byte) ((value >> 0) & 0xFF);
Svetoslav Ganova571a582011-09-20 18:32:20 -0700862 return pos + INTEGER_BYTE_COUNT;
Amith Yamasani220f4d62009-07-02 02:34:14 -0700863 }
864
865 private int writeBytes(byte[] out, int pos, byte[] value) {
866 System.arraycopy(value, 0, out, pos, value.length);
867 return pos + value.length;
868 }
869
870 private int readInt(byte[] in, int pos) {
Ritesh Reddyaeb4c062016-01-26 19:40:48 +0000871 int result = ((in[pos] & 0xFF) << 24)
872 | ((in[pos + 1] & 0xFF) << 16)
873 | ((in[pos + 2] & 0xFF) << 8)
874 | ((in[pos + 3] & 0xFF) << 0);
Amith Yamasani220f4d62009-07-02 02:34:14 -0700875 return result;
876 }
Paul Stewart45e6fec2016-05-20 08:14:30 -0700877}