blob: 744798ee5c914d65606b0ab11bdd9bd8f90678d0 [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
Brad Fitzpatrick70787892010-11-17 11:31:12 -080019import java.io.BufferedOutputStream;
Amith Yamasani2cfab842009-09-09 18:27:31 -070020import java.io.BufferedReader;
21import java.io.BufferedWriter;
Amith Yamasanid1582142009-07-08 20:04:55 -070022import java.io.DataInputStream;
23import java.io.DataOutputStream;
Amith Yamasani2cfab842009-09-09 18:27:31 -070024import java.io.EOFException;
Amith Yamasani220f4d62009-07-02 02:34:14 -070025import java.io.File;
26import java.io.FileInputStream;
27import java.io.FileOutputStream;
Amith Yamasani2cfab842009-09-09 18:27:31 -070028import java.io.FileReader;
29import java.io.FileWriter;
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -080030import java.io.InputStream;
Amith Yamasani220f4d62009-07-02 02:34:14 -070031import java.io.IOException;
Brad Fitzpatrick70787892010-11-17 11:31:12 -080032import java.io.OutputStream;
Amith Yamasani220f4d62009-07-02 02:34:14 -070033import java.util.Arrays;
Amith Yamasanid1582142009-07-08 20:04:55 -070034import java.util.zip.CRC32;
Amith Yamasani220f4d62009-07-02 02:34:14 -070035
Christopher Tate45281862010-03-05 15:46:30 -080036import android.app.backup.BackupDataInput;
37import android.app.backup.BackupDataOutput;
Christopher Tatecc84c692010-03-29 14:54:02 -070038import android.app.backup.BackupAgentHelper;
Amith Yamasani220f4d62009-07-02 02:34:14 -070039import android.content.ContentValues;
40import android.content.Context;
41import android.database.Cursor;
Amith Yamasani220f4d62009-07-02 02:34:14 -070042import android.net.Uri;
43import android.net.wifi.WifiManager;
Amith Yamasanid1582142009-07-08 20:04:55 -070044import android.os.FileUtils;
Amith Yamasani220f4d62009-07-02 02:34:14 -070045import android.os.ParcelFileDescriptor;
Amith Yamasanid1582142009-07-08 20:04:55 -070046import android.os.Process;
Amith Yamasani220f4d62009-07-02 02:34:14 -070047import android.provider.Settings;
48import android.text.TextUtils;
49import android.util.Log;
50
51/**
52 * Performs backup and restore of the System and Secure settings.
53 * List of settings that are backed up are stored in the Settings.java file
54 */
Christopher Tatecc84c692010-03-29 14:54:02 -070055public class SettingsBackupAgent extends BackupAgentHelper {
Christopher Tate436344a2009-09-30 16:17:37 -070056 private static final boolean DEBUG = false;
Amith Yamasani220f4d62009-07-02 02:34:14 -070057
58 private static final String KEY_SYSTEM = "system";
59 private static final String KEY_SECURE = "secure";
Amith Yamasani8823c0a82009-07-07 14:30:17 -070060 private static final String KEY_LOCALE = "locale";
Amith Yamasani220f4d62009-07-02 02:34:14 -070061
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -080062 //Version 2 adds STATE_WIFI_CONFIG
63 private static final int STATE_VERSION_1 = 1;
64 private static final int STATE_VERSION_1_SIZE = 4;
65
Christopher Tatea286f412009-09-18 15:51:15 -070066 // Versioning of the state file. Increment this version
67 // number any time the set of state items is altered.
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -080068 private static final int STATE_VERSION = 2;
Christopher Tatea286f412009-09-18 15:51:15 -070069
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -080070 private static final int STATE_SYSTEM = 0;
71 private static final int STATE_SECURE = 1;
72 private static final int STATE_LOCALE = 2;
73 private static final int STATE_WIFI_SUPPLICANT = 3;
74 private static final int STATE_WIFI_CONFIG = 4;
75 private static final int STATE_SIZE = 5; // The number of state items
Amith Yamasanid1582142009-07-08 20:04:55 -070076
Amith Yamasani220f4d62009-07-02 02:34:14 -070077 private static String[] sortedSystemKeys = null;
78 private static String[] sortedSecureKeys = null;
79
80 private static final byte[] EMPTY_DATA = new byte[0];
81
82 private static final String TAG = "SettingsBackupAgent";
83
Amith Yamasani220f4d62009-07-02 02:34:14 -070084 private static final int COLUMN_NAME = 1;
85 private static final int COLUMN_VALUE = 2;
86
87 private static final String[] PROJECTION = {
88 Settings.NameValueTable._ID,
89 Settings.NameValueTable.NAME,
90 Settings.NameValueTable.VALUE
91 };
92
93 private static final String FILE_WIFI_SUPPLICANT = "/data/misc/wifi/wpa_supplicant.conf";
Amith Yamasani2cfab842009-09-09 18:27:31 -070094 private static final String FILE_WIFI_SUPPLICANT_TEMPLATE =
95 "/system/etc/wifi/wpa_supplicant.conf";
Christian Sonntag92c17522009-08-07 15:16:17 -070096
97 // the key to store the WIFI data under, should be sorted as last, so restore happens last.
98 // use very late unicode character to quasi-guarantee last sort position.
Amith Yamasani2cfab842009-09-09 18:27:31 -070099 private static final String KEY_WIFI_SUPPLICANT = "\uffedWIFI";
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -0800100 private static final String KEY_WIFI_CONFIG = "\uffedCONFIG_WIFI";
Amith Yamasani220f4d62009-07-02 02:34:14 -0700101
102 private SettingsHelper mSettingsHelper;
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -0800103 private WifiManager mWfm;
104 private static String mWifiConfigFile;
Amith Yamasani220f4d62009-07-02 02:34:14 -0700105
106 public void onCreate() {
107 mSettingsHelper = new SettingsHelper(this);
108 super.onCreate();
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -0800109
110 WifiManager mWfm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
111 if (mWfm != null) mWifiConfigFile = mWfm.getConfigFile();
Amith Yamasani220f4d62009-07-02 02:34:14 -0700112 }
113
114 @Override
115 public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
116 ParcelFileDescriptor newState) throws IOException {
117
118 byte[] systemSettingsData = getSystemSettings();
119 byte[] secureSettingsData = getSecureSettings();
Amith Yamasani8823c0a82009-07-07 14:30:17 -0700120 byte[] locale = mSettingsHelper.getLocaleData();
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -0800121 byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
122 byte[] wifiConfigData = getFileData(mWifiConfigFile);
Amith Yamasani220f4d62009-07-02 02:34:14 -0700123
Amith Yamasanid1582142009-07-08 20:04:55 -0700124 long[] stateChecksums = readOldChecksums(oldState);
Amith Yamasani220f4d62009-07-02 02:34:14 -0700125
Amith Yamasanid1582142009-07-08 20:04:55 -0700126 stateChecksums[STATE_SYSTEM] =
127 writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data);
128 stateChecksums[STATE_SECURE] =
129 writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data);
Amith Yamasanid1582142009-07-08 20:04:55 -0700130 stateChecksums[STATE_LOCALE] =
131 writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data);
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -0800132 stateChecksums[STATE_WIFI_SUPPLICANT] =
133 writeIfChanged(stateChecksums[STATE_WIFI_SUPPLICANT], KEY_WIFI_SUPPLICANT,
134 wifiSupplicantData, data);
135 stateChecksums[STATE_WIFI_CONFIG] =
136 writeIfChanged(stateChecksums[STATE_WIFI_CONFIG], KEY_WIFI_CONFIG, wifiConfigData,
137 data);
Amith Yamasani8823c0a82009-07-07 14:30:17 -0700138
Amith Yamasanid1582142009-07-08 20:04:55 -0700139 writeNewChecksums(stateChecksums, newState);
Amith Yamasani220f4d62009-07-02 02:34:14 -0700140 }
141
142 @Override
143 public void onRestore(BackupDataInput data, int appVersionCode,
144 ParcelFileDescriptor newState) throws IOException {
145
Amith Yamasani220f4d62009-07-02 02:34:14 -0700146 while (data.readNextHeader()) {
147 final String key = data.getKey();
Amith Yamasani8823c0a82009-07-07 14:30:17 -0700148 final int size = data.getDataSize();
Amith Yamasani220f4d62009-07-02 02:34:14 -0700149 if (KEY_SYSTEM.equals(key)) {
150 restoreSettings(data, Settings.System.CONTENT_URI);
Amith Yamasanid1582142009-07-08 20:04:55 -0700151 mSettingsHelper.applyAudioSettings();
Amith Yamasani220f4d62009-07-02 02:34:14 -0700152 } else if (KEY_SECURE.equals(key)) {
153 restoreSettings(data, Settings.Secure.CONTENT_URI);
Christian Sonntag92c17522009-08-07 15:16:17 -0700154 } else if (KEY_WIFI_SUPPLICANT.equals(key)) {
Christian Sonntagc5b5b0f2009-08-07 10:00:21 -0700155 int retainedWifiState = enableWifi(false);
Amith Yamasani2cfab842009-09-09 18:27:31 -0700156 restoreWifiSupplicant(FILE_WIFI_SUPPLICANT, data);
Amith Yamasanid1582142009-07-08 20:04:55 -0700157 FileUtils.setPermissions(FILE_WIFI_SUPPLICANT,
158 FileUtils.S_IRUSR | FileUtils.S_IWUSR |
159 FileUtils.S_IRGRP | FileUtils.S_IWGRP,
160 Process.myUid(), Process.WIFI_UID);
Christian Sonntagc5b5b0f2009-08-07 10:00:21 -0700161 // retain the previous WIFI state.
162 enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED ||
163 retainedWifiState == WifiManager.WIFI_STATE_ENABLING);
Amith Yamasani8823c0a82009-07-07 14:30:17 -0700164 } else if (KEY_LOCALE.equals(key)) {
165 byte[] localeData = new byte[size];
166 data.readEntityData(localeData, 0, size);
167 mSettingsHelper.setLocaleData(localeData);
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -0800168 } else if (KEY_WIFI_CONFIG.equals(key)) {
169 restoreFileData(mWifiConfigFile, data);
170 } else {
Amith Yamasani220f4d62009-07-02 02:34:14 -0700171 data.skipEntityData();
172 }
173 }
174 }
175
Amith Yamasanid1582142009-07-08 20:04:55 -0700176 private long[] readOldChecksums(ParcelFileDescriptor oldState) throws IOException {
177 long[] stateChecksums = new long[STATE_SIZE];
178
179 DataInputStream dataInput = new DataInputStream(
180 new FileInputStream(oldState.getFileDescriptor()));
Christopher Tatea286f412009-09-18 15:51:15 -0700181
182 try {
183 int stateVersion = dataInput.readInt();
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -0800184 if (stateVersion == STATE_VERSION_1) {
185 for (int i = 0; i < STATE_VERSION_1_SIZE; i++) {
186 stateChecksums[i] = dataInput.readLong();
187 }
188 } else if (stateVersion == STATE_VERSION) {
Christopher Tatea286f412009-09-18 15:51:15 -0700189 for (int i = 0; i < STATE_SIZE; i++) {
190 stateChecksums[i] = dataInput.readLong();
191 }
Amith Yamasanid1582142009-07-08 20:04:55 -0700192 }
Christopher Tatea286f412009-09-18 15:51:15 -0700193 } catch (EOFException eof) {
194 // With the default 0 checksum we'll wind up forcing a backup of
195 // any unhandled data sets, which is appropriate.
Amith Yamasanid1582142009-07-08 20:04:55 -0700196 }
197 dataInput.close();
198 return stateChecksums;
199 }
200
201 private void writeNewChecksums(long[] checksums, ParcelFileDescriptor newState)
202 throws IOException {
203 DataOutputStream dataOutput = new DataOutputStream(
204 new FileOutputStream(newState.getFileDescriptor()));
Christopher Tatea286f412009-09-18 15:51:15 -0700205
206 dataOutput.writeInt(STATE_VERSION);
Amith Yamasanid1582142009-07-08 20:04:55 -0700207 for (int i = 0; i < STATE_SIZE; i++) {
208 dataOutput.writeLong(checksums[i]);
209 }
210 dataOutput.close();
211 }
212
213 private long writeIfChanged(long oldChecksum, String key, byte[] data,
214 BackupDataOutput output) {
215 CRC32 checkSummer = new CRC32();
216 checkSummer.update(data);
217 long newChecksum = checkSummer.getValue();
218 if (oldChecksum == newChecksum) {
219 return oldChecksum;
220 }
221 try {
222 output.writeEntityHeader(key, data.length);
223 output.writeEntityData(data, data.length);
224 } catch (IOException ioe) {
225 // Bail
226 }
227 return newChecksum;
228 }
229
Amith Yamasani220f4d62009-07-02 02:34:14 -0700230 private byte[] getSystemSettings() {
231 Cursor sortedCursor = getContentResolver().query(Settings.System.CONTENT_URI, PROJECTION,
232 null, null, Settings.NameValueTable.NAME);
233 // Copy and sort the array
234 if (sortedSystemKeys == null) {
235 sortedSystemKeys = copyAndSort(Settings.System.SETTINGS_TO_BACKUP);
236 }
237 byte[] result = extractRelevantValues(sortedCursor, sortedSystemKeys);
238 sortedCursor.close();
239 return result;
240 }
241
242 private byte[] getSecureSettings() {
243 Cursor sortedCursor = getContentResolver().query(Settings.Secure.CONTENT_URI, PROJECTION,
244 null, null, Settings.NameValueTable.NAME);
245 // Copy and sort the array
246 if (sortedSecureKeys == null) {
247 sortedSecureKeys = copyAndSort(Settings.Secure.SETTINGS_TO_BACKUP);
248 }
249 byte[] result = extractRelevantValues(sortedCursor, sortedSecureKeys);
250 sortedCursor.close();
251 return result;
252 }
253
254 private void restoreSettings(BackupDataInput data, Uri contentUri) {
Christopher Tate796e0f02009-09-22 11:57:58 -0700255 if (DEBUG) Log.i(TAG, "restoreSettings: " + contentUri);
256 String[] whitelist = null;
257 if (contentUri.equals(Settings.Secure.CONTENT_URI)) {
258 whitelist = Settings.Secure.SETTINGS_TO_BACKUP;
259 } else if (contentUri.equals(Settings.System.CONTENT_URI)) {
260 whitelist = Settings.System.SETTINGS_TO_BACKUP;
261 }
262
Amith Yamasani220f4d62009-07-02 02:34:14 -0700263 ContentValues cv = new ContentValues(2);
264 byte[] settings = new byte[data.getDataSize()];
265 try {
266 data.readEntityData(settings, 0, settings.length);
267 } catch (IOException ioe) {
268 Log.e(TAG, "Couldn't read entity data");
269 return;
270 }
271 int pos = 0;
272 while (pos < settings.length) {
273 int length = readInt(settings, pos);
274 pos += 4;
275 String settingName = length > 0? new String(settings, pos, length) : null;
276 pos += length;
277 length = readInt(settings, pos);
278 pos += 4;
279 String settingValue = length > 0? new String(settings, pos, length) : null;
280 pos += length;
281 if (!TextUtils.isEmpty(settingName) && !TextUtils.isEmpty(settingValue)) {
282 //Log.i(TAG, "Restore " + settingName + " = " + settingValue);
Christopher Tate0738e882009-09-11 16:35:39 -0700283
Christopher Tate796e0f02009-09-22 11:57:58 -0700284 // Only restore settings in our list of known-acceptable data
285 if (invalidSavedSetting(whitelist, settingName)) {
Christopher Tate0738e882009-09-11 16:35:39 -0700286 continue;
287 }
288
Amith Yamasani70c874b2009-07-06 14:53:25 -0700289 if (mSettingsHelper.restoreValue(settingName, settingValue)) {
290 cv.clear();
291 cv.put(Settings.NameValueTable.NAME, settingName);
292 cv.put(Settings.NameValueTable.VALUE, settingValue);
293 getContentResolver().insert(contentUri, cv);
294 }
Amith Yamasani220f4d62009-07-02 02:34:14 -0700295 }
296 }
297 }
298
Christopher Tate796e0f02009-09-22 11:57:58 -0700299 // Returns 'true' if the given setting is one that we refuse to restore
300 private boolean invalidSavedSetting(String[] knownNames, String candidate) {
301 // no filter? allow everything
302 if (knownNames == null) {
303 return false;
304 }
305
306 // whitelisted setting? allow it
307 for (String name : knownNames) {
308 if (name.equals(candidate)) {
309 return false;
Christopher Tate0738e882009-09-11 16:35:39 -0700310 }
311 }
312
Christopher Tate796e0f02009-09-22 11:57:58 -0700313 // refuse everything else
314 if (DEBUG) Log.v(TAG, "Ignoring restore datum: " + candidate);
315 return true;
Christopher Tate0738e882009-09-11 16:35:39 -0700316 }
317
Amith Yamasani220f4d62009-07-02 02:34:14 -0700318 private String[] copyAndSort(String[] keys) {
319 String[] sortedKeys = new String[keys.length];
320 System.arraycopy(keys, 0, sortedKeys, 0, keys.length);
321 Arrays.sort(sortedKeys);
322 return sortedKeys;
323 }
324
325 /**
Christian Sonntagc5b5b0f2009-08-07 10:00:21 -0700326 * Given a cursor sorted by key name and a set of keys sorted by name,
Amith Yamasani220f4d62009-07-02 02:34:14 -0700327 * extract the required keys and values and write them to a byte array.
328 * @param sortedCursor
329 * @param sortedKeys
330 * @return
331 */
332 byte[] extractRelevantValues(Cursor sortedCursor, String[] sortedKeys) {
333 byte[][] values = new byte[sortedKeys.length * 2][]; // keys and values
334 if (!sortedCursor.moveToFirst()) {
335 Log.e(TAG, "Couldn't read from the cursor");
336 return new byte[0];
337 }
338 int keyIndex = 0;
339 int totalSize = 0;
340 while (!sortedCursor.isAfterLast()) {
341 String name = sortedCursor.getString(COLUMN_NAME);
342 while (sortedKeys[keyIndex].compareTo(name.toString()) < 0) {
343 keyIndex++;
344 if (keyIndex == sortedKeys.length) break;
345 }
346 if (keyIndex < sortedKeys.length && name.equals(sortedKeys[keyIndex])) {
347 String value = sortedCursor.getString(COLUMN_VALUE);
348 byte[] nameBytes = name.toString().getBytes();
349 totalSize += 4 + nameBytes.length;
350 values[keyIndex * 2] = nameBytes;
351 byte[] valueBytes;
352 if (TextUtils.isEmpty(value)) {
353 valueBytes = null;
354 totalSize += 4;
355 } else {
356 valueBytes = value.toString().getBytes();
357 totalSize += 4 + valueBytes.length;
358 //Log.i(TAG, "Backing up " + name + " = " + value);
359 }
360 values[keyIndex * 2 + 1] = valueBytes;
361 keyIndex++;
362 }
363 if (keyIndex == sortedKeys.length || !sortedCursor.moveToNext()) {
364 break;
365 }
366 }
367
368 byte[] result = new byte[totalSize];
369 int pos = 0;
370 for (int i = 0; i < sortedKeys.length * 2; i++) {
371 if (values[i] != null) {
372 pos = writeInt(result, pos, values[i].length);
373 pos = writeBytes(result, pos, values[i]);
374 }
375 }
376 return result;
377 }
378
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -0800379 private byte[] getFileData(String filename) {
380 InputStream is = null;
381 try {
382 File file = new File(filename);
383 is = new FileInputStream(file);
384
385 //Will truncate read on a very long file,
386 //should not happen for a config file
387 byte[] bytes = new byte[(int)file.length()];
388
389 int offset = 0;
390 int numRead = 0;
391 while (offset < bytes.length
392 && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
393 offset += numRead;
394 }
395
396 //read failure
397 if (offset < bytes.length) {
398 Log.w(TAG, "Couldn't backup " + filename);
399 return EMPTY_DATA;
400 }
401 return bytes;
402 } catch (IOException ioe) {
403 Log.w(TAG, "Couldn't backup " + filename);
404 return EMPTY_DATA;
405 } finally {
406 if (is != null) {
407 try {
408 is.close();
409 } catch (IOException e) {
410 }
411 }
412 }
413
414 }
415
416 private void restoreFileData(String filename, BackupDataInput data) {
417 byte[] bytes = new byte[data.getDataSize()];
418 if (bytes.length <= 0) return;
419 try {
420 data.readEntityData(bytes, 0, bytes.length);
421 File file = new File(filename);
422 if (file.exists()) file.delete();
423
424 OutputStream os = new BufferedOutputStream(new FileOutputStream(filename, true));
425 os.write(bytes);
426 os.close();
427 } catch (IOException ioe) {
428 Log.w(TAG, "Couldn't restore " + filename);
429 }
430 }
431
432
Amith Yamasani2cfab842009-09-09 18:27:31 -0700433 private byte[] getWifiSupplicant(String filename) {
Brad Fitzpatrick70787892010-11-17 11:31:12 -0800434 BufferedReader br = null;
Amith Yamasani220f4d62009-07-02 02:34:14 -0700435 try {
436 File file = new File(filename);
437 if (file.exists()) {
Brad Fitzpatrick70787892010-11-17 11:31:12 -0800438 br = new BufferedReader(new FileReader(file));
Amith Yamasani2cfab842009-09-09 18:27:31 -0700439 StringBuffer relevantLines = new StringBuffer();
440 boolean started = false;
441 String line;
442 while ((line = br.readLine()) != null) {
443 if (!started && line.startsWith("network")) {
444 started = true;
445 }
446 if (started) {
447 relevantLines.append(line).append("\n");
448 }
449 }
450 if (relevantLines.length() > 0) {
451 return relevantLines.toString().getBytes();
452 } else {
453 return EMPTY_DATA;
454 }
Amith Yamasani220f4d62009-07-02 02:34:14 -0700455 } else {
Amith Yamasanid1582142009-07-08 20:04:55 -0700456 return EMPTY_DATA;
Amith Yamasani220f4d62009-07-02 02:34:14 -0700457 }
458 } catch (IOException ioe) {
459 Log.w(TAG, "Couldn't backup " + filename);
Amith Yamasanid1582142009-07-08 20:04:55 -0700460 return EMPTY_DATA;
Brad Fitzpatrick70787892010-11-17 11:31:12 -0800461 } finally {
462 if (br != null) {
463 try {
464 br.close();
465 } catch (IOException e) {
466 }
467 }
Amith Yamasani220f4d62009-07-02 02:34:14 -0700468 }
469 }
470
Amith Yamasani2cfab842009-09-09 18:27:31 -0700471 private void restoreWifiSupplicant(String filename, BackupDataInput data) {
Amith Yamasani220f4d62009-07-02 02:34:14 -0700472 byte[] bytes = new byte[data.getDataSize()];
473 if (bytes.length <= 0) return;
474 try {
475 data.readEntityData(bytes, 0, bytes.length);
Amith Yamasani2cfab842009-09-09 18:27:31 -0700476 File supplicantFile = new File(FILE_WIFI_SUPPLICANT);
477 if (supplicantFile.exists()) supplicantFile.delete();
478 copyWifiSupplicantTemplate();
479
Brad Fitzpatrick70787892010-11-17 11:31:12 -0800480 OutputStream os = new BufferedOutputStream(new FileOutputStream(filename, true));
481 os.write("\n".getBytes());
482 os.write(bytes);
483 os.close();
Amith Yamasani220f4d62009-07-02 02:34:14 -0700484 } catch (IOException ioe) {
485 Log.w(TAG, "Couldn't restore " + filename);
486 }
487 }
488
Amith Yamasani2cfab842009-09-09 18:27:31 -0700489 private void copyWifiSupplicantTemplate() {
490 try {
491 BufferedReader br = new BufferedReader(new FileReader(FILE_WIFI_SUPPLICANT_TEMPLATE));
492 BufferedWriter bw = new BufferedWriter(new FileWriter(FILE_WIFI_SUPPLICANT));
493 char[] temp = new char[1024];
494 int size;
495 while ((size = br.read(temp)) > 0) {
496 bw.write(temp, 0, size);
497 }
498 bw.close();
499 br.close();
500 } catch (IOException ioe) {
501 Log.w(TAG, "Couldn't copy wpa_supplicant file");
502 }
503 }
504
Amith Yamasani220f4d62009-07-02 02:34:14 -0700505 /**
506 * Write an int in BigEndian into the byte array.
507 * @param out byte array
508 * @param pos current pos in array
509 * @param value integer to write
510 * @return the index after adding the size of an int (4)
511 */
512 private int writeInt(byte[] out, int pos, int value) {
513 out[pos + 0] = (byte) ((value >> 24) & 0xFF);
514 out[pos + 1] = (byte) ((value >> 16) & 0xFF);
515 out[pos + 2] = (byte) ((value >> 8) & 0xFF);
516 out[pos + 3] = (byte) ((value >> 0) & 0xFF);
517 return pos + 4;
518 }
519
520 private int writeBytes(byte[] out, int pos, byte[] value) {
521 System.arraycopy(value, 0, out, pos, value.length);
522 return pos + value.length;
523 }
524
525 private int readInt(byte[] in, int pos) {
526 int result =
527 ((in[pos ] & 0xFF) << 24) |
528 ((in[pos + 1] & 0xFF) << 16) |
529 ((in[pos + 2] & 0xFF) << 8) |
530 ((in[pos + 3] & 0xFF) << 0);
531 return result;
532 }
533
Christian Sonntagc5b5b0f2009-08-07 10:00:21 -0700534 private int enableWifi(boolean enable) {
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -0800535 if (mWfm != null) {
536 int state = mWfm.getWifiState();
537 mWfm.setWifiEnabled(enable);
Christian Sonntagc5b5b0f2009-08-07 10:00:21 -0700538 return state;
Amith Yamasani220f4d62009-07-02 02:34:14 -0700539 }
Christian Sonntagc5b5b0f2009-08-07 10:00:21 -0700540 return WifiManager.WIFI_STATE_UNKNOWN;
Amith Yamasani220f4d62009-07-02 02:34:14 -0700541 }
Amith Yamasani220f4d62009-07-02 02:34:14 -0700542}