• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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.tv.settings.connectivity;
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.ConnectivityManager;
24 import android.net.EthernetManager;
25 import android.net.IpConfiguration;
26 import android.net.LinkAddress;
27 import android.net.LinkProperties;
28 import android.net.NetworkInfo;
29 import android.net.wifi.ScanResult;
30 import android.net.wifi.WifiConfiguration;
31 import android.net.wifi.WifiConfiguration.KeyMgmt;
32 import android.net.wifi.WifiInfo;
33 import android.net.wifi.WifiManager;
34 import android.text.TextUtils;
35 import android.util.Log;
36 import android.util.Pair;
37 
38 import java.net.Inet4Address;
39 import java.net.InetAddress;
40 import java.util.ArrayList;
41 import java.util.Collections;
42 import java.util.HashMap;
43 import java.util.List;
44 
45 /**
46  * Listens for changes to the current connectivity status.
47  */
48 public class ConnectivityListener {
49 
50     public interface Listener {
onConnectivityChange(Intent intent)51         void onConnectivityChange(Intent intent);
52     }
53 
54     public interface WifiNetworkListener {
onWifiListChanged()55         void onWifiListChanged();
56     }
57 
58     private static final String TAG = "ConnectivityListener";
59     private static final boolean DEBUG = false;
60 
61     private final Context mContext;
62     private final Listener mListener;
63     private final IntentFilter mFilter;
64     private final BroadcastReceiver mReceiver;
65     private boolean mStarted;
66 
67     private final ConnectivityManager mConnectivityManager;
68     private final WifiManager mWifiManager;
69     private final EthernetManager mEthernetManager;
70     private WifiNetworkListener mWifiListener;
71     private final BroadcastReceiver mWifiListReceiver = new BroadcastReceiver() {
72         @Override
73         public void onReceive(Context context, Intent intent) {
74             if (mWifiListener != null) {
75                 mWifiListener.onWifiListChanged();
76                 mWifiListener = null;
77             }
78         }
79     };
80     private final BroadcastReceiver mWifiEnabledReceiver = new BroadcastReceiver() {
81         @Override
82         public void onReceive(Context context, Intent intent) {
83             mListener.onConnectivityChange(intent);
84         }
85     };
86     private final EthernetManager.Listener mEthernetListener = new EthernetManager.Listener() {
87         @Override
88         public void onAvailabilityChanged(boolean isAvailable) {
89             mListener.onConnectivityChange(null);
90         }
91     };
92 
93     public static class ConnectivityStatus {
94         public static final int NETWORK_NONE = 1;
95         public static final int NETWORK_WIFI_OPEN = 3;
96         public static final int NETWORK_WIFI_SECURE = 5;
97         public static final int NETWORK_ETHERNET = 7;
98 
99         public int mNetworkType;
100         public String mWifiSsid;
101         public int mWifiSignalStrength;
102 
isEthernetConnected()103         boolean isEthernetConnected() { return mNetworkType == NETWORK_ETHERNET; }
isWifiConnected()104         boolean isWifiConnected() {
105             return mNetworkType == NETWORK_WIFI_OPEN ||  mNetworkType == NETWORK_WIFI_SECURE;
106         }
107 
108         @Override
toString()109         public String toString() {
110             return new StringBuilder()
111                 .append("mNetworkType ").append(mNetworkType)
112                 .append("  miWifiSsid ").append(mWifiSsid)
113                 .append("  mWifiSignalStrength ").append(mWifiSignalStrength)
114                 .toString();
115         }
116     }
117 
118     private final ConnectivityStatus mConnectivityStatus = new ConnectivityStatus();
119 
ConnectivityListener(Context context, Listener listener)120     public ConnectivityListener(Context context, Listener listener) {
121         mContext = context;
122         mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
123                 Context.CONNECTIVITY_SERVICE);
124         mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
125         mEthernetManager = (EthernetManager) mContext.getSystemService(Context.ETHERNET_SERVICE);
126         mListener = listener;
127         mFilter = new IntentFilter();
128         mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
129         mFilter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
130         mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
131         mReceiver = new BroadcastReceiver() {
132             @Override
133             public void onReceive(Context context, Intent intent) {
134                 if (DEBUG) {
135                     Log.d(TAG, "Connectivity change!");
136                 }
137                 if (updateConnectivityStatus()) {
138                     mListener.onConnectivityChange(intent);
139                 }
140             }
141         };
142     }
143 
144     /**
145      * Starts {@link ConnectivityListener}.
146      * This should be called only from main thread.
147      */
start()148     public void start() {
149         if (!mStarted) {
150             mStarted = true;
151             updateConnectivityStatus();
152             mContext.registerReceiver(mReceiver, mFilter);
153             mContext.registerReceiver(mWifiListReceiver, new IntentFilter(
154                     WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
155             mContext.registerReceiver(mWifiEnabledReceiver, new IntentFilter(
156                     WifiManager.WIFI_STATE_CHANGED_ACTION));
157             mEthernetManager.addListener(mEthernetListener);
158         }
159     }
160 
161     /**
162      * Stops {@link ConnectivityListener}.
163      * This should be called only from main thread.
164      */
stop()165     public void stop() {
166         if (mStarted) {
167             mStarted = false;
168             mContext.unregisterReceiver(mReceiver);
169             mContext.unregisterReceiver(mWifiListReceiver);
170             mContext.unregisterReceiver(mWifiEnabledReceiver);
171             mWifiListener = null;
172             mEthernetManager.removeListener(mEthernetListener);
173         }
174     }
175 
176     /**
177      * Listener is notified when results are available via onWifiListChanged.
178      * Listener should call {@link getAvailableNetworks} to retrieve results.
179      */
scanWifiAccessPoints(WifiNetworkListener callbackListener)180     public void scanWifiAccessPoints(WifiNetworkListener callbackListener) {
181         if (DEBUG) Log.d(TAG, "scanning for wifi access points");
182         mWifiListener = callbackListener;
183         mWifiManager.startScan();
184     }
185 
getConnectivityStatus()186     public ConnectivityStatus getConnectivityStatus() {
187         return mConnectivityStatus;
188     }
189 
getWifiIpAddress()190     public String getWifiIpAddress() {
191         if (mConnectivityStatus.isWifiConnected()) {
192             WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
193             int ip = wifiInfo.getIpAddress();
194             return String.format("%d.%d.%d.%d", (ip & 0xff), (ip >> 8 & 0xff),
195                     (ip >> 16 & 0xff), (ip >> 24 & 0xff));
196         } else {
197             return "";
198         }
199     }
200 
201     /**
202      * Return the MAC address of the currently connected Wifi AP.
203      */
getWifiMacAddress()204     public String getWifiMacAddress() {
205         if (mConnectivityStatus.isWifiConnected()) {
206             WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
207             return wifiInfo.getMacAddress();
208         } else {
209             return "";
210         }
211     }
212 
213     /**
214      * Return whether Ethernet port is available.
215      */
isEthernetAvailable()216     public boolean isEthernetAvailable() {
217         if (mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_ETHERNET)) {
218             return mEthernetManager.isAvailable();
219         }
220 
221         return false;
222     }
223 
getEthernetMacAddress()224     public String getEthernetMacAddress() {
225         NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
226         if (networkInfo == null ||networkInfo.getType() != ConnectivityManager.TYPE_ETHERNET) {
227             return "";
228         } else {
229             return networkInfo.getExtraInfo();
230         }
231     }
232 
getEthernetIpAddress()233     public String getEthernetIpAddress() {
234         LinkProperties linkProperties =
235                 mConnectivityManager.getLinkProperties(ConnectivityManager.TYPE_ETHERNET);
236 
237         for (LinkAddress linkAddress: linkProperties.getAllLinkAddresses()) {
238             InetAddress address = linkAddress.getAddress();
239             if (address instanceof Inet4Address) {
240                 return address.getHostAddress();
241             }
242         }
243 
244         // IPv6 address will not be shown like WifiInfo internally does.
245         return "";
246     }
247 
getWifiSignalStrength(int maxLevel)248     public int getWifiSignalStrength(int maxLevel) {
249         WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
250         return WifiManager.calculateSignalLevel(wifiInfo.getRssi(), maxLevel);
251     }
252 
forgetWifiNetwork()253     public void forgetWifiNetwork() {
254         int networkId = getWifiNetworkId();
255         if (networkId != -1) {
256             mWifiManager.forget(networkId, null);
257         }
258     }
259 
getWifiNetworkId()260     public int getWifiNetworkId() {
261         WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
262         if (wifiInfo != null) {
263             return wifiInfo.getNetworkId();
264         } else {
265             return -1;
266         }
267     }
268 
getWifiConfiguration()269     public WifiConfiguration getWifiConfiguration() {
270         WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
271         if (wifiInfo != null) {
272             int networkId = wifiInfo.getNetworkId();
273             List<WifiConfiguration> configuredNetworks = mWifiManager.getConfiguredNetworks();
274             if (configuredNetworks != null) {
275                 for (WifiConfiguration configuredNetwork : configuredNetworks) {
276                     if (configuredNetwork.networkId == networkId) {
277                         return configuredNetwork;
278                     }
279                 }
280             }
281         }
282         return null;
283     }
284 
285     /**
286      * Return a list of wifi networks. Ensure that if a wifi network is connected that it appears
287      * as the first item on the list.
288      */
getAvailableNetworks()289     public List<ScanResult> getAvailableNetworks() {
290         if (DEBUG) Log.d(TAG, "getAvailableNetworks");
291         WifiInfo connectedWifiInfo = mWifiManager.getConnectionInfo();
292         String currentConnectedSSID = connectedWifiInfo == null ? "" : connectedWifiInfo.getSSID();
293         currentConnectedSSID = WifiInfo.removeDoubleQuotes(currentConnectedSSID);
294         WifiSecurity currentConnectedSecurity = WifiConfigHelper.getCurrentConnectionSecurity(
295                 mWifiManager, connectedWifiInfo);
296 
297         // TODO : Refactor with similar code in SelectFromListWizard
298         final List<ScanResult> results = mWifiManager.getScanResults();
299 
300         if (results.size() == 0) {
301             Log.w(TAG, "No results found! Initiate scan...");
302             mWifiManager.startScan();
303         }
304 
305         final HashMap<Pair<String, WifiSecurity>, ScanResult> consolidatedScanResults =
306                 new HashMap<Pair<String, WifiSecurity>, ScanResult>();
307         HashMap<Pair<String, WifiSecurity>, Boolean> specialNetworks = new HashMap<
308                 Pair<String, WifiSecurity>, Boolean>();
309         for (ScanResult result : results) {
310             if (TextUtils.isEmpty(result.SSID)) {
311                 continue;
312             }
313 
314             Pair<String, WifiSecurity> key = Pair.create(
315                     result.SSID, WifiSecurity.getSecurity(result));
316             ScanResult existing = consolidatedScanResults.get(key);
317 
318             if (WifiConfigHelper.areSameNetwork(mWifiManager, result, connectedWifiInfo)) {
319                 // The currently connected network should always be included.
320                 consolidatedScanResults.put(key, result);
321                 specialNetworks.put(key, true);
322             } else {
323                 if (existing == null ||
324                         (!specialNetworks.containsKey(key) && existing.level < result.level)) {
325                     consolidatedScanResults.put(key, result);
326                 }
327             }
328         }
329 
330         ArrayList<ScanResult> networkList = new ArrayList<ScanResult>(
331                 consolidatedScanResults.size());
332         networkList.addAll(consolidatedScanResults.values());
333         ScanResultComparator comparator = connectedWifiInfo == null ? new ScanResultComparator() :
334                 new ScanResultComparator(currentConnectedSSID, currentConnectedSecurity);
335         Collections.sort(networkList, comparator);
336         return networkList;
337     }
338 
getIpConfiguration()339     public IpConfiguration getIpConfiguration() {
340         return mEthernetManager.getConfiguration();
341     }
342 
isSecureWifi(WifiInfo wifiInfo)343     private boolean isSecureWifi(WifiInfo wifiInfo) {
344         if (wifiInfo == null)
345             return false;
346         int networkId = wifiInfo.getNetworkId();
347         List<WifiConfiguration> configuredNetworks = mWifiManager.getConfiguredNetworks();
348         if (configuredNetworks != null) {
349             for (WifiConfiguration configuredNetwork : configuredNetworks) {
350                 if (configuredNetwork.networkId == networkId) {
351                     return configuredNetwork.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ||
352                         configuredNetwork.allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
353                         configuredNetwork.allowedKeyManagement.get(KeyMgmt.IEEE8021X);
354                 }
355             }
356         }
357         return false;
358     }
359 
isWifiEnabled()360     public boolean isWifiEnabled() {
361         return mWifiManager.isWifiEnabled();
362     }
363 
setWifiEnabled(boolean enable)364     public void setWifiEnabled(boolean enable) {
365         mWifiManager.setWifiEnabled(enable);
366     }
367 
setNetworkType(int networkType)368     private boolean setNetworkType(int networkType) {
369         boolean hasChanged = mConnectivityStatus.mNetworkType != networkType;
370         mConnectivityStatus.mNetworkType = networkType;
371         return hasChanged;
372     }
373 
updateConnectivityStatus()374     private boolean updateConnectivityStatus() {
375         NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
376         if (networkInfo == null) {
377             return setNetworkType(ConnectivityStatus.NETWORK_NONE);
378         } else {
379             switch (networkInfo.getType()) {
380                 case ConnectivityManager.TYPE_WIFI: {
381                     boolean hasChanged;
382 
383                     // Determine if this is an open or secure wifi connection.
384                     WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
385                     if (isSecureWifi(wifiInfo)) {
386                         hasChanged = setNetworkType(ConnectivityStatus.NETWORK_WIFI_SECURE);
387                     } else {
388                         hasChanged = setNetworkType(ConnectivityStatus.NETWORK_WIFI_OPEN);
389                     }
390 
391                     // Find the SSID of network.
392                     String ssid = null;
393                     if (wifiInfo != null) {
394                         ssid = wifiInfo.getSSID();
395                         if (ssid != null) {
396                             ssid = WifiInfo.removeDoubleQuotes(ssid);
397                         }
398                     }
399                     if (!TextUtils.equals(mConnectivityStatus.mWifiSsid, ssid)) {
400                         hasChanged = true;
401                         mConnectivityStatus.mWifiSsid = ssid;
402                     }
403 
404                     // Calculate the signal strength.
405                     int signalStrength;
406                     if (wifiInfo != null) {
407                         // Calculate the signal strength between 0 and 3.
408                         signalStrength = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), 4);
409                     } else {
410                         signalStrength = 0;
411                     }
412                     if (mConnectivityStatus.mWifiSignalStrength != signalStrength) {
413                         hasChanged = true;
414                         mConnectivityStatus.mWifiSignalStrength = signalStrength;
415                     }
416                     return hasChanged;
417                 }
418 
419                 case ConnectivityManager.TYPE_ETHERNET:
420                     return setNetworkType(ConnectivityStatus.NETWORK_ETHERNET);
421 
422                 default:
423                     return setNetworkType(ConnectivityStatus.NETWORK_NONE);
424             }
425         }
426     }
427 }
428