blob: 5e28fcfe54e965f585a658761bc159a65233872a [file] [log] [blame]
Irfan Sheriffffcea7a2011-05-10 16:26:06 -07001/*
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
Vinit Deshapndeffadfb92013-12-06 15:12:41 -080017package com.android.server.wifi;
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070018
19import android.content.Context;
Vinit Deshapndeffadfb92013-12-06 15:12:41 -080020import android.net.wifi.WifiConfiguration;
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070021import android.net.wifi.WifiConfiguration.KeyMgmt;
22import android.os.Environment;
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070023import android.os.Handler;
Irfan Sheriff9575a1b2011-11-07 10:34:54 -080024import android.os.Message;
25import android.os.Messenger;
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070026import android.util.Log;
27
Irfan Sheriff9575a1b2011-11-07 10:34:54 -080028import com.android.internal.util.AsyncChannel;
29import com.android.internal.R;
30import com.android.internal.util.State;
31import com.android.internal.util.StateMachine;
32
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070033import java.io.BufferedInputStream;
34import java.io.BufferedOutputStream;
35import java.io.DataInputStream;
36import java.io.DataOutputStream;
37import java.io.FileInputStream;
38import java.io.FileOutputStream;
39import java.io.IOException;
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070040import java.util.UUID;
41
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070042/**
43 * Provides API to the WifiStateMachine for doing read/write access
44 * to soft access point configuration
45 */
Irfan Sheriff9575a1b2011-11-07 10:34:54 -080046class WifiApConfigStore extends StateMachine {
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070047
Irfan Sheriff9575a1b2011-11-07 10:34:54 -080048 private Context mContext;
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070049 private static final String TAG = "WifiApConfigStore";
50
51 private static final String AP_CONFIG_FILE = Environment.getDataDirectory() +
52 "/misc/wifi/softap.conf";
53
54 private static final int AP_CONFIG_FILE_VERSION = 1;
55
Irfan Sheriff9575a1b2011-11-07 10:34:54 -080056 private State mDefaultState = new DefaultState();
57 private State mInactiveState = new InactiveState();
58 private State mActiveState = new ActiveState();
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070059
Irfan Sheriff9575a1b2011-11-07 10:34:54 -080060 private WifiConfiguration mWifiApConfig = null;
61 private AsyncChannel mReplyChannel = new AsyncChannel();
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070062
Irfan Sheriff9575a1b2011-11-07 10:34:54 -080063 WifiApConfigStore(Context context, Handler target) {
64 super(TAG, target.getLooper());
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070065
Irfan Sheriff9575a1b2011-11-07 10:34:54 -080066 mContext = context;
67 addState(mDefaultState);
68 addState(mInactiveState, mDefaultState);
69 addState(mActiveState, mDefaultState);
70
71 setInitialState(mInactiveState);
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070072 }
73
Irfan Sheriff9575a1b2011-11-07 10:34:54 -080074 public static WifiApConfigStore makeWifiApConfigStore(Context context, Handler target) {
75 WifiApConfigStore s = new WifiApConfigStore(context, target);
76 s.start();
77 return s;
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070078 }
79
Irfan Sheriff9575a1b2011-11-07 10:34:54 -080080 class DefaultState extends State {
81 public boolean processMessage(Message message) {
82 switch (message.what) {
83 case WifiStateMachine.CMD_SET_AP_CONFIG:
84 case WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED:
85 Log.e(TAG, "Unexpected message: " + message);
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070086 break;
Irfan Sheriff9575a1b2011-11-07 10:34:54 -080087 case WifiStateMachine.CMD_REQUEST_AP_CONFIG:
88 mReplyChannel.replyToMessage(message,
89 WifiStateMachine.CMD_RESPONSE_AP_CONFIG, mWifiApConfig);
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070090 break;
91 default:
Irfan Sheriff9575a1b2011-11-07 10:34:54 -080092 Log.e(TAG, "Failed to handle " + message);
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070093 break;
94 }
Irfan Sheriff9575a1b2011-11-07 10:34:54 -080095 return HANDLED;
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070096 }
Irfan Sheriff9575a1b2011-11-07 10:34:54 -080097 }
Irfan Sheriffffcea7a2011-05-10 16:26:06 -070098
Irfan Sheriff9575a1b2011-11-07 10:34:54 -080099 class InactiveState extends State {
100 public boolean processMessage(Message message) {
101 switch (message.what) {
102 case WifiStateMachine.CMD_SET_AP_CONFIG:
103 mWifiApConfig = (WifiConfiguration) message.obj;
104 transitionTo(mActiveState);
105 break;
106 default:
107 return NOT_HANDLED;
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700108 }
Irfan Sheriff9575a1b2011-11-07 10:34:54 -0800109 return HANDLED;
110 }
111 }
112
113 class ActiveState extends State {
114 public void enter() {
115 new Thread(new Runnable() {
116 public void run() {
117 writeApConfiguration(mWifiApConfig);
118 sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED);
119 }
120 }).start();
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700121 }
122
Irfan Sheriff9575a1b2011-11-07 10:34:54 -0800123 public boolean processMessage(Message message) {
124 switch (message.what) {
125 //TODO: have feedback to the user when we do this
126 //to indicate the write is currently in progress
127 case WifiStateMachine.CMD_SET_AP_CONFIG:
128 deferMessage(message);
129 break;
130 case WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED:
131 transitionTo(mInactiveState);
132 break;
133 default:
134 return NOT_HANDLED;
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700135 }
Irfan Sheriff9575a1b2011-11-07 10:34:54 -0800136 return HANDLED;
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700137 }
Irfan Sheriff9575a1b2011-11-07 10:34:54 -0800138 }
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700139
Irfan Sheriff9575a1b2011-11-07 10:34:54 -0800140 void loadApConfiguration() {
141 DataInputStream in = null;
142 try {
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700143 WifiConfiguration config = new WifiConfiguration();
Irfan Sheriff9575a1b2011-11-07 10:34:54 -0800144 in = new DataInputStream(new BufferedInputStream(new FileInputStream(
145 AP_CONFIG_FILE)));
146
147 int version = in.readInt();
148 if (version != 1) {
149 Log.e(TAG, "Bad version on hotspot configuration file, set defaults");
150 setDefaultApConfiguration();
151 return;
152 }
153 config.SSID = in.readUTF();
154 int authType = in.readInt();
155 config.allowedKeyManagement.set(authType);
156 if (authType != KeyMgmt.NONE) {
157 config.preSharedKey = in.readUTF();
158 }
159 mWifiApConfig = config;
160 } catch (IOException ignore) {
161 setDefaultApConfiguration();
162 } finally {
163 if (in != null) {
164 try {
165 in.close();
166 } catch (IOException e) {}
167 }
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700168 }
169 }
Irfan Sheriff9575a1b2011-11-07 10:34:54 -0800170
171 Messenger getMessenger() {
172 return new Messenger(getHandler());
173 }
174
175 private void writeApConfiguration(final WifiConfiguration config) {
176 DataOutputStream out = null;
177 try {
178 out = new DataOutputStream(new BufferedOutputStream(
179 new FileOutputStream(AP_CONFIG_FILE)));
180
181 out.writeInt(AP_CONFIG_FILE_VERSION);
182 out.writeUTF(config.SSID);
183 int authType = config.getAuthType();
184 out.writeInt(authType);
185 if(authType != KeyMgmt.NONE) {
186 out.writeUTF(config.preSharedKey);
187 }
188 } catch (IOException e) {
189 Log.e(TAG, "Error writing hotspot configuration" + e);
190 } finally {
191 if (out != null) {
192 try {
193 out.close();
194 } catch (IOException e) {}
195 }
196 }
197 }
198
199 /* Generate a default WPA2 based configuration with a random password.
200 We are changing the Wifi Ap configuration storage from secure settings to a
201 flat file accessible only by the system. A WPA2 based default configuration
202 will keep the device secure after the update */
203 private void setDefaultApConfiguration() {
204 WifiConfiguration config = new WifiConfiguration();
205 config.SSID = mContext.getString(R.string.wifi_tether_configure_ssid_default);
206 config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
207 String randomUUID = UUID.randomUUID().toString();
208 //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
209 config.preSharedKey = randomUUID.substring(0, 8) + randomUUID.substring(9,13);
210 sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG, config);
211 }
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700212}