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