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