1 /* 2 * Copyright (C) 2015 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.compatibility.common.util; 18 19 import android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.IntentFilter; 23 import android.net.wifi.WifiConfiguration; 24 import android.net.wifi.WifiManager; 25 import android.text.TextUtils; 26 import android.util.Log; 27 28 import java.util.concurrent.CountDownLatch; 29 import java.util.concurrent.TimeUnit; 30 import java.util.List; 31 32 import static android.net.wifi.WifiManager.EXTRA_WIFI_STATE; 33 import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; 34 35 /** 36 * A simple activity to create and manage wifi configurations. 37 */ 38 public class WifiConfigCreator { 39 public static final String ACTION_CREATE_WIFI_CONFIG = 40 "com.android.compatibility.common.util.CREATE_WIFI_CONFIG"; 41 public static final String ACTION_UPDATE_WIFI_CONFIG = 42 "com.android.compatibility.common.util.UPDATE_WIFI_CONFIG"; 43 public static final String ACTION_REMOVE_WIFI_CONFIG = 44 "com.android.compatibility.common.util.REMOVE_WIFI_CONFIG"; 45 public static final String EXTRA_NETID = "extra-netid"; 46 public static final String EXTRA_SSID = "extra-ssid"; 47 public static final String EXTRA_SECURITY_TYPE = "extra-security-type"; 48 public static final String EXTRA_PASSWORD = "extra-password"; 49 50 public static final int SECURITY_TYPE_NONE = 1; 51 public static final int SECURITY_TYPE_WPA = 2; 52 public static final int SECURITY_TYPE_WEP = 3; 53 54 private static final String TAG = "WifiConfigCreator"; 55 56 private static final long ENABLE_WIFI_WAIT_SEC = 10L; 57 58 private final Context mContext; 59 private final WifiManager mWifiManager; 60 WifiConfigCreator(Context context)61 public WifiConfigCreator(Context context) { 62 mContext = context; 63 mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 64 } 65 66 /** 67 * Adds a new WiFi network. 68 * @return network id or -1 in case of error 69 */ addNetwork(String ssid, boolean hidden, int securityType, String password)70 public int addNetwork(String ssid, boolean hidden, int securityType, 71 String password) throws InterruptedException, SecurityException { 72 checkAndEnableWifi(); 73 74 WifiConfiguration wifiConf = createConfig(ssid, hidden, securityType, password); 75 76 int netId = mWifiManager.addNetwork(wifiConf); 77 78 if (netId != -1) { 79 mWifiManager.enableNetwork(netId, true); 80 } else { 81 Log.w(TAG, "Unable to add SSID '" + ssid + "': netId = " + netId); 82 } 83 return netId; 84 } 85 86 /** 87 * Updates a new WiFi network. 88 * @return network id (may differ from original) or -1 in case of error 89 */ updateNetwork(WifiConfiguration wifiConf, String ssid, boolean hidden, int securityType, String password)90 public int updateNetwork(WifiConfiguration wifiConf, String ssid, boolean hidden, 91 int securityType, String password) throws InterruptedException, SecurityException { 92 checkAndEnableWifi(); 93 if (wifiConf == null) { 94 return -1; 95 } 96 97 WifiConfiguration conf = createConfig(ssid, hidden, securityType, password); 98 conf.networkId = wifiConf.networkId; 99 100 int newNetId = mWifiManager.updateNetwork(conf); 101 102 if (newNetId != -1) { 103 mWifiManager.saveConfiguration(); 104 mWifiManager.enableNetwork(newNetId, true); 105 } else { 106 Log.w(TAG, "Unable to update SSID '" + ssid + "': netId = " + newNetId); 107 } 108 return newNetId; 109 } 110 111 /** 112 * Updates a new WiFi network. 113 * @return network id (may differ from original) or -1 in case of error 114 */ updateNetwork(int netId, String ssid, boolean hidden, int securityType, String password)115 public int updateNetwork(int netId, String ssid, boolean hidden, 116 int securityType, String password) throws InterruptedException, SecurityException { 117 checkAndEnableWifi(); 118 119 WifiConfiguration wifiConf = null; 120 List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks(); 121 for (WifiConfiguration config : configs) { 122 if (config.networkId == netId) { 123 wifiConf = config; 124 break; 125 } 126 } 127 return updateNetwork(wifiConf, ssid, hidden, securityType, password); 128 } 129 removeNetwork(int netId)130 public boolean removeNetwork(int netId) { 131 return mWifiManager.removeNetwork(netId); 132 } 133 134 /** 135 * Creates a WifiConfiguration set up according to given parameters 136 * @param ssid SSID of the network 137 * @param hidden Is SSID not broadcast? 138 * @param securityType One of {@link #SECURITY_TYPE_NONE}, {@link #SECURITY_TYPE_WPA} or 139 * {@link #SECURITY_TYPE_WEP} 140 * @param password Password for WPA or WEP 141 * @return Created configuration object 142 */ createConfig(String ssid, boolean hidden, int securityType, String password)143 private WifiConfiguration createConfig(String ssid, boolean hidden, int securityType, 144 String password) { 145 WifiConfiguration wifiConf = new WifiConfiguration(); 146 if (!TextUtils.isEmpty(ssid)) { 147 wifiConf.SSID = '"' + ssid + '"'; 148 } 149 wifiConf.status = WifiConfiguration.Status.ENABLED; 150 wifiConf.hiddenSSID = hidden; 151 switch (securityType) { 152 case SECURITY_TYPE_NONE: 153 wifiConf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 154 break; 155 case SECURITY_TYPE_WPA: 156 updateForWPAConfiguration(wifiConf, password); 157 break; 158 case SECURITY_TYPE_WEP: 159 updateForWEPConfiguration(wifiConf, password); 160 break; 161 } 162 return wifiConf; 163 } 164 updateForWPAConfiguration(WifiConfiguration wifiConf, String wifiPassword)165 private void updateForWPAConfiguration(WifiConfiguration wifiConf, String wifiPassword) { 166 wifiConf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); 167 if (!TextUtils.isEmpty(wifiPassword)) { 168 wifiConf.preSharedKey = '"' + wifiPassword + '"'; 169 } 170 } 171 updateForWEPConfiguration(WifiConfiguration wifiConf, String password)172 private void updateForWEPConfiguration(WifiConfiguration wifiConf, String password) { 173 wifiConf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 174 wifiConf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); 175 wifiConf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED); 176 if (!TextUtils.isEmpty(password)) { 177 int length = password.length(); 178 if ((length == 10 || length == 26 179 || length == 58) && password.matches("[0-9A-Fa-f]*")) { 180 wifiConf.wepKeys[0] = password; 181 } else { 182 wifiConf.wepKeys[0] = '"' + password + '"'; 183 } 184 wifiConf.wepTxKeyIndex = 0; 185 } 186 } 187 checkAndEnableWifi()188 private void checkAndEnableWifi() throws InterruptedException { 189 final CountDownLatch enabledLatch = new CountDownLatch(1); 190 191 // Register a change receiver first to pick up events between isEnabled and setEnabled 192 final BroadcastReceiver watcher = new BroadcastReceiver() { 193 @Override 194 public void onReceive(Context context, Intent intent) { 195 if (intent.getIntExtra(EXTRA_WIFI_STATE, -1) == WIFI_STATE_ENABLED) { 196 enabledLatch.countDown(); 197 } 198 } 199 }; 200 201 mContext.registerReceiver(watcher, new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION)); 202 try { 203 // In case wifi is not already enabled, wait for it to come up 204 if (!mWifiManager.isWifiEnabled()) { 205 mWifiManager.setWifiEnabled(true); 206 enabledLatch.await(ENABLE_WIFI_WAIT_SEC, TimeUnit.SECONDS); 207 } 208 } finally { 209 mContext.unregisterReceiver(watcher); 210 } 211 } 212 } 213 214