blob: af72d202b4f9416ef607324e71ab6c7bf95014e5 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tv.settings.connectivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.EthernetManager;
import android.net.IpConfiguration;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
/**
* Listens for changes to the current connectivity status.
*/
public class ConnectivityListener {
public interface Listener {
void onConnectivityChange(Intent intent);
}
public interface WifiNetworkListener {
void onWifiListChanged();
}
private static final String TAG = "ConnectivityListener";
private static final boolean DEBUG = false;
class WifiReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
for (WifiNetworkListener listener : mWifiNetworkListeners) {
listener.onWifiListChanged();
}
}
}
private final Context mContext;
private final Listener mListener;
private final IntentFilter mFilter;
private final BroadcastReceiver mReceiver;
private boolean mIsRegistered;
private final ConnectivityManager mConnectivityManager;
private final WifiManager mWifiManager;
private WifiReceiver mWifiReceiver;
private final EthernetManager mEthernetManager;
private final ArrayList<WifiNetworkListener> mWifiNetworkListeners =
new ArrayList<WifiNetworkListener>();
public static class ConnectivityStatus {
public static final int NETWORK_NONE = 1;
public static final int NETWORK_WIFI_OPEN = 3;
public static final int NETWORK_WIFI_SECURE = 5;
public static final int NETWORK_ETHERNET = 7;
public int mNetworkType;
public String mWifiSsid;
public int mWifiSignalStrength;
boolean isEthernetConnected() { return mNetworkType == NETWORK_ETHERNET; }
boolean isWifiConnected() {
return mNetworkType == NETWORK_WIFI_OPEN || mNetworkType == NETWORK_WIFI_SECURE;
}
@Override
public String toString() {
return new StringBuilder()
.append("mNetworkType ").append(mNetworkType)
.append(" miWifiSsid ").append(mWifiSsid)
.append(" mWifiSignalStrength ").append(mWifiSignalStrength)
.toString();
}
};
private ConnectivityStatus mConnectivityStatus = new ConnectivityStatus();
public ConnectivityListener(Context context, Listener listener) {
mContext = context;
mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
Context.CONNECTIVITY_SERVICE);
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
mEthernetManager = (EthernetManager) mContext.getSystemService(Context.ETHERNET_SERVICE);
mListener = listener;
mFilter = new IntentFilter();
mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE);
mFilter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) {
Log.d(TAG, "Connectivity change!");
}
if (updateConnectivityStatus()) {
mListener.onConnectivityChange(intent);
}
}
};
}
public void start() {
if (!mIsRegistered) {
boolean hasChanged = updateConnectivityStatus();
mContext.registerReceiver(mReceiver, mFilter);
mIsRegistered = true;
}
}
public void stop() {
if (mIsRegistered) {
mContext.unregisterReceiver(mReceiver);
mIsRegistered = false;
}
if (mWifiReceiver != null) {
mContext.unregisterReceiver(mWifiReceiver);
mWifiReceiver = null;
}
}
public void startScanningWifi(WifiNetworkListener wifiNetworkListener) {
if (!mWifiNetworkListeners.contains(wifiNetworkListener)) {
mWifiNetworkListeners.add(wifiNetworkListener);
if (mWifiNetworkListeners.size () == 1) {
mWifiReceiver = new WifiReceiver();
mContext.registerReceiver(mWifiReceiver, new IntentFilter(
WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
mWifiManager.startScan();
}
}
}
public void stopScanningWifi(WifiNetworkListener wifiNetworkListener) {
mWifiNetworkListeners.remove(wifiNetworkListener);
if (mWifiNetworkListeners.isEmpty() && mWifiReceiver != null) {
mContext.unregisterReceiver(mWifiReceiver);
mWifiReceiver = null;
}
}
public ConnectivityStatus getConnectivityStatus() {
return mConnectivityStatus;
}
public String getWifiIpAddress() {
if (mConnectivityStatus.isWifiConnected()) {
WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
int ip = wifiInfo.getIpAddress();
return String.format("%d.%d.%d.%d", (ip & 0xff), (ip >> 8 & 0xff),
(ip >> 16 & 0xff), (ip >> 24 & 0xff));
} else {
return "";
}
}
/**
* Return the MAC address of the currently connected Wifi AP.
*/
public String getWifiMacAddress() {
if (mConnectivityStatus.isWifiConnected()) {
WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
return wifiInfo.getMacAddress();
} else {
return "";
}
}
public String getEthernetMacAddress() {
NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
if (networkInfo == null ||networkInfo.getType() != ConnectivityManager.TYPE_ETHERNET) {
return "";
} else {
return networkInfo.getExtraInfo();
}
}
public String getEthernetIpAddress() {
LinkProperties linkProperties =
mConnectivityManager.getLinkProperties(ConnectivityManager.TYPE_ETHERNET);
for (LinkAddress linkAddress: linkProperties.getAllLinkAddresses()) {
InetAddress address = linkAddress.getAddress();
if (address instanceof Inet4Address) {
return address.getHostAddress();
}
}
// IPv6 address will not be shown like WifiInfo internally does.
return "";
}
public int getWifiSignalStrength(int maxLevel) {
WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
return WifiManager.calculateSignalLevel(wifiInfo.getRssi(), maxLevel);
}
public void forgetWifiNetwork() {
int networkId = getWifiNetworkId();
if (networkId != -1) {
mWifiManager.forget(networkId, null);
}
}
public int getWifiNetworkId() {
WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
if (wifiInfo != null) {
return wifiInfo.getNetworkId();
} else {
return -1;
}
}
public WifiConfiguration getWifiConfiguration() {
WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
if (wifiInfo != null) {
int networkId = wifiInfo.getNetworkId();
List<WifiConfiguration> configuredNetworks = mWifiManager.getConfiguredNetworks();
if (configuredNetworks != null) {
for (WifiConfiguration configuredNetwork : configuredNetworks) {
if (configuredNetwork.networkId == networkId) {
return configuredNetwork;
}
}
}
}
return null;
}
/**
* Return a list of wifi networks. Ensure that if a wifi network is connected that it appears
* as the first item on the list.
*/
public List<ScanResult> getAvailableNetworks() {
WifiInfo connectedWifiInfo = mWifiManager.getConnectionInfo();
String currentConnectedSSID = connectedWifiInfo == null ? "" : connectedWifiInfo.getSSID();
currentConnectedSSID = WifiInfo.removeDoubleQuotes(currentConnectedSSID);
WifiSecurity currentConnectedSecurity = WifiConfigHelper.getCurrentConnectionSecurity(
mWifiManager, connectedWifiInfo);
// TODO : Refactor with similar code in SelectFromListWizard
final List<ScanResult> results = mWifiManager.getScanResults();
if (results.size() == 0) {
Log.w(TAG, "No results found! Initiate scan...");
mWifiManager.startScan();
}
final HashMap<Pair<String, WifiSecurity>, ScanResult> consolidatedScanResults =
new HashMap<Pair<String, WifiSecurity>, ScanResult>();
HashMap<Pair<String, WifiSecurity>, Boolean> specialNetworks = new HashMap<
Pair<String, WifiSecurity>, Boolean>();
for (ScanResult result : results) {
if (TextUtils.isEmpty(result.SSID)) {
continue;
}
Pair<String, WifiSecurity> key = Pair.create(
result.SSID, WifiSecurity.getSecurity(result));
ScanResult existing = consolidatedScanResults.get(key);
if (WifiConfigHelper.areSameNetwork(mWifiManager, result, connectedWifiInfo)) {
// The currently connected network should always be included.
consolidatedScanResults.put(key, result);
specialNetworks.put(key, true);
} else {
if (existing == null ||
(!specialNetworks.containsKey(key) && existing.level < result.level)) {
consolidatedScanResults.put(key, result);
}
}
}
ArrayList<ScanResult> networkList = new ArrayList<ScanResult>(
consolidatedScanResults.size());
networkList.addAll(consolidatedScanResults.values());
ScanResultComparator comparator = connectedWifiInfo == null ? new ScanResultComparator() :
new ScanResultComparator(currentConnectedSSID, currentConnectedSecurity);
Collections.sort(networkList, comparator);
return networkList;
}
public IpConfiguration getIpConfiguration() {
return mEthernetManager.getConfiguration();
}
private boolean isSecureWifi(WifiInfo wifiInfo) {
if (wifiInfo == null)
return false;
int networkId = wifiInfo.getNetworkId();
List<WifiConfiguration> configuredNetworks = mWifiManager.getConfiguredNetworks();
if (configuredNetworks != null) {
for (WifiConfiguration configuredNetwork : configuredNetworks) {
if (configuredNetwork.networkId == networkId) {
return configuredNetwork.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ||
configuredNetwork.allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
configuredNetwork.allowedKeyManagement.get(KeyMgmt.IEEE8021X);
}
}
}
return false;
}
private boolean setNetworkType(int networkType) {
boolean hasChanged = mConnectivityStatus.mNetworkType != networkType;
mConnectivityStatus.mNetworkType = networkType;
return hasChanged;
}
private boolean updateConnectivityStatus() {
NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
if (networkInfo == null) {
return setNetworkType(ConnectivityStatus.NETWORK_NONE);
} else {
switch (networkInfo.getType()) {
case ConnectivityManager.TYPE_WIFI: {
boolean hasChanged;
// Determine if this is an open or secure wifi connection.
WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
if (isSecureWifi(wifiInfo)) {
hasChanged = setNetworkType(ConnectivityStatus.NETWORK_WIFI_SECURE);
} else {
hasChanged = setNetworkType(ConnectivityStatus.NETWORK_WIFI_OPEN);
}
// Find the SSID of network.
String ssid = null;
if (wifiInfo != null) {
ssid = wifiInfo.getSSID();
if (ssid != null) {
ssid = WifiInfo.removeDoubleQuotes(ssid);
}
}
if (!TextUtils.equals(mConnectivityStatus.mWifiSsid, ssid)) {
hasChanged = true;
mConnectivityStatus.mWifiSsid = ssid;
}
// Calculate the signal strength.
int signalStrength;
if (wifiInfo != null) {
// Calculate the signal strength between 0 and 3.
signalStrength = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), 4);
} else {
signalStrength = 0;
}
if (mConnectivityStatus.mWifiSignalStrength != signalStrength) {
hasChanged = true;
mConnectivityStatus.mWifiSignalStrength = signalStrength;
}
return hasChanged;
}
case ConnectivityManager.TYPE_ETHERNET:
return setNetworkType(ConnectivityStatus.NETWORK_ETHERNET);
default:
return setNetworkType(ConnectivityStatus.NETWORK_NONE);
}
}
}
}