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