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.Handler; 239575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriffimport android.os.Message; 249575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriffimport android.os.Messenger; 25ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriffimport android.util.Log; 26ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff 279575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriffimport com.android.internal.util.AsyncChannel; 289575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriffimport com.android.internal.R; 299575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriffimport com.android.internal.util.State; 309575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriffimport com.android.internal.util.StateMachine; 319575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff 32ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriffimport java.io.BufferedInputStream; 33ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriffimport java.io.BufferedOutputStream; 34ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriffimport java.io.DataInputStream; 35ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriffimport java.io.DataOutputStream; 36ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriffimport java.io.FileInputStream; 37ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriffimport java.io.FileOutputStream; 38ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriffimport java.io.IOException; 39ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriffimport java.net.InetAddress; 40ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriffimport java.util.UUID; 41ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff 42ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff/** 43ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff * Provides API to the WifiStateMachine for doing read/write access 44ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff * to soft access point configuration 45ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff */ 469575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriffclass WifiApConfigStore extends StateMachine { 47ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff 489575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff private Context mContext; 49ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff private static final String TAG = "WifiApConfigStore"; 50ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff 51ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff private static final String AP_CONFIG_FILE = Environment.getDataDirectory() + 52ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff "/misc/wifi/softap.conf"; 53ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff 54ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff private static final int AP_CONFIG_FILE_VERSION = 1; 55ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff 569575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff private State mDefaultState = new DefaultState(); 579575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff private State mInactiveState = new InactiveState(); 589575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff private State mActiveState = new ActiveState(); 599575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff 609575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff private WifiConfiguration mWifiApConfig = null; 619575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff private AsyncChannel mReplyChannel = new AsyncChannel(); 62ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff 639575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff WifiApConfigStore(Context context, Handler target) { 649575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff super(TAG, target.getLooper()); 65ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff 669575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff mContext = context; 679575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff addState(mDefaultState); 689575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff addState(mInactiveState, mDefaultState); 699575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff addState(mActiveState, mDefaultState); 70ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff 719575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff setInitialState(mInactiveState); 72ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff } 73ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff 749575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff public static WifiApConfigStore makeWifiApConfigStore(Context context, Handler target) { 759575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff WifiApConfigStore s = new WifiApConfigStore(context, target); 769575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff s.start(); 779575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff return s; 789575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } 79ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff 809575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff class DefaultState extends State { 819575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff public boolean processMessage(Message message) { 829575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff switch (message.what) { 839575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff case WifiStateMachine.CMD_SET_AP_CONFIG: 849575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff case WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED: 859575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff Log.e(TAG, "Unexpected message: " + message); 869575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff break; 879575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff case WifiStateMachine.CMD_REQUEST_AP_CONFIG: 889575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff mReplyChannel.replyToMessage(message, 899575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff WifiStateMachine.CMD_RESPONSE_AP_CONFIG, mWifiApConfig); 909575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff break; 919575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff default: 929575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff Log.e(TAG, "Failed to handle " + message); 939575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff break; 949575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } 959575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff return HANDLED; 96ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff } 97ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff } 98ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff 999575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff class InactiveState extends State { 1009575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff public boolean processMessage(Message message) { 1019575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff switch (message.what) { 1029575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff case WifiStateMachine.CMD_SET_AP_CONFIG: 1039575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff mWifiApConfig = (WifiConfiguration) message.obj; 1049575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff transitionTo(mActiveState); 1059575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff break; 1069575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff default: 1079575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff return NOT_HANDLED; 1089575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } 1099575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff return HANDLED; 110ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff } 111ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff } 112ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff 1139575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff class ActiveState extends State { 1149575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff public void enter() { 1159575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff new Thread(new Runnable() { 1169575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff public void run() { 1179575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff writeApConfiguration(mWifiApConfig); 1189575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED); 1199575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } 1209575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff }).start(); 121ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff } 122ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff 1239575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff public boolean processMessage(Message message) { 1249575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff switch (message.what) { 1259575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff //TODO: have feedback to the user when we do this 1269575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff //to indicate the write is currently in progress 1279575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff case WifiStateMachine.CMD_SET_AP_CONFIG: 1289575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff deferMessage(message); 129ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff break; 1309575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff case WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED: 1319575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff transitionTo(mInactiveState); 132ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff break; 133ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff default: 1349575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff return NOT_HANDLED; 135ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff } 1369575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff return HANDLED; 137ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff } 1389575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } 139ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff 1409575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff void loadApConfiguration() { 1419575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff DataInputStream in = null; 1429575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff try { 1439575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff WifiConfiguration config = new WifiConfiguration(); 1449575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff in = new DataInputStream(new BufferedInputStream(new FileInputStream( 1459575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff AP_CONFIG_FILE))); 146ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff 1479575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff int version = in.readInt(); 1489575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff if (version != 1) { 1499575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff Log.e(TAG, "Bad version on hotspot configuration file, set defaults"); 150ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff setDefaultApConfiguration(); 1519575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff return; 1529575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } 1539575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff config.SSID = in.readUTF(); 1549575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff int authType = in.readInt(); 1559575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff config.allowedKeyManagement.set(authType); 1569575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff if (authType != KeyMgmt.NONE) { 1579575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff config.preSharedKey = in.readUTF(); 1589575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } 1599575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff mWifiApConfig = config; 1609575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } catch (IOException ignore) { 1619575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff setDefaultApConfiguration(); 1629575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } finally { 1639575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff if (in != null) { 1649575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff try { 1659575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff in.close(); 1669575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } catch (IOException e) {} 167ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff } 168ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff } 1699575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } 170ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff 1719575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff Messenger getMessenger() { 1729575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff return new Messenger(getHandler()); 1739575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } 1749575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff 1759575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff private void writeApConfiguration(final WifiConfiguration config) { 1769575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff DataOutputStream out = null; 1779575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff try { 1789575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff out = new DataOutputStream(new BufferedOutputStream( 1799575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff new FileOutputStream(AP_CONFIG_FILE))); 1809575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff 1819575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff out.writeInt(AP_CONFIG_FILE_VERSION); 1829575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff out.writeUTF(config.SSID); 1839575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff int authType = config.getAuthType(); 1849575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff out.writeInt(authType); 1859575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff if(authType != KeyMgmt.NONE) { 1869575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff out.writeUTF(config.preSharedKey); 1879575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } 1889575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } catch (IOException e) { 1899575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff Log.e(TAG, "Error writing hotspot configuration" + e); 1909575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } finally { 1919575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff if (out != null) { 1929575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff try { 1939575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff out.close(); 1949575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } catch (IOException e) {} 1959575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } 196ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff } 197ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff } 1989575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff 1999575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff /* Generate a default WPA2 based configuration with a random password. 2009575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff We are changing the Wifi Ap configuration storage from secure settings to a 2019575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff flat file accessible only by the system. A WPA2 based default configuration 2029575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff will keep the device secure after the update */ 2039575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff private void setDefaultApConfiguration() { 2049575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff WifiConfiguration config = new WifiConfiguration(); 2059575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff config.SSID = mContext.getString(R.string.wifi_tether_configure_ssid_default); 2069575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK); 2079575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff String randomUUID = UUID.randomUUID().toString(); 2089575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx 2099575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff config.preSharedKey = randomUUID.substring(0, 8) + randomUUID.substring(9,13); 2109575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG, config); 2119575a1bea1787efe1686bd8562bcc70c72d01721Irfan Sheriff } 212ffcea7ae7316ab748a49f5e8f6c6798356f35719Irfan Sheriff} 213