WifiApConfigStore.java revision c79666b79e273ceaa2f74090b02ca6cf83c61387
1/*
2 * Copyright (C) 2010 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.server.wifi;
18
19import android.content.Context;
20import android.net.wifi.WifiConfiguration;
21import android.net.wifi.WifiConfiguration.KeyMgmt;
22import android.os.Environment;
23import android.util.Log;
24
25import com.android.internal.R;
26
27import java.io.BufferedInputStream;
28import java.io.BufferedOutputStream;
29import java.io.DataInputStream;
30import java.io.DataOutputStream;
31import java.io.FileInputStream;
32import java.io.FileOutputStream;
33import java.io.IOException;
34import java.util.ArrayList;
35import java.util.UUID;
36
37/**
38 * Provides API for reading/writing soft access point configuration.
39 */
40public class WifiApConfigStore {
41
42    private static final String TAG = "WifiApConfigStore";
43
44    private static final String DEFAULT_AP_CONFIG_FILE =
45            Environment.getDataDirectory() + "/misc/wifi/softap.conf";
46
47    private static final int AP_CONFIG_FILE_VERSION = 2;
48
49    private WifiConfiguration mWifiApConfig = null;
50
51    private ArrayList<Integer> mAllowed2GChannel = null;
52
53    private final Context mContext;
54    private final String mApConfigFile;
55
56    WifiApConfigStore(Context context) {
57        this(context, DEFAULT_AP_CONFIG_FILE);
58    }
59
60    WifiApConfigStore(Context context, String apConfigFile) {
61        mContext = context;
62        mApConfigFile = apConfigFile;
63
64        String ap2GChannelListStr = mContext.getResources().getString(
65                R.string.config_wifi_framework_sap_2G_channel_list);
66        Log.d(TAG, "2G band allowed channels are:" + ap2GChannelListStr);
67
68        if (ap2GChannelListStr != null) {
69            mAllowed2GChannel = new ArrayList<Integer>();
70            String channelList[] = ap2GChannelListStr.split(",");
71            for (String tmp : channelList) {
72                mAllowed2GChannel.add(Integer.parseInt(tmp));
73            }
74        }
75
76        /* Load AP configuration from persistent storage. */
77        mWifiApConfig = loadApConfiguration(mApConfigFile);
78        if (mWifiApConfig == null) {
79            /* Use default configuration. */
80            Log.d(TAG, "Fallback to use default AP configuration");
81            mWifiApConfig = getDefaultApConfiguration();
82
83            /* Save the default configuration to persistent storage. */
84            writeApConfiguration(mApConfigFile, mWifiApConfig);
85        }
86    }
87
88    /**
89     * Return the current soft access point configuration.
90     */
91    public synchronized WifiConfiguration getApConfiguration() {
92        return mWifiApConfig;
93    }
94
95    /**
96     * Update the current soft access point configuration.
97     * Restore to default AP configuration if null is provided.
98     * This can be invoked under context of binder threads (WifiManager.setWifiApConfiguration)
99     * and WifiStateMachine thread (CMD_START_AP).
100     */
101    public synchronized void setApConfiguration(WifiConfiguration config) {
102        if (config == null) {
103            mWifiApConfig = getDefaultApConfiguration();
104        } else {
105            mWifiApConfig = config;
106        }
107        writeApConfiguration(mApConfigFile, mWifiApConfig);
108    }
109
110    public ArrayList<Integer> getAllowed2GChannel() {
111        return mAllowed2GChannel;
112    }
113
114    /**
115     * Load AP configuration from persistent storage.
116     */
117    private static WifiConfiguration loadApConfiguration(final String filename) {
118        WifiConfiguration config = null;
119        DataInputStream in = null;
120        try {
121            config = new WifiConfiguration();
122            in = new DataInputStream(
123                    new BufferedInputStream(new FileInputStream(filename)));
124
125            int version = in.readInt();
126            if ((version != 1) && (version != 2)) {
127                Log.e(TAG, "Bad version on hotspot configuration file");
128                return null;
129            }
130            config.SSID = in.readUTF();
131
132            if (version >= 2) {
133                config.apBand = in.readInt();
134                config.apChannel = in.readInt();
135            }
136
137            int authType = in.readInt();
138            config.allowedKeyManagement.set(authType);
139            if (authType != KeyMgmt.NONE) {
140                config.preSharedKey = in.readUTF();
141            }
142        } catch (IOException e) {
143            Log.e(TAG, "Error reading hotspot configuration " + e);
144            config = null;
145        } finally {
146            if (in != null) {
147                try {
148                    in.close();
149                } catch (IOException e) {
150                    Log.e(TAG, "Error closing hotspot configuration during read" + e);
151                }
152            }
153        }
154        return config;
155    }
156
157    /**
158     * Write AP configuration to persistent storage.
159     */
160    private static boolean writeApConfiguration(final String filename,
161                                                final WifiConfiguration config) {
162        DataOutputStream out = null;
163        try {
164            out = new DataOutputStream(new BufferedOutputStream(
165                        new FileOutputStream(filename)));
166
167            out.writeInt(AP_CONFIG_FILE_VERSION);
168            out.writeUTF(config.SSID);
169            out.writeInt(config.apBand);
170            out.writeInt(config.apChannel);
171            int authType = config.getAuthType();
172            out.writeInt(authType);
173            if (authType != KeyMgmt.NONE) {
174                out.writeUTF(config.preSharedKey);
175            }
176        } catch (IOException e) {
177            Log.e(TAG, "Error writing hotspot configuration" + e);
178            return false;
179        } finally {
180            if (out != null) {
181                try {
182                    out.close();
183                } catch (IOException e) {
184                    Log.e(TAG, "Error closing hotspot configuration during write" + e);
185                    return false;
186                }
187            }
188        }
189        return true;
190    }
191
192    /**
193     * Generate a default WPA2 based configuration with a random password.
194     * We are changing the Wifi Ap configuration storage from secure settings to a
195     * flat file accessible only by the system. A WPA2 based default configuration
196     * will keep the device secure after the update.
197     */
198    private WifiConfiguration getDefaultApConfiguration() {
199        WifiConfiguration config = new WifiConfiguration();
200        config.SSID = mContext.getResources().getString(
201                R.string.wifi_tether_configure_ssid_default);
202        config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
203        String randomUUID = UUID.randomUUID().toString();
204        //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
205        config.preSharedKey = randomUUID.substring(0, 8) + randomUUID.substring(9, 13);
206        return config;
207    }
208}
209