Home | History | Annotate | Download | only in wifi
      1 /*
      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 
     17 package com.android.server.wifi;
     18 
     19 import android.content.Context;
     20 import android.net.wifi.WifiConfiguration;
     21 import android.net.wifi.WifiConfiguration.KeyMgmt;
     22 import android.os.Environment;
     23 import android.util.Log;
     24 
     25 import com.android.internal.R;
     26 
     27 import java.io.BufferedInputStream;
     28 import java.io.BufferedOutputStream;
     29 import java.io.DataInputStream;
     30 import java.io.DataOutputStream;
     31 import java.io.FileInputStream;
     32 import java.io.FileOutputStream;
     33 import java.io.IOException;
     34 import java.util.ArrayList;
     35 import java.util.UUID;
     36 
     37 /**
     38  * Provides API for reading/writing soft access point configuration.
     39  */
     40 public class WifiApConfigStore {
     41 
     42     private static final String TAG = "WifiApConfigStore";
     43 
     44     private static final String DEFAULT_AP_CONFIG_FILE =
     45             Environment.getDataDirectory() + "/misc/wifi/softap.conf";
     46 
     47     private static final int AP_CONFIG_FILE_VERSION = 2;
     48 
     49     private WifiConfiguration mWifiApConfig = null;
     50 
     51     private ArrayList<Integer> mAllowed2GChannel = null;
     52 
     53     private final Context mContext;
     54     private final String mApConfigFile;
     55     private final BackupManagerProxy mBackupManagerProxy;
     56 
     57     WifiApConfigStore(Context context, BackupManagerProxy backupManagerProxy) {
     58         this(context, backupManagerProxy, DEFAULT_AP_CONFIG_FILE);
     59     }
     60 
     61     WifiApConfigStore(Context context,
     62                       BackupManagerProxy backupManagerProxy,
     63                       String apConfigFile) {
     64         mContext = context;
     65         mBackupManagerProxy = backupManagerProxy;
     66         mApConfigFile = apConfigFile;
     67 
     68         String ap2GChannelListStr = mContext.getResources().getString(
     69                 R.string.config_wifi_framework_sap_2G_channel_list);
     70         Log.d(TAG, "2G band allowed channels are:" + ap2GChannelListStr);
     71 
     72         if (ap2GChannelListStr != null) {
     73             mAllowed2GChannel = new ArrayList<Integer>();
     74             String channelList[] = ap2GChannelListStr.split(",");
     75             for (String tmp : channelList) {
     76                 mAllowed2GChannel.add(Integer.parseInt(tmp));
     77             }
     78         }
     79 
     80         /* Load AP configuration from persistent storage. */
     81         mWifiApConfig = loadApConfiguration(mApConfigFile);
     82         if (mWifiApConfig == null) {
     83             /* Use default configuration. */
     84             Log.d(TAG, "Fallback to use default AP configuration");
     85             mWifiApConfig = getDefaultApConfiguration();
     86 
     87             /* Save the default configuration to persistent storage. */
     88             writeApConfiguration(mApConfigFile, mWifiApConfig);
     89         }
     90     }
     91 
     92     /**
     93      * Return the current soft access point configuration.
     94      */
     95     public synchronized WifiConfiguration getApConfiguration() {
     96         return mWifiApConfig;
     97     }
     98 
     99     /**
    100      * Update the current soft access point configuration.
    101      * Restore to default AP configuration if null is provided.
    102      * This can be invoked under context of binder threads (WifiManager.setWifiApConfiguration)
    103      * and WifiStateMachine thread (CMD_START_AP).
    104      */
    105     public synchronized void setApConfiguration(WifiConfiguration config) {
    106         if (config == null) {
    107             mWifiApConfig = getDefaultApConfiguration();
    108         } else {
    109             mWifiApConfig = config;
    110         }
    111         writeApConfiguration(mApConfigFile, mWifiApConfig);
    112 
    113         // Stage the backup of the SettingsProvider package which backs this up
    114         mBackupManagerProxy.notifyDataChanged();
    115     }
    116 
    117     public ArrayList<Integer> getAllowed2GChannel() {
    118         return mAllowed2GChannel;
    119     }
    120 
    121     /**
    122      * Load AP configuration from persistent storage.
    123      */
    124     private static WifiConfiguration loadApConfiguration(final String filename) {
    125         WifiConfiguration config = null;
    126         DataInputStream in = null;
    127         try {
    128             config = new WifiConfiguration();
    129             in = new DataInputStream(
    130                     new BufferedInputStream(new FileInputStream(filename)));
    131 
    132             int version = in.readInt();
    133             if ((version != 1) && (version != 2)) {
    134                 Log.e(TAG, "Bad version on hotspot configuration file");
    135                 return null;
    136             }
    137             config.SSID = in.readUTF();
    138 
    139             if (version >= 2) {
    140                 config.apBand = in.readInt();
    141                 config.apChannel = in.readInt();
    142             }
    143 
    144             int authType = in.readInt();
    145             config.allowedKeyManagement.set(authType);
    146             if (authType != KeyMgmt.NONE) {
    147                 config.preSharedKey = in.readUTF();
    148             }
    149         } catch (IOException e) {
    150             Log.e(TAG, "Error reading hotspot configuration " + e);
    151             config = null;
    152         } finally {
    153             if (in != null) {
    154                 try {
    155                     in.close();
    156                 } catch (IOException e) {
    157                     Log.e(TAG, "Error closing hotspot configuration during read" + e);
    158                 }
    159             }
    160         }
    161         return config;
    162     }
    163 
    164     /**
    165      * Write AP configuration to persistent storage.
    166      */
    167     private static void writeApConfiguration(final String filename,
    168                                              final WifiConfiguration config) {
    169         try (DataOutputStream out = new DataOutputStream(new BufferedOutputStream(
    170                         new FileOutputStream(filename)))) {
    171             out.writeInt(AP_CONFIG_FILE_VERSION);
    172             out.writeUTF(config.SSID);
    173             out.writeInt(config.apBand);
    174             out.writeInt(config.apChannel);
    175             int authType = config.getAuthType();
    176             out.writeInt(authType);
    177             if (authType != KeyMgmt.NONE) {
    178                 out.writeUTF(config.preSharedKey);
    179             }
    180         } catch (IOException e) {
    181             Log.e(TAG, "Error writing hotspot configuration" + e);
    182         }
    183     }
    184 
    185     /**
    186      * Generate a default WPA2 based configuration with a random password.
    187      * We are changing the Wifi Ap configuration storage from secure settings to a
    188      * flat file accessible only by the system. A WPA2 based default configuration
    189      * will keep the device secure after the update.
    190      */
    191     private WifiConfiguration getDefaultApConfiguration() {
    192         WifiConfiguration config = new WifiConfiguration();
    193         config.SSID = mContext.getResources().getString(
    194                 R.string.wifi_tether_configure_ssid_default);
    195         config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
    196         String randomUUID = UUID.randomUUID().toString();
    197         //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
    198         config.preSharedKey = randomUUID.substring(0, 8) + randomUUID.substring(9, 13);
    199         return config;
    200     }
    201 }
    202