Move softap config to flat file and read/write on a seperate handler thread Bug: 4391796 Change-Id: Iafe43200d7f829df7ced20a4e7b0ed451ad22a05
182 lines
6.4 KiB
Java
182 lines
6.4 KiB
Java
/*
|
|
* Copyright (C) 2010 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package android.net.wifi;
|
|
|
|
import android.content.Context;
|
|
import android.net.wifi.WifiConfiguration.KeyMgmt;
|
|
import android.os.Environment;
|
|
import android.os.Message;
|
|
import android.os.Handler;
|
|
import android.os.HandlerThread;
|
|
import android.util.Log;
|
|
|
|
import java.io.BufferedInputStream;
|
|
import java.io.BufferedOutputStream;
|
|
import java.io.DataInputStream;
|
|
import java.io.DataOutputStream;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.net.InetAddress;
|
|
import java.util.UUID;
|
|
|
|
import com.android.internal.R;
|
|
|
|
|
|
/**
|
|
* Provides API to the WifiStateMachine for doing read/write access
|
|
* to soft access point configuration
|
|
*/
|
|
class WifiApConfigStore {
|
|
|
|
private static Context sContext;
|
|
private static final String TAG = "WifiApConfigStore";
|
|
|
|
private static final String AP_CONFIG_FILE = Environment.getDataDirectory() +
|
|
"/misc/wifi/softap.conf";
|
|
|
|
private static final int AP_CONFIG_FILE_VERSION = 1;
|
|
|
|
private static WifiConfiguration sApConfig = new WifiConfiguration();
|
|
private static final Object sApConfigLock = new Object();
|
|
|
|
private static FileReadWriteHandler sFileReadWriteHandler;
|
|
private static final int READ_AP_CONFIG = 1;
|
|
private static final int WRITE_AP_CONFIG = 2;
|
|
|
|
static void initialize(Context context) {
|
|
sContext = context;
|
|
|
|
/* File operations happen on a seperate thread */
|
|
HandlerThread configThread = new HandlerThread("WifiApConfigStore");
|
|
configThread.start();
|
|
sFileReadWriteHandler = new FileReadWriteHandler(configThread.getLooper());
|
|
Message.obtain(sFileReadWriteHandler, READ_AP_CONFIG).sendToTarget();
|
|
}
|
|
|
|
|
|
static void setApConfiguration(WifiConfiguration config) {
|
|
synchronized (sApConfigLock) {
|
|
sApConfig = config;
|
|
}
|
|
Message.obtain(sFileReadWriteHandler, WRITE_AP_CONFIG, new WifiConfiguration(config))
|
|
.sendToTarget();
|
|
}
|
|
|
|
static WifiConfiguration getApConfiguration() {
|
|
synchronized (sApConfigLock) {
|
|
return new WifiConfiguration(sApConfig);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* File read/write handler
|
|
*/
|
|
private static class FileReadWriteHandler extends Handler {
|
|
|
|
public FileReadWriteHandler(android.os.Looper looper) {
|
|
super(looper);
|
|
}
|
|
|
|
@Override
|
|
public void handleMessage(Message msg) {
|
|
switch (msg.what) {
|
|
case WRITE_AP_CONFIG:
|
|
writeApConfiguration((WifiConfiguration) msg.obj);
|
|
break;
|
|
case READ_AP_CONFIG:
|
|
readApConfiguration();
|
|
break;
|
|
default:
|
|
Log.e(TAG, "Unknown command in FileReadWriteHandler: " + msg);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private static void writeApConfiguration(final WifiConfiguration config) {
|
|
DataOutputStream out = null;
|
|
try {
|
|
out = new DataOutputStream(new BufferedOutputStream(
|
|
new FileOutputStream(AP_CONFIG_FILE)));
|
|
|
|
out.writeInt(AP_CONFIG_FILE_VERSION);
|
|
out.writeUTF(config.SSID);
|
|
int authType = config.getAuthType();
|
|
out.writeInt(authType);
|
|
if(authType != KeyMgmt.NONE) {
|
|
out.writeUTF(config.preSharedKey);
|
|
}
|
|
} catch (IOException e) {
|
|
Log.e(TAG, "Error writing hotspot configuration" + e);
|
|
} finally {
|
|
if (out != null) {
|
|
try {
|
|
out.close();
|
|
} catch (IOException e) {}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void readApConfiguration() {
|
|
DataInputStream in = null;
|
|
try {
|
|
WifiConfiguration config = new WifiConfiguration();
|
|
in = new DataInputStream(new BufferedInputStream(new FileInputStream(
|
|
AP_CONFIG_FILE)));
|
|
|
|
int version = in.readInt();
|
|
if (version != 1) {
|
|
Log.e(TAG, "Bad version on hotspot configuration file, set defaults");
|
|
setDefaultApConfiguration();
|
|
return;
|
|
}
|
|
config.SSID = in.readUTF();
|
|
int authType = in.readInt();
|
|
config.allowedKeyManagement.set(authType);
|
|
if (authType != KeyMgmt.NONE) {
|
|
config.preSharedKey = in.readUTF();
|
|
}
|
|
synchronized (sApConfigLock) {
|
|
sApConfig = config;
|
|
}
|
|
} catch (IOException ignore) {
|
|
setDefaultApConfiguration();
|
|
} finally {
|
|
if (in != null) {
|
|
try {
|
|
in.close();
|
|
} catch (IOException e) {}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Generate a default WPA2 based configuration with a random password.
|
|
We are changing the Wifi Ap configuration storage from secure settings to a
|
|
flat file accessible only by the system. A WPA2 based default configuration
|
|
will keep the device secure after the update */
|
|
private static void setDefaultApConfiguration() {
|
|
WifiConfiguration config = new WifiConfiguration();
|
|
config.SSID = sContext.getString(R.string.wifi_tether_configure_ssid_default);
|
|
config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
|
|
String randomUUID = UUID.randomUUID().toString();
|
|
//first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
|
|
config.preSharedKey = randomUUID.substring(0, 8) + randomUUID.substring(9,13);
|
|
setApConfiguration(config);
|
|
}
|
|
}
|
|
}
|