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 17 package android.net.wifi; 18 19 import android.content.Context; 20 import android.net.wifi.WifiConfiguration.KeyMgmt; 21 import android.os.Environment; 22 import android.os.Message; 23 import android.os.Handler; 24 import android.os.HandlerThread; 25 import android.util.Log; 26 27 import java.io.BufferedInputStream; 28 import java.io.BufferedOutputStream; 29 import java.io.DataInputStream; 30 import java.io.DataOutputStream; 31 import java.io.FileInputStream; 32 import java.io.FileOutputStream; 33 import java.io.IOException; 34 import java.net.InetAddress; 35 import java.util.UUID; 36 37 import com.android.internal.R; 38 39 40 /** 41 * Provides API to the WifiStateMachine for doing read/write access 42 * to soft access point configuration 43 */ 44 class WifiApConfigStore { 45 46 private static Context sContext; 47 private static final String TAG = "WifiApConfigStore"; 48 49 private static final String AP_CONFIG_FILE = Environment.getDataDirectory() + 50 "/misc/wifi/softap.conf"; 51 52 private static final int AP_CONFIG_FILE_VERSION = 1; 53 54 private static WifiConfiguration sApConfig = new WifiConfiguration(); 55 private static final Object sApConfigLock = new Object(); 56 57 private static FileReadWriteHandler sFileReadWriteHandler; 58 private static final int READ_AP_CONFIG = 1; 59 private static final int WRITE_AP_CONFIG = 2; 60 61 static void initialize(Context context) { 62 sContext = context; 63 64 /* File operations happen on a seperate thread */ 65 HandlerThread configThread = new HandlerThread("WifiApConfigStore"); 66 configThread.start(); 67 sFileReadWriteHandler = new FileReadWriteHandler(configThread.getLooper()); 68 Message.obtain(sFileReadWriteHandler, READ_AP_CONFIG).sendToTarget(); 69 } 70 71 72 static void setApConfiguration(WifiConfiguration config) { 73 synchronized (sApConfigLock) { 74 sApConfig = config; 75 } 76 Message.obtain(sFileReadWriteHandler, WRITE_AP_CONFIG, new WifiConfiguration(config)) 77 .sendToTarget(); 78 } 79 80 static WifiConfiguration getApConfiguration() { 81 synchronized (sApConfigLock) { 82 return new WifiConfiguration(sApConfig); 83 } 84 } 85 86 /** 87 * File read/write handler 88 */ 89 private static class FileReadWriteHandler extends Handler { 90 91 public FileReadWriteHandler(android.os.Looper looper) { 92 super(looper); 93 } 94 95 @Override 96 public void handleMessage(Message msg) { 97 switch (msg.what) { 98 case WRITE_AP_CONFIG: 99 writeApConfiguration((WifiConfiguration) msg.obj); 100 break; 101 case READ_AP_CONFIG: 102 readApConfiguration(); 103 break; 104 default: 105 Log.e(TAG, "Unknown command in FileReadWriteHandler: " + msg); 106 break; 107 } 108 } 109 110 private static void writeApConfiguration(final WifiConfiguration config) { 111 DataOutputStream out = null; 112 try { 113 out = new DataOutputStream(new BufferedOutputStream( 114 new FileOutputStream(AP_CONFIG_FILE))); 115 116 out.writeInt(AP_CONFIG_FILE_VERSION); 117 out.writeUTF(config.SSID); 118 int authType = config.getAuthType(); 119 out.writeInt(authType); 120 if(authType != KeyMgmt.NONE) { 121 out.writeUTF(config.preSharedKey); 122 } 123 } catch (IOException e) { 124 Log.e(TAG, "Error writing hotspot configuration" + e); 125 } finally { 126 if (out != null) { 127 try { 128 out.close(); 129 } catch (IOException e) {} 130 } 131 } 132 } 133 134 private static void readApConfiguration() { 135 DataInputStream in = null; 136 try { 137 WifiConfiguration config = new WifiConfiguration(); 138 in = new DataInputStream(new BufferedInputStream(new FileInputStream( 139 AP_CONFIG_FILE))); 140 141 int version = in.readInt(); 142 if (version != 1) { 143 Log.e(TAG, "Bad version on hotspot configuration file, set defaults"); 144 setDefaultApConfiguration(); 145 return; 146 } 147 config.SSID = in.readUTF(); 148 int authType = in.readInt(); 149 config.allowedKeyManagement.set(authType); 150 if (authType != KeyMgmt.NONE) { 151 config.preSharedKey = in.readUTF(); 152 } 153 synchronized (sApConfigLock) { 154 sApConfig = config; 155 } 156 } catch (IOException ignore) { 157 setDefaultApConfiguration(); 158 } finally { 159 if (in != null) { 160 try { 161 in.close(); 162 } catch (IOException e) {} 163 } 164 } 165 } 166 167 /* Generate a default WPA2 based configuration with a random password. 168 We are changing the Wifi Ap configuration storage from secure settings to a 169 flat file accessible only by the system. A WPA2 based default configuration 170 will keep the device secure after the update */ 171 private static void setDefaultApConfiguration() { 172 WifiConfiguration config = new WifiConfiguration(); 173 config.SSID = sContext.getString(R.string.wifi_tether_configure_ssid_default); 174 config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK); 175 String randomUUID = UUID.randomUUID().toString(); 176 //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx 177 config.preSharedKey = randomUUID.substring(0, 8) + randomUUID.substring(9,13); 178 setApConfiguration(config); 179 } 180 } 181 } 182