summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/DummyWifiLogger.java29
-rw-r--r--service/java/com/android/server/wifi/WifiConfigStore.java125
-rw-r--r--service/java/com/android/server/wifi/WifiController.java41
-rw-r--r--service/java/com/android/server/wifi/WifiLogger.java11
-rw-r--r--service/java/com/android/server/wifi/WifiMonitor.java7
-rw-r--r--service/java/com/android/server/wifi/WifiNative.java157
-rw-r--r--service/java/com/android/server/wifi/WifiScanningServiceImpl.java20
-rw-r--r--service/java/com/android/server/wifi/WifiServiceImpl.java62
-rw-r--r--service/java/com/android/server/wifi/WifiStateMachine.java489
-rw-r--r--service/jni/com_android_server_wifi_WifiNative.cpp99
10 files changed, 910 insertions, 130 deletions
diff --git a/service/java/com/android/server/wifi/DummyWifiLogger.java b/service/java/com/android/server/wifi/DummyWifiLogger.java
new file mode 100644
index 000000000..2727b8c07
--- /dev/null
+++ b/service/java/com/android/server/wifi/DummyWifiLogger.java
@@ -0,0 +1,29 @@
+
+package com.android.server.wifi;
+
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+class DummyWifiLogger {
+
+ public DummyWifiLogger() { }
+
+ public synchronized void startLogging(boolean verboseEnabled) { }
+
+ public synchronized void startPacketLog() { }
+
+ public synchronized void stopPacketLog() { }
+
+ public synchronized void stopLogging() { }
+
+ public synchronized void captureBugReportData(int reason) { }
+
+ public synchronized void captureAlertData(int errorCode, byte[] alertData) { }
+
+ public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("*** firmware logging disabled, no debug data ****");
+ pw.println("set config_wifi_enable_wifi_firmware_debugging to enable");
+ }
+} \ No newline at end of file
diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java
index dd47b0805..76a1ca5b8 100644
--- a/service/java/com/android/server/wifi/WifiConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiConfigStore.java
@@ -469,7 +469,7 @@ public class WifiConfigStore extends IpConfigStore {
WifiEnterpriseConfig.CA_CERT_KEY, WifiEnterpriseConfig.SUBJECT_MATCH_KEY,
WifiEnterpriseConfig.ENGINE_KEY, WifiEnterpriseConfig.ENGINE_ID_KEY,
WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY,
- WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY
+ WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY, WifiEnterpriseConfig.PHASE1_KEY
};
@@ -1024,6 +1024,8 @@ public class WifiConfigStore extends IpConfigStore {
}
}
+ mWifiNative.setHs20(config.isPasspoint());
+
if (updatePriorities)
mWifiNative.saveConfig();
else
@@ -1313,7 +1315,7 @@ public class WifiConfigStore extends IpConfigStore {
// Sort by descending priority
Collections.sort(sortedWifiConfigurations, new Comparator<WifiConfiguration>() {
public int compare(WifiConfiguration a, WifiConfiguration b) {
- return a.priority >= b.priority ? 1 : -1;
+ return a.priority - b.priority;
}
});
}
@@ -1330,6 +1332,109 @@ public class WifiConfigStore extends IpConfigStore {
}
}
+ /**
+ * Returns whether the provided network config is enabled for autojoin or not.
+ */
+ private static boolean isNetworkEnabled(WifiConfiguration config) {
+ return (config.status == Status.ENABLED && !config.ephemeral
+ && (config.autoJoinStatus == WifiConfiguration.AUTO_JOIN_ENABLED));
+ }
+
+ /**
+ * Returns whether the provided network config is only temporarily disabled for autojoin or not.
+ */
+ private static boolean isNetworkTempDisabled(WifiConfiguration config) {
+ return (config.status == Status.ENABLED && !config.ephemeral
+ && ((config.autoJoinStatus <= WifiConfiguration.AUTO_JOIN_DISABLED_ON_AUTH_FAILURE)
+ && (config.autoJoinStatus > WifiConfiguration.AUTO_JOIN_ENABLED)));
+ }
+
+ /**
+ * Returns an integer representing a score for each configuration. The scores are assigned based
+ * on the status of the configuration. The scores are assigned according to this order:
+ * Fully enabled network > Temporarily disabled network > Permanently disabled network.
+ */
+ private static int getPnoNetworkSortScore(WifiConfiguration config) {
+ // Do we need static constants for these scores? We're not using them anywhere else though.
+ if (isNetworkEnabled(config)) {
+ return 3;
+ } else if (isNetworkTempDisabled(config)) {
+ return 2;
+ } else {
+ return 1;
+ }
+ }
+
+ /**
+ * PnoNetwork list sorting algorithm:
+ * 1, Place the fully enabled networks first. Among the fully enabled networks,
+ * sort them in descending order of their |numAssociation| values. If networks have
+ * the same |numAssociation|, then sort them in descending order of their |priority|
+ * values.
+ * 2. Next place all the temporarily disabled networks. Among the temporarily disabled
+ * networks, sort them in the same order as the fully enabled networks.
+ * 3. Place the permanently disabled networks last. The order among permanently disabled
+ * networks doesn't matter.
+ */
+ private static final Comparator<WifiConfiguration> sPnoListSortComparator =
+ new Comparator<WifiConfiguration>() {
+ public int compare(WifiConfiguration a, WifiConfiguration b) {
+ int configAScore = getPnoNetworkSortScore(a);
+ int configBScore = getPnoNetworkSortScore(b);
+ if (configAScore == configBScore) {
+ // If 2 networks have the same saved |numAssociation| value, sort them
+ // according to their priority.
+ if (a.numAssociation != b.numAssociation) {
+ return Long.compare(b.numAssociation, a.numAssociation);
+ } else {
+ return Integer.compare(b.priority, a.priority);
+ }
+ } else {
+ return Integer.compare(configBScore, configAScore);
+ }
+ }
+ };
+
+ /**
+ * Retrieves an updated list of priorities for all the saved networks before
+ * enabling/disabling PNO.
+ *
+ * wpa_supplicant uses the priority of networks to build the list of SSID's to monitor
+ * during PNO. If there are a lot of saved networks, this list will be truncated and we
+ * might end up not connecting to the networks we use most frequently. So, We want the networks
+ * to be re-sorted based on the relative |numAssociation| values.
+ *
+ * @param enablePno boolean indicating whether PNO is being enabled or disabled.
+ * @return list of networks with updated priorities.
+ */
+ ArrayList<WifiNative.PnoNetworkPriority> retrievePnoNetworkPriorityList(boolean enablePno) {
+ ArrayList<WifiNative.PnoNetworkPriority> pnoList =
+ new ArrayList<WifiNative.PnoNetworkPriority>();
+ ArrayList<WifiConfiguration> wifiConfigurations =
+ new ArrayList<WifiConfiguration>(mConfiguredNetworks.values());
+ if (enablePno) {
+ Collections.sort(wifiConfigurations, sPnoListSortComparator);
+ // Let's use the network list size as the highest priority and then go down from there.
+ // So, the most frequently connected network has the highest priority now.
+ int priority = wifiConfigurations.size();
+ if (DBG) {
+ Log.d(TAG, "Retrieve network priorities before PNO. Max priority: " + priority);
+ }
+ for (WifiConfiguration config : wifiConfigurations) {
+ pnoList.add(new WifiNative.PnoNetworkPriority(config.networkId, priority));
+ priority--;
+ }
+ } else {
+ // Revert the priorities back to the saved config values after PNO.
+ if (DBG) Log.d(TAG, "Retrieve network priorities after PNO.");
+ for (WifiConfiguration config : wifiConfigurations) {
+ pnoList.add(new WifiNative.PnoNetworkPriority(config.networkId, config.priority));
+ }
+ }
+ return pnoList;
+ }
+
+
String[] getWhiteListedSsids(WifiConfiguration config) {
int num_ssids = 0;
String nonQuoteSSID;
@@ -1792,7 +1897,7 @@ public class WifiConfigStore extends IpConfigStore {
mLastPriority = 0;
mConfiguredNetworks.clear();
-
+ List<WifiConfiguration> configTlsResetList = new ArrayList<WifiConfiguration>();
int last_id = -1;
boolean done = false;
while (!done) {
@@ -1861,6 +1966,14 @@ public class WifiConfigStore extends IpConfigStore {
if (showNetworks) log("Ignoring loaded configured for network " + config.networkId
+ " because config are not valid");
}
+
+ if (config != null && config.enterpriseConfig != null &&
+ config.enterpriseConfig.getEapMethod() < WifiEnterpriseConfig.Eap.PWD) {
+ if (!config.enterpriseConfig.getTls12Enable()) {
+ //re-enable the TLS1.2 every time when load the network
+ configTlsResetList.add(config);
+ }
+ }
}
done = (lines.length == 1);
@@ -1884,6 +1997,12 @@ public class WifiConfigStore extends IpConfigStore {
logContents(SUPPLICANT_CONFIG_FILE_BACKUP);
logContents(networkHistoryConfigFile);
}
+
+ //reset TLS default to 1.2
+ for (WifiConfiguration config : configTlsResetList) {
+ config.enterpriseConfig.setTls12Enable(true);
+ addOrUpdateNetwork(config, WifiConfiguration.UNKNOWN_UID);
+ }
}
private void logContents(String file) {
diff --git a/service/java/com/android/server/wifi/WifiController.java b/service/java/com/android/server/wifi/WifiController.java
index 3b41e3b81..9a8967bf2 100644
--- a/service/java/com/android/server/wifi/WifiController.java
+++ b/service/java/com/android/server/wifi/WifiController.java
@@ -116,6 +116,9 @@ class WifiController extends StateMachine {
static final int CMD_USER_PRESENT = BASE + 12;
static final int CMD_AP_START_FAILURE = BASE + 13;
+ private static final int WIFI_DISABLED = 0;
+ private static final int WIFI_ENABLED = 1;
+
private DefaultState mDefaultState = new DefaultState();
private StaEnabledState mStaEnabledState = new StaEnabledState();
private ApStaDisabledState mApStaDisabledState = new ApStaDisabledState();
@@ -441,6 +444,10 @@ class WifiController extends StateMachine {
break;
case CMD_SET_AP:
if (msg.arg1 == 1) {
+ if (msg.arg2 == 0) { // previous wifi state has not been saved yet
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_SAVED_STATE, WIFI_DISABLED);
+ }
mWifiStateMachine.setHostApRunning((WifiConfiguration) msg.obj,
true);
transitionTo(mApEnabledState);
@@ -509,6 +516,15 @@ class WifiController extends StateMachine {
transitionTo(mEcmState);
break;
}
+ case CMD_SET_AP:
+ if (msg.arg1 == 1) {
+ // remeber that we were enabled
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_SAVED_STATE, WIFI_ENABLED);
+ deferMessage(obtainMessage(msg.what, msg.arg1, 1, msg.obj));
+ transitionTo(mApStaDisabledState);
+ }
+ break;
default:
return NOT_HANDLED;
@@ -567,7 +583,9 @@ class WifiController extends StateMachine {
case CMD_SET_AP:
// Before starting tethering, turn off supplicant for scan mode
if (msg.arg1 == 1) {
- deferMessage(msg);
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_SAVED_STATE, WIFI_DISABLED);
+ deferMessage(obtainMessage(msg.what, msg.arg1, 1, msg.obj));
transitionTo(mApStaDisabledState);
}
break;
@@ -617,9 +635,27 @@ class WifiController extends StateMachine {
case CMD_SET_AP:
if (msg.arg1 == 0) {
mWifiStateMachine.setHostApRunning(null, false);
- transitionTo(mApStaDisabledState);
+ int wifiSavedState = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_SAVED_STATE, WIFI_DISABLED);
+ if (wifiSavedState == WIFI_ENABLED) {
+ transitionTo(mStaEnabledState);
+ }
+ else {
+ if (mSettingsStore.isScanAlwaysAvailable()) {
+ transitionTo(mStaDisabledWithScanState);
+ }
+ else {
+ transitionTo(mApStaDisabledState);
+ }
+ }
}
break;
+ case CMD_EMERGENCY_MODE_CHANGED:
+ if (msg.arg1 == 1) {
+ mWifiStateMachine.setHostApRunning(null, false);
+ transitionTo(mEcmState);
+ break;
+ }
case CMD_AP_START_FAILURE:
if(!mSettingsStore.isScanAlwaysAvailable()) {
transitionTo(mApStaDisabledState);
@@ -637,6 +673,7 @@ class WifiController extends StateMachine {
@Override
public void enter() {
mWifiStateMachine.setSupplicantRunning(false);
+ mWifiStateMachine.clearANQPCache();
}
@Override
diff --git a/service/java/com/android/server/wifi/WifiLogger.java b/service/java/com/android/server/wifi/WifiLogger.java
index 8add77970..c3f651039 100644
--- a/service/java/com/android/server/wifi/WifiLogger.java
+++ b/service/java/com/android/server/wifi/WifiLogger.java
@@ -35,7 +35,7 @@ import java.util.zip.Deflater;
/**
* Tracks various logs for framework
*/
-class WifiLogger {
+class WifiLogger extends DummyWifiLogger {
private static final String TAG = "WifiLogger";
private static final boolean DBG = false;
@@ -92,6 +92,7 @@ class WifiLogger {
mWifiStateMachine = wifiStateMachine;
}
+ @Override
public synchronized void startLogging(boolean verboseEnabled) {
mFirmwareVersion = WifiNative.getFirmwareVersion();
mDriverVersion = WifiNative.getDriverVersion();
@@ -112,6 +113,7 @@ class WifiLogger {
}
}
+ @Override
public synchronized void startPacketLog() {
if (mPerPacketRingBuffer != null) {
startLoggingRingBuffer(mPerPacketRingBuffer);
@@ -120,6 +122,7 @@ class WifiLogger {
}
}
+ @Override
public synchronized void stopPacketLog() {
if (mPerPacketRingBuffer != null) {
stopLoggingRingBuffer(mPerPacketRingBuffer);
@@ -128,6 +131,7 @@ class WifiLogger {
}
}
+ @Override
public synchronized void stopLogging() {
if (mLogLevel != VERBOSE_NO_LOG) {
//resetLogHandler only can be used when you terminate all logging since all handler will
@@ -143,17 +147,20 @@ class WifiLogger {
}
}
+ @Override
public synchronized void captureBugReportData(int reason) {
BugReport report = captureBugreport(reason, true);
mLastBugReports.addLast(report);
}
+ @Override
public synchronized void captureAlertData(int errorCode, byte[] alertData) {
BugReport report = captureBugreport(errorCode, /* captureFWDump = */ true);
report.alertData = alertData;
mLastAlerts.addLast(report);
}
+ @Override
public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("Chipset information :-----------------------------------------------");
pw.println("FW Version is: " + mFirmwareVersion);
@@ -236,7 +243,7 @@ class WifiLogger {
}
}
- static class LimitedCircularArray<E> {
+ private static class LimitedCircularArray<E> {
private CircularArray<E> mArray;
private int mMax;
LimitedCircularArray(int max) {
diff --git a/service/java/com/android/server/wifi/WifiMonitor.java b/service/java/com/android/server/wifi/WifiMonitor.java
index 9758d5769..ffca502d4 100644
--- a/service/java/com/android/server/wifi/WifiMonitor.java
+++ b/service/java/com/android/server/wifi/WifiMonitor.java
@@ -230,6 +230,10 @@ public class WifiMonitor {
private static final String BSS_REMOVED_STR = "BSS-REMOVED";
/**
+ * This indicate supplicant encounter RSN PMKID mismatch error
+ */
+ private static final String RSN_PMKID_STR = "RSN: PMKID mismatch";
+ /**
* Regex pattern for extracting an Ethernet-style MAC address from a string.
* Matches a strings like the following:<pre>
* CTRL-EVENT-CONNECTED - Connection to 00:1e:58:ec:d5:6d completed (reauth) [id=1 id_str=]</pre>
@@ -502,6 +506,7 @@ public class WifiMonitor {
public static final int HS20_REMEDIATION_EVENT = BASE + 61;
public static final int HS20_DEAUTH_EVENT = BASE + 62;
+ public static final int RSN_PMKID_MISMATCH_EVENT = BASE + 63;
/**
* This indicates a read error on the monitor socket conenction
*/
@@ -829,6 +834,8 @@ public class WifiMonitor {
} else if (eventStr.startsWith(AUTH_EVENT_PREFIX_STR) &&
eventStr.endsWith(AUTH_TIMEOUT_STR)) {
mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
+ } else if (eventStr.startsWith(RSN_PMKID_STR)) {
+ mStateMachine.sendMessage(RSN_PMKID_MISMATCH_EVENT);
} else {
if (DBG) Log.w(TAG, "couldn't identify event type - " + eventStr);
}
diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java
index 899529ddd..620f8b505 100644
--- a/service/java/com/android/server/wifi/WifiNative.java
+++ b/service/java/com/android/server/wifi/WifiNative.java
@@ -36,6 +36,8 @@ import android.util.Base64;
import android.util.LocalLog;
import android.util.Log;
+import com.android.server.connectivity.KeepalivePacketData;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -654,8 +656,47 @@ public class WifiNative {
return doBooleanCommand("DRIVER COUNTRY");
}
- public boolean enableBackgroundScan(boolean enable) {
+ /**
+ * Object holding the network ID and the corresponding priority to be set before enabling/
+ * disabling PNO.
+ */
+ public static class PnoNetworkPriority {
+ public int networkId;
+ public int priority;
+
+ PnoNetworkPriority(int networkId, int priority) {
+ this.networkId = networkId;
+ this.priority = priority;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sbuf = new StringBuilder();
+ sbuf.append(" Network ID=").append(this.networkId);
+ sbuf.append(" Priority=").append(this.priority);
+ return sbuf.toString();
+ }
+ }
+
+ public boolean enableBackgroundScan(
+ boolean enable,
+ List<PnoNetworkPriority> pnoNetworkList) {
boolean ret;
+ // TODO: Couple of cases yet to be handled:
+ // 1. What if the network priority update fails, should we bail out of PNO setting?
+ // 2. If PNO setting fails below, should we go back and revert this priority change?
+ if (pnoNetworkList != null) {
+ if (DBG) Log.i(mTAG, "Update priorities for PNO. Enable: " + enable);
+ for (PnoNetworkPriority pnoNetwork : pnoNetworkList) {
+ // What if this fails? Should we bail out?
+ boolean isSuccess = setNetworkVariable(pnoNetwork.networkId,
+ WifiConfiguration.priorityVarName,
+ Integer.toString(pnoNetwork.priority));
+ if (!isSuccess) {
+ Log.e(mTAG, "Update priority failed for :" + pnoNetwork.networkId);
+ }
+ }
+ }
if (enable) {
ret = doBooleanCommand("SET pno 1");
} else {
@@ -676,6 +717,14 @@ public class WifiNative {
doBooleanCommand("SCAN_INTERVAL " + scanInterval);
}
+ public void setHs20(boolean hs20) {
+ if (hs20) {
+ doBooleanCommand("SET HS20 1");
+ } else {
+ doBooleanCommand("SET HS20 0");
+ }
+ }
+
public void startTdls(String macAddr, boolean enable) {
if (enable) {
doBooleanCommand("TDLS_DISCOVER " + macAddr);
@@ -1466,8 +1515,8 @@ public class WifiNative {
int secondChanelOffset = 0;
byte channelMode = 0;
- byte centerFreqIndex1 = 0;
- byte centerFreqIndex2 = 0;
+ int centerFreqIndex1 = 0;
+ int centerFreqIndex2 = 0;
boolean is80211McRTTResponder = false;
@@ -1490,8 +1539,8 @@ public class WifiNative {
secondChanelOffset = bytes[inforStart + 1] & 0x3;
} else if(type == EID_VHT_OPERATION) {
channelMode = bytes[inforStart];
- centerFreqIndex1 = bytes[inforStart + 1];
- centerFreqIndex2 = bytes[inforStart + 2];
+ centerFreqIndex1 = bytes[inforStart + 1] & 0xFF;
+ centerFreqIndex2 = bytes[inforStart + 2] & 0xFF;
} else if (type == EID_EXTENDED_CAPS) {
int tempIndex = RTT_RESP_ENABLE_BIT / 8;
byte offset = RTT_RESP_ENABLE_BIT % 8;
@@ -1604,7 +1653,9 @@ public class WifiNative {
synchronized public static void stopScan() {
synchronized (mLock) {
if (isHalStarted()) {
- stopScanNative(sWlan0Index, sScanCmdId);
+ if (sScanCmdId != 0) {
+ stopScanNative(sWlan0Index, sScanCmdId);
+ }
sScanSettings = null;
sScanEventHandler = null;
sScanCmdId = 0;
@@ -2391,4 +2442,98 @@ public class WifiNative {
}
}
}
+
+ private native static int startSendingOffloadedPacketNative(int iface, int idx,
+ byte[] srcMac, byte[] dstMac, byte[] pktData, int period);
+
+ synchronized public int
+ startSendingOffloadedPacket(int slot, KeepalivePacketData keepAlivePacket, int period) {
+ Log.d(TAG, "startSendingOffloadedPacket slot=" + slot + " period=" + period);
+
+ String[] macAddrStr = getMacAddress().split(":");
+ byte[] srcMac = new byte[6];
+ for(int i = 0; i < 6; i++) {
+ Integer hexVal = Integer.parseInt(macAddrStr[i], 16);
+ srcMac[i] = hexVal.byteValue();
+ }
+ synchronized (mLock) {
+ if (isHalStarted()) {
+ return startSendingOffloadedPacketNative(sWlan0Index, slot, srcMac,
+ keepAlivePacket.dstMac, keepAlivePacket.data, period);
+ } else {
+ return -1;
+ }
+ }
+ }
+
+ private native static int stopSendingOffloadedPacketNative(int iface, int idx);
+
+ synchronized public int
+ stopSendingOffloadedPacket(int slot) {
+ Log.d(TAG, "stopSendingOffloadedPacket " + slot);
+ synchronized (mLock) {
+ if (isHalStarted()) {
+ return stopSendingOffloadedPacketNative(sWlan0Index, slot);
+ } else {
+ return -1;
+ }
+ }
+ }
+
+ public static interface WifiRssiEventHandler {
+ void onRssiThresholdBreached(byte curRssi);
+ }
+
+ private static WifiRssiEventHandler sWifiRssiEventHandler;
+
+ synchronized static void onRssiThresholdBreached(int id, byte curRssi) {
+ sWifiRssiEventHandler.onRssiThresholdBreached(curRssi);
+ }
+
+ private native static int startRssiMonitoringNative(int iface, int id,
+ byte maxRssi, byte minRssi);
+
+ private static int sRssiMonitorCmdId = 0;
+
+ synchronized public int startRssiMonitoring(byte maxRssi, byte minRssi,
+ WifiRssiEventHandler rssiEventHandler) {
+ Log.d(TAG, "startRssiMonitoring: maxRssi=" + maxRssi + " minRssi=" + minRssi);
+ sWifiRssiEventHandler = rssiEventHandler;
+ synchronized (mLock) {
+ if (isHalStarted()) {
+ if (sRssiMonitorCmdId != 0) {
+ stopRssiMonitoring();
+ }
+
+ sRssiMonitorCmdId = getNewCmdIdLocked();
+ Log.d(TAG, "sRssiMonitorCmdId = " + sRssiMonitorCmdId);
+ int ret = startRssiMonitoringNative(sWlan0Index, sRssiMonitorCmdId,
+ maxRssi, minRssi);
+ if (ret != 0) { // if not success
+ sRssiMonitorCmdId = 0;
+ }
+ return ret;
+ } else {
+ return -1;
+ }
+ }
+ }
+
+ private native static int stopRssiMonitoringNative(int iface, int idx);
+
+ synchronized public int stopRssiMonitoring() {
+ Log.d(TAG, "stopRssiMonitoring, cmdId " + sRssiMonitorCmdId);
+ synchronized (mLock) {
+ if (isHalStarted()) {
+ int ret = 0;
+ if (sRssiMonitorCmdId != 0) {
+ ret = stopRssiMonitoringNative(sWlan0Index, sRssiMonitorCmdId);
+ }
+ sRssiMonitorCmdId = 0;
+ return ret;
+ } else {
+ return -1;
+ }
+ }
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiScanningServiceImpl.java b/service/java/com/android/server/wifi/WifiScanningServiceImpl.java
index 8f2cd3bd7..a0f506113 100644
--- a/service/java/com/android/server/wifi/WifiScanningServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiScanningServiceImpl.java
@@ -658,6 +658,17 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
reportScanWorkUpdate();
}
+ void removeAllScanRequests() {
+ Iterator<Map.Entry<Integer, ScanSettings>> it = mScanSettings.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<Integer, ScanSettings> entry = it.next();
+ ScanSettings settings = entry.getValue();
+ Log.d(TAG, "Pending scan removed, handler=" + entry.getKey() +
+ ", period=" + settings.periodInMs);
+ it.remove();
+ }
+ }
+
Iterator<Map.Entry<Integer, ScanSettings>> getScans() {
return mScanSettings.entrySet().iterator();
}
@@ -1249,6 +1260,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
}
logScanRequest("addScanRequest", ci, handler, settings);
+ removeAllScanRequests();
ci.addScanRequest(settings, handler);
if (resetBuckets()) {
return true;
@@ -1272,6 +1284,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
}
logScanRequest("addSingleScanRequest", ci, handler, settings);
+ removeAllScanRequests();
ci.addScanRequest(settings, handler);
if (resetBuckets()) {
/* reset periodInMs to 0 to indicate single shot scan */
@@ -1292,6 +1305,13 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
}
}
+ void removeAllScanRequests() {
+ Collection<ClientInfo> clients = mClients.values();
+ for (ClientInfo ci : clients) {
+ ci.removeAllScanRequests();
+ }
+ }
+
boolean reportScanResults() {
ScanData results[] = WifiNative.getScanResults(/* flush = */ true);
Collection<ClientInfo> clients = mClients.values();
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index ca85fbc50..33ce852e2 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -69,6 +69,7 @@ import android.util.Slog;
import com.android.internal.R;
import com.android.internal.app.IBatteryStats;
+import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.AsyncChannel;
import com.android.server.am.BatteryStatsService;
@@ -358,10 +359,27 @@ public final class WifiServiceImpl extends IWifiManager.Stub {
if (mSettingsStore.handleAirplaneModeToggled()) {
mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED);
}
+ if (mSettingsStore.isAirplaneModeOn()) {
+ Log.d(TAG, "resetting country code because Airplane mode is ON");
+ mWifiStateMachine.resetCountryCode();
+ }
}
},
new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
+ mContext.registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String state = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
+ if (state.equals(IccCardConstants.INTENT_VALUE_ICC_ABSENT)) {
+ Log.d(TAG, "resetting country code because SIM is removed");
+ mWifiStateMachine.resetCountryCode();
+ }
+ }
+ },
+ new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED));
+
// Adding optimizations of only receiving broadcasts when wifi is enabled
// can result in race conditions when apps toggle wifi in the background
// without active user involvement. Always receive broadcasts.
@@ -970,7 +988,7 @@ public final class WifiServiceImpl extends IWifiManager.Stub {
long ident = Binder.clearCallingIdentity();
try {
if (!canReadPeerMacAddresses && !isActiveNetworkScorer
- && !isLocationEnabled()) {
+ && !isLocationEnabled(callingPackage)) {
return new ArrayList<ScanResult>();
}
if (!canReadPeerMacAddresses && !isActiveNetworkScorer
@@ -990,9 +1008,12 @@ public final class WifiServiceImpl extends IWifiManager.Stub {
}
}
- private boolean isLocationEnabled() {
- return Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.LOCATION_MODE,
- Settings.Secure.LOCATION_MODE_OFF) != Settings.Secure.LOCATION_MODE_OFF;
+ private boolean isLocationEnabled(String callingPackage) {
+ boolean legacyForegroundApp = !isMApp(mContext, callingPackage)
+ && isForegroundApp(callingPackage);
+ return legacyForegroundApp || Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF)
+ != Settings.Secure.LOCATION_MODE_OFF;
}
/**
@@ -1101,7 +1122,7 @@ public final class WifiServiceImpl extends IWifiManager.Stub {
*/
public String getCountryCode() {
enforceConnectivityInternalPermission();
- String country = mWifiStateMachine.getCountryCode();
+ String country = mWifiStateMachine.getCurrentCountryCode();
return country;
}
/**
@@ -2046,29 +2067,18 @@ public final class WifiServiceImpl extends IWifiManager.Stub {
private boolean checkCallerCanAccessScanResults(String callingPackage, int uid) {
if (ActivityManager.checkUidPermission(Manifest.permission.ACCESS_FINE_LOCATION, uid)
== PackageManager.PERMISSION_GRANTED
- && isAppOppAllowed(AppOpsManager.OP_FINE_LOCATION, callingPackage, uid)) {
+ && checkAppOppAllowed(AppOpsManager.OP_FINE_LOCATION, callingPackage, uid)) {
return true;
}
if (ActivityManager.checkUidPermission(Manifest.permission.ACCESS_COARSE_LOCATION, uid)
== PackageManager.PERMISSION_GRANTED
- && isAppOppAllowed(AppOpsManager.OP_COARSE_LOCATION, callingPackage, uid)) {
+ && checkAppOppAllowed(AppOpsManager.OP_COARSE_LOCATION, callingPackage, uid)) {
return true;
}
- // Enforce location permission for apps targeting M and later versions
- boolean enforceLocationPermission = true;
- try {
- enforceLocationPermission = mContext.getPackageManager().getApplicationInfo(
- callingPackage, 0).targetSdkVersion >= Build.VERSION_CODES.M;
- } catch (PackageManager.NameNotFoundException e) {
- // In case of exception, enforce permission anyway
- }
- if (enforceLocationPermission) {
- throw new SecurityException("Need ACCESS_COARSE_LOCATION or "
- + "ACCESS_FINE_LOCATION permission to get scan results");
- }
+ boolean apiLevel23App = isMApp(mContext, callingPackage);
// Pre-M apps running in the foreground should continue getting scan results
- if (isForegroundApp(callingPackage)) {
+ if (!apiLevel23App && isForegroundApp(callingPackage)) {
return true;
}
Log.e(TAG, "Permission denial: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION "
@@ -2076,10 +2086,20 @@ public final class WifiServiceImpl extends IWifiManager.Stub {
return false;
}
- private boolean isAppOppAllowed(int op, String callingPackage, int uid) {
+ private boolean checkAppOppAllowed(int op, String callingPackage, int uid) {
return mAppOps.noteOp(op, uid, callingPackage) == AppOpsManager.MODE_ALLOWED;
}
+ private static boolean isMApp(Context context, String pkgName) {
+ try {
+ return context.getPackageManager().getApplicationInfo(pkgName, 0)
+ .targetSdkVersion >= Build.VERSION_CODES.M;
+ } catch (PackageManager.NameNotFoundException e) {
+ // In case of exception, assume M app (more strict checking)
+ }
+ return true;
+ }
+
/**
* Return true if the specified package name is a foreground app.
*
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 4bc62b324..4e40f7353 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -110,6 +110,7 @@ import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
+import com.android.server.connectivity.KeepalivePacketData;
import com.android.server.net.NetlinkTracker;
import com.android.server.wifi.hotspot2.NetworkDetail;
import com.android.server.wifi.hotspot2.SupplicantBridge;
@@ -125,6 +126,7 @@ import java.io.PrintWriter;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Calendar;
import java.util.HashSet;
import java.util.LinkedList;
@@ -147,7 +149,8 @@ import java.util.regex.Pattern;
*
* @hide
*/
-public class WifiStateMachine extends StateMachine implements WifiNative.WifiPnoEventHandler {
+public class WifiStateMachine extends StateMachine implements WifiNative.WifiPnoEventHandler,
+ WifiNative.WifiRssiEventHandler {
private static final String NETWORKTYPE = "WIFI";
private static final String NETWORKTYPE_UNTRUSTED = "WIFI_UT";
@@ -191,7 +194,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
private WifiAutoJoinController mWifiAutoJoinController;
private INetworkManagementService mNwService;
private ConnectivityManager mCm;
- private WifiLogger mWifiLogger;
+ private DummyWifiLogger mWifiLogger;
private WifiApConfigStore mWifiApConfigStore;
private final boolean mP2pSupported;
private final AtomicBoolean mP2pConnected = new AtomicBoolean(false);
@@ -209,7 +212,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
private int mNumScanResultsReturned;
private boolean mScreenOn = false;
-
+ private int mCurrentAssociateNetworkId = -1;
/* Chipset supports background scan */
private final boolean mBackgroundScanSupported;
@@ -269,6 +272,37 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
mRestartAutoJoinOffloadCounter++;
}
+ @Override
+ public void onRssiThresholdBreached(byte curRssi) {
+ if (DBG) {
+ Log.e(TAG, "onRssiThresholdBreach event. Cur Rssi = " + curRssi);
+ }
+ sendMessage(CMD_RSSI_THRESHOLD_BREACH, curRssi);
+ }
+
+ public void processRssiThreshold(byte curRssi, int reason) {
+ if (curRssi == Byte.MAX_VALUE || curRssi == Byte.MIN_VALUE) {
+ Log.wtf(TAG, "processRssiThreshold: Invalid rssi " + curRssi);
+ return;
+ }
+ for (int i = 0; i < mRssiRanges.length; i++) {
+ if (curRssi < mRssiRanges[i]) {
+ // Assume sorted values(ascending order) for rssi,
+ // bounded by high(127) and low(-128) at extremeties
+ byte maxRssi = mRssiRanges[i];
+ byte minRssi = mRssiRanges[i-1];
+ // This value of hw has to be believed as this value is averaged and has breached
+ // the rssi thresholds and raised event to host. This would be eggregious if this
+ // value is invalid
+ mWifiInfo.setRssi((int) curRssi);
+ updateCapabilities(getCurrentWifiConfiguration());
+ int ret = startRssiMonitoringOffload(maxRssi, minRssi);
+ Log.d(TAG, "Re-program RSSI thresholds for " + smToString(reason) +
+ ": [" + minRssi + ", " + maxRssi + "], curRssi=" + curRssi + " ret=" + ret);
+ break;
+ }
+ }
+ }
public void registerNetworkDisabled(int netId) {
// Restart legacy PNO and autojoin offload if needed
sendMessage(CMD_RESTART_AUTOJOIN_OFFLOAD, 0,
@@ -542,6 +576,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
private String[] mWhiteListedSsids = null;
+ private byte[] mRssiRanges;
+
// Keep track of various statistics, for retrieval by System Apps, i.e. under @SystemApi
// We should really persist that into the networkHistory.txt file, and read it back when
// WifiStateMachine starts up
@@ -786,6 +822,22 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
/* used to log if GSCAN was started */
static final int CMD_STARTED_GSCAN_DBG = BASE + 159;
+ /* used to offload sending IP packet */
+ static final int CMD_START_IP_PACKET_OFFLOAD = BASE + 160;
+
+ /* used to stop offload sending IP packet */
+ static final int CMD_STOP_IP_PACKET_OFFLOAD = BASE + 161;
+
+ /* used to start rssi monitoring in hw */
+ static final int CMD_START_RSSI_MONITORING_OFFLOAD = BASE + 162;
+
+ /* used to stop rssi moniroting in hw */
+ static final int CMD_STOP_RSSI_MONITORING_OFFLOAD = BASE + 163;
+
+ /* used to indicated RSSI threshold breach in hw */
+ static final int CMD_RSSI_THRESHOLD_BREACH = BASE + 164;
+
+
/* Wifi state machine modes of operation */
/* CONNECT_MODE - connect to any 'known' AP when it becomes available */
@@ -870,9 +922,13 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
private int mDelayedStopCounter;
private boolean mInDelayedStop = false;
- // there is a delay between StateMachine change country code and Supplicant change country code
- // here save the current WifiStateMachine set country code
- private volatile String mSetCountryCode = null;
+ // config option that indicate whether or not to reset country code to default when
+ // cellular radio indicates country code loss
+ private boolean mRevertCountryCodeOnCellularLoss = false;
+
+ private String mDefaultCountryCode;
+
+ private static final String BOOT_DEFAULT_WIFI_COUNTRY_CODE = "ro.boot.wificountrycode";
// Supplicant doesn't like setting the same country code multiple times (it may drop
// currently connected network), so we save the current device set country code here to avoid
@@ -1052,8 +1108,6 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
WifiTrafficPoller trafficPoller) {
super("WifiStateMachine");
mContext = context;
- mSetCountryCode = Settings.Global.getString(
- mContext.getContentResolver(), Settings.Global.WIFI_COUNTRY_CODE);
mInterfaceName = wlanInterface;
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
@@ -1070,7 +1124,15 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
mWifiAutoJoinController = new WifiAutoJoinController(context, this,
mWifiConfigStore, mWifiConnectionStatistics, mWifiNative);
mWifiMonitor = new WifiMonitor(this, mWifiNative);
- mWifiLogger = new WifiLogger(this);
+
+ boolean enableFirmwareLogs = mContext.getResources().getBoolean(
+ R.bool.config_wifi_enable_wifi_firmware_debugging);
+
+ if (enableFirmwareLogs) {
+ mWifiLogger = new WifiLogger(this);
+ } else {
+ mWifiLogger = new DummyWifiLogger();
+ }
mWifiInfo = new WifiInfo();
mSupplicantStateTracker = new SupplicantStateTracker(context, this, mWifiConfigStore,
@@ -1122,6 +1184,27 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
mPrimaryDeviceType = mContext.getResources().getString(
R.string.config_wifi_p2p_device_type);
+ mRevertCountryCodeOnCellularLoss = mContext.getResources().getBoolean(
+ R.bool.config_wifi_revert_country_code_on_cellular_loss);
+
+ mDefaultCountryCode = SystemProperties.get(BOOT_DEFAULT_WIFI_COUNTRY_CODE);
+ if (TextUtils.isEmpty(mDefaultCountryCode) == false) {
+ mDefaultCountryCode = mDefaultCountryCode.toUpperCase(Locale.ROOT);
+ }
+
+ if (mRevertCountryCodeOnCellularLoss && TextUtils.isEmpty(mDefaultCountryCode)) {
+ logw("config_wifi_revert_country_code_on_cellular_loss is set, " +
+ "but there is no default country code!! Resetting ...");
+ mRevertCountryCodeOnCellularLoss = false;
+ } else if (mRevertCountryCodeOnCellularLoss) {
+ logd("initializing with and will revert to " + mDefaultCountryCode + " on MCC loss");
+ }
+
+ if (mRevertCountryCodeOnCellularLoss) {
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.WIFI_COUNTRY_CODE, mDefaultCountryCode);
+ }
+
mUserWantsSuspendOpt.set(Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);
@@ -1272,7 +1355,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
PendingIntent getPrivateBroadcast(String action, int requestCode) {
Intent intent = new Intent(action, null);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- //intent.setPackage(this.getClass().getPackage().getName());
+ // TODO: Find the correct value so this is not hard coded
intent.setPackage("android");
return PendingIntent.getBroadcast(mContext, requestCode, intent, 0);
}
@@ -1783,8 +1866,40 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
}
+ int startWifiIPPacketOffload(int slot, KeepalivePacketData packetData, int intervalSeconds) {
+ int ret = mWifiNative.startSendingOffloadedPacket(slot, packetData, intervalSeconds * 1000);
+ if (ret != 0) {
+ loge("startWifiIPPacketOffload(" + slot + ", " + intervalSeconds +
+ "): hardware error " + ret);
+ return ConnectivityManager.PacketKeepalive.ERROR_HARDWARE_ERROR;
+ } else {
+ return ConnectivityManager.PacketKeepalive.SUCCESS;
+ }
+ }
+
+ int stopWifiIPPacketOffload(int slot) {
+ int ret = mWifiNative.stopSendingOffloadedPacket(slot);
+ if (ret != 0) {
+ loge("stopWifiIPPacketOffload(" + slot + "): hardware error " + ret);
+ return ConnectivityManager.PacketKeepalive.ERROR_HARDWARE_ERROR;
+ } else {
+ return ConnectivityManager.PacketKeepalive.SUCCESS;
+ }
+ }
+
+ int startRssiMonitoringOffload(byte maxRssi, byte minRssi) {
+ return mWifiNative.startRssiMonitoring(maxRssi, minRssi, WifiStateMachine.this);
+ }
+
+ int stopRssiMonitoringOffload() {
+ return mWifiNative.stopRssiMonitoring();
+ }
+
// If workSource is not null, blame is given to it, otherwise blame is given to callingUid.
private void noteScanStart(int callingUid, WorkSource workSource) {
+ if (lastStartScanTimeStamp != 0) {
+ noteScanEnd();
+ }
long now = System.currentTimeMillis();
lastStartScanTimeStamp = now;
lastScanDuration = 0;
@@ -1804,14 +1919,13 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
|| workSource != null)) {
mScanWorkSource = workSource != null ? workSource : new WorkSource(callingUid);
- WorkSource batteryWorkSource = mScanWorkSource;
if (mScanWorkSource.size() == 1 && mScanWorkSource.get(0) < 0) {
// WiFi uses negative UIDs to mean special things. BatteryStats don't care!
- batteryWorkSource = new WorkSource(Process.WIFI_UID);
+ mScanWorkSource = new WorkSource(Process.WIFI_UID);
}
try {
- mBatteryStats.noteWifiScanStartedFromSource(batteryWorkSource);
+ mBatteryStats.noteWifiScanStartedFromSource(mScanWorkSource);
} catch (RemoteException e) {
log(e.toString());
}
@@ -1819,6 +1933,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
private void noteScanEnd() {
+ closeRadioScanStats();
long now = System.currentTimeMillis();
if (lastStartScanTimeStamp != 0) {
lastScanDuration = now - lastStartScanTimeStamp;
@@ -2242,7 +2357,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
if (enable) {
mWifiConfigStore.enableAllNetworks();
}
- boolean ret = mWifiNative.enableBackgroundScan(enable);
+ List<WifiNative.PnoNetworkPriority> pnoList =
+ mWifiConfigStore.retrievePnoNetworkPriorityList(enable);
+ boolean ret = mWifiNative.enableBackgroundScan(enable, pnoList);
if (ret) {
mLegacyPnoEnabled = enable;
} else {
@@ -2328,25 +2445,31 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
// for now (it is unclear what the chipset should do when
// country code is reset)
+ // if mCountryCodeSequence == 0, it is the first time to set country code, always set
+ // else only when the new country code is different from the current one to set
+
if (TextUtils.isEmpty(countryCode)) {
- log("Ignoring resetting of country code");
+ if (DBG) log("Ignoring resetting of country code");
} else {
- // if mCountryCodeSequence == 0, it is the first time to set country code, always set
- // else only when the new country code is different from the current one to set
int countryCodeSequence = mCountryCodeSequence.get();
- if (countryCodeSequence == 0 || countryCode.equals(mSetCountryCode) == false) {
+ String currentCountryCode = getCurrentCountryCode();
+ if (countryCodeSequence == 0
+ || TextUtils.equals(countryCode, currentCountryCode) == false) {
countryCodeSequence = mCountryCodeSequence.incrementAndGet();
- mSetCountryCode = countryCode;
- sendMessage(CMD_SET_COUNTRY_CODE, countryCodeSequence, persist ? 1 : 0,
+ sendMessage(CMD_SET_COUNTRY_CODE, countryCodeSequence, persist ? 1 : 0,
countryCode);
}
+ }
+ }
- if (persist) {
- Settings.Global.putString(mContext.getContentResolver(),
- Settings.Global.WIFI_COUNTRY_CODE,
- countryCode);
- }
+ /**
+ * reset the country code to default
+ */
+ public synchronized void resetCountryCode() {
+ if (mRevertCountryCodeOnCellularLoss && TextUtils.isEmpty(mDefaultCountryCode) == false) {
+ logd("resetting country code to " + mDefaultCountryCode);
+ setCountryCode(mDefaultCountryCode, /* persist = */ true);
}
}
@@ -2365,13 +2488,13 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
/**
* Get the country code
*
- * @param countryCode following ISO 3166 format
+ * @return countryCode following ISO 3166 format
*/
- public String getCountryCode() {
- return mSetCountryCode;
+ public String getCurrentCountryCode() {
+ return Settings.Global.getString(
+ mContext.getContentResolver(), Settings.Global.WIFI_COUNTRY_CODE);
}
-
/**
* Set the operational frequency band
*
@@ -2499,7 +2622,6 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
pw.println("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled);
pw.println("Supplicant status " + mWifiNative.status(true));
pw.println("mLegacyPnoEnabled " + mLegacyPnoEnabled);
- pw.println("mSetCountryCode " + mSetCountryCode);
pw.println("mDriverSetCountryCode " + mDriverSetCountryCode);
pw.println("mConnectedModeGScanOffloadStarted " + mConnectedModeGScanOffloadStarted);
pw.println("mGScanPeriodMilli " + mGScanPeriodMilli);
@@ -3123,6 +3245,14 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
sb.append(Integer.toString(msg.arg2));
sb.append(" cur=").append(disconnectingWatchdogCount);
break;
+ case CMD_START_RSSI_MONITORING_OFFLOAD:
+ case CMD_STOP_RSSI_MONITORING_OFFLOAD:
+ case CMD_RSSI_THRESHOLD_BREACH:
+ sb.append(" rssi=");
+ sb.append(Integer.toString(msg.arg1));
+ sb.append(" thresholds=");
+ sb.append(Arrays.toString(mRssiRanges));
+ break;
default:
sb.append(" ");
sb.append(Integer.toString(msg.arg1));
@@ -3426,7 +3556,6 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
+ " suppState:" + mSupplicantStateTracker.getSupplicantStateName());
}
enableRssiPolling(screenOn);
- if (screenOn) enableAllNetworks();
if (mUserWantsSuspendOpt.get()) {
if (screenOn) {
sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 0, 0);
@@ -3588,9 +3717,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
/**
* Set the country code from the system setting value, if any.
*/
- private void setCountryCode() {
- String countryCode = Settings.Global.getString(mContext.getContentResolver(),
- Settings.Global.WIFI_COUNTRY_CODE);
+ private void initializeCountryCode() {
+ String countryCode = getCurrentCountryCode();
if (countryCode != null && !countryCode.isEmpty()) {
setCountryCode(countryCode, false);
} else {
@@ -3615,8 +3743,6 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
}
-
-
private void setSuspendOptimizationsNative(int reason, boolean enabled) {
if (DBG) {
log("setSuspendOptimizationsNative: " + reason + " " + enabled
@@ -3711,21 +3837,6 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
- /*
- void ageOutScanResults(int age) {
- synchronized(mScanResultCache) {
- // Trim mScanResults, which prevent WifiStateMachine to return
- // obsolete scan results to queriers
- long now = System.CurrentTimeMillis();
- for (int i = 0; i < mScanResults.size(); i++) {
- ScanResult result = mScanResults.get(i);
- if ((result.seen > now || (now - result.seen) > age)) {
- mScanResults.remove(i);
- }
- }
- }
- }*/
-
private static final String IE_STR = "ie=";
private static final String ID_STR = "id=";
private static final String BSSID_STR = "bssid=";
@@ -3737,8 +3848,6 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
private static final String DELIMITER_STR = "====";
private static final String END_STR = "####";
- int emptyScanResultCount = 0;
-
// Used for matching BSSID strings, at least one characteer must be a non-zero number
private static Pattern mNotZero = Pattern.compile("[1-9a-fA-F]");
@@ -3798,23 +3907,13 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
if (sid == -1) break;
}
- // Age out scan results, we return all scan results found in the last 12 seconds,
- // and NOT all scan results since last scan.
- // ageOutScanResults(12000);
-
scanResults = scanResultsBuf.toString();
+
if (TextUtils.isEmpty(scanResults)) {
- emptyScanResultCount++;
- if (emptyScanResultCount > 10) {
- // If we got too many empty scan results, the current scan cache is stale,
- // hence clear it.
- mScanResults = new ArrayList<>();
- }
+ mScanResults = new ArrayList<>();
return;
}
- emptyScanResultCount = 0;
-
mWifiConfigStore.trimANQPCache(false);
// note that all these splits and substrings keep references to the original
@@ -3929,7 +4028,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
|| state == SupplicantState.GROUP_HANDSHAKE
|| (/* keep autojoin enabled if user has manually selected a wifi network,
so as to make sure we reliably remain connected to this network */
- mConnectionRequests == 0 && selection == null)) {
+ mConnectionRequests == 0 && selection == null)
+ || mInDelayedStop) {
// Dont attempt auto-joining again while we are already attempting to join
// and/or obtaining Ip address
attemptAutoJoin = false;
@@ -3974,9 +4074,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
* Fetch RSSI, linkspeed, and frequency on current connection
*/
private void fetchRssiLinkSpeedAndFrequencyNative() {
- int newRssi = -1;
- int newLinkSpeed = -1;
- int newFrequency = -1;
+ Integer newRssi = null;
+ Integer newLinkSpeed = null;
+ Integer newFrequency = null;
String signalPoll = mWifiNative.signalPoll();
@@ -4000,12 +4100,11 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
if (PDBG) {
- logd("fetchRssiLinkSpeedAndFrequencyNative rssi="
- + Integer.toString(newRssi) + " linkspeed="
- + Integer.toString(newLinkSpeed));
+ logd("fetchRssiLinkSpeedAndFrequencyNative rssi=" + newRssi +
+ " linkspeed=" + newLinkSpeed + " freq=" + newFrequency);
}
- if (newRssi > WifiInfo.INVALID_RSSI && newRssi < WifiInfo.MAX_RSSI) {
+ if (newRssi != null && newRssi > WifiInfo.INVALID_RSSI && newRssi < WifiInfo.MAX_RSSI) {
// screen out invalid values
/* some implementations avoid negative values by adding 256
* so we need to adjust for that here.
@@ -4024,17 +4123,19 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
*/
int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, WifiManager.RSSI_LEVELS);
if (newSignalLevel != mLastSignalLevel) {
+ updateCapabilities(getCurrentWifiConfiguration());
sendRssiChangeBroadcast(newRssi);
}
mLastSignalLevel = newSignalLevel;
} else {
mWifiInfo.setRssi(WifiInfo.INVALID_RSSI);
+ updateCapabilities(getCurrentWifiConfiguration());
}
- if (newLinkSpeed != -1) {
+ if (newLinkSpeed != null) {
mWifiInfo.setLinkSpeed(newLinkSpeed);
}
- if (newFrequency > 0) {
+ if (newFrequency != null && newFrequency > 0) {
if (ScanResult.is5GHz(newFrequency)) {
mWifiConnectionStatistics.num5GhzConnected++;
}
@@ -4856,6 +4957,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
+ " - " + Thread.currentThread().getStackTrace()[4].getMethodName()
+ " - " + Thread.currentThread().getStackTrace()[5].getMethodName());
+ stopRssiMonitoringOffload();
clearCurrentConfigBSSID("handleNetworkDisconnect");
@@ -5204,8 +5306,10 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
//not available, like razor, we regress to original implementaion (2GHz, channel 6)
if (mWifiNative.isHalStarted()) {
//set country code through HAL Here
- if (mSetCountryCode != null) {
- if (!mWifiNative.setCountryCodeHal(mSetCountryCode.toUpperCase(Locale.ROOT))) {
+ String countryCode = getCurrentCountryCode();
+
+ if (countryCode != null) {
+ if (!mWifiNative.setCountryCodeHal(countryCode.toUpperCase(Locale.ROOT))) {
if (config.apBand != 0) {
Log.e(TAG, "Fail to set country code. Can not setup Softap on 5GHz");
//countrycode is mandatory for 5GHz
@@ -5264,6 +5368,19 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}).start();
}
+ private byte[] macAddressFromString(String macString) {
+ String[] macBytes = macString.split(":");
+ if (macBytes.length != 6) {
+ throw new IllegalArgumentException("MAC address should be 6 bytes long!");
+ }
+ byte[] mac = new byte[6];
+ for (int i = 0; i < macBytes.length; i++) {
+ Integer hexVal = Integer.parseInt(macBytes[i], 16);
+ mac[i] = hexVal.byteValue();
+ }
+ return mac;
+ }
+
/*
* Read a MAC address in /proc/arp/table, used by WifistateMachine
* so as to record MAC address of default gateway.
@@ -5492,7 +5609,6 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
case CMD_BLACKLIST_NETWORK:
case CMD_CLEAR_BLACKLIST:
case CMD_SET_OPERATIONAL_MODE:
- case CMD_SET_COUNTRY_CODE:
case CMD_SET_FREQUENCY_BAND:
case CMD_RSSI_POLL:
case CMD_ENABLE_ALL_NETWORKS:
@@ -5526,6 +5642,24 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
case CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION:
messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
break;
+ case CMD_SET_COUNTRY_CODE:
+ String country = (String) message.obj;
+ final boolean persist = (message.arg2 == 1);
+ final int sequence = message.arg1;
+ if (sequence != mCountryCodeSequence.get()) {
+ if (DBG) log("set country code ignored due to sequnce num");
+ break;
+ }
+
+ if (persist) {
+ country = country.toUpperCase(Locale.ROOT);
+ if (DBG) log("set country code " + (country == null ? "(null)" : country));
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.WIFI_COUNTRY_CODE,
+ country == null ? "" : country);
+ }
+
+ break;
case DhcpStateMachine.CMD_ON_QUIT:
mDhcpStateMachine = null;
break;
@@ -5613,6 +5747,22 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
case CMD_REMOVE_USER_CONFIGURATIONS:
deferMessage(message);
break;
+ case CMD_START_IP_PACKET_OFFLOAD:
+ if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent(
+ message.arg1,
+ ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
+ break;
+ case CMD_STOP_IP_PACKET_OFFLOAD:
+ if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent(
+ message.arg1,
+ ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
+ break;
+ case CMD_START_RSSI_MONITORING_OFFLOAD:
+ messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
+ break;
+ case CMD_STOP_RSSI_MONITORING_OFFLOAD:
+ messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
+ break;
default:
loge("Error! unhandled message" + message);
break;
@@ -5843,7 +5993,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
WifiNative.setDfsFlag(true);
/* set country code */
- setCountryCode();
+ initializeCountryCode();
setRandomMacOui();
mWifiNative.enableAutoConnect(false);
@@ -5876,7 +6026,6 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
case WifiMonitor.SCAN_RESULTS_EVENT:
case WifiMonitor.SCAN_FAILED_EVENT:
maybeRegisterNetworkFactory(); // Make sure our NetworkFactory is registered
- closeRadioScanStats();
noteScanEnd();
setScanResults();
if (mIsFullScanOngoing || mSendScanResultsBroadcast) {
@@ -5924,18 +6073,18 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
break;
case CMD_SET_COUNTRY_CODE:
String country = (String) message.obj;
-
final boolean persist = (message.arg2 == 1);
final int sequence = message.arg1;
-
if (sequence != mCountryCodeSequence.get()) {
if (DBG) log("set country code ignored due to sequnce num");
break;
}
- if (DBG) log("set country code " + country);
+
country = country.toUpperCase(Locale.ROOT);
- if (mDriverSetCountryCode == null || !mDriverSetCountryCode.equals(country)) {
+ if (DBG) log("set country code " + (country == null ? "(null)" : country));
+
+ if (!TextUtils.equals(mDriverSetCountryCode, country)) {
if (mWifiNative.setCountryCode(country)) {
mDriverSetCountryCode = country;
} else {
@@ -5943,6 +6092,12 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
}
+ if (persist) {
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.WIFI_COUNTRY_CODE,
+ country == null ? "" : country);
+ }
+
mWifiP2pChannel.sendMessage(WifiP2pServiceImpl.SET_COUNTRY_CODE, country);
break;
default:
@@ -6241,7 +6396,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
/* send regular delayed shut down */
Intent driverStopIntent = new Intent(ACTION_DELAYED_DRIVER_STOP, null);
- driverStopIntent.setPackage(this.getClass().getPackage().getName());
+ driverStopIntent.setPackage("android");
driverStopIntent.putExtra(DELAYED_STOP_COUNTER, mDelayedStopCounter);
mDriverStopIntent = PendingIntent.getBroadcast(mContext,
DRIVER_STOP_REQUEST, driverStopIntent,
@@ -6320,6 +6475,14 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
case WifiMonitor.ANQP_DONE_EVENT:
mWifiConfigStore.notifyANQPDone((Long) message.obj, message.arg1 != 0);
break;
+ case CMD_STOP_IP_PACKET_OFFLOAD: {
+ int slot = message.arg1;
+ int ret = stopWifiIPPacketOffload(slot);
+ if (mNetworkAgent != null) {
+ mNetworkAgent.onPacketKeepaliveEvent(slot, ret);
+ }
+ break;
+ }
default:
return NOT_HANDLED;
}
@@ -6505,6 +6668,10 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
case CMD_START_SCAN:
handleScanRequest(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, message);
break;
+ case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
+ SupplicantState state = handleSupplicantStateChange(message);
+ if(DBG) log("SupplicantState= " + state);
+ break;
default:
return NOT_HANDLED;
}
@@ -6760,6 +6927,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
case WifiMonitor.GAS_QUERY_START_EVENT:
s = "WifiMonitor.GAS_QUERY_START_EVENT";
break;
+ case WifiMonitor.RSN_PMKID_MISMATCH_EVENT:
+ s = "WifiMonitor.RSN_PMKID_MISMATCH_EVENT";
+ break;
case CMD_SET_OPERATIONAL_MODE:
s = "CMD_SET_OPERATIONAL_MODE";
break;
@@ -6877,6 +7047,21 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
case CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION:
s = "CMD_UPDATE_ASSOCIATED_SCAN_PERMISSION";
break;
+ case CMD_START_IP_PACKET_OFFLOAD:
+ s = "CMD_START_IP_PACKET_OFFLOAD";
+ break;
+ case CMD_STOP_IP_PACKET_OFFLOAD:
+ s = "CMD_STOP_IP_PACKET_OFFLOAD";
+ break;
+ case CMD_START_RSSI_MONITORING_OFFLOAD:
+ s = "CMD_START_RSSI_MONITORING_OFFLOAD";
+ break;
+ case CMD_STOP_RSSI_MONITORING_OFFLOAD:
+ s = "CMD_STOP_RSSI_MONITORING_OFFLOAD";
+ break;
+ case CMD_RSSI_THRESHOLD_BREACH:
+ s = "CMD_RSSI_THRESHOLD_BREACH";
+ break;
default:
s = "what:" + Integer.toString(what);
break;
@@ -7065,6 +7250,13 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
mIpReachabilityMonitor.probeAll();
}
}
+
+ if (state == SupplicantState.ASSOCIATED) {
+ StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
+ if (stateChangeResult != null) {
+ mCurrentAssociateNetworkId = stateChangeResult.networkId;
+ }
+ }
break;
case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST:
if (message.arg1 == 1) {
@@ -7769,13 +7961,17 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
private void updateCapabilities(WifiConfiguration config) {
- if (config.ephemeral) {
- mNetworkCapabilities.removeCapability(
- NetworkCapabilities.NET_CAPABILITY_TRUSTED);
- } else {
- mNetworkCapabilities.addCapability(
- NetworkCapabilities.NET_CAPABILITY_TRUSTED);
+ if (config != null) {
+ if (config.ephemeral) {
+ mNetworkCapabilities.removeCapability(
+ NetworkCapabilities.NET_CAPABILITY_TRUSTED);
+ } else {
+ mNetworkCapabilities.addCapability(
+ NetworkCapabilities.NET_CAPABILITY_TRUSTED);
+ }
}
+ mNetworkCapabilities.setSignalStrength(mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI ?
+ mWifiInfo.getRssi() : NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED);
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
}
@@ -7813,6 +8009,59 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
@Override
+ protected void startPacketKeepalive(Message msg) {
+ WifiStateMachine.this.sendMessage(
+ CMD_START_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj);
+ }
+
+ @Override
+ protected void stopPacketKeepalive(Message msg) {
+ WifiStateMachine.this.sendMessage(
+ CMD_STOP_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj);
+ }
+
+ @Override
+ protected void setSignalStrengthThresholds(int[] thresholds) {
+ // 0. If there are no thresholds, or if the thresholds are invalid, stop RSSI monitoring.
+ // 1. Tell the hardware to start RSSI monitoring here, possibly adding MIN_VALUE and
+ // MAX_VALUE at the start/end of the thresholds array if necessary.
+ // 2. Ensure that when the hardware event fires, we fetch the RSSI from the hardware
+ // event, call mWifiInfo.setRssi() with it, and call updateCapabilities(), and then
+ // re-arm the hardware event. This needs to be done on the state machine thread to
+ // avoid race conditions. The RSSI used to re-arm the event (and perhaps also the one
+ // sent in the NetworkCapabilities) must be the one received from the hardware event
+ // received, or we might skip callbacks.
+ // 3. Ensure that when we disconnect, RSSI monitoring is stopped.
+ log("Received signal strength thresholds: " + Arrays.toString(thresholds));
+ if (thresholds.length == 0) {
+ WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD,
+ mWifiInfo.getRssi());
+ return;
+ }
+ int [] rssiVals = Arrays.copyOf(thresholds, thresholds.length + 2);
+ rssiVals[rssiVals.length - 2] = Byte.MIN_VALUE;
+ rssiVals[rssiVals.length - 1] = Byte.MAX_VALUE;
+ Arrays.sort(rssiVals);
+ byte[] rssiRange = new byte[rssiVals.length];
+ for (int i = 0; i < rssiVals.length; i++) {
+ int val = rssiVals[i];
+ if (val <= Byte.MAX_VALUE && val >= Byte.MIN_VALUE) {
+ rssiRange[i] = (byte) val;
+ } else {
+ Log.e(TAG, "Illegal value " + val + " for RSSI thresholds: "
+ + Arrays.toString(rssiVals));
+ WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD,
+ mWifiInfo.getRssi());
+ return;
+ }
+ }
+ // TODO: Do we quash rssi values in this sorted array which are very close?
+ mRssiRanges = rssiRange;
+ WifiStateMachine.this.sendMessage(CMD_START_RSSI_MONITORING_OFFLOAD,
+ mWifiInfo.getRssi());
+ }
+
+ @Override
protected void preventAutomaticReconnect() {
if (this != mNetworkAgent) return;
unwantedNetwork(NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN);
@@ -7963,6 +8212,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
try {
mIpReachabilityMonitor = new IpReachabilityMonitor(
+ mContext,
mInterfaceName,
new IpReachabilityMonitor.Callback() {
@Override
@@ -8227,8 +8477,14 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
break;
}
return NOT_HANDLED;
- /* Ignore */
case WifiMonitor.NETWORK_CONNECTION_EVENT:
+ mWifiInfo.setBSSID((String) message.obj);
+ mLastNetworkId = message.arg1;
+ mWifiInfo.setNetworkId(mLastNetworkId);
+ if(!mLastBssid.equals((String) message.obj)) {
+ mLastBssid = (String) message.obj;
+ sendNetworkStateChangeBroadcast(mLastBssid);
+ }
break;
case CMD_RSSI_POLL:
if (message.arg1 == mRssiPollToken) {
@@ -8310,6 +8566,14 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
sendNetworkStateChangeBroadcast(mLastBssid);
}
break;
+ case CMD_START_RSSI_MONITORING_OFFLOAD:
+ case CMD_RSSI_THRESHOLD_BREACH:
+ byte currRssi = (byte) message.arg1;
+ processRssiThreshold(currRssi, message.what);
+ break;
+ case CMD_STOP_RSSI_MONITORING_OFFLOAD:
+ stopRssiMonitoringOffload();
+ break;
default:
return NOT_HANDLED;
}
@@ -8928,6 +9192,27 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
break;
}
break;
+ case CMD_START_IP_PACKET_OFFLOAD: {
+ int slot = message.arg1;
+ int intervalSeconds = message.arg2;
+ KeepalivePacketData pkt = (KeepalivePacketData) message.obj;
+ byte[] dstMac;
+ try {
+ InetAddress gateway = RouteInfo.selectBestRoute(
+ mLinkProperties.getRoutes(), pkt.dstAddress).getGateway();
+ String dstMacStr = macAddressFromRoute(gateway.getHostAddress());
+ dstMac = macAddressFromString(dstMacStr);
+ } catch (NullPointerException|IllegalArgumentException e) {
+ loge("Can't find MAC address for next hop to " + pkt.dstAddress);
+ mNetworkAgent.onPacketKeepaliveEvent(slot,
+ ConnectivityManager.PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
+ break;
+ }
+ pkt.dstMac = dstMac;
+ int result = startWifiIPPacketOffload(slot, pkt, intervalSeconds);
+ mNetworkAgent.onPacketKeepaliveEvent(slot, result);
+ break;
+ }
default:
return NOT_HANDLED;
}
@@ -9033,9 +9318,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
} else {
if (mScreenOn) {
/**
- * screen lit and => delayed timer
+ * screen lit and => start scan immediately
*/
- startDelayedScan(500, null, null);
+ startScan(UNKNOWN_SCAN_SOURCE, 0, null, null);
} else {
/**
* screen dark and PNO supported => scan alarm disabled
@@ -9284,6 +9569,22 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
case CMD_SCREEN_STATE_CHANGED:
handleScreenStateChanged(message.arg1 != 0);
break;
+ case WifiMonitor.RSN_PMKID_MISMATCH_EVENT:
+ //WAR: In release M, there is a TLS bugs for some radius. M upgrade the TLS to
+ // 1.2. However,some old radius can not support it. So if possibly disconnected
+ // due to TLS failure, we will toggler the TLS version between 1.1 and 1.2 for
+ // next retry connection
+ int nid = mCurrentAssociateNetworkId;
+ WifiConfiguration currentNet = mWifiConfigStore.getWifiConfiguration(nid);
+ if (currentNet != null && currentNet.enterpriseConfig != null) {
+ currentNet.enterpriseConfig.setTls12Enable(
+ !currentNet.enterpriseConfig.getTls12Enable());
+ mWifiConfigStore.saveNetwork(currentNet, WifiConfiguration.UNKNOWN_UID);
+ Log.e(TAG, "NetWork ID =" + nid + " switch to TLS1.2: " +
+ currentNet.enterpriseConfig.getTls12Enable());
+ }
+
+ break;
default:
ret = NOT_HANDLED;
}
diff --git a/service/jni/com_android_server_wifi_WifiNative.cpp b/service/jni/com_android_server_wifi_WifiNative.cpp
index bf073f7cd..4c450b3b3 100644
--- a/service/jni/com_android_server_wifi_WifiNative.cpp
+++ b/service/jni/com_android_server_wifi_WifiNative.cpp
@@ -32,7 +32,7 @@
#include "jni_helper.h"
#include "rtt.h"
#include "wifi_hal_stub.h"
-#define REPLY_BUF_SIZE 4096 // wpa_supplicant's maximum size.
+#define REPLY_BUF_SIZE 4096 + 1 // wpa_supplicant's maximum size + 1 for nul
#define EVENT_BUF_SIZE 2048
namespace android {
@@ -138,7 +138,12 @@ static jboolean doBooleanCommand(JNIEnv* env, jstring javaCommand) {
if (!doCommand(env, javaCommand, reply, sizeof(reply))) {
return JNI_FALSE;
}
- return (strcmp(reply, "OK") == 0);
+ jboolean result = (strcmp(reply, "OK") == 0);
+ if (!result) {
+ ScopedUtfChars command(env, javaCommand);
+ ALOGI("command '%s' returned '%s", command.c_str(), reply);
+ }
+ return result;
}
// Send a command to the supplicant, and return the reply as a String.
@@ -2080,6 +2085,88 @@ static jboolean android_net_wifi_setSsidWhitelist(
return hal_fn.wifi_set_ssid_white_list(id, handle, num_ssids, ssids) == WIFI_SUCCESS;
}
+static jint android_net_wifi_start_sending_offloaded_packet(JNIEnv *env, jclass cls, jint iface,
+ jint idx, jbyteArray srcMac, jbyteArray dstMac, jbyteArray pkt, jint period) {
+ JNIHelper helper(env);
+ wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
+ ALOGD("Start packet offload [%d] = %p", idx, handle);
+ wifi_error ret;
+ wifi_request_id id = idx;
+
+ ScopedBytesRO pktBytes(env, pkt), srcMacBytes(env, srcMac), dstMacBytes(env, dstMac);
+
+ byte * pkt_data = (byte*) pktBytes.get();
+ unsigned short pkt_len = env->GetArrayLength(pkt);
+ byte* src_mac_addr = (byte*) srcMacBytes.get();
+ byte* dst_mac_addr = (byte*) dstMacBytes.get();
+ int i;
+ char macAddr[32];
+ sprintf(macAddr, "%0x:%0x:%0x:%0x:%0x:%0x", src_mac_addr[0], src_mac_addr[1],
+ src_mac_addr[2], src_mac_addr[3], src_mac_addr[4], src_mac_addr[5]);
+ ALOGD("src_mac_addr %s", macAddr);
+ sprintf(macAddr, "%0x:%0x:%0x:%0x:%0x:%0x", dst_mac_addr[0], dst_mac_addr[1],
+ dst_mac_addr[2], dst_mac_addr[3], dst_mac_addr[4], dst_mac_addr[5]);
+ ALOGD("dst_mac_addr %s", macAddr);
+ ALOGD("pkt_len %d\n", pkt_len);
+ ALOGD("Pkt data : ");
+ for(i = 0; i < pkt_len; i++) {
+ ALOGD(" %x ", pkt_data[i]);
+ }
+ ALOGD("\n");
+ ret = hal_fn.wifi_start_sending_offloaded_packet(id, handle, pkt_data, pkt_len,
+ src_mac_addr, dst_mac_addr, period);
+ ALOGD("ret= %d\n", ret);
+ return ret;
+}
+
+static jint android_net_wifi_stop_sending_offloaded_packet(JNIEnv *env, jclass cls,
+ jint iface, jint idx) {
+ int ret;
+ JNIHelper helper(env);
+ wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
+ ALOGD("Stop packet offload [%d] = %p", idx, handle);
+ ret = hal_fn.wifi_stop_sending_offloaded_packet(idx, handle);
+ ALOGD("ret= %d\n", ret);
+ return ret;
+}
+
+static void onRssiThresholdbreached(wifi_request_id id, u8 *cur_bssid, s8 cur_rssi) {
+
+ ALOGD("RSSI threshold breached, cur RSSI - %d!!\n", cur_rssi);
+ ALOGD("BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
+ cur_bssid[0], cur_bssid[1], cur_bssid[2],
+ cur_bssid[3], cur_bssid[4], cur_bssid[5]);
+ JNIHelper helper(mVM);
+ //ALOGD("onRssiThresholdbreached called, vm = %p, obj = %p, env = %p", mVM, mCls, env);
+ helper.reportEvent(mCls, "onRssiThresholdBreached", "(IB)V", id, cur_rssi);
+}
+
+static jint android_net_wifi_start_rssi_monitoring_native(JNIEnv *env, jclass cls, jint iface,
+ jint idx, jbyte maxRssi, jbyte minRssi) {
+
+ JNIHelper helper(env);
+ wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
+ ALOGD("Start Rssi monitoring = %p", handle);
+ ALOGD("MinRssi %d MaxRssi %d", minRssi, maxRssi);
+ wifi_error ret;
+ wifi_request_id id = idx;
+ wifi_rssi_event_handler eh;
+ eh.on_rssi_threshold_breached = onRssiThresholdbreached;
+ ret = hal_fn.wifi_start_rssi_monitoring(id, handle, maxRssi, minRssi, eh);
+ return ret;
+}
+
+static jint android_net_wifi_stop_rssi_monitoring_native(JNIEnv *env, jclass cls,
+ jint iface, jint idx) {
+ JNIHelper helper(env);
+ wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
+ ALOGD("Stop Rssi monitoring = %p", handle);
+ wifi_error ret;
+ wifi_request_id id = idx;
+ ret = hal_fn.wifi_stop_rssi_monitoring(id, handle);
+ return ret;
+}
+
// ----------------------------------------------------------------------------
/*
@@ -2167,6 +2254,14 @@ static JNINativeMethod gWifiMethods[] = {
(void*)android_net_wifi_setSsidWhitelist},
{"setLoggingEventHandlerNative", "(II)Z", (void *) android_net_wifi_set_log_handler},
{"resetLogHandlerNative", "(II)Z", (void *) android_net_wifi_reset_log_handler},
+ { "startSendingOffloadedPacketNative", "(II[B[B[BI)I",
+ (void*)android_net_wifi_start_sending_offloaded_packet},
+ { "stopSendingOffloadedPacketNative", "(II)I",
+ (void*)android_net_wifi_stop_sending_offloaded_packet},
+ {"startRssiMonitoringNative", "(IIBB)I",
+ (void*)android_net_wifi_start_rssi_monitoring_native},
+ {"stopRssiMonitoringNative", "(II)I",
+ (void*)android_net_wifi_stop_rssi_monitoring_native},
{"isGetChannelsForBandSupportedNative", "()Z",
(void*)android_net_wifi_is_get_channels_for_band_supported}
};