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