1220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani/*
2220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani * Copyright (C) 2008 The Android Open Source Project
3220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani *
4220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani * Licensed under the Apache License, Version 2.0 (the "License");
5220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani * you may not use this file except in compliance with the License.
6220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani * You may obtain a copy of the License at
7220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani *
8220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani *      http://www.apache.org/licenses/LICENSE-2.0
9220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani *
10220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani * Unless required by applicable law or agreed to in writing, software
11220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani * distributed under the License is distributed on an "AS IS" BASIS,
12220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani * See the License for the specific language governing permissions and
14220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani * limitations under the License.
15220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani */
16220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
17220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasanipackage com.android.providers.settings;
18220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
192cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasaniimport java.io.BufferedReader;
202cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasaniimport java.io.BufferedWriter;
21d158214511a3c04753de04fa6389e46d33135c38Amith Yamasaniimport java.io.DataInputStream;
22d158214511a3c04753de04fa6389e46d33135c38Amith Yamasaniimport java.io.DataOutputStream;
232cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasaniimport java.io.EOFException;
24220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasaniimport java.io.File;
25220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasaniimport java.io.FileInputStream;
26220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasaniimport java.io.FileOutputStream;
272cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasaniimport java.io.FileReader;
282cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasaniimport java.io.FileWriter;
29220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasaniimport java.io.IOException;
30220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasaniimport java.util.Arrays;
31d158214511a3c04753de04fa6389e46d33135c38Amith Yamasaniimport java.util.zip.CRC32;
32220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
334528186e0d65fc68ef0dd1941aa2ac8aefcd55a3Christopher Tateimport android.app.backup.BackupDataInput;
344528186e0d65fc68ef0dd1941aa2ac8aefcd55a3Christopher Tateimport android.app.backup.BackupDataOutput;
35cc84c69726507a85116f5664e20e2ebfac76edbeChristopher Tateimport android.app.backup.BackupAgentHelper;
36220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasaniimport android.content.ContentValues;
37220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasaniimport android.content.Context;
38220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasaniimport android.database.Cursor;
39220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasaniimport android.net.Uri;
40220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasaniimport android.net.wifi.WifiManager;
41d158214511a3c04753de04fa6389e46d33135c38Amith Yamasaniimport android.os.FileUtils;
42220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasaniimport android.os.ParcelFileDescriptor;
43d158214511a3c04753de04fa6389e46d33135c38Amith Yamasaniimport android.os.Process;
44220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasaniimport android.provider.Settings;
45220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasaniimport android.text.TextUtils;
46220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasaniimport android.util.Log;
47220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
48220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani/**
49220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani * Performs backup and restore of the System and Secure settings.
50220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani * List of settings that are backed up are stored in the Settings.java file
51220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani */
52cc84c69726507a85116f5664e20e2ebfac76edbeChristopher Tatepublic class SettingsBackupAgent extends BackupAgentHelper {
53436344ae12c819f58306ceb94241a266141e1218Christopher Tate    private static final boolean DEBUG = false;
54220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
55220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private static final String KEY_SYSTEM = "system";
56220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private static final String KEY_SECURE = "secure";
578823c0a8c68fe669c21c539eef9fc6541f0c7494Amith Yamasani    private static final String KEY_LOCALE = "locale";
58220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
59a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate    // Versioning of the state file.  Increment this version
60a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate    // number any time the set of state items is altered.
61a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate    private static final int STATE_VERSION = 1;
62a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate
63d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani    private static final int STATE_SYSTEM = 0;
64d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani    private static final int STATE_SECURE = 1;
65a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate    private static final int STATE_LOCALE = 2;
66a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate    private static final int STATE_WIFI   = 3;
67a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate    private static final int STATE_SIZE   = 4; // The number of state items
68d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani
69220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private static String[] sortedSystemKeys = null;
70220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private static String[] sortedSecureKeys = null;
71220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
72220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private static final byte[] EMPTY_DATA = new byte[0];
73220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
74220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private static final String TAG = "SettingsBackupAgent";
75220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
76220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private static final int COLUMN_NAME = 1;
77220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private static final int COLUMN_VALUE = 2;
78220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
79220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private static final String[] PROJECTION = {
80220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        Settings.NameValueTable._ID,
81220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        Settings.NameValueTable.NAME,
82220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        Settings.NameValueTable.VALUE
83220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    };
84220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
85220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private static final String FILE_WIFI_SUPPLICANT = "/data/misc/wifi/wpa_supplicant.conf";
862cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani    private static final String FILE_WIFI_SUPPLICANT_TEMPLATE =
872cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani            "/system/etc/wifi/wpa_supplicant.conf";
8892c1752175f0880a0e0a05fdca37b54a8fb2b52dChristian Sonntag
8992c1752175f0880a0e0a05fdca37b54a8fb2b52dChristian Sonntag    // the key to store the WIFI data under, should be sorted as last, so restore happens last.
9092c1752175f0880a0e0a05fdca37b54a8fb2b52dChristian Sonntag    // use very late unicode character to quasi-guarantee last sort position.
912cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani    private static final String KEY_WIFI_SUPPLICANT = "\uffedWIFI";
92220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
93220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private SettingsHelper mSettingsHelper;
94220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
95220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    public void onCreate() {
96220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        mSettingsHelper = new SettingsHelper(this);
97220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        super.onCreate();
98220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    }
99220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
100220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    @Override
101220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
102220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            ParcelFileDescriptor newState) throws IOException {
103220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
104220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        byte[] systemSettingsData = getSystemSettings();
105220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        byte[] secureSettingsData = getSecureSettings();
1068823c0a8c68fe669c21c539eef9fc6541f0c7494Amith Yamasani        byte[] locale = mSettingsHelper.getLocaleData();
1072cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani        byte[] wifiData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
108220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
109d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        long[] stateChecksums = readOldChecksums(oldState);
1108823c0a8c68fe669c21c539eef9fc6541f0c7494Amith Yamasani
111d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        stateChecksums[STATE_SYSTEM] =
112d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani                writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data);
113d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        stateChecksums[STATE_SECURE] =
114d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani                writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data);
115d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        stateChecksums[STATE_LOCALE] =
116d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani                writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data);
117d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        stateChecksums[STATE_WIFI] =
11892c1752175f0880a0e0a05fdca37b54a8fb2b52dChristian Sonntag                writeIfChanged(stateChecksums[STATE_WIFI], KEY_WIFI_SUPPLICANT, wifiData, data);
1198823c0a8c68fe669c21c539eef9fc6541f0c7494Amith Yamasani
120d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        writeNewChecksums(stateChecksums, newState);
121220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    }
122220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
123220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    @Override
124220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    public void onRestore(BackupDataInput data, int appVersionCode,
125220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            ParcelFileDescriptor newState) throws IOException {
126220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
127220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        while (data.readNextHeader()) {
128220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            final String key = data.getKey();
1298823c0a8c68fe669c21c539eef9fc6541f0c7494Amith Yamasani            final int size = data.getDataSize();
130220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            if (KEY_SYSTEM.equals(key)) {
131220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                restoreSettings(data, Settings.System.CONTENT_URI);
132d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani                mSettingsHelper.applyAudioSettings();
133220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            } else if (KEY_SECURE.equals(key)) {
134220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                restoreSettings(data, Settings.Secure.CONTENT_URI);
13592c1752175f0880a0e0a05fdca37b54a8fb2b52dChristian Sonntag            } else if (KEY_WIFI_SUPPLICANT.equals(key)) {
136c5b5b0fb94d078148b5fe5f6b8bb4ee361949f3eChristian Sonntag                int retainedWifiState = enableWifi(false);
1372cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                restoreWifiSupplicant(FILE_WIFI_SUPPLICANT, data);
138d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani                FileUtils.setPermissions(FILE_WIFI_SUPPLICANT,
139d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani                        FileUtils.S_IRUSR | FileUtils.S_IWUSR |
140d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani                        FileUtils.S_IRGRP | FileUtils.S_IWGRP,
141d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani                        Process.myUid(), Process.WIFI_UID);
142c5b5b0fb94d078148b5fe5f6b8bb4ee361949f3eChristian Sonntag                // retain the previous WIFI state.
143c5b5b0fb94d078148b5fe5f6b8bb4ee361949f3eChristian Sonntag                enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED ||
144c5b5b0fb94d078148b5fe5f6b8bb4ee361949f3eChristian Sonntag                        retainedWifiState == WifiManager.WIFI_STATE_ENABLING);
1458823c0a8c68fe669c21c539eef9fc6541f0c7494Amith Yamasani            } else if (KEY_LOCALE.equals(key)) {
1468823c0a8c68fe669c21c539eef9fc6541f0c7494Amith Yamasani                byte[] localeData = new byte[size];
1478823c0a8c68fe669c21c539eef9fc6541f0c7494Amith Yamasani                data.readEntityData(localeData, 0, size);
1488823c0a8c68fe669c21c539eef9fc6541f0c7494Amith Yamasani                mSettingsHelper.setLocaleData(localeData);
149220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            } else {
150220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                data.skipEntityData();
151220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            }
152220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        }
153220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    }
154220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
155d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani    private long[] readOldChecksums(ParcelFileDescriptor oldState) throws IOException {
156d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        long[] stateChecksums = new long[STATE_SIZE];
157d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani
158d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        DataInputStream dataInput = new DataInputStream(
159d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani                new FileInputStream(oldState.getFileDescriptor()));
160a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate
161a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate        try {
162a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate            int stateVersion = dataInput.readInt();
163a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate            if (stateVersion == STATE_VERSION) {
164a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate                for (int i = 0; i < STATE_SIZE; i++) {
165a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate                    stateChecksums[i] = dataInput.readLong();
166a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate                }
167d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani            }
168a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate        } catch (EOFException eof) {
169a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate            // With the default 0 checksum we'll wind up forcing a backup of
170a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate            // any unhandled data sets, which is appropriate.
171d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        }
172d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        dataInput.close();
173d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        return stateChecksums;
174d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani    }
175d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani
176d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani    private void writeNewChecksums(long[] checksums, ParcelFileDescriptor newState)
177d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani            throws IOException {
178d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        DataOutputStream dataOutput = new DataOutputStream(
179d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani                new FileOutputStream(newState.getFileDescriptor()));
180a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate
181a286f419084d56217f05a64f1d24c9e07917212eChristopher Tate        dataOutput.writeInt(STATE_VERSION);
182d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        for (int i = 0; i < STATE_SIZE; i++) {
183d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani            dataOutput.writeLong(checksums[i]);
184d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        }
185d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        dataOutput.close();
186d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani    }
187d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani
188d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani    private long writeIfChanged(long oldChecksum, String key, byte[] data,
189d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani            BackupDataOutput output) {
190d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        CRC32 checkSummer = new CRC32();
191d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        checkSummer.update(data);
192d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        long newChecksum = checkSummer.getValue();
193d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        if (oldChecksum == newChecksum) {
194d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani            return oldChecksum;
195d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        }
196d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        try {
197d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani            output.writeEntityHeader(key, data.length);
198d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani            output.writeEntityData(data, data.length);
199d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        } catch (IOException ioe) {
200d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani            // Bail
201d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        }
202d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani        return newChecksum;
203d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani    }
204d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani
205220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private byte[] getSystemSettings() {
206220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        Cursor sortedCursor = getContentResolver().query(Settings.System.CONTENT_URI, PROJECTION,
207220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                null, null, Settings.NameValueTable.NAME);
208220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        // Copy and sort the array
209220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        if (sortedSystemKeys == null) {
210220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            sortedSystemKeys = copyAndSort(Settings.System.SETTINGS_TO_BACKUP);
211220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        }
212220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        byte[] result = extractRelevantValues(sortedCursor, sortedSystemKeys);
213220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        sortedCursor.close();
214220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        return result;
215220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    }
216220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
217220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private byte[] getSecureSettings() {
218220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        Cursor sortedCursor = getContentResolver().query(Settings.Secure.CONTENT_URI, PROJECTION,
219220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                null, null, Settings.NameValueTable.NAME);
220220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        // Copy and sort the array
221220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        if (sortedSecureKeys == null) {
222220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            sortedSecureKeys = copyAndSort(Settings.Secure.SETTINGS_TO_BACKUP);
223220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        }
224220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        byte[] result = extractRelevantValues(sortedCursor, sortedSecureKeys);
225220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        sortedCursor.close();
226220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        return result;
227220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    }
228220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
229220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private void restoreSettings(BackupDataInput data, Uri contentUri) {
230796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate        if (DEBUG) Log.i(TAG, "restoreSettings: " + contentUri);
231796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate        String[] whitelist = null;
232796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate        if (contentUri.equals(Settings.Secure.CONTENT_URI)) {
233796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate            whitelist = Settings.Secure.SETTINGS_TO_BACKUP;
234796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate        } else if (contentUri.equals(Settings.System.CONTENT_URI)) {
235796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate            whitelist = Settings.System.SETTINGS_TO_BACKUP;
236796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate        }
237796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate
238220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        ContentValues cv = new ContentValues(2);
239220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        byte[] settings = new byte[data.getDataSize()];
240220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        try {
241220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            data.readEntityData(settings, 0, settings.length);
242220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        } catch (IOException ioe) {
243220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            Log.e(TAG, "Couldn't read entity data");
244220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            return;
245220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        }
246220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        int pos = 0;
247220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        while (pos < settings.length) {
248220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            int length = readInt(settings, pos);
249220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            pos += 4;
250220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            String settingName = length > 0? new String(settings, pos, length) : null;
251220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            pos += length;
252220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            length = readInt(settings, pos);
253220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            pos += 4;
254220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            String settingValue = length > 0? new String(settings, pos, length) : null;
255220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            pos += length;
256220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            if (!TextUtils.isEmpty(settingName) && !TextUtils.isEmpty(settingValue)) {
257220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                //Log.i(TAG, "Restore " + settingName + " = " + settingValue);
2580738e8893540e8f7fac7c193be5fe24b67f04672Christopher Tate
259796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate                // Only restore settings in our list of known-acceptable data
260796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate                if (invalidSavedSetting(whitelist, settingName)) {
2610738e8893540e8f7fac7c193be5fe24b67f04672Christopher Tate                    continue;
2620738e8893540e8f7fac7c193be5fe24b67f04672Christopher Tate                }
2630738e8893540e8f7fac7c193be5fe24b67f04672Christopher Tate
26470c874ba20b586712a7550b6c5efeb6dc0fdf9faAmith Yamasani                if (mSettingsHelper.restoreValue(settingName, settingValue)) {
26570c874ba20b586712a7550b6c5efeb6dc0fdf9faAmith Yamasani                    cv.clear();
26670c874ba20b586712a7550b6c5efeb6dc0fdf9faAmith Yamasani                    cv.put(Settings.NameValueTable.NAME, settingName);
26770c874ba20b586712a7550b6c5efeb6dc0fdf9faAmith Yamasani                    cv.put(Settings.NameValueTable.VALUE, settingValue);
26870c874ba20b586712a7550b6c5efeb6dc0fdf9faAmith Yamasani                    getContentResolver().insert(contentUri, cv);
26970c874ba20b586712a7550b6c5efeb6dc0fdf9faAmith Yamasani                }
270220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            }
271220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        }
272220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    }
273220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
274796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate    // Returns 'true' if the given setting is one that we refuse to restore
275796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate    private boolean invalidSavedSetting(String[] knownNames, String candidate) {
276796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate        // no filter? allow everything
277796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate        if (knownNames == null) {
278796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate            return false;
279796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate        }
280796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate
281796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate        // whitelisted setting?  allow it
282796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate        for (String name : knownNames) {
283796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate            if (name.equals(candidate)) {
284796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate                return false;
2850738e8893540e8f7fac7c193be5fe24b67f04672Christopher Tate            }
2860738e8893540e8f7fac7c193be5fe24b67f04672Christopher Tate        }
2870738e8893540e8f7fac7c193be5fe24b67f04672Christopher Tate
288796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate        // refuse everything else
289796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate        if (DEBUG) Log.v(TAG, "Ignoring restore datum: " + candidate);
290796e0f0ed531b7ff9922cd632d70d8f1da8f5829Christopher Tate        return true;
2910738e8893540e8f7fac7c193be5fe24b67f04672Christopher Tate    }
2920738e8893540e8f7fac7c193be5fe24b67f04672Christopher Tate
293220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private String[] copyAndSort(String[] keys) {
294220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        String[] sortedKeys = new String[keys.length];
295220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        System.arraycopy(keys, 0, sortedKeys, 0, keys.length);
296220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        Arrays.sort(sortedKeys);
297220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        return sortedKeys;
298220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    }
299220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
300220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    /**
301c5b5b0fb94d078148b5fe5f6b8bb4ee361949f3eChristian Sonntag     * Given a cursor sorted by key name and a set of keys sorted by name,
302220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani     * extract the required keys and values and write them to a byte array.
303220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani     * @param sortedCursor
304220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani     * @param sortedKeys
305220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani     * @return
306220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani     */
307220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    byte[] extractRelevantValues(Cursor sortedCursor, String[] sortedKeys) {
308220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        byte[][] values = new byte[sortedKeys.length * 2][]; // keys and values
309220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        if (!sortedCursor.moveToFirst()) {
310220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            Log.e(TAG, "Couldn't read from the cursor");
311220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            return new byte[0];
312220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        }
313220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        int keyIndex = 0;
314220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        int totalSize = 0;
315220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        while (!sortedCursor.isAfterLast()) {
316220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            String name = sortedCursor.getString(COLUMN_NAME);
317220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            while (sortedKeys[keyIndex].compareTo(name.toString()) < 0) {
318220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                keyIndex++;
319220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                if (keyIndex == sortedKeys.length) break;
320220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            }
321220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            if (keyIndex < sortedKeys.length && name.equals(sortedKeys[keyIndex])) {
322220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                String value = sortedCursor.getString(COLUMN_VALUE);
323220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                byte[] nameBytes = name.toString().getBytes();
324220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                totalSize += 4 + nameBytes.length;
325220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                values[keyIndex * 2] = nameBytes;
326220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                byte[] valueBytes;
327220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                if (TextUtils.isEmpty(value)) {
328220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                    valueBytes = null;
329220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                    totalSize += 4;
330220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                } else {
331220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                    valueBytes = value.toString().getBytes();
332220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                    totalSize += 4 + valueBytes.length;
333220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                    //Log.i(TAG, "Backing up " + name + " = " + value);
334220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                }
335220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                values[keyIndex * 2 + 1] = valueBytes;
336220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                keyIndex++;
337220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            }
338220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            if (keyIndex == sortedKeys.length || !sortedCursor.moveToNext()) {
339220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                break;
340220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            }
341220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        }
342220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
343220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        byte[] result = new byte[totalSize];
344220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        int pos = 0;
345220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        for (int i = 0; i < sortedKeys.length * 2; i++) {
346220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            if (values[i] != null) {
347220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                pos = writeInt(result, pos, values[i].length);
348220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                pos = writeBytes(result, pos, values[i]);
349220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            }
350220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        }
351220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        return result;
352220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    }
353220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
3542cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani    private byte[] getWifiSupplicant(String filename) {
355220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        try {
356220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            File file = new File(filename);
357220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            if (file.exists()) {
3582cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                BufferedReader br = new BufferedReader(new FileReader(file));
3592cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                StringBuffer relevantLines = new StringBuffer();
3602cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                boolean started = false;
3612cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                String line;
3622cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                while ((line = br.readLine()) != null) {
3632cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                    if (!started && line.startsWith("network")) {
3642cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                        started = true;
3652cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                    }
3662cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                    if (started) {
3672cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                        relevantLines.append(line).append("\n");
3682cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                    }
3692cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                }
3702cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                if (relevantLines.length() > 0) {
3712cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                    return relevantLines.toString().getBytes();
3722cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                } else {
3732cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                    return EMPTY_DATA;
3742cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                }
375220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            } else {
376d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani                return EMPTY_DATA;
377220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            }
378220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        } catch (IOException ioe) {
379220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            Log.w(TAG, "Couldn't backup " + filename);
380d158214511a3c04753de04fa6389e46d33135c38Amith Yamasani            return EMPTY_DATA;
381220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        }
382220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    }
383220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
3842cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani    private void restoreWifiSupplicant(String filename, BackupDataInput data) {
385220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        byte[] bytes = new byte[data.getDataSize()];
386220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        if (bytes.length <= 0) return;
387220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        try {
388220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            data.readEntityData(bytes, 0, bytes.length);
3892cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani            File supplicantFile = new File(FILE_WIFI_SUPPLICANT);
3902cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani            if (supplicantFile.exists()) supplicantFile.delete();
3912cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani            copyWifiSupplicantTemplate();
3922cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani
3932cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani            FileOutputStream fos = new FileOutputStream(filename, true);
3942cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani            fos.write("\n".getBytes());
395220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            fos.write(bytes);
396220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        } catch (IOException ioe) {
397220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            Log.w(TAG, "Couldn't restore " + filename);
398220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        }
399220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    }
400220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
4012cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani    private void copyWifiSupplicantTemplate() {
4022cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani        try {
4032cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani            BufferedReader br = new BufferedReader(new FileReader(FILE_WIFI_SUPPLICANT_TEMPLATE));
4042cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani            BufferedWriter bw = new BufferedWriter(new FileWriter(FILE_WIFI_SUPPLICANT));
4052cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani            char[] temp = new char[1024];
4062cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani            int size;
4072cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani            while ((size = br.read(temp)) > 0) {
4082cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani                bw.write(temp, 0, size);
4092cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani            }
4102cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani            bw.close();
4112cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani            br.close();
4122cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani        } catch (IOException ioe) {
4132cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani            Log.w(TAG, "Couldn't copy wpa_supplicant file");
4142cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani        }
4152cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani    }
4162cfab8445851c59f7da07d81645ece8d70e8ce28Amith Yamasani
417220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    /**
418220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani     * Write an int in BigEndian into the byte array.
419220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani     * @param out byte array
420220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani     * @param pos current pos in array
421220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani     * @param value integer to write
422220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani     * @return the index after adding the size of an int (4)
423220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani     */
424220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private int writeInt(byte[] out, int pos, int value) {
425220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        out[pos + 0] = (byte) ((value >> 24) & 0xFF);
426220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        out[pos + 1] = (byte) ((value >> 16) & 0xFF);
427220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        out[pos + 2] = (byte) ((value >>  8) & 0xFF);
428220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        out[pos + 3] = (byte) ((value >>  0) & 0xFF);
429220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        return pos + 4;
430220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    }
431220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
432220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private int writeBytes(byte[] out, int pos, byte[] value) {
433220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        System.arraycopy(value, 0, out, pos, value.length);
434220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        return pos + value.length;
435220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    }
436220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
437220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    private int readInt(byte[] in, int pos) {
438220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        int result =
439220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                ((in[pos    ] & 0xFF) << 24) |
440220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                ((in[pos + 1] & 0xFF) << 16) |
441220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                ((in[pos + 2] & 0xFF) <<  8) |
442220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani                ((in[pos + 3] & 0xFF) <<  0);
443220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        return result;
444220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    }
445220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani
446c5b5b0fb94d078148b5fe5f6b8bb4ee361949f3eChristian Sonntag    private int enableWifi(boolean enable) {
447220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        WifiManager wfm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
448220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        if (wfm != null) {
449c5b5b0fb94d078148b5fe5f6b8bb4ee361949f3eChristian Sonntag            int state = wfm.getWifiState();
450220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani            wfm.setWifiEnabled(enable);
451c5b5b0fb94d078148b5fe5f6b8bb4ee361949f3eChristian Sonntag            return state;
452220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani        }
453c5b5b0fb94d078148b5fe5f6b8bb4ee361949f3eChristian Sonntag        return WifiManager.WIFI_STATE_UNKNOWN;
454220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani    }
455220f4d633be1098e7887dbd06f179138bf19f1adAmith Yamasani}
456