]> rtime.felk.cvut.cz Git - hornmich/skoda-qr-demo.git/blob - BarCodeScanner/mobile/src/main/java/cz/cvut/fel/dce/barcodescanner/wifi/WifiConfigManager.java
Initial commit
[hornmich/skoda-qr-demo.git] / BarCodeScanner / mobile / src / main / java / cz / cvut / fel / dce / barcodescanner / wifi / WifiConfigManager.java
1 /*
2  * Copyright (C) 2011 ZXing authors
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 cz.cvut.fel.dce.barcodescanner.wifi;
18
19 import android.net.wifi.WifiConfiguration;
20 import android.net.wifi.WifiManager;
21 import android.os.AsyncTask;
22 import android.util.Log;
23
24 import com.google.zxing.client.result.WifiParsedResult;
25
26 import java.util.regex.Pattern;
27
28 /**
29  * @author Vikram Aggarwal
30  * @author Sean Owen
31  */
32 public final class WifiConfigManager extends AsyncTask<WifiParsedResult,Object,Object> {
33
34   private static final String TAG = WifiConfigManager.class.getSimpleName();
35
36   private static final Pattern HEX_DIGITS = Pattern.compile("[0-9A-Fa-f]+");
37
38   private final WifiManager wifiManager;
39
40   public WifiConfigManager(WifiManager wifiManager) {
41     this.wifiManager = wifiManager;
42   }
43
44   @Override
45   protected Object doInBackground(WifiParsedResult... args) {
46     WifiParsedResult theWifiResult = args[0];
47     // Start WiFi, otherwise nothing will work
48     if (!wifiManager.isWifiEnabled()) {
49       Log.i(TAG, "Enabling wi-fi...");
50       if (wifiManager.setWifiEnabled(true)) {
51         Log.i(TAG, "Wi-fi enabled");
52       } else {
53         Log.w(TAG, "Wi-fi could not be enabled!");
54         return null;
55       }
56       // This happens very quickly, but need to wait for it to enable. A little busy wait?
57       int count = 0;
58       while (!wifiManager.isWifiEnabled()) {
59         if (count >= 10) {
60           Log.i(TAG, "Took too long to enable wi-fi, quitting");
61           return null;
62         }
63         Log.i(TAG, "Still waiting for wi-fi to enable...");
64         try {
65           Thread.sleep(1000L);
66         } catch (InterruptedException ie) {
67           // continue
68         }
69         count++;
70       }
71     }
72     String networkTypeString = theWifiResult.getNetworkEncryption();
73     NetworkType networkType;
74     try {
75       networkType = NetworkType.forIntentValue(networkTypeString);
76     } catch (IllegalArgumentException ignored) {
77       Log.w(TAG, "Bad network type; see NetworkType values: " + networkTypeString);
78       return null;
79     }
80     if (networkType == NetworkType.NO_PASSWORD) {
81       changeNetworkUnEncrypted(wifiManager, theWifiResult);
82     } else {
83       String password = theWifiResult.getPassword();
84       if (password != null && !password.isEmpty()) {
85         if (networkType == NetworkType.WEP) {
86           changeNetworkWEP(wifiManager, theWifiResult);
87         } else if (networkType == NetworkType.WPA) {
88           changeNetworkWPA(wifiManager, theWifiResult);
89         }
90       }
91     }
92     return null;
93   }
94
95   /**
96    * Update the network: either create a new network or modify an existing network
97    * @param config the new network configuration
98    */
99   private static void updateNetwork(WifiManager wifiManager, WifiConfiguration config) {
100     Integer foundNetworkID = findNetworkInExistingConfig(wifiManager, config.SSID);
101     if (foundNetworkID != null) {
102       Log.i(TAG, "Removing old configuration for network " + config.SSID);
103       wifiManager.removeNetwork(foundNetworkID);
104       wifiManager.saveConfiguration();
105     }
106     int networkId = wifiManager.addNetwork(config);
107     if (networkId >= 0) {
108       // Try to disable the current network and start a new one.
109       if (wifiManager.enableNetwork(networkId, true)) {
110         Log.i(TAG, "Associating to network " + config.SSID);
111         wifiManager.saveConfiguration();
112       } else {
113         Log.w(TAG, "Failed to enable network " + config.SSID);
114       }
115     } else {
116       Log.w(TAG, "Unable to add network " + config.SSID);
117     }
118   }
119
120   private static WifiConfiguration changeNetworkCommon(WifiParsedResult wifiResult) {
121     WifiConfiguration config = new WifiConfiguration();
122     config.allowedAuthAlgorithms.clear();
123     config.allowedGroupCiphers.clear();
124     config.allowedKeyManagement.clear();
125     config.allowedPairwiseCiphers.clear();
126     config.allowedProtocols.clear();
127     // Android API insists that an ascii SSID must be quoted to be correctly handled.
128     config.SSID = quoteNonHex(wifiResult.getSsid());
129     config.hiddenSSID = wifiResult.isHidden();
130     return config;
131   }
132
133   // Adding a WEP network
134   private static void changeNetworkWEP(WifiManager wifiManager, WifiParsedResult wifiResult) {
135     WifiConfiguration config = changeNetworkCommon(wifiResult);
136     config.wepKeys[0] = quoteNonHex(wifiResult.getPassword(), 10, 26, 58);
137     config.wepTxKeyIndex = 0;
138     config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
139     config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
140     config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
141     config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
142     config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
143     config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
144     updateNetwork(wifiManager, config);
145   }
146
147   // Adding a WPA or WPA2 network
148   private static void changeNetworkWPA(WifiManager wifiManager, WifiParsedResult wifiResult) {
149     WifiConfiguration config = changeNetworkCommon(wifiResult);
150     // Hex passwords that are 64 bits long are not to be quoted.
151     config.preSharedKey = quoteNonHex(wifiResult.getPassword(), 64);
152     config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
153     config.allowedProtocols.set(WifiConfiguration.Protocol.WPA); // For WPA
154     config.allowedProtocols.set(WifiConfiguration.Protocol.RSN); // For WPA2
155     config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
156     config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
157     config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
158     config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
159     config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
160     config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
161     updateNetwork(wifiManager, config);
162   }
163
164   // Adding an open, unsecured network
165   private static void changeNetworkUnEncrypted(WifiManager wifiManager, WifiParsedResult wifiResult) {
166     WifiConfiguration config = changeNetworkCommon(wifiResult);
167     config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
168     updateNetwork(wifiManager, config);
169   }
170
171   private static Integer findNetworkInExistingConfig(WifiManager wifiManager, String ssid) {
172     Iterable<WifiConfiguration> existingConfigs = wifiManager.getConfiguredNetworks();
173     for (WifiConfiguration existingConfig : existingConfigs) {
174       String existingSSID = existingConfig.SSID;
175       if (existingSSID != null && existingSSID.equals(ssid)) {
176         return existingConfig.networkId;
177       }
178     }
179     return null;
180   }
181
182   private static String quoteNonHex(String value, int... allowedLengths) {
183     return isHexOfLength(value, allowedLengths) ? value : convertToQuotedString(value);
184   }
185
186   /**
187    * Encloses the incoming string inside double quotes, if it isn't already quoted.
188    * @param s the input string
189    * @return a quoted string, of the form "input".  If the input string is null, it returns null
190    * as well.
191    */
192   private static String convertToQuotedString(String s) {
193     if (s == null || s.isEmpty()) {
194       return null;
195     }
196     // If already quoted, return as-is
197     if (s.charAt(0) == '"' && s.charAt(s.length() - 1) == '"') {
198       return s;
199     }
200     return '\"' + s + '\"';
201   }
202
203   /**
204    * @param value input to check
205    * @param allowedLengths allowed lengths, if any
206    * @return true if value is a non-null, non-empty string of hex digits, and if allowed lengths are given, has
207    *  an allowed length
208    */
209   private static boolean isHexOfLength(CharSequence value, int... allowedLengths) {
210     if (value == null || !HEX_DIGITS.matcher(value).matches()) {
211       return false;
212     }
213     if (allowedLengths.length == 0) {
214       return true;
215     }
216     for (int length : allowedLengths) {
217       if (value.length() == length) {
218         return true;
219       }
220     }
221     return false;
222   }
223
224 }