summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--service/Android.mk9
-rw-r--r--service/java/com/android/server/wifi/ScanDetailCache.java37
-rw-r--r--service/java/com/android/server/wifi/SupplicantStateTracker.java8
-rw-r--r--service/java/com/android/server/wifi/WifiApConfigStore.java37
-rw-r--r--service/java/com/android/server/wifi/WifiAutoJoinController.java78
-rw-r--r--service/java/com/android/server/wifi/WifiConfigStore.java440
-rw-r--r--service/java/com/android/server/wifi/WifiController.java195
-rw-r--r--service/java/com/android/server/wifi/WifiMonitor.java36
-rw-r--r--service/java/com/android/server/wifi/WifiNative.java47
-rw-r--r--service/java/com/android/server/wifi/WifiNotificationController.java45
-rw-r--r--service/java/com/android/server/wifi/WifiScanningServiceImpl.java6
-rw-r--r--service/java/com/android/server/wifi/WifiServiceImpl.java84
-rw-r--r--service/java/com/android/server/wifi/WifiStateMachine.java710
-rw-r--r--service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java237
-rw-r--r--service/jni/COPYING22
-rw-r--r--service/jni/README56
-rw-r--r--service/jni/com_android_server_wifi_Gbk2Utf.cpp605
-rw-r--r--service/jni/com_android_server_wifi_Gbk2Utf.h56
-rw-r--r--service/jni/com_android_server_wifi_WifiNative.cpp77
19 files changed, 2495 insertions, 290 deletions
diff --git a/service/Android.mk b/service/Android.mk
index f325782..a347c9c 100644
--- a/service/Android.mk
+++ b/service/Android.mk
@@ -86,6 +86,8 @@ LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
$(call include-path-for, libhardware)/hardware \
$(call include-path-for, libhardware_legacy)/hardware_legacy \
+ external/icu/icu4c/source/common \
+ external/icu/icu4c/source/i18n \
libcore/include
LOCAL_SHARED_LIBRARIES += \
@@ -96,13 +98,16 @@ LOCAL_SHARED_LIBRARIES += \
libhardware_legacy \
libandroid_runtime \
libnl \
- libdl
+ libicuuc \
+ libicui18n \
+ libdl
LOCAL_STATIC_LIBRARIES += libwifi-hal-stub
LOCAL_STATIC_LIBRARIES += $(LIB_WIFI_HAL)
LOCAL_SRC_FILES := \
jni/com_android_server_wifi_WifiNative.cpp \
+ jni/com_android_server_wifi_Gbk2Utf.cpp \
jni/jni_helper.cpp
LOCAL_MODULE := libwifi-service
@@ -120,7 +125,7 @@ LOCAL_SRC_FILES := $(call all-java-files-under, java) \
$(call all-logtags-files-under, java)
LOCAL_JNI_SHARED_LIBRARIES := libandroid_runtime
-LOCAL_JAVA_LIBRARIES := bouncycastle conscrypt services
+LOCAL_JAVA_LIBRARIES := bouncycastle conscrypt services org.cyanogenmod.platform.internal
LOCAL_STATIC_JAVA_LIBRARIES := ksoap2 android-support-v4
LOCAL_REQUIRED_MODULES := services
LOCAL_MODULE_TAGS :=
diff --git a/service/java/com/android/server/wifi/ScanDetailCache.java b/service/java/com/android/server/wifi/ScanDetailCache.java
index d246c55..5030ef9 100644
--- a/service/java/com/android/server/wifi/ScanDetailCache.java
+++ b/service/java/com/android/server/wifi/ScanDetailCache.java
@@ -3,6 +3,7 @@ package com.android.server.wifi;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
import android.util.Log;
import android.os.SystemClock;
@@ -145,20 +146,32 @@ class ScanDetailCache {
}
public WifiConfiguration.Visibility getVisibilityByRssi(long age) {
+ return getVisibilityByRssi(age, WifiManager.WIFI_FREQUENCY_BAND_AUTO);
+ }
+
+ public WifiConfiguration.Visibility getVisibilityByRssi(long age, int configBand) {
WifiConfiguration.Visibility status = new WifiConfiguration.Visibility();
long now_ms = System.currentTimeMillis();
long now_elapsed_ms = SystemClock.elapsedRealtime();
+ boolean isNetworkFound = false;
+ String profileConfigKey = mConfig.configKey();
for(ScanDetail scanDetail : values()) {
ScanResult result = scanDetail.getScanResult();
if (scanDetail.getSeen() == 0)
continue;
if (result.is5GHz()) {
+ if (configBand == WifiManager.WIFI_FREQUENCY_BAND_2GHZ) {
+ continue;
+ }
//strictly speaking: [4915, 5825]
//number of known BSSID on 5GHz band
status.num5 = status.num5 + 1;
} else if (result.is24GHz()) {
+ if (configBand == WifiManager.WIFI_FREQUENCY_BAND_5GHZ) {
+ continue;
+ }
//strictly speaking: [2412, 2482]
//number of known BSSID on 2.4Ghz band
status.num24 = status.num24 + 1;
@@ -177,12 +190,18 @@ class ScanDetailCache {
}
if (result.is5GHz()) {
+ if (profileConfigKey.equals(WifiConfiguration.configKey(result))) {
+ isNetworkFound = true;
+ }
if (result.level > status.rssi5) {
status.rssi5 = result.level;
status.age5 = result.seen;
status.BSSID5 = result.BSSID;
}
} else if (result.is24GHz()) {
+ if (profileConfigKey.equals(WifiConfiguration.configKey(result))) {
+ isNetworkFound = true;
+ }
if (result.level > status.rssi24) {
status.rssi24 = result.level;
status.age24 = result.seen;
@@ -190,8 +209,16 @@ class ScanDetailCache {
}
}
}
-
- return status;
+ /*
+ * Visibility should be set to null if there is no BSSIDs in
+ * both bands,so that auto join will not consider this network
+ * for connection attempt.
+ */
+ if (isNetworkFound) {
+ return status;
+ } else {
+ return null;
+ }
}
public WifiConfiguration.Visibility getVisibilityByPasspointMatch(long age) {
@@ -244,10 +271,14 @@ class ScanDetailCache {
}
public WifiConfiguration.Visibility getVisibility(long age) {
+ return getVisibility(age, WifiManager.WIFI_FREQUENCY_BAND_AUTO);
+ }
+
+ public WifiConfiguration.Visibility getVisibility(long age, int configBand) {
if (mConfig.isPasspoint()) {
return getVisibilityByPasspointMatch(age);
} else {
- return getVisibilityByRssi(age);
+ return getVisibilityByRssi(age, configBand);
}
}
diff --git a/service/java/com/android/server/wifi/SupplicantStateTracker.java b/service/java/com/android/server/wifi/SupplicantStateTracker.java
index 219140d..1c7e48c 100644
--- a/service/java/com/android/server/wifi/SupplicantStateTracker.java
+++ b/service/java/com/android/server/wifi/SupplicantStateTracker.java
@@ -28,6 +28,7 @@ import android.content.Context;
import android.content.Intent;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.Message;
@@ -126,6 +127,13 @@ class SupplicantStateTracker extends StateMachine {
mWifiConfigStore.enableAllNetworks();
mNetworksDisabledDuringConnect = false;
}
+ WifiConfiguration config = mWifiConfigStore.getWifiConfiguration(netId);
+ if ((config != null) &&
+ config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) &&
+ (disableReason == WifiConfiguration.DISABLED_AUTH_FAILURE)) {
+ config.setAutoJoinStatus(WifiConfiguration.AUTO_JOIN_DISABLED_ON_AUTH_FAILURE);
+ }
+
/* Disable failed network */
mWifiConfigStore.disableNetwork(netId, disableReason);
}
diff --git a/service/java/com/android/server/wifi/WifiApConfigStore.java b/service/java/com/android/server/wifi/WifiApConfigStore.java
index ed5ddf7..3fae0d8 100644
--- a/service/java/com/android/server/wifi/WifiApConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiApConfigStore.java
@@ -19,10 +19,12 @@ package com.android.server.wifi;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
+import android.text.TextUtils;
import android.util.Log;
import com.android.internal.util.AsyncChannel;
@@ -180,6 +182,10 @@ class WifiApConfigStore extends StateMachine {
if (authType != KeyMgmt.NONE) {
config.preSharedKey = in.readUTF();
}
+ // read in wifiApInactivityTimeout if bytes are available from in
+ if (in.available() != 0) {
+ config.wifiApInactivityTimeout = in.readLong();
+ }
mWifiApConfig = config;
} catch (IOException ignore) {
@@ -212,6 +218,7 @@ class WifiApConfigStore extends StateMachine {
if(authType != KeyMgmt.NONE) {
out.writeUTF(config.preSharedKey);
}
+ out.writeLong(config.wifiApInactivityTimeout);
} catch (IOException e) {
Log.e(TAG, "Error writing hotspot configuration" + e);
} finally {
@@ -229,11 +236,31 @@ class WifiApConfigStore extends StateMachine {
will keep the device secure after the update */
private void setDefaultApConfiguration() {
WifiConfiguration config = new WifiConfiguration();
- config.SSID = mContext.getString(R.string.wifi_tether_configure_ssid_default);
- config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
- String randomUUID = UUID.randomUUID().toString();
- //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
- config.preSharedKey = randomUUID.substring(0, 8) + randomUUID.substring(9,13);
+
+ config.SSID = mContext.getResources().getString(
+ org.cyanogenmod.platform.internal.R.string.config_wifiHotSpotSsid);
+ if (TextUtils.isEmpty(config.SSID)) {
+ config.SSID = mContext.getString(R.string.wifi_tether_configure_ssid_default);
+ }
+ if (TextUtils.isEmpty(config.SSID)) {
+ config.SSID = Build.MODEL;
+ }
+
+ boolean set_security_none = mContext.getResources().getBoolean(
+ org.cyanogenmod.platform.internal.R.bool.config_wifiHotspotSecurityNone);
+ config.allowedKeyManagement.set(set_security_none ? KeyMgmt.NONE : KeyMgmt.WPA2_PSK);
+
+ config.preSharedKey = mContext.getResources().getString(
+ org.cyanogenmod.platform.internal.R.string.config_wifiHotSpotPass);
+ if (TextUtils.isEmpty(config.preSharedKey)) {
+ String randomUUID = UUID.randomUUID().toString();
+ // first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
+ config.preSharedKey = randomUUID.substring(0, 8)
+ + randomUUID.substring(9, 13);
+ }
+ config.wifiApInactivityTimeout = 0;
+
sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG, config);
}
+
}
diff --git a/service/java/com/android/server/wifi/WifiAutoJoinController.java b/service/java/com/android/server/wifi/WifiAutoJoinController.java
index a1a9a82..e525949 100644
--- a/service/java/com/android/server/wifi/WifiAutoJoinController.java
+++ b/service/java/com/android/server/wifi/WifiAutoJoinController.java
@@ -24,6 +24,7 @@ import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConnectionStatistics;
+import android.net.wifi.WifiManager;
import android.os.Process;
import android.provider.Settings;
import android.text.TextUtils;
@@ -67,6 +68,8 @@ public class WifiAutoJoinController {
private final HashMap<String, ScanDetail> scanResultCache = new HashMap<>();
+ private ArrayList<String> mBlacklistedBssids;
+
private WifiConnectionStatistics mWifiConnectionStatistics;
/**
@@ -131,6 +134,7 @@ public class WifiAutoJoinController {
+ " service " + Context.NETWORK_SCORE_SERVICE);
mNetworkScoreCache = null;
}
+ mBlacklistedBssids = new ArrayList<String>();
}
void enableVerboseLogging(int verbose) {
@@ -968,6 +972,10 @@ public class WifiAutoJoinController {
if (!mWifiConfigStore.enable5GHzPreference) {
return 0;
}
+ if (mWifiStateMachine.getFrequencyBand()
+ == WifiManager.WIFI_FREQUENCY_BAND_2GHZ) {
+ return 0;
+ }
if (rssi
> mWifiConfigStore.bandPreferenceBoostThreshold5.get()) {
// Boost by 2 dB for each point
@@ -1042,6 +1050,7 @@ public class WifiAutoJoinController {
// Determine which BSSID we want to associate to, taking account
// relative strength of 5 and 2.4 GHz BSSIDs
long nowMs = System.currentTimeMillis();
+ int currentBand = mWifiStateMachine.getFrequencyBand();
for (ScanDetail sd : scanDetailCache.values()) {
ScanResult b = sd.getScanResult();
@@ -1049,6 +1058,14 @@ public class WifiAutoJoinController {
int aRssiBoost5 = 0;
int bRssiBoost = 0;
int aRssiBoost = 0;
+ if (b.is5GHz()
+ && (currentBand == WifiManager.WIFI_FREQUENCY_BAND_2GHZ)) {
+ continue;
+ }
+ if (b.is24GHz()
+ && (currentBand == WifiManager.WIFI_FREQUENCY_BAND_5GHZ)) {
+ continue;
+ }
if ((sd.getSeen() == 0) || (b.BSSID == null)
|| ((nowMs - sd.getSeen()) > age)
|| b.autoJoinStatus != ScanResult.ENABLED
@@ -1176,10 +1193,19 @@ public class WifiAutoJoinController {
long nowMs = System.currentTimeMillis();
int startScore = -10000;
+ int currentBand = mWifiStateMachine.getFrequencyBand();
// Run thru all cached scan results
for (ScanDetail sd : mWifiConfigStore.getScanDetailCache(config).values()) {
ScanResult result = sd.getScanResult();
+ if (result.is5GHz()
+ && (currentBand == WifiManager.WIFI_FREQUENCY_BAND_2GHZ)) {
+ continue;
+ }
+ if (result.is24GHz()
+ && (currentBand == WifiManager.WIFI_FREQUENCY_BAND_5GHZ)) {
+ continue;
+ }
if ((nowMs - sd.getSeen()) < age) {
int sc = mNetworkScoreCache.getNetworkScore(result, isActive);
if (sc > startScore) {
@@ -1205,6 +1231,43 @@ public class WifiAutoJoinController {
}
/**
+ * Add or remove the BSSID from list of blacklisted BSSID's
+ *
+ * @param enable
+ * @param bssid
+ * @param reason
+ */
+ void handleBSSIDBlackList(boolean enable, String bssid, int reason) {
+ if( reason == 5 ) // Enable Auto Join for all BSSIDs
+ {
+ mBlacklistedBssids.clear();
+ return;
+ }
+ if( !enable ) {
+ if( !mBlacklistedBssids.contains(bssid) )
+ {
+ mBlacklistedBssids.add(bssid);
+ }
+ }
+ else {
+ if( mBlacklistedBssids.contains(bssid) ) {
+ mBlacklistedBssids.remove(bssid);
+ }
+ }
+ }
+
+ /**
+ * Is BSSID blacklisted
+ *
+ * @param bssid
+ *
+ * @return boolean
+ */
+ boolean isBlacklistedBSSID( String bssid ) {
+ return mBlacklistedBssids.contains(bssid);
+ }
+
+ /**
* Set whether connections to untrusted connections are allowed.
*/
void setAllowUntrustedConnections(boolean allow) {
@@ -1302,6 +1365,13 @@ public class WifiAutoJoinController {
logDbg("attemptAutoJoin() status=" + wpaStatus);
}
+ if (wpaStatus == null) {
+ if (VDBG) {
+ logDbg("wpaStatus is null");
+ }
+ return WifiConfiguration.INVALID_NETWORK_ID;
+ }
+
try {
int id = WifiConfiguration.INVALID_NETWORK_ID;
String state = null;
@@ -1499,6 +1569,14 @@ public class WifiAutoJoinController {
continue;
}
+ if ( this.isBlacklistedBSSID(config.BSSID) ) {
+ if (DBG) {
+ logDbg("attemptAutoJoin skip candidate as AP is Blacklisted config.SSID = "
+ + config.SSID + " config.BSSID=" + config.BSSID);
+ }
+ continue;
+ }
+
if (config.autoJoinStatus >= WifiConfiguration.AUTO_JOIN_DISABLED_ON_AUTH_FAILURE) {
updateBlackListStatus(config, now);
continue;
diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java
index d6e41a1..767607b 100644
--- a/service/java/com/android/server/wifi/WifiConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiConfigStore.java
@@ -71,6 +71,8 @@ import com.android.server.wifi.hotspot2.omadm.MOManager;
import com.android.server.wifi.hotspot2.pps.Credential;
import com.android.server.wifi.hotspot2.pps.HomeSP;
+import cyanogenmod.providers.CMSettings;
+
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
@@ -387,6 +389,7 @@ public class WifiConfigStore extends IpConfigStore {
public boolean enable5GHzPreference = true;
public boolean enableWifiCellularHandoverUserTriggeredAdjustment = true;
+ private int mConfiguredBand = 0;
public int currentNetworkBoost = 25;
public int scanResultRssiLevelPatchUp = -85;
@@ -834,7 +837,7 @@ public class WifiConfigStore extends IpConfigStore {
if (cache == null) {
continue;
}
- config.setVisibility(cache.getVisibility(milli));
+ config.setVisibility(cache.getVisibility(milli, mConfiguredBand));
if (config.visibility == null) {
continue;
}
@@ -985,24 +988,42 @@ public class WifiConfigStore extends IpConfigStore {
if (VDBG) localLog("selectNetwork", config.networkId);
if (config.networkId == INVALID_NETWORK_ID) return false;
- // Reset the priority of each network at start or if it goes too high.
- if (mLastPriority == -1 || mLastPriority > 1000000) {
- for(WifiConfiguration config2 : mConfiguredNetworks.values()) {
- if (updatePriorities) {
- if (config2.networkId != INVALID_NETWORK_ID) {
- config2.priority = 0;
- setNetworkPriorityNative(config2.networkId, config.priority);
+ final boolean autoConfigure = isAutoConfigPriorities();
+ if (autoConfigure) {
+ // Reset the priority of each network at start or if it goes too high.
+ if (mLastPriority == -1 || mLastPriority > 1000000) {
+ for (WifiConfiguration config2 : mConfiguredNetworks.values()) {
+ if (updatePriorities) {
+ if (config2.networkId != INVALID_NETWORK_ID) {
+ config2.priority = 0;
+ setNetworkPriorityNative(config2.networkId, config.priority);
+ }
}
}
}
- mLastPriority = 0;
+ } else {
+ // Ensure that last priority is reestablished if auto configuration is reenabled
+ for (WifiConfiguration wifiConfiguration : mConfiguredNetworks.values()) {
+ if (wifiConfiguration != null && wifiConfiguration.priority > mLastPriority) {
+ mLastPriority = wifiConfiguration.priority;
+ }
+ }
}
+
// Set to the highest priority and save the configuration.
- if (updatePriorities) {
- config.priority = ++mLastPriority;
- setNetworkPriorityNative(config.networkId, config.priority);
- buildPnoList();
+ if (autoConfigure) {
+ if (updatePriorities) {
+ config.priority = ++mLastPriority;
+ setNetworkPriorityNative(config.networkId, config.priority);
+ buildPnoList();
+ }
+ } else {
+ // Use the lastknown configuration to recover the priority
+ WifiConfiguration lastKnown = mConfiguredNetworks.get(config.networkId);
+ if (lastKnown != null) {
+ config.priority = lastKnown.priority;
+ }
}
if (config.isPasspoint()) {
@@ -1033,7 +1054,7 @@ public class WifiConfigStore extends IpConfigStore {
writeKnownNetworkHistory(false);
/* Enable the given network while disabling all other networks */
- enableNetworkWithoutBroadcast(config.networkId, true);
+ enableNetworkWithoutBroadcast(config.networkId, autoConfigure);
/* Avoid saving the config & sending a broadcast to prevent settings
* from displaying a disabled list of networks */
@@ -1135,6 +1156,24 @@ public class WifiConfigStore extends IpConfigStore {
}
}
+ void unblackListDriverRoamedBSSID(String bssid) {
+ for (WifiConfiguration config : mConfiguredNetworks.values()) {
+ ScanDetailCache cache = getScanDetailCache(config);
+ if (cache != null) {
+ ScanResult result = cache.get(bssid);
+ if (result != null) {
+ if (result.autoJoinStatus == (ScanResult.AUTO_ROAM_DISABLED + 1)) {
+ if (DBG) {
+ Log.d(TAG,"unblacklisted driver roamed BSSID = "+result.BSSID);
+ }
+ result.setAutoJoinStatus(ScanResult.ENABLED);
+ }
+ }
+ }
+ }
+ }
+
+
void noteRoamingFailure(WifiConfiguration config, int reason) {
if (config == null) return;
config.lastRoamingFailure = System.currentTimeMillis();
@@ -1895,6 +1934,7 @@ public class WifiConfigStore extends IpConfigStore {
mLastPriority = 0;
mConfiguredNetworks.clear();
+ mScanDetailCaches.clear();
List<WifiConfiguration> configTlsResetList = new ArrayList<WifiConfiguration>();
int last_id = -1;
boolean done = false;
@@ -1951,8 +1991,8 @@ public class WifiConfigStore extends IpConfigStore {
mLastPriority = config.priority;
}
- config.setIpAssignment(IpAssignment.DHCP);
- config.setProxySettings(ProxySettings.NONE);
+ config.setIpAssignment(IpAssignment.DHCP);
+ config.setProxySettings(ProxySettings.NONE);
if (mConfiguredNetworks.getByConfigKey(config.configKey()) != null) {
// That SSID is already known, just ignore this duplicate entry
@@ -2172,6 +2212,14 @@ public class WifiConfigStore extends IpConfigStore {
needUpdate = true;
}
}
+ final List<Long> deletedSSIDs = new ArrayList<Long>();
+ for (Long csum : mDeletedSSIDs) {
+ deletedSSIDs.add(new Long(csum));
+ }
+ final List<String> deletedEphemeralSSIDs = new ArrayList<String>();
+ for (String ssid: mDeletedEphemeralSSIDs) {
+ deletedEphemeralSSIDs.add(new String(ssid));
+ }
if (VDBG) {
loge(" writeKnownNetworkHistory() num networks:" +
mConfiguredNetworks.size() + " needWrite=" + needUpdate);
@@ -2313,8 +2361,9 @@ public class WifiConfigStore extends IpConfigStore {
out.writeUTF(DEFAULT_GW_KEY + SEPARATOR + macAddress + NL);
}
- if (getScanDetailCache(config) != null) {
- for (ScanDetail scanDetail : getScanDetailCache(config).values()) {
+ ScanDetailCache cache = getScanDetailCacheIfExist(config);
+ if (cache != null) {
+ for (ScanDetail scanDetail : cache.values()) {
ScanResult result = scanDetail.getScanResult();
out.writeUTF(BSSID_KEY + SEPARATOR +
result.BSSID + NL);
@@ -2343,15 +2392,15 @@ public class WifiConfigStore extends IpConfigStore {
out.writeUTF(NL);
out.writeUTF(NL);
}
- if (mDeletedSSIDs != null && mDeletedSSIDs.size() > 0) {
- for (Long i : mDeletedSSIDs) {
+ if (deletedSSIDs.size() > 0) {
+ for (Long i : deletedSSIDs) {
out.writeUTF(DELETED_CRC32_KEY);
out.writeUTF(String.valueOf(i));
out.writeUTF(NL);
}
}
- if (mDeletedEphemeralSSIDs != null && mDeletedEphemeralSSIDs.size() > 0) {
- for (String ssid : mDeletedEphemeralSSIDs) {
+ if (deletedEphemeralSSIDs.size() > 0) {
+ for (String ssid : deletedEphemeralSSIDs) {
out.writeUTF(DELETED_EPHEMERAL_KEY);
out.writeUTF(ssid);
out.writeUTF(NL);
@@ -2388,6 +2437,10 @@ public class WifiConfigStore extends IpConfigStore {
return lastSelectedConfiguration;
}
+ public void setConfiguredBand(int band) {
+ mConfiguredBand = band;
+ }
+
public boolean isLastSelectedConfiguration(WifiConfiguration config) {
return (lastSelectedConfiguration != null
&& config != null
@@ -2405,6 +2458,8 @@ public class WifiConfigStore extends IpConfigStore {
String bssid = null;
String ssid = null;
+ String key = null;
+ String value = null;
int freq = 0;
int status = 0;
@@ -2419,17 +2474,21 @@ public class WifiConfigStore extends IpConfigStore {
break;
}
int colon = line.indexOf(':');
- if (colon < 0) {
+ char slash = line.charAt(0);
+ if ((colon < 0)&& (slash != '/')) {
continue;
}
-
- String key = line.substring(0, colon).trim();
- String value = line.substring(colon + 1).trim();
+ if (slash == '/') {
+ key = line.trim();
+ } else {
+ key = line.substring(0, colon).trim();
+ value = line.substring(colon + 1).trim();
+ }
if (key.equals(CONFIG_KEY)) {
config = mConfiguredNetworks.getByConfigKey(value);
-
+
// skip reading that configuration data
// since we don't have a corresponding network ID
if (config == null) {
@@ -2570,8 +2629,15 @@ public class WifiConfigStore extends IpConfigStore {
break;
case BSSID_KEY:
status = 0;
- ssid = null;
- bssid = null;
+ /*
+ * The intention here is to put the scanDetail in to
+ * the scanDetailCache per config , as done in
+ * BSSID_KEY_END . Thus store bssid value and
+ * comment ssid = null to ensure the code in the if
+ * loop is executed for the case BSSID_KEY_END.
+ */
+ // ssid = null;
+ bssid = value;
freq = 0;
seen = 0;
rssi = WifiConfiguration.INVALID_RSSI;
@@ -2756,14 +2822,24 @@ public class WifiConfigStore extends IpConfigStore {
}
boolean updateFailed = true;
+ WifiConfiguration savedConfig = null;
setVariables: {
+ if (newNetwork == false ) {
+ savedConfig = mConfiguredNetworks.get(netId);
+ if (savedConfig != null) {
+ readNetworkVariables(savedConfig);
+ }
+ }
- if (config.SSID != null &&
+ if (!((newNetwork == false) && (savedConfig != null) &&
+ (savedConfig.SSID != null) && (config.SSID != null) &&
+ (savedConfig.SSID.equals(config.SSID))) &&
+ (config.SSID != null &&
!mWifiNative.setNetworkVariable(
netId,
WifiConfiguration.ssidVarName,
- encodeSSID(config.SSID))) {
+ encodeSSID(config.SSID)))) {
loge("failed to set SSID: "+config.SSID);
break setVariables;
}
@@ -2778,7 +2854,10 @@ public class WifiConfigStore extends IpConfigStore {
}
}
- if (config.BSSID != null) {
+ if (!((newNetwork == false) && (savedConfig != null) &&
+ (savedConfig.BSSID != null) && (config.BSSID != null) &&
+ (savedConfig.BSSID.equals(config.BSSID)))
+ && (config.BSSID != null)) {
log("Setting BSSID for " + config.configKey() + " to " + config.BSSID);
if (!mWifiNative.setNetworkVariable(
netId,
@@ -2789,13 +2868,46 @@ public class WifiConfigStore extends IpConfigStore {
}
}
+ if (!((newNetwork == false) && (savedConfig != null) &&
+ (savedConfig.SIMNum == config.SIMNum)) && (config.SIMNum != 0)){
+ if (!mWifiNative.setNetworkVariable(
+ netId,
+ WifiConfiguration.SIMNumVarName,
+ Integer.toString(config.SIMNum))) {
+ loge(config.SIMNum + ": failed to set sim no: "
+ +config.SIMNum);
+ break setVariables;
+ }
+ }
+
+ if (config.isIBSS) {
+ if(!mWifiNative.setNetworkVariable(
+ netId,
+ WifiConfiguration.modeVarName,
+ "1")) {
+ loge("failed to set adhoc mode");
+ break setVariables;
+ }
+ if(!mWifiNative.setNetworkVariable(
+ netId,
+ WifiConfiguration.frequencyVarName,
+ Integer.toString(config.frequency))) {
+ loge("failed to set frequency");
+ break setVariables;
+ }
+ }
+
String allowedKeyManagementString =
makeString(config.allowedKeyManagement, WifiConfiguration.KeyMgmt.strings);
- if (config.allowedKeyManagement.cardinality() != 0 &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.KeyMgmt.varName,
- allowedKeyManagementString)) {
+ if (!((newNetwork == false) && (savedConfig != null) &&
+ (allowedKeyManagementString != null) &&
+ (savedConfig.allowedKeyManagement.equals(
+ config.allowedKeyManagement))) &&
+ config.allowedKeyManagement.cardinality() != 0 &&
+ !mWifiNative.setNetworkVariable(
+ netId,
+ WifiConfiguration.KeyMgmt.varName,
+ allowedKeyManagementString)) {
loge("failed to set key_mgmt: "+
allowedKeyManagementString);
break setVariables;
@@ -2803,8 +2915,11 @@ public class WifiConfigStore extends IpConfigStore {
String allowedProtocolsString =
makeString(config.allowedProtocols, WifiConfiguration.Protocol.strings);
- if (config.allowedProtocols.cardinality() != 0 &&
- !mWifiNative.setNetworkVariable(
+ if (!((newNetwork == false) && (savedConfig != null) &&
+ (allowedProtocolsString != null) &&
+ (savedConfig.allowedProtocols.equals(config.allowedProtocols)))
+ && config.allowedProtocols.cardinality() != 0 &&
+ !mWifiNative.setNetworkVariable(
netId,
WifiConfiguration.Protocol.varName,
allowedProtocolsString)) {
@@ -2815,11 +2930,15 @@ public class WifiConfigStore extends IpConfigStore {
String allowedAuthAlgorithmsString =
makeString(config.allowedAuthAlgorithms, WifiConfiguration.AuthAlgorithm.strings);
- if (config.allowedAuthAlgorithms.cardinality() != 0 &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.AuthAlgorithm.varName,
- allowedAuthAlgorithmsString)) {
+ if (!((newNetwork == false) && (savedConfig != null)
+ && (allowedAuthAlgorithmsString != null) &&
+ (savedConfig.allowedAuthAlgorithms.equals(
+ config.allowedAuthAlgorithms))) &&
+ config.allowedAuthAlgorithms.cardinality() != 0 &&
+ !mWifiNative.setNetworkVariable(
+ netId,
+ WifiConfiguration.AuthAlgorithm.varName,
+ allowedAuthAlgorithmsString)) {
loge("failed to set auth_alg: "+
allowedAuthAlgorithmsString);
break setVariables;
@@ -2828,11 +2947,15 @@ public class WifiConfigStore extends IpConfigStore {
String allowedPairwiseCiphersString =
makeString(config.allowedPairwiseCiphers,
WifiConfiguration.PairwiseCipher.strings);
- if (config.allowedPairwiseCiphers.cardinality() != 0 &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.PairwiseCipher.varName,
- allowedPairwiseCiphersString)) {
+ if (!((newNetwork == false) && (savedConfig != null) &&
+ (allowedPairwiseCiphersString != null) &&
+ (savedConfig.allowedPairwiseCiphers.equals(
+ config.allowedPairwiseCiphers))) &&
+ config.allowedPairwiseCiphers.cardinality() != 0 &&
+ !mWifiNative.setNetworkVariable(
+ netId,
+ WifiConfiguration.PairwiseCipher.varName,
+ allowedPairwiseCiphersString)) {
loge("failed to set pairwise: "+
allowedPairwiseCiphersString);
break setVariables;
@@ -2840,11 +2963,15 @@ public class WifiConfigStore extends IpConfigStore {
String allowedGroupCiphersString =
makeString(config.allowedGroupCiphers, WifiConfiguration.GroupCipher.strings);
- if (config.allowedGroupCiphers.cardinality() != 0 &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.GroupCipher.varName,
- allowedGroupCiphersString)) {
+ if (!((newNetwork == false) && (savedConfig != null) &&
+ (allowedGroupCiphersString != null) &&
+ (savedConfig.allowedGroupCiphers.equals(
+ config.allowedGroupCiphers))) &&
+ config.allowedGroupCiphers.cardinality() != 0 &&
+ !mWifiNative.setNetworkVariable(
+ netId,
+ WifiConfiguration.GroupCipher.varName,
+ allowedGroupCiphersString)) {
loge("failed to set group: "+
allowedGroupCiphersString);
break setVariables;
@@ -2852,8 +2979,13 @@ public class WifiConfigStore extends IpConfigStore {
// Prevent client screw-up by passing in a WifiConfiguration we gave it
// by preventing "*" as a key.
- if (config.preSharedKey != null && !config.preSharedKey.equals("*") &&
- !mWifiNative.setNetworkVariable(
+ if (!((newNetwork == false) && (savedConfig != null) &&
+ (savedConfig.preSharedKey != null) &&
+ (config.preSharedKey != null) &&
+ (savedConfig.preSharedKey.equals(config.preSharedKey)))
+ && config.preSharedKey != null &&
+ !config.preSharedKey.equals("*") &&
+ !mWifiNative.setNetworkVariable(
netId,
WifiConfiguration.pskVarName,
config.preSharedKey)) {
@@ -2866,15 +2998,20 @@ public class WifiConfigStore extends IpConfigStore {
for (int i = 0; i < config.wepKeys.length; i++) {
// Prevent client screw-up by passing in a WifiConfiguration we gave it
// by preventing "*" as a key.
- if (config.wepKeys[i] != null && !config.wepKeys[i].equals("*")) {
- if (!mWifiNative.setNetworkVariable(
+ if (!((newNetwork == false) && (savedConfig != null) &&
+ (config.wepKeys[i] != null) &&
+ (savedConfig.wepKeys[i] != null) &&
+ (savedConfig.wepKeys[i].equals(config.wepKeys[i])))) {
+ if (config.wepKeys[i] != null && !config.wepKeys[i].equals("*")) {
+ if (!mWifiNative.setNetworkVariable(
netId,
WifiConfiguration.wepKeyVarNames[i],
config.wepKeys[i])) {
- loge("failed to set wep_key" + i + ": " + config.wepKeys[i]);
- break setVariables;
+ loge("failed to set wep_key" + i + ": " + config.wepKeys[i]);
+ break setVariables;
+ }
+ hasSetKey = true;
}
- hasSetKey = true;
}
}
}
@@ -2889,7 +3026,9 @@ public class WifiConfigStore extends IpConfigStore {
}
}
- if (!mWifiNative.setNetworkVariable(
+ if (!((newNetwork == false) && (savedConfig != null) &&
+ (config.priority == savedConfig.priority )) &&
+ !mWifiNative.setNetworkVariable(
netId,
WifiConfiguration.priorityVarName,
Integer.toString(config.priority))) {
@@ -2898,7 +3037,9 @@ public class WifiConfigStore extends IpConfigStore {
break setVariables;
}
- if (config.hiddenSSID && !mWifiNative.setNetworkVariable(
+ if (!((newNetwork == false) && (savedConfig != null) &&
+ (savedConfig.hiddenSSID == config.hiddenSSID)) &&
+ config.hiddenSSID && !mWifiNative.setNetworkVariable(
netId,
WifiConfiguration.hiddenSSIDVarName,
Integer.toString(config.hiddenSSID ? 1 : 0))) {
@@ -2907,7 +3048,9 @@ public class WifiConfigStore extends IpConfigStore {
break setVariables;
}
- if (config.requirePMF && !mWifiNative.setNetworkVariable(
+ if (!((newNetwork == false) && (savedConfig != null) &&
+ (savedConfig.requirePMF == config.requirePMF)) &&
+ config.requirePMF && !mWifiNative.setNetworkVariable(
netId,
WifiConfiguration.pmfVarName,
"2")) {
@@ -2916,7 +3059,11 @@ public class WifiConfigStore extends IpConfigStore {
break setVariables;
}
- if (config.updateIdentifier != null && !mWifiNative.setNetworkVariable(
+ if (!((newNetwork == false) && (savedConfig != null) &&
+ (savedConfig.updateIdentifier != null) &&
+ (config.updateIdentifier != null) &&
+ (savedConfig.updateIdentifier.equals(config.updateIdentifier)))
+ && config.updateIdentifier != null && !mWifiNative.setNetworkVariable(
netId,
WifiConfiguration.updateIdentiferVarName,
config.updateIdentifier)) {
@@ -2926,7 +3073,7 @@ public class WifiConfigStore extends IpConfigStore {
}
if (config.enterpriseConfig != null &&
- config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE) {
+ config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE) {
WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig;
@@ -2961,8 +3108,16 @@ public class WifiConfigStore extends IpConfigStore {
}
HashMap<String, String> enterpriseFields = enterpriseConfig.getFields();
+ HashMap<String, String> savedEnterpriseFields = null;
+ String savedValue = null;
+ if (savedConfig != null && savedConfig.enterpriseConfig != null) {
+ savedEnterpriseFields = savedConfig.enterpriseConfig.getFields();
+ }
for (String key : enterpriseFields.keySet()) {
String value = enterpriseFields.get(key);
+ if (savedEnterpriseFields != null) {
+ savedValue = savedEnterpriseFields.get(key);
+ }
if (key.equals("password") && value != null && value.equals("*")) {
// No need to try to set an obfuscated password, which will fail
continue;
@@ -2972,7 +3127,63 @@ public class WifiConfigStore extends IpConfigStore {
// No need to save realm or PLMN in supplicant
continue;
}
- if (!mWifiNative.setNetworkVariable(
+ if (key.equals(WifiEnterpriseConfig.IDENTITY_KEY)) {
+ if ((config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.SIM)||
+ (config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.AKA)||
+ (config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.AKA_PRIME)) {
+ if ( (!newNetwork) && (value != null) && !mWifiNative.setNetworkVariable(
+ netId,
+ key,
+ "NULL")) {
+ loge(config.SSID + ": failed to set " + key +
+ ": " + value);
+ break setVariables;
+ }
+ } else {
+ if (!((newNetwork == false) && (savedValue != null) &&
+ (value != null) && value.equals(savedValue)) &&
+ !mWifiNative.setNetworkVariable(
+ netId,
+ key,
+ value)) {
+ removeKeys(enterpriseConfig);
+ loge(config.SSID + ": failed to set " + key +
+ ": " + value);
+ break setVariables;
+ }
+ }
+ continue;
+ }
+ if (key.equals(WifiEnterpriseConfig.ANON_IDENTITY_KEY)) {
+ if ((config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.SIM)||
+ (config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.AKA)||
+ (config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.AKA_PRIME)) {
+ if ( (!newNetwork) && (value != null) && !mWifiNative.setNetworkVariable(
+ netId,
+ key,
+ "NULL")) {
+ loge(config.SSID + ": failed to set " + key +
+ ": " + value);
+ break setVariables;
+ }
+ } else {
+ if (!((newNetwork == false) && (savedValue != null) &&
+ (value != null) && value.equals(savedValue)) &&
+ !mWifiNative.setNetworkVariable(
+ netId,
+ key,
+ value)) {
+ removeKeys(enterpriseConfig);
+ loge(config.SSID + ": failed to set " + key +
+ ": " + value);
+ break setVariables;
+ }
+ }
+ continue;
+ }
+ if (!((newNetwork == false) && (savedValue != null) &&
+ (value != null) && value.equals(savedValue)) &&
+ !mWifiNative.setNetworkVariable(
netId,
key,
value)) {
@@ -3161,6 +3372,12 @@ public class WifiConfigStore extends IpConfigStore {
return cache;
}
+ public ScanDetailCache getScanDetailCacheIfExist(WifiConfiguration config) {
+ if (config == null) return null;
+ return mScanDetailCaches.get(config.networkId);
+ }
+
+
/**
* This function run thru the Saved WifiConfigurations and check if some should be linked.
* @param config
@@ -3773,6 +3990,15 @@ public class WifiConfigStore extends IpConfigStore {
}
}
+ value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.SIMNumVarName);
+ if (!TextUtils.isEmpty(value)) {
+ try {
+ config.SIMNum = Integer.parseInt(value);
+ } catch (NumberFormatException ignore) {
+ Log.e(TAG,"error in parsing Selected Sim number " + config.SIMNum);
+ }
+ }
+
value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.hiddenSSIDVarName);
config.hiddenSSID = false;
if (!TextUtils.isEmpty(value)) {
@@ -3782,6 +4008,24 @@ public class WifiConfigStore extends IpConfigStore {
}
}
+ value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.modeVarName);
+ config.isIBSS = false;
+ if (!TextUtils.isEmpty(value)) {
+ try {
+ config.isIBSS = Integer.parseInt(value) != 0;
+ } catch (NumberFormatException ignore) {
+ }
+ }
+
+ value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.frequencyVarName);
+ config.frequency = 0;
+ if (!TextUtils.isEmpty(value)) {
+ try {
+ config.frequency = Integer.parseInt(value);
+ } catch (NumberFormatException ignore) {
+ }
+ }
+
value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.wepTxKeyIdxVarName);
config.wepTxKeyIndex = -1;
if (!TextUtils.isEmpty(value)) {
@@ -4094,6 +4338,31 @@ public class WifiConfigStore extends IpConfigStore {
return false;
}
+ static boolean isSimConfig(WifiConfiguration config) {
+ if (config == null) {
+ return false;
+ }
+
+ if (config.enterpriseConfig == null) {
+ return false;
+ }
+
+ int method = config.enterpriseConfig.getEapMethod();
+ return (method == WifiEnterpriseConfig.Eap.SIM
+ || method == WifiEnterpriseConfig.Eap.AKA
+ || method == WifiEnterpriseConfig.Eap.AKA_PRIME);
+ }
+
+ void resetSimNetworks() {
+ for(WifiConfiguration config : mConfiguredNetworks.values()) {
+ if (isSimConfig(config)) {
+ /* This configuration may have cached Pseudonym IDs; lets remove them */
+ mWifiNative.setNetworkVariable(config.networkId, "identity", "NULL");
+ mWifiNative.setNetworkVariable(config.networkId, "anonymous_identity", "NULL");
+ }
+ }
+ }
+
boolean isNetworkConfigured(WifiConfiguration config) {
// Check if either we have a network Id or a WifiConfiguration
// matching the one we are trying to add.
@@ -4254,6 +4523,38 @@ public class WifiConfigStore extends IpConfigStore {
return found;
}
+ /**
+ * Handle blacklisting per BSSID and unblacklisting
+ *
+ * @param enable
+ * @param BSSID
+ * @param reason
+ */
+ void handleDisabledAPs( boolean enable, String BSSID, int reason) {
+ if (BSSID == null)
+ return;
+ for (WifiConfiguration config : mConfiguredNetworks.values()) {
+ if (getScanDetailCache(config) != null) {
+ for (ScanDetail scanDetail : getScanDetailCache(config).values()) {
+ if (scanDetail.getBSSIDString().equals(BSSID)) {
+ if (enable) {
+ config.BSSID = "any";
+ scanDetail.getScanResult().setAutoJoinStatus(ScanResult.ENABLED);
+ // enable auto join for the blacklisted BSSID
+ config.setAutoJoinStatus(WifiConfiguration.AUTO_JOIN_ENABLED);
+ } else {
+ // blacklist only the specified BSSID
+ scanDetail.getScanResult().setAutoJoinStatus(ScanResult.AUTO_ROAM_DISABLED);
+ config.BSSID = BSSID;
+ config.setAutoJoinStatus(WifiConfiguration.AUTO_JOIN_TEMPORARY_DISABLED);
+ }
+ }
+ }
+ }
+ }
+ }
+
+
int getMaxDhcpRetries() {
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
@@ -4584,4 +4885,9 @@ public class WifiConfigStore extends IpConfigStore {
}
}
}
+
+ private boolean isAutoConfigPriorities() {
+ return CMSettings.Global.getInt(mContext.getContentResolver(),
+ CMSettings.Global.WIFI_AUTO_PRIORITIES_CONFIGURATION, 1) != 0;
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiController.java b/service/java/com/android/server/wifi/WifiController.java
index 9a8967b..a22f985 100644
--- a/service/java/com/android/server/wifi/WifiController.java
+++ b/service/java/com/android/server/wifi/WifiController.java
@@ -36,8 +36,12 @@ import android.os.Message;
import android.os.SystemClock;
import android.os.WorkSource;
import android.provider.Settings;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
import android.util.Slog;
+import android.widget.Toast;
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
@@ -57,21 +61,13 @@ class WifiController extends StateMachine {
private long mIdleMillis;
private int mSleepPolicy;
private boolean mFirstUserSignOnSeen = false;
+ private int mDefaultWifiIdleMs;
private AlarmManager mAlarmManager;
private PendingIntent mIdleIntent;
private static final int IDLE_REQUEST = 0;
/**
- * See {@link Settings.Global#WIFI_IDLE_MS}. This is the default value if a
- * Settings.Global value is not present. This timeout value is chosen as
- * the approximate point at which the battery drain caused by Wi-Fi
- * being enabled but not active exceeds the battery drain caused by
- * re-establishing a connection to the mobile data network.
- */
- private static final long DEFAULT_IDLE_MS = 15 * 60 * 1000; /* 15 minutes */
-
- /**
* See {@link Settings.Global#WIFI_REENABLE_DELAY_MS}. This is the default value if a
* Settings.Global value is not present. This is the minimum time after wifi is disabled
* we'll act on an enable. Enable requests received before this delay will be deferred.
@@ -102,19 +98,20 @@ class WifiController extends StateMachine {
private static final int BASE = Protocol.BASE_WIFI_CONTROLLER;
- static final int CMD_EMERGENCY_MODE_CHANGED = BASE + 1;
- static final int CMD_SCREEN_ON = BASE + 2;
- static final int CMD_SCREEN_OFF = BASE + 3;
- static final int CMD_BATTERY_CHANGED = BASE + 4;
- static final int CMD_DEVICE_IDLE = BASE + 5;
- static final int CMD_LOCKS_CHANGED = BASE + 6;
- static final int CMD_SCAN_ALWAYS_MODE_CHANGED = BASE + 7;
- static final int CMD_WIFI_TOGGLED = BASE + 8;
- static final int CMD_AIRPLANE_TOGGLED = BASE + 9;
- static final int CMD_SET_AP = BASE + 10;
- static final int CMD_DEFERRED_TOGGLE = BASE + 11;
- static final int CMD_USER_PRESENT = BASE + 12;
- static final int CMD_AP_START_FAILURE = BASE + 13;
+ static final int CMD_EMERGENCY_MODE_CHANGED = BASE + 1;
+ static final int CMD_SCREEN_ON = BASE + 2;
+ static final int CMD_SCREEN_OFF = BASE + 3;
+ static final int CMD_BATTERY_CHANGED = BASE + 4;
+ static final int CMD_DEVICE_IDLE = BASE + 5;
+ static final int CMD_LOCKS_CHANGED = BASE + 6;
+ static final int CMD_SCAN_ALWAYS_MODE_CHANGED = BASE + 7;
+ static final int CMD_WIFI_TOGGLED = BASE + 8;
+ static final int CMD_AIRPLANE_TOGGLED = BASE + 9;
+ static final int CMD_SET_AP = BASE + 10;
+ static final int CMD_DEFERRED_TOGGLE = BASE + 11;
+ static final int CMD_USER_PRESENT = BASE + 12;
+ static final int CMD_AP_START_FAILURE = BASE + 13;
+ static final int CMD_EMERGENCY_CALL_STATE_CHANGED = BASE + 14;
private static final int WIFI_DISABLED = 0;
private static final int WIFI_ENABLED = 1;
@@ -125,6 +122,7 @@ class WifiController extends StateMachine {
private StaDisabledWithScanState mStaDisabledWithScanState = new StaDisabledWithScanState();
private ApEnabledState mApEnabledState = new ApEnabledState();
private DeviceActiveState mDeviceActiveState = new DeviceActiveState();
+ private DeviceActiveHighPerfState mDeviceActiveHighPerfState = new DeviceActiveHighPerfState();
private DeviceInactiveState mDeviceInactiveState = new DeviceInactiveState();
private ScanOnlyLockHeldState mScanOnlyLockHeldState = new ScanOnlyLockHeldState();
private FullLockHeldState mFullLockHeldState = new FullLockHeldState();
@@ -138,6 +136,8 @@ class WifiController extends StateMachine {
mWifiStateMachine = service.mWifiStateMachine;
mSettingsStore = service.mSettingsStore;
mLocks = service.mLocks;
+ mDefaultWifiIdleMs = context.getResources().getInteger(com.android.internal.
+ R.integer.def_wifi_idle_ms);
mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null);
@@ -147,6 +147,7 @@ class WifiController extends StateMachine {
addState(mApStaDisabledState, mDefaultState);
addState(mStaEnabledState, mDefaultState);
addState(mDeviceActiveState, mStaEnabledState);
+ addState(mDeviceActiveHighPerfState, mDeviceActiveState);
addState(mDeviceInactiveState, mStaEnabledState);
addState(mScanOnlyLockHeldState, mDeviceInactiveState);
addState(mFullLockHeldState, mDeviceInactiveState);
@@ -221,7 +222,7 @@ class WifiController extends StateMachine {
private void readWifiIdleTime() {
mIdleMillis = Settings.Global.getLong(mContext.getContentResolver(),
- Settings.Global.WIFI_IDLE_MS, DEFAULT_IDLE_MS);
+ Settings.Global.WIFI_IDLE_MS, mDefaultWifiIdleMs);
}
private void readWifiSleepPolicy() {
@@ -384,6 +385,7 @@ class WifiController extends StateMachine {
case CMD_WIFI_TOGGLED:
case CMD_AIRPLANE_TOGGLED:
case CMD_EMERGENCY_MODE_CHANGED:
+ case CMD_EMERGENCY_CALL_STATE_CHANGED:
case CMD_AP_START_FAILURE:
break;
case CMD_USER_PRESENT:
@@ -429,7 +431,7 @@ class WifiController extends StateMachine {
break;
}
if (mDeviceIdle == false) {
- transitionTo(mDeviceActiveState);
+ checkLocksAndTransitionWhenDeviceActive();
} else {
checkLocksAndTransitionWhenDeviceIdle();
}
@@ -511,6 +513,7 @@ class WifiController extends StateMachine {
transitionTo(mApStaDisabledState);
}
break;
+ case CMD_EMERGENCY_CALL_STATE_CHANGED:
case CMD_EMERGENCY_MODE_CHANGED:
if (msg.arg1 == 1) {
transitionTo(mEcmState);
@@ -564,7 +567,7 @@ class WifiController extends StateMachine {
break;
}
if (mDeviceIdle == false) {
- transitionTo(mDeviceActiveState);
+ checkLocksAndTransitionWhenDeviceActive();
} else {
checkLocksAndTransitionWhenDeviceIdle();
}
@@ -623,6 +626,74 @@ class WifiController extends StateMachine {
}
class ApEnabledState extends State {
+
+ private SubscriptionManager.OnSubscriptionsChangedListener mSubListener;
+
+ @Override
+ public void enter() {
+ mSubListener = new SubscriptionManager.OnSubscriptionsChangedListener() {
+ boolean firstChange = true;
+ SubscriptionInfo lastSub;
+ String lastSubscriberId;
+
+ @Override
+ public void onSubscriptionsChanged() {
+ TelephonyManager tm = (TelephonyManager)
+ mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ final SubscriptionInfo currentSub = SubscriptionManager.from(mContext)
+ .getDefaultDataSubscriptionInfo();
+
+ if (currentSub == null) {
+ // don't disable when we're not sure yet.
+ return;
+ }
+
+ String currentSubscriberId =
+ tm.getSubscriberId(currentSub.getSubscriptionId());
+
+ if (currentSubscriberId == null) {
+ // don't disable when we're not sure yet.
+ return;
+ }
+
+ if (firstChange) {
+ lastSub = currentSub;
+ lastSubscriberId = currentSubscriberId;
+ // we always get a state change on registration.
+ firstChange = false;
+ return;
+ }
+
+ // SubscriptionInfo#getSubscriptionId() returns a
+ // framework handle and is not an IMSI. Don't use it to
+ // determine if the sub changed.
+ //
+ // TelephonyManager#getSubscriberId() returns the IMSI,
+ // so use that instead
+ if (currentSubscriberId.equals(lastSubscriberId)) {
+ // don't disable if it's the same subscription
+ return;
+ }
+
+ lastSub = currentSub;
+ lastSubscriberId = currentSubscriberId;
+
+ Toast.makeText(mContext,
+ com.android.internal.R.string.subscription_change_disabled_wifi_ap,
+ Toast.LENGTH_SHORT).show();
+ log("disabling Wifi AP due to Subscriber Id (IMSI) change");
+ WifiController.this.obtainMessage(CMD_SET_AP, 0, 0, null).sendToTarget();
+ }
+ };
+ SubscriptionManager.from(mContext).addOnSubscriptionsChangedListener(mSubListener);
+ }
+
+ @Override
+ public void exit() {
+ SubscriptionManager.from(mContext).removeOnSubscriptionsChangedListener(mSubListener);
+ mSubListener = null;
+ }
+
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
@@ -650,6 +721,7 @@ class WifiController extends StateMachine {
}
}
break;
+ case CMD_EMERGENCY_CALL_STATE_CHANGED:
case CMD_EMERGENCY_MODE_CHANGED:
if (msg.arg1 == 1) {
mWifiStateMachine.setHostApRunning(null, false);
@@ -670,18 +742,58 @@ class WifiController extends StateMachine {
}
class EcmState extends State {
+ // we can enter EcmState either because an emergency call started or because
+ // emergency callback mode started. This count keeps track of how many such
+ // events happened; so we can exit after all are undone
+
+ private int mEcmEntryCount;
@Override
public void enter() {
mWifiStateMachine.setSupplicantRunning(false);
mWifiStateMachine.clearANQPCache();
+ mEcmEntryCount = 1;
}
@Override
public boolean processMessage(Message msg) {
- if (msg.what == CMD_EMERGENCY_MODE_CHANGED && msg.arg1 == 0) {
+ if (msg.what == CMD_EMERGENCY_CALL_STATE_CHANGED) {
+ if (msg.arg1 == 1) {
+ // nothing to do - just says emergency call started
+ mEcmEntryCount++;
+ } else if (msg.arg1 == 0) {
+ // emergency call ended
+ decrementCountAndReturnToAppropriateState();
+ }
+ return HANDLED;
+ } else if (msg.what == CMD_EMERGENCY_MODE_CHANGED) {
+
+ if (msg.arg1 == 1) {
+ // Transitioned into emergency callback mode
+ mEcmEntryCount++;
+ } else if (msg.arg1 == 0) {
+ // out of emergency callback mode
+ decrementCountAndReturnToAppropriateState();
+ }
+ return HANDLED;
+ } else {
+ return NOT_HANDLED;
+ }
+ }
+
+ private void decrementCountAndReturnToAppropriateState() {
+ boolean exitEcm = false;
+
+ if (mEcmEntryCount == 0) {
+ loge("mEcmEntryCount is 0; exiting Ecm");
+ exitEcm = true;
+ } else if (--mEcmEntryCount == 0) {
+ exitEcm = true;
+ }
+
+ if (exitEcm) {
if (mSettingsStore.isWifiToggleEnabled()) {
if (mDeviceIdle == false) {
- transitionTo(mDeviceActiveState);
+ checkLocksAndTransitionWhenDeviceActive();
} else {
checkLocksAndTransitionWhenDeviceIdle();
}
@@ -690,9 +802,6 @@ class WifiController extends StateMachine {
} else {
transitionTo(mApStaDisabledState);
}
- return HANDLED;
- } else {
- return NOT_HANDLED;
}
}
}
@@ -711,6 +820,9 @@ class WifiController extends StateMachine {
if (msg.what == CMD_DEVICE_IDLE) {
checkLocksAndTransitionWhenDeviceIdle();
// We let default state handle the rest of work
+ } else if (msg.what == CMD_LOCKS_CHANGED) {
+ checkLocksAndTransitionWhenDeviceActive();
+ return HANDLED;
} else if (msg.what == CMD_USER_PRESENT) {
// TLS networks can't connect until user unlocks keystore. KeyStore
// unlocks when the user punches PIN after the reboot. So use this
@@ -725,6 +837,16 @@ class WifiController extends StateMachine {
}
}
+ /* Parent: DeviceActiveState. Device is active, and an app is holding a high perf lock. */
+ class DeviceActiveHighPerfState extends State {
+ @Override
+ public void enter() {
+ mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE);
+ mWifiStateMachine.setDriverStart(true);
+ mWifiStateMachine.setHighPerfModeEnabled(true);
+ }
+ }
+
/* Parent: StaEnabledState */
class DeviceInactiveState extends State {
@Override
@@ -735,7 +857,7 @@ class WifiController extends StateMachine {
updateBatteryWorkSource();
return HANDLED;
case CMD_SCREEN_ON:
- transitionTo(mDeviceActiveState);
+ checkLocksAndTransitionWhenDeviceActive();
// More work in default state
return NOT_HANDLED;
default:
@@ -781,6 +903,17 @@ class WifiController extends StateMachine {
}
}
+ private void checkLocksAndTransitionWhenDeviceActive() {
+ if (mLocks.hasLocks() && mLocks.getStrongestLockMode() == WIFI_MODE_FULL_HIGH_PERF) {
+ // It is possible for the screen to be off while the device is
+ // is active (mIdleMillis), so we need the high-perf mode
+ // otherwise powersaving mode will be turned on.
+ transitionTo(mDeviceActiveHighPerfState);
+ } else {
+ transitionTo(mDeviceActiveState);
+ }
+ }
+
private void checkLocksAndTransitionWhenDeviceIdle() {
if (mLocks.hasLocks()) {
switch (mLocks.getStrongestLockMode()) {
diff --git a/service/java/com/android/server/wifi/WifiMonitor.java b/service/java/com/android/server/wifi/WifiMonitor.java
index ffca502..cd324b4 100644
--- a/service/java/com/android/server/wifi/WifiMonitor.java
+++ b/service/java/com/android/server/wifi/WifiMonitor.java
@@ -27,6 +27,7 @@ import android.net.wifi.p2p.WifiP2pGroup;
import android.net.wifi.p2p.WifiP2pProvDiscEvent;
import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
import android.os.Message;
+import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Log;
@@ -421,6 +422,12 @@ public class WifiMonitor {
*/
private static final String P2P_SERV_DISC_RESP_STR = "P2P-SERV-DISC-RESP";
+ /* P2P-REMOVE-AND-REFORM-GROUP */
+ /* Supplicant is supposed to generate this event only when p2p
+ * is connected
+ */
+ private static final String P2P_REMOVE_AND_REFORM_GROUP_STR = "P2P-REMOVE-AND-REFORM-GROUP";
+
private static final String HOST_AP_EVENT_PREFIX_STR = "AP";
/* AP-STA-CONNECTED 42:fc:89:a8:96:09 dev_addr=02:90:4c:a0:92:54 */
private static final String AP_STA_CONNECTED_STR = "AP-STA-CONNECTED";
@@ -488,6 +495,7 @@ public class WifiMonitor {
public static final int P2P_FIND_STOPPED_EVENT = BASE + 37;
public static final int P2P_SERV_DISC_RESP_EVENT = BASE + 38;
public static final int P2P_PROV_DISC_FAILURE_EVENT = BASE + 39;
+ public static final int P2P_REMOVE_AND_REFORM_GROUP_EVENT = BASE + 40;
/* hostap events */
public static final int AP_STA_DISCONNECTED_EVENT = BASE + 41;
@@ -559,8 +567,8 @@ public class WifiMonitor {
mStateMachine2 = stateMachine;
}
- public void startMonitoring() {
- WifiMonitorSingleton.sInstance.startMonitoring(mInterfaceName);
+ public boolean startMonitoring() {
+ return WifiMonitorSingleton.sInstance.startMonitoring(mInterfaceName);
}
public void stopMonitoring() {
@@ -585,11 +593,11 @@ public class WifiMonitor {
private WifiMonitorSingleton() {
}
- public synchronized void startMonitoring(String iface) {
+ public synchronized boolean startMonitoring(String iface) {
WifiMonitor m = mIfaceMap.get(iface);
if (m == null) {
Log.e(TAG, "startMonitor called with unknown iface=" + iface);
- return;
+ return false;
}
Log.d(TAG, "startMonitoring(" + iface + ") with mConnected = " + mConnected);
@@ -597,7 +605,12 @@ public class WifiMonitor {
if (mConnected) {
m.mMonitoring = true;
m.mStateMachine.sendMessage(SUP_CONNECTION_EVENT);
+ return true;
} else {
+ if (iface.equals("p2p0")) {
+ Log.e(TAG, "Monitoring(" + iface +") failed!, wlan0 interface restarted");
+ return false;
+ }
if (DBG) Log.d(TAG, "connecting to supplicant");
int connectTries = 0;
while (true) {
@@ -606,11 +619,11 @@ public class WifiMonitor {
m.mStateMachine.sendMessage(SUP_CONNECTION_EVENT);
mConnected = true;
new MonitorThread(mWifiNative, this).start();
- break;
+ return true;
}
- if (connectTries++ < 5) {
+ if (connectTries++ < 50) {
try {
- Thread.sleep(1000);
+ Thread.sleep(100);
} catch (InterruptedException ignore) {
}
} else {
@@ -620,6 +633,7 @@ public class WifiMonitor {
}
}
}
+ return false;
}
public synchronized void stopMonitoring(String iface) {
@@ -672,6 +686,11 @@ public class WifiMonitor {
int space = eventStr.indexOf(' ');
if (space != -1) {
iface = eventStr.substring(7, space);
+ if ((SystemProperties.getInt("persist.fst.rate.upgrade.en", 0) == 1) &&
+ iface.startsWith("wlan1")) {
+ Log.i(TAG, "Ignoring fst rate upgrade event: " + eventStr);
+ return false;
+ }
if (!mIfaceMap.containsKey(iface) && iface.startsWith("p2p-")) {
// p2p interfaces are created dynamically, but we have
// only one P2p state machine monitoring all of them; look
@@ -1189,6 +1208,9 @@ public class WifiMonitor {
} else {
Log.e(TAG, "Null service resp " + dataString);
}
+ } else if (dataString.startsWith(P2P_REMOVE_AND_REFORM_GROUP_STR)) {
+ Log.d(TAG, "Received event= " + dataString);
+ mStateMachine.sendMessage(P2P_REMOVE_AND_REFORM_GROUP_EVENT);
}
}
diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java
index 620f8b5..5ac5564 100644
--- a/service/java/com/android/server/wifi/WifiNative.java
+++ b/service/java/com/android/server/wifi/WifiNative.java
@@ -334,7 +334,7 @@ public class WifiNative {
if (disableOthers) {
return doBooleanCommand("SELECT_NETWORK " + netId);
} else {
- return doBooleanCommand("ENABLE_NETWORK " + netId);
+ return doBooleanCommand("ENABLE_NETWORK " + netId + " " + "no-connect");
}
}
@@ -820,6 +820,16 @@ public class WifiNative {
}
}
+ public boolean simAuthFailedResponse(int id) {
+ // should be used with type GSM-AUTH
+ return doBooleanCommand("CTRL-RSP-SIM-" + id + ":GSM-FAIL");
+ }
+
+ public boolean umtsAuthFailedResponse(int id) {
+ // should be used with type UMTS-AUTH
+ return doBooleanCommand("CTRL-RSP-SIM-" + id + ":UMTS-FAIL");
+ }
+
public boolean simIdentityResponse(int id, String response) {
synchronized (mLock) {
return doBooleanCommand("CTRL-RSP-IDENTITY-" + id + ":" + response);
@@ -1251,6 +1261,18 @@ public class WifiNative {
doBooleanCommand("DRIVER MIRACAST " + mode);
}
+ public boolean getModeCapability(String mode) {
+ String ret = doStringCommand("GET_CAPABILITY modes");
+ if (!TextUtils.isEmpty(ret)) {
+ String[] tokens = ret.split(" ");
+ for (String t : tokens) {
+ if (t.compareTo(mode) == 0)
+ return true;
+ }
+ }
+ return false;
+ }
+
public boolean fetchAnqp(String bssid, String subtypes) {
return doBooleanCommand("ANQP_GET " + bssid + " " + subtypes);
}
@@ -1278,6 +1300,8 @@ public class WifiNative {
return doBooleanCommand("NFC_REPORT_HANDOVER RESP P2P " + requestMessage + " 00");
}
+ public native static boolean setMode(int mode);
+
/* WIFI HAL support */
private static final String TAG = "WifiNative-HAL";
@@ -1698,10 +1722,15 @@ public class WifiNative {
synchronized public static WifiScanner.ScanData[] getScanResults(boolean flush) {
synchronized (mLock) {
+ WifiScanner.ScanData[] sd = null;
if (isHalStarted()) {
- return getScanResultsNative(sWlan0Index, flush);
+ sd = getScanResultsNative(sWlan0Index, flush);
+ }
+
+ if (sd != null) {
+ return sd;
} else {
- return null;
+ return new WifiScanner.ScanData[0];
}
}
}
@@ -1971,6 +2000,15 @@ public class WifiNative {
}
}
+ public boolean disable5GHzFrequencies(boolean disable) {
+ if (disable) {
+ return doBooleanCommand("P2P_SET disallow_freq 2485-6000");
+ } else {
+ //Empty set means,it will enable all frequences
+ return doBooleanCommand("P2P_SET disallow_freq \"\"");
+ }
+ }
+
private static native boolean setDfsFlagNative(int iface, boolean dfsOn);
synchronized public static boolean setDfsFlag(boolean dfsOn) {
synchronized (mLock) {
@@ -2158,11 +2196,12 @@ public class WifiNative {
Log.e(TAG,"Can not reset handler Before set any handler");
return false;
}
- sWifiLoggerEventHandler = null;
if (resetLogHandlerNative(sWlan0Index, sLogCmdId)) {
sLogCmdId = -1;
+ sWifiLoggerEventHandler = null;
return true;
} else {
+ sWifiLoggerEventHandler = null;
return false;
}
} else {
diff --git a/service/java/com/android/server/wifi/WifiNotificationController.java b/service/java/com/android/server/wifi/WifiNotificationController.java
index 406a764..ed0e80b 100644
--- a/service/java/com/android/server/wifi/WifiNotificationController.java
+++ b/service/java/com/android/server/wifi/WifiNotificationController.java
@@ -18,6 +18,7 @@ package com.android.server.wifi;
import android.app.Notification;
import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -25,13 +26,15 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
+import android.graphics.drawable.Icon;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
+import android.os.AsyncTask;
import android.os.Handler;
-import android.os.Message;
import android.os.UserHandle;
import android.provider.Settings;
+import com.android.internal.R;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -46,6 +49,11 @@ final class WifiNotificationController {
private static final int ICON_NETWORKS_AVAILABLE =
com.android.internal.R.drawable.stat_notify_wifi_in_range;
/**
+ * Intent that the user requests the wifi be turned off from the notification
+ */
+ private static final String ACTION_TURN_WIFI_OFF
+ = "com.android.server.WifiService.ACTION_TURN_WIFI_OFF";
+ /**
* When a notification is shown, we wait this amount before possibly showing it again.
*/
private final long NOTIFICATION_REPEAT_DELAY_MS;
@@ -86,6 +94,11 @@ final class WifiNotificationController {
* something other than scanning, we reset this to 0.
*/
private int mNumScansSinceNetworkStateChange;
+ /**
+ * Turns wifi off when run (IntentFilter responsible for specifying the action
+ * {@link #ACTION_TURN_WIFI_OFF})
+ */
+ private BroadcastReceiver mNotificationBroadcastReceiver = null;
private final Context mContext;
private final WifiStateMachine mWifiStateMachine;
@@ -221,7 +234,6 @@ final class WifiNotificationController {
NotificationManager notificationManager = (NotificationManager) mContext
.getSystemService(Context.NOTIFICATION_SERVICE);
- Message message;
if (visible) {
// Not enough time has passed to show the notification again
@@ -230,6 +242,13 @@ final class WifiNotificationController {
}
if (mNotificationBuilder == null) {
+ final CharSequence wifiOffText = mContext.getText(
+ com.android.internal.R.string.notify_turn_wifi_off_title);
+ final PendingIntent wifiOffPi = PendingIntent.getBroadcast(mContext, 0,
+ new Intent(ACTION_TURN_WIFI_OFF).setPackage(
+ mContext.getPackageName()),
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
// Cache the Notification builder object.
mNotificationBuilder = new Notification.Builder(mContext)
.setWhen(0)
@@ -239,6 +258,8 @@ final class WifiNotificationController {
.addNextIntentWithParentStack(
new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK))
.getPendingIntent(0, 0, null, UserHandle.CURRENT))
+ .addAction(new Notification.Action.Builder(null,
+ wifiOffText, wifiOffPi).build())
.setColor(mContext.getResources().getColor(
com.android.internal.R.color.system_notification_accent_color));
}
@@ -255,7 +276,27 @@ final class WifiNotificationController {
notificationManager.notifyAsUser(null, ICON_NETWORKS_AVAILABLE,
mNotificationBuilder.build(), UserHandle.ALL);
+
+ if (mNotificationBroadcastReceiver == null) {
+ mNotificationBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ AsyncTask.execute(new Runnable() {
+ public void run() {
+ WifiManager wifiManager = (WifiManager)
+ mContext.getSystemService(Context.WIFI_SERVICE);
+ wifiManager.setWifiEnabled(false);
+ }
+ });
+ }
+ };
+ }
+ mContext.registerReceiver(mNotificationBroadcastReceiver,
+ new IntentFilter(ACTION_TURN_WIFI_OFF));
} else {
+ if (mNotificationBroadcastReceiver != null) {
+ mContext.unregisterReceiver(mNotificationBroadcastReceiver);
+ }
notificationManager.cancelAsUser(null, ICON_NETWORKS_AVAILABLE, UserHandle.ALL);
}
diff --git a/service/java/com/android/server/wifi/WifiScanningServiceImpl.java b/service/java/com/android/server/wifi/WifiScanningServiceImpl.java
index a0f5061..a2ff1d8 100644
--- a/service/java/com/android/server/wifi/WifiScanningServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiScanningServiceImpl.java
@@ -445,6 +445,10 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
break;
case CMD_SCAN_RESULTS_AVAILABLE: {
ScanData[] results = WifiNative.getScanResults(/* flush = */ true);
+ if (results == null) {
+ loge("Wifi HAL SCAN results NULL");
+ break;
+ }
Collection<ClientInfo> clients = mClients.values();
for (ClientInfo ci2 : clients) {
ci2.reportScanResults(results);
@@ -1004,7 +1008,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
}
int bestBucketIndex = -1; // best by period
- for (int i = 0; i < mTimeBuckets.length; i++) {
+ for (int i = 0; i < mTimeBuckets.length && i < mSettings.buckets.length; i++) {
TimeBucket bucket = mTimeBuckets[i];
if (bucket.periodMinInSecond * 1000 <= settings.periodInMs
&& settings.periodInMs < bucket.periodMaxInSecond * 1000) {
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index 33ce852..02ba186 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -70,6 +70,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.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.AsyncChannel;
import com.android.server.am.BatteryStatsService;
@@ -99,6 +100,7 @@ import java.util.List;
import static com.android.server.wifi.WifiController.CMD_AIRPLANE_TOGGLED;
import static com.android.server.wifi.WifiController.CMD_BATTERY_CHANGED;
+import static com.android.server.wifi.WifiController.CMD_EMERGENCY_CALL_STATE_CHANGED;
import static com.android.server.wifi.WifiController.CMD_EMERGENCY_MODE_CHANGED;
import static com.android.server.wifi.WifiController.CMD_LOCKS_CHANGED;
import static com.android.server.wifi.WifiController.CMD_SCAN_ALWAYS_MODE_CHANGED;
@@ -153,6 +155,7 @@ public final class WifiServiceImpl extends IWifiManager.Stub {
/* Tracks the persisted states for wi-fi & airplane mode */
final WifiSettingsStore mSettingsStore;
+ private boolean mIsControllerStarted = false;
/**
* Asynchronous channel to WifiStateMachine
*/
@@ -373,6 +376,8 @@ public final class WifiServiceImpl extends IWifiManager.Stub {
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 networks because SIM was removed");
+ mWifiStateMachine.resetSimAuthNetworks();
Log.d(TAG, "resetting country code because SIM is removed");
mWifiStateMachine.resetCountryCode();
}
@@ -389,6 +394,8 @@ public final class WifiServiceImpl extends IWifiManager.Stub {
mWifiController.start();
+ mIsControllerStarted = true;
+
// If we are already disabled (could be due to airplane mode), avoid changing persist
// state here
if (wifiEnabled) setWifiEnabled(wifiEnabled);
@@ -607,6 +614,11 @@ public final class WifiServiceImpl extends IWifiManager.Stub {
Binder.restoreCallingIdentity(ident);
}
+ if (!mIsControllerStarted) {
+ Slog.e(TAG,"WifiController is not yet started, abort setWifiEnabled");
+ return false;
+ }
+
mWifiController.sendMessage(CMD_WIFI_TOGGLED);
return true;
}
@@ -1162,6 +1174,21 @@ public final class WifiServiceImpl extends IWifiManager.Stub {
com.android.internal.R.bool.config_wifi_dual_band_support);
}
+ /**
+ * Is Ad-Hoc (IBSS) mode supported by the driver?
+ * Will only return correct results when we have reached WIFI_STATE_ENABLED
+ * @return {@code true} if IBSS mode is supported, {@code false} if not
+ */
+ public boolean isIbssSupported() {
+ enforceAccessPermission();
+ if (mWifiStateMachineChannel != null) {
+ return (mWifiStateMachine.syncIsIbssSupported(mWifiStateMachineChannel) == 1);
+ } else {
+ Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
+ return false;
+ }
+ }
+
/**
* Return the DHCP-assigned addresses from the last successful DHCP request,
* if any.
@@ -1176,7 +1203,10 @@ public final class WifiServiceImpl extends IWifiManager.Stub {
if (dhcpResults.ipAddress != null &&
dhcpResults.ipAddress.getAddress() instanceof Inet4Address) {
- info.ipAddress = NetworkUtils.inetAddressToInt((Inet4Address) dhcpResults.ipAddress.getAddress());
+ info.ipAddress = NetworkUtils.inetAddressToInt(
+ (Inet4Address) dhcpResults.ipAddress.getAddress());
+ info.netmask = NetworkUtils.prefixLengthToNetmaskInt(
+ dhcpResults.ipAddress.getNetworkPrefixLength());
}
if (dhcpResults.gateway != null) {
@@ -1390,10 +1420,47 @@ public final class WifiServiceImpl extends IWifiManager.Stub {
BluetoothAdapter.STATE_DISCONNECTED);
mWifiStateMachine.sendBluetoothAdapterStateChange(state);
} else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
- boolean emergencyMode = intent.getBooleanExtra("phoneinECMState", false);
- mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0, 0);
+ if (mContext.getResources().getBoolean(R.bool.config_wifi_ecbm_mode_change)) {
+ boolean emergencyMode = intent.getBooleanExtra("phoneinECMState", false);
+ mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0, 0);
+ }
+ } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED)) {
+ boolean inCall = intent.getBooleanExtra(PhoneConstants.PHONE_IN_EMERGENCY_CALL, false);
+ mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, inCall ? 1 : 0, 0);
} else if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) {
handleIdleModeChanged();
+ } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
+ int wifiApState = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE,
+ WifiManager.WIFI_AP_STATE_FAILED);
+ Slog.d(TAG, "wifiApState=" + wifiApState);
+ /*
+ * If start SoftAp fails, WifiStateMachine would transition to InitialState,
+ * but WifiController is left stuck in ApEnabledState, which in turn
+ * fails to turn on WLAN again.
+ *
+ * Register WifiService to receive WIFI_AP_STATE_CHANGED_ACTION intent
+ * from WifiStateMachine, and if wifiApState is failed, inform WifiController
+ * to transtion to ApStaDisabledState.
+ */
+ if (wifiApState == WifiManager.WIFI_AP_STATE_FAILED) {
+ setWifiApEnabled(null, false);
+ }
+ } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+ int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+ WifiManager.WIFI_STATE_UNKNOWN);
+ /*
+ * If Wi-Fi turn on fails, WifiStateMachine stays in InitialState,
+ * but WifiController is left stuck in StaEnabledState, which in turn
+ * fails to turn on WLAN again.
+ *
+ * Register WifiService to receive WIFI_STATE_CHANGED_ACTION intent
+ * from WifiStateMachine, and if wifiState is failed, inform WifiController
+ * to transtion to ApStaDisabledState.
+ */
+ if (wifiState == WifiManager.WIFI_STATE_FAILED) {
+ Slog.e(TAG, "Wi-Fi state is failed");
+ setWifiEnabled(false);
+ }
}
}
};
@@ -1422,9 +1489,18 @@ public final class WifiServiceImpl extends IWifiManager.Stub {
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+ intentFilter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
- intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
+ intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
+
+ boolean trackEmergencyCallState = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_wifi_turn_off_during_emergency_call);
+ if (trackEmergencyCallState) {
+ intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED);
+ }
+
mContext.registerReceiver(mReceiver, intentFilter);
}
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 4e40f73..360bd97 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -25,6 +25,7 @@ import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING;
import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING;
+
/**
* TODO:
* Deprecate WIFI_STATE_UNKNOWN
@@ -99,6 +100,7 @@ import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.Settings;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -197,6 +199,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
private DummyWifiLogger mWifiLogger;
private WifiApConfigStore mWifiApConfigStore;
private final boolean mP2pSupported;
+ private boolean mIbssSupported;
private final AtomicBoolean mP2pConnected = new AtomicBoolean(false);
private boolean mTemporarilyDisconnectWifi = false;
private final String mPrimaryDeviceType;
@@ -212,11 +215,17 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
private int mNumScanResultsReturned;
private boolean mScreenOn = false;
+
+ private boolean mIsWiFiIpReachabilityEnabled ;
+
private int mCurrentAssociateNetworkId = -1;
+
/* Chipset supports background scan */
private final boolean mBackgroundScanSupported;
private final String mInterfaceName;
+ /* The interface for dhcp to act on */
+ private final String mDataInterfaceName;
/* Tethering interface could be separate from wlan interface */
private String mTetherInterfaceName;
@@ -231,6 +240,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
private boolean mEnableAssociatedNetworkSwitchingInDevSettings = true;
private boolean mHalBasedPnoEnableInDevSettings = false;
+ /* Tracks sequence number on a periodic scan message for PNO failure */
+ private int mPnoPeriodicScanToken = 0;
private int mHalFeatureSet = 0;
private static int mPnoResultFound = 0;
@@ -316,6 +327,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
private boolean mEnableRssiPolling = false;
private boolean mLegacyPnoEnabled = false;
+ private boolean mDisabled5GhzFrequencies = false;
+ private boolean mIsRandomMacCleared = false;
private int mRssiPollToken = 0;
/* 3 operational states for STA operation: CONNECT_MODE, SCAN_ONLY_MODE, SCAN_ONLY_WIFI_OFF_MODE
* In CONNECT_MODE, the STA can scan and connect to an access point
@@ -361,7 +374,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
* Interval in milliseconds between receiving a disconnect event
* while connected to a good AP, and handling the disconnect proper
*/
- private static final int LINK_FLAPPING_DEBOUNCE_MSEC = 7000;
+ private static final int LINK_FLAPPING_DEBOUNCE_MSEC = 4000;
/**
* Delay between supplicant restarts upon failure to establish connection
@@ -586,6 +599,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
// Used to filter out requests we couldn't possibly satisfy.
private final NetworkCapabilities mNetworkCapabilitiesFilter = new NetworkCapabilities();
+ private static final int WIFI_AUTO_CONNECT_TYPE_AUTO = 0;
+
/* The base for wifi message types */
static final int BASE = Protocol.BASE_WIFI;
/* Start the supplicant */
@@ -743,6 +758,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
/* alert from firmware */
static final int CMD_FIRMWARE_ALERT = BASE + 100;
+ /* SIM is removed; reset any cached data for it */
+ static final int CMD_RESET_SIM_NETWORKS = BASE + 101;
+
/**
* Make this timer 40 seconds, which is about the normal DHCP timeout.
* In no valid case, the WiFiStateMachine should remain stuck in ObtainingIpAddress
@@ -837,6 +855,12 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
/* used to indicated RSSI threshold breach in hw */
static final int CMD_RSSI_THRESHOLD_BREACH = BASE + 164;
+ /* When there are saved networks and PNO fails, we do a periodic scan to notify
+ a saved/open network in suspend mode */
+ static final int CMD_PNO_PERIODIC_SCAN = BASE + 165;
+
+ /* Is IBSS mode supported by the driver? */
+ static final int CMD_GET_IBSS_SUPPORTED = BASE + 200;
/* Wifi state machine modes of operation */
@@ -1093,9 +1117,14 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
private final IBatteryStats mBatteryStats;
private String mTcpBufferSizes = null;
+ private int mTcpDelayedAckSegments = 1;
+ private int mTcpUserCfg = 0;
// Used for debug and stats gathering
private static int sScanAlarmIntentCount = 0;
+ private boolean isPropFeatureEnabled = false;
+
+ private static int DEFAULT_SCORE = NetworkAgent.WIFI_BASE_SCORE;
final static int frameworkMinScanIntervalSaneValue = 10000;
@@ -1109,6 +1138,13 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
super("WifiStateMachine");
mContext = context;
mInterfaceName = wlanInterface;
+ if (SystemProperties.getInt("persist.fst.rate.upgrade.en", 0) == 1) {
+ log("fst enabled");
+ mDataInterfaceName = "bond0";
+ } else {
+ mDataInterfaceName = wlanInterface;
+ }
+
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
BatteryStats.SERVICE_NAME));
@@ -1149,7 +1185,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
mLastSignalLevel = -1;
- mNetlinkTracker = new NetlinkTracker(mInterfaceName, new NetlinkTracker.Callback() {
+ mNetlinkTracker = new NetlinkTracker(mDataInterfaceName, new NetlinkTracker.Callback() {
public void update() {
sendMessage(CMD_UPDATE_LINKPROPERTIES);
}
@@ -1181,6 +1217,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
mBackgroundScanSupported = mContext.getResources().getBoolean(
R.bool.config_wifi_background_scan_support);
+ mIsWiFiIpReachabilityEnabled = mContext.getResources().getBoolean(
+ R.bool.config_wifi_ipreachability_monitor);
+
mPrimaryDeviceType = mContext.getResources().getString(
R.string.config_wifi_p2p_device_type);
@@ -1256,6 +1295,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
+ addCneAction(filter);
+
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
@@ -1266,6 +1307,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
sendMessage(CMD_SCREEN_STATE_CHANGED, 1);
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
sendMessage(CMD_SCREEN_STATE_CHANGED, 0);
+ } else {
+ handleCneAction(intent, action);
}
}
}, filter);
@@ -1290,6 +1333,15 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
});
+ mContext.getContentResolver().registerContentObserver(Settings.System.getUriFor(
+ Settings.System.WIFI_AUTO_CONNECT_TYPE), false,
+ new ContentObserver(getHandler()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ checkAndSetAutoConnection();
+ }
+ });
+
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
@@ -1309,6 +1361,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
mTcpBufferSizes = mContext.getResources().getString(
com.android.internal.R.string.config_wifi_tcp_buffers);
+ mTcpDelayedAckSegments = SystemProperties.getInt("net.tcp.delack.wifi", 1);
+ mTcpUserCfg = SystemProperties.getInt("net.tcp.usercfg.wifi", 0);
addState(mDefaultState);
addState(mInitialState, mDefaultState);
@@ -1381,6 +1435,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
mLogMessages = false;
mWifiNative.setSupplicantLogLevel("INFO");
}
+ mWifiP2pServiceImpl.enableVerboseLogging(verbose);
mWifiLogger.startLogging(mVerboseLoggingLevel > 0);
mWifiAutoJoinController.enableVerboseLogging(verbose);
mWifiMonitor.enableVerboseLogging(verbose);
@@ -1614,6 +1669,11 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
logd("Setting OUI to " + oui);
return mWifiNative.setScanningMacOui(ouiBytes);
}
+ private boolean clearRandomMacOui() {
+ byte[] ouiBytes = new byte[]{0,0,0};
+ logd("Clear random OUI");
+ return mWifiNative.setScanningMacOui(ouiBytes);
+ }
/**
* ******************************************************
@@ -1658,6 +1718,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
} catch (NumberFormatException e) {
}
c.isDFS = line.contains("(DFS)");
+ c.ibssAllowed = !line.contains("(NO_IBSS)");
list.add(c);
} else if (line.contains("Mode[B] Channels:")) {
// B channels are the same as G channels, skipped
@@ -1830,8 +1891,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
}
if (stats == null || mWifiLinkLayerStatsSupported <= 0) {
- long mTxPkts = TrafficStats.getTxPackets(mInterfaceName);
- long mRxPkts = TrafficStats.getRxPackets(mInterfaceName);
+ long mTxPkts = TrafficStats.getTxPackets(mDataInterfaceName);
+ long mRxPkts = TrafficStats.getRxPackets(mDataInterfaceName);
mWifiInfo.updatePacketRates(mTxPkts, mRxPkts);
} else {
mWifiInfo.updatePacketRates(stats);
@@ -2054,6 +2115,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
*/
public void setSupplicantRunning(boolean enable) {
if (enable) {
+ WifiNative.setMode(0);
sendMessage(CMD_START_SUPPLICANT);
} else {
sendMessage(CMD_STOP_SUPPLICANT);
@@ -2065,6 +2127,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
*/
public void setHostApRunning(WifiConfiguration wifiConfig, boolean enable) {
if (enable) {
+ WifiNative.setMode(1);
sendMessage(CMD_START_AP, wifiConfig);
} else {
sendMessage(CMD_STOP_AP);
@@ -2353,9 +2416,16 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
return mWifiNative.getNfcWpsConfigurationToken(netId);
}
- void enableBackgroundScan(boolean enable) {
+ boolean enableBackgroundScan(boolean enable) {
if (enable) {
- mWifiConfigStore.enableAllNetworks();
+ if (mContext.getResources().getBoolean(R.bool.wifi_autocon)
+ && !shouldAutoConnect()) {
+ if (DBG) {
+ logd("No auto connect, skip enable networks during pno");
+ }
+ } else {
+ mWifiConfigStore.enableAllNetworks();
+ }
}
List<WifiNative.PnoNetworkPriority> pnoList =
mWifiConfigStore.retrievePnoNetworkPriorityList(enable);
@@ -2365,6 +2435,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
} else {
Log.e(TAG, " Fail to set up pno, want " + enable + " now " + mLegacyPnoEnabled);
}
+ return ret;
}
/**
@@ -2474,6 +2545,14 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
/**
+ * reset cached SIM credential data
+ */
+ public synchronized void resetSimAuthNetworks() {
+ sendMessage(CMD_RESET_SIM_NETWORKS);
+ }
+
+
+ /**
* Get Network object of current wifi network
* @return Network object of current wifi network
*/
@@ -2485,6 +2564,13 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
}
+ public int syncIsIbssSupported(AsyncChannel channel) {
+ Message resultMsg = channel.sendMessageSynchronously(CMD_GET_IBSS_SUPPORTED);
+ int result = resultMsg.arg1;
+ resultMsg.recycle();
+ return result;
+ }
+
/**
* Get the country code
*
@@ -2646,13 +2732,10 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
* ******************************************************
*/
- private void logStateAndMessage(Message message, String state) {
+ private void logStateAndMessage(Message message, State state) {
messageHandlingStatus = 0;
if (mLogMessages) {
- //long now = SystemClock.elapsedRealtimeNanos();
- //String ts = String.format("[%,d us]", now/1000);
-
- logd(" " + state + " " + getLogRecString(message));
+ logd(" " + state.getClass().getSimpleName() + " " + getLogRecString(message));
}
}
@@ -3556,6 +3639,21 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
+ " suppState:" + mSupplicantStateTracker.getSupplicantStateName());
}
enableRssiPolling(screenOn);
+ if (screenOn) {
+ if (mContext.getResources().getBoolean(R.bool.wifi_autocon)) {
+ if (!shouldAutoConnect()) {
+ if (DBG) {
+ logd("Don't auto connect skip enable networks if screen on");
+ }
+ } else {
+ if (!mWifiConfigStore.enableAutoJoinWhenAssociated.get()) {
+ enableAllNetworks();
+ }
+ }
+ } else {
+ enableAllNetworks();
+ }
+ }
if (mUserWantsSuspendOpt.get()) {
if (screenOn) {
sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 0, 0);
@@ -3567,9 +3665,11 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
mScreenBroadcastReceived.set(true);
- getWifiLinkLayerStats(false);
- mOnTimeScreenStateChange = mOnTime;
- lastScreenStateChangeTimeStamp = lastLinkLayerStatsUpdate;
+ if (mIsRunning) {
+ getWifiLinkLayerStats(false);
+ mOnTimeScreenStateChange = mOnTime;
+ lastScreenStateChangeTimeStamp = lastLinkLayerStatsUpdate;
+ }
cancelDelayedScan();
@@ -3611,7 +3711,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
setScanAlarm(true);
} else {
if (!mIsScanOngoing) {
- enableBackgroundScan(true);
+ if (!enableBackgroundScan(true)) {
+ handlePnoFailError();
+ }
}
}
}
@@ -3735,6 +3837,15 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
if (mWifiNative.setBand(band)) {
mFrequencyBand.set(band);
+ mWifiConfigStore.setConfiguredBand(band);
+ if (mFrequencyBand.get() == WifiManager.WIFI_FREQUENCY_BAND_2GHZ) {
+ mWifiNative.disable5GHzFrequencies(true);
+ mDisabled5GhzFrequencies = true;
+ } else if ((mFrequencyBand.get() != WifiManager.WIFI_FREQUENCY_BAND_2GHZ)
+ && (mDisabled5GhzFrequencies)) {
+ mWifiNative.disable5GHzFrequencies(false);
+ mDisabled5GhzFrequencies = false;
+ }
if (PDBG) {
logd("done set frequency band " + band);
}
@@ -3837,6 +3948,116 @@ 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);
+ }
+ }
+ }
+ }*/
+
+ /**
+ * Allow blacklist by BSSID
+ *
+ * @param enable
+ * @param bssid
+ * @param reason
+ */
+ private void handleBSSIDBlacklist(boolean enable, String bssid, int reason) {
+ if (DBG) log("Blacklisting BSSID: " + bssid + ",reason:" + reason + ",enable:" + enable );
+ if (bssid != null) {
+ // Tell configStore to black list it
+ synchronized(mScanResultCache) {
+ mWifiAutoJoinController.handleBSSIDBlackList( enable, bssid, reason );
+ mWifiConfigStore.handleDisabledAPs( enable, bssid, reason );
+ }
+ }
+ }
+
+ /**
+ * Update the score based on indication of wifi quality
+ *
+ * @param state
+ */
+ private void handleStateChange(int state) {
+ int offset;
+ if (DBG) log("handle state change: " + state);
+ if(state == 0) {
+ // wifi is not good, reduce the score
+ mWifiInfo.score = 1;
+ } else {
+ // wifi is good, increase the score
+ mWifiInfo.score = NetworkAgent.WIFI_BASE_SCORE;
+ }
+ if(mNetworkAgent != null) {
+ mNetworkAgent.sendNetworkScore(mWifiInfo.score);
+ }
+ }
+
+ /**
+ * Handle change of preference
+ *
+ * @param featureId
+ * @param featureParam
+ * @param value
+ */
+ private void handlePrefChange(int featureId, int featureParam, int value) {
+ if (DBG) log("handle pref change : featurevalue: " + value);
+ if(featureId == 1 && featureParam == 1) {
+ if(value == 2/*enabled*/) {
+ DEFAULT_SCORE = 1;
+ isPropFeatureEnabled = true;
+ } else if(value == 1/*disabled*/) {
+ DEFAULT_SCORE = NetworkAgent.WIFI_BASE_SCORE;
+ isPropFeatureEnabled = false;
+ }
+ }
+ }
+
+ /**
+ * register for additional intents
+ */
+ private void addCneAction(IntentFilter filter) {
+ int val = SystemProperties.getInt("persist.cne.feature", 0);
+ boolean isPropFeatureAvail = (val == 3) ? true : false;
+ if (isPropFeatureAvail) {
+ DEFAULT_SCORE = 1;
+ filter.addAction("com.quicinc.cne.CNE_PREFERENCE_CHANGED");
+ filter.addAction("prop_state_change");
+ filter.addAction("blacklist_bad_bssid");
+ }
+ }
+
+ /**
+ * handle intents for preference change, wifi quality indication,
+ * and blackisting/unblacklisting indication
+ */
+ private void handleCneAction(Intent intent, String action) {
+ if (null == action) return;
+ if (action.equals("com.quicinc.cne.CNE_PREFERENCE_CHANGED")) {
+ int featureId = intent.getIntExtra("cneFeatureId", -1);
+ int featureParam = intent.getIntExtra("cneFeatureParameter", -1);
+ int featureVal = intent.getIntExtra("cneParameterValue", -1);
+ handlePrefChange(featureId, featureParam, featureVal);
+ } else if (action.equals("prop_state_change")) {
+ int state = intent.getIntExtra("state", 0);
+ handleStateChange(state);
+ } else if (action.equals("blacklist_bad_bssid") ) {
+ // 1 = blacklist, 0 = unblacklist
+ int blacklist = intent.getIntExtra("blacklistBSSID", -1);
+ String bssid = intent.getStringExtra("BSSIDToBlacklist");
+ int reason = intent.getIntExtra("blacklistReason", -1 );
+ handleBSSIDBlacklist( ( blacklist == 0) ? true : false, bssid, reason );
+ }
+ }
+
private static final String IE_STR = "ie=";
private static final String ID_STR = "id=";
private static final String BSSID_STR = "bssid=";
@@ -3990,6 +4211,17 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
flags, level, freq, tsf);
mScanResultCache.put(networkDetail, scanDetail);
}
+ if (mFrequencyBand.get()
+ == WifiManager.WIFI_FREQUENCY_BAND_2GHZ) {
+ if (ScanResult.is5GHz(freq)) {
+ continue;
+ }
+ } else if (mFrequencyBand.get()
+ == WifiManager.WIFI_FREQUENCY_BAND_5GHZ) {
+ if (ScanResult.is24GHz(freq)) {
+ continue;
+ }
+ }
mNumScanResultsReturned++; // Keep track of how many scan results we got
// as part of this scan's processing
@@ -4056,6 +4288,10 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
if (attemptAutoJoin) {
synchronized (mScanResultCache) {
+ if (mContext.getResources().getBoolean(R.bool.wifi_autocon)
+ && !shouldAutoConnect()) {
+ attemptAutoJoin = false;
+ }
// AutoJoincontroller will directly acces the scan result list and update it with
// ScanResult status
mNumScanResultsKnown = mWifiAutoJoinController.newSupplicantResults(attemptAutoJoin);
@@ -4240,7 +4476,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
ScanDetailCache scanDetailCache =
mWifiConfigStore.getScanDetailCache(currentConfiguration);
if (currentConfiguration != null && scanDetailCache != null) {
- currentConfiguration.setVisibility(scanDetailCache.getVisibility(12000));
+ currentConfiguration.setVisibility(scanDetailCache.getVisibility(12000, mFrequencyBand.get()));
if (currentConfiguration.visibility != null) {
if (currentConfiguration.visibility.rssi24 != WifiConfiguration.INVALID_RSSI
&& currentConfiguration.visibility.rssi24
@@ -4439,9 +4675,11 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
if (DBG) {
logd("calculateWifiScore() report new score " + Integer.toString(score));
}
- mWifiInfo.score = score;
- if (mNetworkAgent != null) {
- mNetworkAgent.sendNetworkScore(score);
+ if (!isPropFeatureEnabled) {
+ mWifiInfo.score = score;
+ if(mNetworkAgent != null) {
+ mNetworkAgent.sendNetworkScore(score);
+ }
}
}
wifiScoringReport = sb.toString();
@@ -4493,6 +4731,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
return true;
} catch (RemoteException e) {
return false;
+ } catch (IllegalStateException ie) {
+ loge("Unable to set interface config: " + ie);
+ return false;
}
}
@@ -4523,11 +4764,13 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
LinkProperties newLp = new LinkProperties();
// Interface name, proxy, and TCP buffer sizes are locally configured.
- newLp.setInterfaceName(mInterfaceName);
+ newLp.setInterfaceName(mDataInterfaceName);
newLp.setHttpProxy(mWifiConfigStore.getProxyProperties(mLastNetworkId));
if (!TextUtils.isEmpty(mTcpBufferSizes)) {
newLp.setTcpBufferSizes(mTcpBufferSizes);
}
+ newLp.setTcpDelayedAckSegments(mTcpDelayedAckSegments);
+ newLp.setTcpUserCfg(mTcpUserCfg);
// IPv4/v6 addresses, IPv6 routes and IPv6 DNS servers come from netlink.
LinkProperties netlinkLinkProperties = mNetlinkTracker.getLinkProperties();
@@ -4548,7 +4791,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
// Even when we're using static configuration, we don't need to look at the config
// store, because static IP configuration also populates mDhcpResults.
if ((mDhcpResults != null)) {
- for (RouteInfo route : mDhcpResults.getRoutes(mInterfaceName)) {
+ for (RouteInfo route : mDhcpResults.getRoutes(mDataInterfaceName)) {
newLp.addRoute(route);
}
for (InetAddress dns : mDhcpResults.dnsServers) {
@@ -4672,7 +4915,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
// for now it's only here for extra redundancy. However, it will increase
// robustness if we move to getting IPv4 routes from netlink as well.
loge("DHCP failure: provisioned, clearing IPv4 address.");
- if (!clearIPv4Address(mInterfaceName)) {
+ if (!clearIPv4Address(mDataInterfaceName)) {
sendMessage(CMD_IP_CONFIGURATION_LOST);
}
}
@@ -4793,6 +5036,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
mNetworkInfo.getDetailedState() == DetailedState.CONNECTED) {
// We no longer report MAC address to third-parties and our code does
// not rely on this broadcast, so just send the default MAC address.
+ fetchRssiLinkSpeedAndFrequencyNative();
WifiInfo sentWifiInfo = new WifiInfo(mWifiInfo);
sentWifiInfo.setMacAddress(WifiInfo.DEFAULT_MAC_ADDRESS);
intent.putExtra(WifiManager.EXTRA_WIFI_INFO, sentWifiInfo);
@@ -4960,12 +5204,22 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
stopRssiMonitoringOffload();
clearCurrentConfigBSSID("handleNetworkDisconnect");
+ if (mContext.getResources().getBoolean(R.bool.wifi_autocon)
+ && !shouldAutoConnect()) {
+ /*
+ * The following logic shall address the requirement for the DUT to
+ * not reconnect to the last connected network when the Auto
+ * Connect is disabled. This asks for the user prompt for any
+ * connection attempt (as per the requirement)
+ */
+ disableLastNetwork();
+ }
stopDhcp();
try {
- mNwService.clearInterfaceAddresses(mInterfaceName);
- mNwService.disableIpv6(mInterfaceName);
+ mNwService.clearInterfaceAddresses(mDataInterfaceName);
+ mNwService.disableIpv6(mDataInterfaceName);
} catch (Exception e) {
loge("Failed to clear addresses or disable ipv6" + e);
}
@@ -5020,27 +5274,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
void handlePreDhcpSetup() {
mDhcpActive = true;
- if (!mBluetoothConnectionActive) {
- /*
- * There are problems setting the Wi-Fi driver's power
- * mode to active when bluetooth coexistence mode is
- * enabled or sense.
- * <p>
- * We set Wi-Fi to active mode when
- * obtaining an IP address because we've found
- * compatibility issues with some routers with low power
- * mode.
- * <p>
- * In order for this active power mode to properly be set,
- * we disable coexistence mode until we're done with
- * obtaining an IP address. One exception is if we
- * are currently connected to a headset, since disabling
- * coexistence would interrupt that connection.
- */
- // Disable the coexistence mode
- mWifiNative.setBluetoothCoexistenceMode(
- mWifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED);
- }
+ // Disable the coexistence mode
+ mWifiNative.setBluetoothCoexistenceMode(
+ mWifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED);
// Disable power save and suspend optimizations during DHCP
// Note: The order here is important for now. Brcm driver changes
@@ -5072,10 +5308,10 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
if (mDhcpStateMachine == null) {
if (useLegacyDhcpClient()) {
mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(
- mContext, WifiStateMachine.this, mInterfaceName);
+ mContext, WifiStateMachine.this, mDataInterfaceName);
} else {
mDhcpStateMachine = DhcpClient.makeDhcpStateMachine(
- mContext, WifiStateMachine.this, mInterfaceName);
+ mContext, WifiStateMachine.this, mDataInterfaceName);
}
}
}
@@ -5275,8 +5511,10 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
try {
- mNwService.wifiFirmwareReload(mInterfaceName, "AP");
- if (DBG) Log.d(TAG, "Firmware reloaded in AP mode");
+ if (!SystemProperties.getBoolean("ro.disableWifiApFirmwareReload", false)) {
+ mNwService.wifiFirmwareReload(mInterfaceName, "AP");
+ if (DBG) Log.d(TAG, "Firmware reloaded in AP mode");
+ }
} catch (Exception e) {
Log.e(TAG, "Failed to reload AP firmware " + e);
}
@@ -5512,7 +5750,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
class DefaultState extends State {
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch (message.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
@@ -5548,6 +5786,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
case CMD_ADD_OR_UPDATE_NETWORK:
case CMD_REMOVE_NETWORK:
case CMD_SAVE_CONFIG:
+ case CMD_GET_IBSS_SUPPORTED:
replyToMessage(message, message.what, FAILURE);
break;
case CMD_GET_CAPABILITY_FREQ:
@@ -5747,6 +5986,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
case CMD_REMOVE_USER_CONFIGURATIONS:
deferMessage(message);
break;
+ case CMD_PNO_PERIODIC_SCAN:
+ deferMessage(message);
case CMD_START_IP_PACKET_OFFLOAD:
if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent(
message.arg1,
@@ -5776,6 +6017,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
public void enter() {
WifiNative.stopHal();
mWifiNative.unloadDriver();
+ lastConnectAttemptTimestamp = 0;
if (mWifiP2pChannel == null) {
mWifiP2pChannel = new AsyncChannel();
mWifiP2pChannel.connect(mContext, getHandler(),
@@ -5798,9 +6040,15 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch (message.what) {
case CMD_START_SUPPLICANT:
+ /* Stop a running supplicant after a runtime restart
+ * Avoids issues with drivers that do not handle interface down
+ * on a running supplicant properly.
+ */
+ mWifiMonitor.killSupplicant(mP2pSupported);
+
if (mWifiNative.loadDriver()) {
try {
mNwService.wifiFirmwareReload(mInterfaceName, "STA");
@@ -5816,28 +6064,22 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
// Ensure interface is down and we have no IP
// addresses before a supplicant start.
mNwService.setInterfaceDown(mInterfaceName);
- mNwService.clearInterfaceAddresses(mInterfaceName);
+ mNwService.clearInterfaceAddresses(mDataInterfaceName);
// Set privacy extensions
- mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
+ mNwService.setInterfaceIpv6PrivacyExtensions(mDataInterfaceName, true);
// IPv6 is enabled only as long as access point is connected since:
// - IPv6 addresses and routes stick around after disconnection
// - kernel is unaware when connected and fails to start IPv6 negotiation
// - kernel can start autoconfiguration when 802.1x is not complete
- mNwService.disableIpv6(mInterfaceName);
+ mNwService.disableIpv6(mDataInterfaceName);
} catch (RemoteException re) {
loge("Unable to change interface settings: " + re);
} catch (IllegalStateException ie) {
loge("Unable to change interface settings: " + ie);
}
- /* Stop a running supplicant after a runtime restart
- * Avoids issues with drivers that do not handle interface down
- * on a running supplicant properly.
- */
- mWifiMonitor.killSupplicant(mP2pSupported);
-
if (WifiNative.startHal() == false) {
/* starting HAL is optional */
loge("Failed to start HAL");
@@ -5850,9 +6092,11 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
transitionTo(mSupplicantStartingState);
} else {
loge("Failed to start supplicant!");
+ setWifiState(WifiManager.WIFI_STATE_FAILED);
}
} else {
loge("Failed to load driver");
+ setWifiState(WifiManager.WIFI_STATE_FAILED);
}
break;
case CMD_START_AP:
@@ -5909,7 +6153,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch(message.what) {
case WifiMonitor.SUP_CONNECTION_EVENT:
@@ -5928,12 +6172,21 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
/* set frequency band of operation */
setFrequencyBand();
mWifiNative.enableSaveConfig();
+ if (mWifiConfigStore.enableAutoJoinWhenAssociated.get()) {
+ mWifiNative.disconnect();
+ }
mWifiConfigStore.loadAndEnableAllNetworks();
if (mWifiConfigStore.enableVerboseLogging.get() > 0) {
enableVerboseLogging(mWifiConfigStore.enableVerboseLogging.get());
}
+ if (mContext.getResources().getBoolean(R.bool.wifi_autocon)
+ && !shouldAutoConnect()) {
+ mWifiConfigStore.disableAllNetworks();
+ }
initializeWpsDetails();
+ mIbssSupported = mWifiNative.getModeCapability("IBSS");
+
sendSupplicantConnectionChangedBroadcast(true);
transitionTo(mDriverStartedState);
break;
@@ -5962,6 +6215,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
case CMD_SET_FREQUENCY_BAND:
case CMD_START_PACKET_FILTERING:
case CMD_STOP_PACKET_FILTERING:
+ case CMD_GET_IBSS_SUPPORTED:
messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED;
deferMessage(message);
break;
@@ -6001,7 +6255,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch(message.what) {
case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */
@@ -6100,6 +6354,15 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
mWifiP2pChannel.sendMessage(WifiP2pServiceImpl.SET_COUNTRY_CODE, country);
break;
+
+ case CMD_GET_IBSS_SUPPORTED:
+ deferMessage(message);
+ break;
+
+ case CMD_RESET_SIM_NETWORKS:
+ log("resetting EAP-SIM/AKA/AKA' networks since SIM was removed");
+ mWifiConfigStore.resetSimNetworks();
+ break;
default:
return NOT_HANDLED;
}
@@ -6140,7 +6403,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch(message.what) {
case WifiMonitor.SUP_CONNECTION_EVENT:
@@ -6189,7 +6452,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch(message.what) {
case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
@@ -6349,7 +6612,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch(message.what) {
case CMD_START_SCAN:
@@ -6363,8 +6626,17 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
if (PDBG) logd("did set frequency band " + band);
mFrequencyBand.set(band);
+ mWifiConfigStore.setConfiguredBand(band);
// Flush old data - like scan results
mWifiNative.bssFlush();
+ if (mFrequencyBand.get() == WifiManager.WIFI_FREQUENCY_BAND_2GHZ) {
+ mWifiNative.disable5GHzFrequencies(true);
+ mDisabled5GhzFrequencies = true;
+ } else if ((mFrequencyBand.get() != WifiManager.WIFI_FREQUENCY_BAND_2GHZ)
+ && (mDisabled5GhzFrequencies)) {
+ mWifiNative.disable5GHzFrequencies(false);
+ mDisabled5GhzFrequencies = false;
+ }
// Fetch the latest scan results when frequency band is set
// startScanNative(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, null);
@@ -6412,7 +6684,14 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
mAlarmManager.cancel(mDriverStopIntent);
if (DBG) log("Delayed stop ignored due to start");
if (mOperationalMode == CONNECT_MODE) {
- mWifiConfigStore.enableAllNetworks();
+ if (mContext.getResources().getBoolean(R.bool.wifi_autocon)
+ && !shouldAutoConnect()) {
+ if (DBG) {
+ logd("Auto connect disabled, skip enable networks");
+ }
+ } else {
+ mWifiConfigStore.enableAllNetworks();
+ }
}
}
break;
@@ -6475,6 +6754,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
case WifiMonitor.ANQP_DONE_EVENT:
mWifiConfigStore.notifyANQPDone((Long) message.obj, message.arg1 != 0);
break;
+ case CMD_GET_IBSS_SUPPORTED:
+ replyToMessage(message, message.what, mIbssSupported ? 1 : 0);
+ break;
case CMD_STOP_IP_PACKET_OFFLOAD: {
int slot = message.arg1;
int ret = stopWifiIPPacketOffload(slot);
@@ -6528,7 +6810,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch(message.what) {
case WifiStateMachine.CMD_DISABLE_P2P_RSP:
@@ -6564,7 +6846,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
class DriverStoppingState extends State {
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch(message.what) {
case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
@@ -6597,7 +6879,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
class DriverStoppedState extends State {
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch (message.what) {
case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
@@ -6629,7 +6911,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch(message.what) {
case CMD_SET_OPERATIONAL_MODE:
@@ -6642,7 +6924,14 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
mWifiConfigStore.loadAndEnableAllNetworks();
mWifiP2pChannel.sendMessage(CMD_ENABLE_P2P);
} else {
- mWifiConfigStore.enableAllNetworks();
+ if (mContext.getResources().getBoolean(R.bool.wifi_autocon)
+ && !shouldAutoConnect()) {
+ if (DBG) {
+ logd("No auto, skip enable networks on mode change");
+ }
+ } else {
+ mWifiConfigStore.enableAllNetworks();
+ }
}
// Try autojoining with recent network already present in the cache
@@ -7180,7 +7469,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
String bssid;
String ssid;
NetworkUpdateResult result;
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch (message.what) {
case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
@@ -7203,6 +7492,17 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
mWifiLogger.captureBugReportData(WifiLogger.REPORT_REASON_AUTH_FAILURE);
mSupplicantStateTracker.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT);
+ if ((mScreenOn == false) && mBackgroundScanSupported) {
+ // Background SCAN should trigger to initiate
+ // connection attempt on authentication failure.
+ // Hence issue PNO SCAN if authentication fails
+ // and LCD is off.
+ if (!mIsScanOngoing) {
+ if (!enableBackgroundScan(true)) {
+ handlePnoFailError();
+ }
+ }
+ }
break;
case WifiMonitor.SSID_TEMP_DISABLED:
case WifiMonitor.SSID_REENABLED:
@@ -7433,11 +7733,23 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
TelephonyManager tm = (TelephonyManager)
mContext.getSystemService(Context.TELEPHONY_SERVICE);
if (tm != null) {
- String imsi = tm.getSubscriberId();
+ int subId = SubscriptionManager.getDefaultSubId();
+ int slotId = tm.getDefaultSim();
+
+ if (targetWificonfiguration != null && targetWificonfiguration.SIMNum > 0 &&
+ tm.getDefault().getPhoneCount() >= 2) {
+ int[] subIds = SubscriptionManager.getSubId(targetWificonfiguration.SIMNum - 1);
+ if (subIds != null) {
+ subId = subIds[0];
+ slotId = SubscriptionManager.getSlotId(subId);
+ }
+ }
+
+ String imsi = tm.getSubscriberId(subId);
String mccMnc = "";
- if (tm.getSimState() == TelephonyManager.SIM_STATE_READY)
- mccMnc = tm.getSimOperator();
+ if (tm.getSimState(slotId) == TelephonyManager.SIM_STATE_READY)
+ mccMnc = tm.getSimOperator(subId);
String identity = buildIdentity(eapMethod, imsi, mccMnc);
@@ -7902,6 +8214,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
WpsResult wpsResult;
switch (wpsInfo.setup) {
case WpsInfo.PBC:
+ clearRandomMacOui();
+ mIsRandomMacCleared = true;
wpsResult = mWifiConfigStore.startWpsPbc(wpsInfo);
break;
case WpsInfo.KEYPAD:
@@ -8105,9 +8419,17 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
if (mnc.length() == 2)
mnc = "0" + mnc;
} else {
- // extract mcc & mnc from IMSI, assume mnc size is 3
+ // extract mcc & mnc from IMSI, assume mnc size is 3 if in this list, 2 otherwise
+ String ThreeDigitMnc[] = {"302", "310", "311", "312", "313", "314", "315", "316", "334", "348"};
+
mcc = imsi.substring(0, 3);
mnc = imsi.substring(3, 6);
+
+ if (!Arrays.asList(ThreeDigitMnc).contains(mcc))
+ mnc = mnc.substring(0, 2);
+
+ if (mnc.length() == 2)
+ mnc = "0" + mnc;
}
return prefix + imsi + "@wlan.mnc" + mnc + ".mcc" + mcc + ".3gppnetwork.org";
@@ -8177,7 +8499,12 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
+ " config.bssid " + config.BSSID);
}
config.autoJoinBSSID = "any";
- config.BSSID = "any";
+
+ // If an app specified a BSSID then dont over-write it
+ if ( !mWifiAutoJoinController.isBlacklistedBSSID(config.BSSID) ) {
+ config.BSSID = "any";
+ }
+
if (DBG) {
logd(dbg + " " + config.SSID
+ " nid=" + Integer.toString(config.networkId));
@@ -8201,27 +8528,32 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
if (!TextUtils.isEmpty(mTcpBufferSizes)) {
mLinkProperties.setTcpBufferSizes(mTcpBufferSizes);
}
+ mLinkProperties.setTcpDelayedAckSegments(mTcpDelayedAckSegments);
+ mLinkProperties.setTcpUserCfg(mTcpUserCfg);
+
mNetworkAgent = new WifiNetworkAgent(getHandler().getLooper(), mContext,
"WifiNetworkAgent", mNetworkInfo, mNetworkCapabilitiesFilter,
- mLinkProperties, 60);
+ mLinkProperties, DEFAULT_SCORE);
// We must clear the config BSSID, as the wifi chipset may decide to roam
// from this point on and having the BSSID specified in the network block would
// cause the roam to faile and the device to disconnect
clearCurrentConfigBSSID("L2ConnectedState");
- try {
- mIpReachabilityMonitor = new IpReachabilityMonitor(
- mContext,
- mInterfaceName,
- new IpReachabilityMonitor.Callback() {
- @Override
- public void notifyLost(InetAddress ip, String logMsg) {
- sendMessage(CMD_IP_REACHABILITY_LOST, logMsg);
- }
- });
- } catch (IllegalArgumentException e) {
- Log.wtf("Failed to create IpReachabilityMonitor", e);
+ if (mIsWiFiIpReachabilityEnabled) {
+ try {
+ mIpReachabilityMonitor = new IpReachabilityMonitor(
+ mContext,
+ mInterfaceName,
+ new IpReachabilityMonitor.Callback() {
+ @Override
+ public void notifyLost(InetAddress ip, String logMsg) {
+ sendMessage(CMD_IP_REACHABILITY_LOST, logMsg);
+ }
+ });
+ } catch (IllegalArgumentException e) {
+ Log.wtf("Failed to create IpReachabilityMonitor", e);
+ }
}
}
@@ -8251,7 +8583,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch (message.what) {
case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
@@ -8574,6 +8906,17 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
case CMD_STOP_RSSI_MONITORING_OFFLOAD:
stopRssiMonitoringOffload();
break;
+ case CMD_RESET_SIM_NETWORKS:
+ if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) {
+ WifiConfiguration config =
+ mWifiConfigStore.getWifiConfiguration(mLastNetworkId);
+ if (mWifiConfigStore.isSimConfig(config)) {
+ mWifiNative.disconnect();
+ transitionTo(mDisconnectingState);
+ }
+ }
+ /* allow parent state to reset data for other networks */
+ return NOT_HANDLED;
default:
return NOT_HANDLED;
}
@@ -8610,7 +8953,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
clearCurrentConfigBSSID("ObtainingIpAddress");
try {
- mNwService.enableIpv6(mInterfaceName);
+ mNwService.enableIpv6(mDataInterfaceName);
} catch (RemoteException re) {
loge("Failed to enable IPv6: " + re);
} catch (IllegalStateException e) {
@@ -8624,7 +8967,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
// Remove any IP address on the interface in case we're switching from static
// IP configuration to DHCP. This is safe because if we get here when not
// roaming, we don't have a usable address.
- clearIPv4Address(mInterfaceName);
+ clearIPv4Address(mDataInterfaceName);
startDhcp();
}
obtainingIpWatchdogCount++;
@@ -8646,7 +8989,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
ifcg.setLinkAddress(config.ipAddress);
ifcg.setInterfaceUp();
try {
- mNwService.setInterfaceConfig(mInterfaceName, ifcg);
+ mNwService.setInterfaceConfig(mDataInterfaceName, ifcg);
if (DBG) log("Static IP configuration succeeded");
DhcpResults dhcpResults = new DhcpResults(config);
sendMessage(CMD_STATIC_IP_SUCCESS, dhcpResults);
@@ -8662,7 +9005,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch(message.what) {
case CMD_STATIC_IP_SUCCESS:
@@ -8721,7 +9064,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch (message.what) {
case WifiWatchdogStateMachine.POOR_LINK_DETECTED:
@@ -8785,7 +9128,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
WifiConfiguration config;
switch (message.what) {
case CMD_IP_CONFIGURATION_LOST:
@@ -8948,9 +9291,20 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
sendMessageDelayed(obtainMessage(CMD_TEST_NETWORK_DISCONNECT,
testNetworkDisconnectCounter, 0), 15000);
}
-
- // Reenable all networks, allow for hidden networks to be scanned
- mWifiConfigStore.enableAllNetworks();
+ if (!mWifiConfigStore.enableAutoJoinWhenAssociated.get()) {
+ if (mContext.getResources().getBoolean(R.bool.wifi_autocon)
+ && !shouldAutoConnect()) {
+ if (DBG) {
+ logd("Auto connect disabled, skip enable networks");
+ }
+ } else {
+ // Reenable all networks, allow for hidden networks to be scanned
+ mWifiConfigStore.enableAllNetworks();
+ }
+ } else {
+ // Reenable all networks, allow for hidden networks to be scanned
+ mWifiConfigStore.enableAllNetworks();
+ }
mLastDriverRoamAttempt = 0;
@@ -8959,7 +9313,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
@Override
public boolean processMessage(Message message) {
WifiConfiguration config = null;
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch (message.what) {
case CMD_RESTART_AUTOJOIN_OFFLOAD:
@@ -9058,6 +9412,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
if (toBSSID != null && !toBSSID.equals(mWifiInfo.getBSSID())) {
mWifiConfigStore.driverRoamedFrom(mWifiInfo);
}
+ mWifiConfigStore.unblackListDriverRoamedBSSID(toBSSID);
return NOT_HANDLED;
case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
long lastRoam = 0;
@@ -9086,7 +9441,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
WifiConfiguration.BAD_RSSI_5))) {
// Start de-bouncing the L2 disconnection:
// this L2 disconnection might be spurious.
- // Hence we allow 7 seconds for the state machine to try
+ // Hence we allow 4 seconds for the state machine to try
// to reconnect, go thru the
// roaming cycle and enter Obtaining IP address
// before signalling the disconnect to ConnectivityService and L3
@@ -9257,7 +9612,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch (message.what) {
case CMD_SET_OPERATIONAL_MODE:
if (message.arg1 != CONNECT_MODE) {
@@ -9333,7 +9688,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
* cleared
*/
if (!mIsScanOngoing) {
- enableBackgroundScan(true);
+ if (!enableBackgroundScan(true)) {
+ handlePnoFailError();
+ }
}
} else {
setScanAlarm(true);
@@ -9359,7 +9716,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
public boolean processMessage(Message message) {
boolean ret = HANDLED;
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch (message.what) {
case CMD_NO_NETWORKS_PERIODIC_SCAN:
@@ -9371,6 +9728,17 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
++mPeriodicScanToken, 0), mNoNetworksPeriodicScan);
}
break;
+ case CMD_PNO_PERIODIC_SCAN:
+ if ((message.arg1 == mPnoPeriodicScanToken) &&
+ mBackgroundScanSupported && (mP2pConnected.get() ||
+ (mWifiConfigStore.getConfiguredNetworks().size()
+ != 0))) {
+ startScan(UNKNOWN_SCAN_SOURCE, -1, null, null);
+ sendMessageDelayed(obtainMessage(CMD_PNO_PERIODIC_SCAN,
+ ++mPnoPeriodicScanToken, 0),
+ mDefaultFrameworkScanIntervalMs);
+ }
+ break;
case WifiManager.FORGET_NETWORK:
case CMD_REMOVE_NETWORK:
case CMD_REMOVE_APP_CONFIGURATIONS:
@@ -9491,7 +9859,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
// attempt again to join that network.
if (!mScreenOn && !mIsScanOngoing && mBackgroundScanSupported) {
enableBackgroundScan(false);
- enableBackgroundScan(true);
+ if (!enableBackgroundScan(true)) {
+ handlePnoFailError();
+ }
}
return HANDLED;
}
@@ -9502,7 +9872,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
if (!mScreenOn && mIsScanOngoing
&& mBackgroundScanSupported
&& !useHalBasedAutoJoinOffload()) {
- enableBackgroundScan(true);
+ if (!enableBackgroundScan(true)) {
+ handlePnoFailError();
+ }
} else if (!mScreenOn
&& !mIsScanOngoing
&& mBackgroundScanSupported
@@ -9541,6 +9913,10 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
if (DBG) log("Turn on scanning after p2p disconnected");
sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
++mPeriodicScanToken, 0), mNoNetworksPeriodicScan);
+ } else if (!mP2pConnected.get() && (!mScreenOn)) {
+ if (!enableBackgroundScan(true)) {
+ handlePnoFailError();
+ }
} else {
// If P2P is not connected and there are saved networks, then restart
// scanning at the normal period. This is necessary because scanning might
@@ -9610,7 +9986,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch (message.what) {
case WifiMonitor.WPS_SUCCESS_EVENT:
@@ -9708,6 +10084,10 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
public void exit() {
mWifiConfigStore.enableAllNetworks();
mWifiConfigStore.loadConfiguredNetworks();
+ if (mIsRandomMacCleared) {
+ setRandomMacOui();
+ mIsRandomMacCleared = false;
+ }
}
}
@@ -9730,7 +10110,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch(message.what) {
case CMD_START_SUPPLICANT:
@@ -9774,7 +10154,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
class SoftApStartedState extends State {
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch(message.what) {
case CMD_STOP_AP:
@@ -9818,7 +10198,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch(message.what) {
case CMD_TETHER_STATE_CHANGE:
@@ -9831,6 +10211,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
if (message.arg1 == mTetherToken) {
loge("Failed to get tether update, shutdown soft access point");
transitionTo(mSoftApStartedState);
+ setWifiApState(WIFI_AP_STATE_FAILED,WifiManager.SAP_START_FAILURE_GENERAL);
// Needs to be first thing handled
sendMessageAtFrontOfQueue(CMD_STOP_AP);
}
@@ -9858,7 +10239,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
class TetheredState extends State {
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch(message.what) {
case CMD_TETHER_STATE_CHANGE:
@@ -9894,7 +10275,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
@Override
public boolean processMessage(Message message) {
- logStateAndMessage(message, getClass().getSimpleName());
+ logStateAndMessage(message, this);
switch(message.what) {
case CMD_TETHER_STATE_CHANGE:
@@ -10139,13 +10520,13 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
* com.android.internal.telephony.PhoneConstants#APPTYPE_xxx
*/
int appType = 2;
- String tmResponse = tm.getIccSimChallengeResponse(appType, base64Challenge);
+ String tmResponse = getIccSimChallengeResponse(appType, base64Challenge, tm);
if (tmResponse == null) {
/* Then, in case of failure, issue may be due to sim type, retry as a simple sim
* appType = 1 => SIM
*/
appType = 1;
- tmResponse = tm.getIccSimChallengeResponse(appType, base64Challenge);
+ tmResponse = getIccSimChallengeResponse(appType, base64Challenge, tm);
}
logv("Raw Response - " + tmResponse);
@@ -10160,16 +10541,20 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
String kc = makeHex(result, 1+kc_offset, kc_len);
sb.append(":" + kc + ":" + sres);
logv("kc:" + kc + " sres:" + sres);
+
} else {
loge("bad response - " + tmResponse);
+ mWifiNative.simAuthFailedResponse(requestData.networkId);
}
}
String response = sb.toString();
logv("Supplicant Response -" + response);
mWifiNative.simAuthResponse(requestData.networkId, "GSM-AUTH", response);
+
} else {
loge("could not get telephony manager");
+ mWifiNative.simAuthFailedResponse(requestData.networkId);
}
}
@@ -10206,13 +10591,14 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
mContext.getSystemService(Context.TELEPHONY_SERVICE);
if (tm != null) {
int appType = 2; // 2 => USIM
- tmResponse = tm.getIccSimChallengeResponse(appType, base64Challenge);
+ tmResponse = getIccSimChallengeResponse(appType, base64Challenge, tm);
logv("Raw Response - " + tmResponse);
} else {
loge("could not get telephony manager");
}
}
+ boolean good_response = false;
if (tmResponse != null && tmResponse.length() > 4) {
byte[] result = android.util.Base64.decode(tmResponse,
android.util.Base64.DEFAULT);
@@ -10228,6 +10614,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
String ik = makeHex(result, res_len + ck_len + 4, ik_len);
sb.append(":" + ik + ":" + ck + ":" + res);
logv("ik:" + ik + "ck:" + ck + " res:" + res);
+ good_response = true;
} else if (tag == (byte) 0xdc) {
loge("synchronisation failure");
int auts_len = result[1];
@@ -10235,18 +10622,45 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
res_type = "UMTS-AUTS";
sb.append(":" + auts);
logv("auts:" + auts);
+ good_response = true;
} else {
loge("bad response - unknown tag = " + tag);
- return;
}
} else {
loge("bad response - " + tmResponse);
- return;
}
- String response = sb.toString();
- logv("Supplicant Response -" + response);
- mWifiNative.simAuthResponse(requestData.networkId, res_type, response);
+ if (good_response) {
+ String response = sb.toString();
+ if (VDBG) logv("Supplicant Response -" + response);
+ mWifiNative.simAuthResponse(requestData.networkId, res_type, response);
+ } else {
+ mWifiNative.umtsAuthFailedResponse(requestData.networkId);
+ }
+ }
+
+ private String getIccSimChallengeResponse(
+ int appType, String base64Challenge, TelephonyManager tm) {
+ String tmResponse = null;
+ int subId = SubscriptionManager.getDefaultSubId();
+
+ if (targetWificonfiguration != null && targetWificonfiguration.SIMNum > 0 &&
+ tm.getDefault().getPhoneCount() >= 2) {
+ int[] subIds = SubscriptionManager.getSubId(targetWificonfiguration.SIMNum - 1);
+ if (subIds != null) {
+ subId = subIds[0];
+ }
+ }
+
+
+ if (subId >= 0) {
+ log("Requesting SIM challenge response from sub " + subId);
+ tmResponse = tm.getIccSimChallengeResponse(subId, appType, base64Challenge);
+ } else {
+ log("Requesting SIM challenge response");
+ tmResponse = tm.getIccSimChallengeResponse(appType, base64Challenge);
+ }
+ return tmResponse;
}
/**
@@ -10267,4 +10681,58 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
|| reason == 23 // IEEE_802_1X_AUTH_FAILED
|| reason == 34; // DISASSOC_LOW_ACK
}
+ private void handlePnoFailError() {
+ if (mBackgroundScanSupported && (mP2pConnected.get() ||
+ (mWifiConfigStore.getConfiguredNetworks().size() != 0))) {
+ sendMessageDelayed(obtainMessage(CMD_PNO_PERIODIC_SCAN,
+ ++mPnoPeriodicScanToken, 0),
+ mDefaultFrameworkScanIntervalMs);
+ }
+ }
+
+ boolean shouldAutoConnect() {
+ int autoConnectPolicy = Settings.System.getInt(
+ mContext.getContentResolver(),
+ Settings.System.WIFI_AUTO_CONNECT_TYPE,
+ WIFI_AUTO_CONNECT_TYPE_AUTO);
+ if (DBG) {
+ if (autoConnectPolicy == WIFI_AUTO_CONNECT_TYPE_AUTO) {
+ Log.d(TAG, "Wlan connection type is auto, should auto connect");
+ } else {
+ Log.d(TAG, "Shouldn't auto connect");
+ }
+ }
+ return (autoConnectPolicy == WIFI_AUTO_CONNECT_TYPE_AUTO);
+ }
+
+ void disableLastNetwork() {
+ if (getCurrentState() != mSupplicantStoppingState) {
+ mWifiConfigStore.disableNetwork(mLastNetworkId,
+ WifiConfiguration.DISABLED_UNKNOWN_REASON);
+ }
+ }
+
+ void checkAndSetAutoConnection() {
+ if (mContext.getResources().getBoolean(R.bool.wifi_autocon)) {
+ if (shouldAutoConnect()){
+ if(!mWifiConfigStore.enableAutoJoinWhenAssociated.get()) {
+ /*
+ * This is AutoConnect-> Automatic, but auto join
+ * is disabled , hence re enable supplicant auto
+ * connection ability, also enable all networks
+ * so that supplicant shall try for connection.
+ */
+ mWifiNative.enableAutoConnect(true);
+ mWifiConfigStore.enableAllNetworks();
+ }
+ } else {
+ /*
+ * This is AutoConnect -> Manual selection case
+ * Device should not auto connect to network, hence
+ * disable supplicants auto connection ability.
+ */
+ mWifiNative.enableAutoConnect(false);
+ }
+ }
+ }
}
diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
index 9a034ad..7e5192f 100644
--- a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
+++ b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
@@ -48,6 +48,7 @@ import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
import android.net.wifi.p2p.nsd.WifiP2pServiceRequest;
import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
@@ -102,7 +103,7 @@ import java.util.Locale;
*/
public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
private static final String TAG = "WifiP2pService";
- private static final boolean DBG = false;
+ private static boolean DBG = false;
private static final String NETWORKTYPE = "WIFI_P2P";
private Context mContext;
@@ -184,6 +185,9 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
public static final int ENABLED = 1;
public static final int DISABLED = 0;
+ static final int P2P_BLUETOOTH_COEXISTENCE_MODE_DISABLED = 1;
+ static final int P2P_BLUETOOTH_COEXISTENCE_MODE_SENSE = 2;
+
private final boolean mP2pSupported;
private WifiP2pDevice mThisDevice = new WifiP2pDevice();
@@ -196,6 +200,8 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
/* Invitation to join an existing p2p group */
private boolean mJoinExistingGroup;
+ private boolean mIsInvite = false;
+
/* Track whether we are in p2p discovery. This is used to avoid sending duplicate
* broadcasts
*/
@@ -437,6 +443,14 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
return new Messenger(mP2pStateMachine.getHandler());
}
+ public void enableVerboseLogging(int verbose) {
+ if (verbose > 0 ) {
+ DBG = true;
+ } else {
+ DBG = false;
+ }
+ }
+
/** This is used to provide information to drivers to optimize performance depending
* on the current mode of operation.
* 0 - disabled
@@ -522,6 +536,8 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
});
private final WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo();
private WifiP2pGroup mGroup;
+ private boolean mPendingReformGroupIndication = false;
+ private boolean mIsBTCoexDisabled = false;
// Saved WifiP2pConfig for an ongoing peer connection. This will never be null.
// The deviceAddress will be an empty string when the device is inactive
@@ -563,7 +579,7 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
class DefaultState extends State {
@Override
public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
+ if (DBG) logd(getName() + " " + message.toString());
switch (message.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
@@ -761,6 +777,7 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
class P2pNotSupportedState extends State {
@Override
public boolean processMessage(Message message) {
+ if (DBG) logd(getName() + " " + message.toString());
switch (message.what) {
case WifiP2pManager.DISCOVER_PEERS:
replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
@@ -858,7 +875,7 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
@Override
public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
+ if (DBG) logd(getName() + " " + message.toString());
switch (message.what) {
case WifiMonitor.SUP_DISCONNECTION_EVENT:
if (DBG) logd("p2p socket connection lost");
@@ -894,7 +911,7 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
@Override
public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
+ if (DBG) logd(getName() + " " + message.toString());
switch (message.what) {
case WifiStateMachine.CMD_ENABLE_P2P:
try {
@@ -904,8 +921,11 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
} catch (IllegalStateException ie) {
loge("Unable to change interface settings: " + ie);
}
- mWifiMonitor.startMonitoring();
- transitionTo(mP2pEnablingState);
+ if (mWifiMonitor.startMonitoring()) {
+ transitionTo(mP2pEnablingState);
+ } else {
+ loge("start monitoring failed, do not transition");
+ }
break;
default:
return NOT_HANDLED;
@@ -922,7 +942,7 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
@Override
public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
+ if (DBG) logd(getName() + " " + message.toString());
switch (message.what) {
case WifiMonitor.SUP_CONNECTION_EVENT:
if (DBG) logd("P2p socket connection successful");
@@ -955,7 +975,7 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
@Override
public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
+ if (DBG) logd(getName() + " " + message.toString());
switch (message.what) {
case WifiMonitor.SUP_DISCONNECTION_EVENT:
loge("Unexpected loss of p2p socket connection");
@@ -1207,12 +1227,13 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
@Override
public void enter() {
if (DBG) logd(getName());
+ mIsInvite = false;
mSavedPeerConfig.invalidate();
}
@Override
public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
+ if (DBG) logd(getName() + " " + message.toString());
switch (message.what) {
case WifiP2pManager.CONNECT:
if (DBG) logd(getName() + " sending connect");
@@ -1290,16 +1311,28 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
mAutonomousGroup = false;
mJoinExistingGroup = true;
+ mIsInvite = true;
transitionTo(mUserAuthorizingInviteRequestState);
break;
case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT:
case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
- case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
//We let the supplicant handle the provision discovery response
//and wait instead for the GO_NEGOTIATION_REQUEST_EVENT.
//Handling provision discovery and issuing a p2p_connect before
//group negotiation comes through causes issues
break;
+ case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
+ WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj;
+ WifiP2pDevice device = provDisc.device;
+ if (device == null) {
+ Slog.d(TAG, "Device entry is null");
+ break;
+ }
+ notifyP2pProvDiscShowPinRequest(provDisc.pin, device.deviceAddress);
+ mPeers.updateStatus(device.deviceAddress, WifiP2pDevice.INVITED);
+ sendPeersChangedBroadcast();
+ transitionTo(mGroupNegotiationState);
+ break;
case WifiP2pManager.CREATE_GROUP:
mAutonomousGroup = true;
int netId = message.arg1;
@@ -1417,7 +1450,7 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
@Override
public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
+ if (DBG) logd(getName() + " " + message.toString());
boolean ret = HANDLED;
switch (message.what) {
case GROUP_CREATING_TIMED_OUT:
@@ -1479,7 +1512,7 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
@Override
public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
+ if (DBG) logd(getName() + " " + message.toString());
boolean ret = HANDLED;
switch (message.what) {
case PEER_CONNECTION_USER_ACCEPT:
@@ -1514,7 +1547,7 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
@Override
public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
+ if (DBG) logd(getName() + " " + message.toString());
boolean ret = HANDLED;
switch (message.what) {
case PEER_CONNECTION_USER_ACCEPT:
@@ -1554,7 +1587,7 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
@Override
public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
+ if (DBG) logd(getName() + " " + message.toString());
WifiP2pProvDiscEvent provDisc;
WifiP2pDevice device;
switch (message.what) {
@@ -1615,11 +1648,12 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
@Override
public void enter() {
if (DBG) logd(getName());
+ mPendingReformGroupIndication = false;
}
@Override
public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
+ if (DBG) logd(getName() + " " + message.toString());
switch (message.what) {
// We ignore these right now, since we get a GROUP_STARTED notification
// afterwards
@@ -1627,6 +1661,13 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
case WifiMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT:
if (DBG) logd(getName() + " go success");
break;
+ // Action of removing and reforming group will be taken
+ // when we enter in GroupCreatedState
+ case WifiMonitor.P2P_REMOVE_AND_REFORM_GROUP_EVENT:
+ logd("P2P_REMOVE_AND_REFORM_GROUP_EVENT event received"
+ + " in GroupNegotiationState state");
+ mPendingReformGroupIndication = true;
+ break;
case WifiMonitor.P2P_GROUP_STARTED_EVENT:
mGroup = (WifiP2pGroup) message.obj;
if (DBG) logd(getName() + " group started");
@@ -1661,6 +1702,9 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
P2pStateMachine.this, mGroup.getInterface());
// TODO: We should use DHCP state machine PRE message like WifiStateMachine
mWifiNative.setP2pPowerSave(mGroup.getInterface(), false);
+ mWifiNative.setBluetoothCoexistenceMode(
+ P2P_BLUETOOTH_COEXISTENCE_MODE_DISABLED);
+ mIsBTCoexDisabled = true;
mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
WifiP2pDevice groupOwner = mGroup.getOwner();
WifiP2pDevice peer = mPeers.get(groupOwner.deviceAddress);
@@ -1788,14 +1832,14 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
@Override
public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
+ if (DBG) logd(getName() + " " + message.toString());
switch (message.what) {
case WifiMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT:
case WifiMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT:
- loge(getName() + "group sucess during freq conflict!");
+ loge(getName() + " group sucess during freq conflict!");
break;
case WifiMonitor.P2P_GROUP_STARTED_EVENT:
- loge(getName() + "group started after freq conflict, handle anyway");
+ loge(getName() + " group started after freq conflict, handle anyway");
deferMessage(message);
transitionTo(mGroupNegotiationState);
break;
@@ -1816,7 +1860,7 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
break;
case DISCONNECT_WIFI_RESPONSE:
// Got a response from wifistatemachine, retry p2p
- if (DBG) logd(getName() + "Wifi disconnected, retry p2p");
+ if (DBG) logd(getName() + " Wifi disconnected, retry p2p");
transitionTo(mInactiveState);
sendMessage(WifiP2pManager.CONNECT, mSavedPeerConfig);
break;
@@ -1832,30 +1876,56 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
}
class GroupCreatedState extends State {
+
+ private boolean handlP2pGroupRestart() {
+ boolean remove = true;
+ if (mWifiNative.p2pGroupRemove(mGroup.getInterface())) {
+ Slog.d(TAG, "Removed P2P group successfully");
+ transitionTo(mOngoingGroupRemovalState);
+ } else {
+ Slog.d(TAG, "Failed to remove the P2P group");
+ handleGroupRemoved();
+ transitionTo(mInactiveState);
+ remove = false;
+ }
+ if (mAutonomousGroup) {
+ Slog.d(TAG, "AutonomousGroup is set, reform P2P Group");
+ sendMessage(WifiP2pManager.CREATE_GROUP);
+ } else {
+ Slog.d(TAG, "AutonomousGroup is not set, will not reform P2P Group");
+ }
+ return remove;
+ }
+
@Override
public void enter() {
- if (DBG) logd(getName());
- // Once connected, peer config details are invalid
- mSavedPeerConfig.invalidate();
- mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
+ logd(getName() + " mPendingReformGroupIndication=" + mPendingReformGroupIndication);
+ if (mPendingReformGroupIndication) {
+ mPendingReformGroupIndication = false;
+ handlP2pGroupRestart();
+ } else {
+ // Once connected, peer config details are invalid
+ mSavedPeerConfig.invalidate();
+ mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
- updateThisDevice(WifiP2pDevice.CONNECTED);
+ updateThisDevice(WifiP2pDevice.CONNECTED);
- //DHCP server has already been started if I am a group owner
- if (mGroup.isGroupOwner()) {
- setWifiP2pInfoOnGroupFormation(NetworkUtils.numericToInetAddress(SERVER_ADDRESS));
- }
+ //DHCP server has already been started if I am a group owner
+ if (mGroup.isGroupOwner()) {
+ setWifiP2pInfoOnGroupFormation(NetworkUtils.numericToInetAddress(SERVER_ADDRESS));
+ }
- // In case of a negotiation group, connection changed is sent
- // after a client joins. For autonomous, send now
- if (mAutonomousGroup) {
- sendP2pConnectionChangedBroadcast();
+ // In case of a negotiation group, connection changed is sent
+ // after a client joins. For autonomous, send now
+ if (mAutonomousGroup) {
+ sendP2pConnectionChangedBroadcast();
+ }
}
}
@Override
public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
+ if (DBG) logd(getName() + " " + message.toString());
switch (message.what) {
case WifiMonitor.AP_STA_CONNECTED_EVENT:
WifiP2pDevice device = (WifiP2pDevice) message.obj;
@@ -1904,8 +1974,23 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
loge("Disconnect on unknown device: " + device);
}
break;
+ case WifiMonitor.P2P_REMOVE_AND_REFORM_GROUP_EVENT:
+ /* First remove p2p group and then restart only if
+ * autonoums group formation is set to true
+ */
+ Slog.d(TAG, "Received event P2P_REMOVE_AND_REFORM_GROUP, remove P2P group");
+ if (handlP2pGroupRestart()) {
+ replyToMessage(message,
+ WifiP2pManager.REMOVE_GROUP_SUCCEEDED);
+ } else {
+ replyToMessage(message,
+ WifiP2pManager.REMOVE_GROUP_FAILED,
+ WifiP2pManager.ERROR);
+ }
+ break;
case DhcpStateMachine.CMD_POST_DHCP_ACTION:
DhcpResults dhcpResults = (DhcpResults) message.obj;
+ enableBTCoex();
if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS &&
dhcpResults != null) {
if (DBG) logd("DhcpResults: " + dhcpResults);
@@ -1919,6 +2004,8 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
dhcpResults.getRoutes(iface));
} catch (RemoteException e) {
loge("Failed to add iface to local network " + e);
+ } catch (IllegalStateException ie) {
+ loge("Failed to add iface to local network " + ie);
}
} else {
loge("DHCP failed");
@@ -1927,6 +2014,11 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
break;
case WifiP2pManager.REMOVE_GROUP:
if (DBG) logd(getName() + " remove group");
+ /* We need to check BTCOex state, because some times
+ * user can interupt connection before dhcp sucess, then
+ * BTcoex will be in disabled state.
+ */
+ enableBTCoex();
if (mWifiNative.p2pGroupRemove(mGroup.getInterface())) {
transitionTo(mOngoingGroupRemovalState);
replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED);
@@ -1950,7 +2042,13 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
*/
case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
if (DBG) logd(getName() + " group removed");
+ /* We need to check BTCOex state, because if group
+ * is removed at GO side before dhcp sucess, then
+ * BTCoex will be in disabled state.
+ */
+ enableBTCoex();
handleGroupRemoved();
+ mWifiNative.p2pFlush();
transitionTo(mInactiveState);
break;
case WifiMonitor.P2P_DEVICE_LOST_EVENT:
@@ -2031,7 +2129,6 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
mSavedPeerConfig.deviceAddress, false)) {
// not found the client on the list
loge("Already removed the client, ignore");
- break;
}
// try invitation.
sendMessage(WifiP2pManager.CONNECT, mSavedPeerConfig);
@@ -2052,7 +2149,13 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
} else {
mSavedPeerConfig.wps.setup = WpsInfo.PBC;
}
- transitionTo(mUserAuthorizingJoinState);
+ if (DBG) logd("mGroup.isGroupOwner()" + mGroup.isGroupOwner());
+ if (mGroup.isGroupOwner()) {
+ if (DBG) {
+ logd("Device is GO, going to mUserAuthorizingJoinState");
+ }
+ transitionTo(mUserAuthorizingJoinState);
+ }
break;
case WifiMonitor.P2P_GROUP_STARTED_EVENT:
loge("Duplicate group creation event notice, ignore");
@@ -2080,7 +2183,7 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
@Override
public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
+ if (DBG) logd(getName() + " " + message.toString());
switch (message.what) {
case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT:
case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
@@ -2122,7 +2225,7 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
@Override
public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
+ if (DBG) logd(getName() + " " + message.toString());
switch (message.what) {
// Group removal ongoing. Multiple calls
// end up removing persisted network. Do nothing.
@@ -2299,6 +2402,36 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
dialog.show();
}
+ private void notifyP2pProvDiscShowPinRequest(String pin, String peerAddress) {
+ Resources r = Resources.getSystem();
+ final String tempDevAddress = peerAddress;
+ final String tempPin = pin;
+
+ final View textEntryView = LayoutInflater.from(mContext)
+ .inflate(R.layout.wifi_p2p_dialog, null);
+
+ ViewGroup group = (ViewGroup) textEntryView.findViewById(R.id.info);
+ addRowToDialog(group, R.string.wifi_p2p_to_message, getDeviceName(peerAddress));
+ addRowToDialog(group, R.string.wifi_p2p_show_pin_message, pin);
+
+ AlertDialog dialog = new AlertDialog.Builder(mContext)
+ .setTitle(r.getString(R.string.wifi_p2p_invitation_sent_title))
+ .setView(textEntryView)
+ .setPositiveButton(r.getString(R.string.accept), new OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ mSavedPeerConfig = new WifiP2pConfig();
+ mSavedPeerConfig.deviceAddress = tempDevAddress;
+ mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY;
+ mSavedPeerConfig.wps.pin = tempPin;
+ mWifiNative.p2pConnect(mSavedPeerConfig, FORM_GROUP);
+ }
+ })
+ .setCancelable(false)
+ .create();
+ dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ dialog.show();
+ }
+
private void notifyInvitationReceived() {
Resources r = Resources.getSystem();
final WpsInfo wps = mSavedPeerConfig.wps;
@@ -2482,15 +2615,22 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
* @param config for the peer
*/
private void p2pConnectWithPinDisplay(WifiP2pConfig config) {
+ boolean join = false;
WifiP2pDevice dev = fetchCurrentDeviceDetails(config);
+ if (mIsInvite) {
+ join = true;
+ } else {
+ join = dev.isGroupOwner();
+ }
- String pin = mWifiNative.p2pConnect(config, dev.isGroupOwner());
+ String pin = mWifiNative.p2pConnect(config, join);
try {
Integer.parseInt(pin);
notifyInvitationSent(pin, config.deviceAddress);
} catch (NumberFormatException ignore) {
// do nothing if p2pConnect did not return a pin
}
+ mIsInvite = false;
}
/**
@@ -2665,6 +2805,14 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
String deviceName = Settings.Global.getString(mContext.getContentResolver(),
Settings.Global.WIFI_P2P_DEVICE_NAME);
if (deviceName == null) {
+ String name = mContext.getResources().getString(
+ org.cyanogenmod.platform.internal.R.string.config_wifiDirectName);
+ if (!TextUtils.isEmpty(name)) {
+ if (name.equals("%m")) {
+ return Build.MODEL;
+ }
+ return name;
+ }
/* We use the 4 digits of the ANDROID_ID to have a friendly
* default that has low likelihood of collision with a peer */
String id = Settings.Secure.getString(mContext.getContentResolver(),
@@ -2782,6 +2930,8 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
mNwService.removeInterfaceFromLocalNetwork(mGroup.getInterface());
} catch (RemoteException e) {
loge("Failed to remove iface from local network " + e);
+ } catch (IllegalStateException ie) {
+ loge("Failed to remove iface from local network " + ie);
}
}
@@ -3108,6 +3258,17 @@ public final class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
return clientInfo;
}
+ /**
+ * Enable BTCOEXMODE after DHCP or GROUP REMOVE
+ */
+ private void enableBTCoex() {
+ if (mIsBTCoexDisabled) {
+ mWifiNative.setBluetoothCoexistenceMode(
+ P2P_BLUETOOTH_COEXISTENCE_MODE_SENSE);
+ mIsBTCoexDisabled = false;
+ }
+ }
+
}
/**
diff --git a/service/jni/COPYING b/service/jni/COPYING
new file mode 100644
index 0000000..8a98582
--- /dev/null
+++ b/service/jni/COPYING
@@ -0,0 +1,22 @@
+wpa_supplicant and hostapd
+--------------------------
+
+Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> and contributors
+All Rights Reserved.
+
+
+See the README file for the current license terms.
+
+This software was previously distributed under BSD/GPL v2 dual license
+terms that allowed either of those license alternatives to be
+selected. As of February 11, 2012, the project has chosen to use only
+the BSD license option for future distribution. As such, the GPL v2
+license option is no longer used. It should be noted that the BSD
+license option (the one with advertisement clause removed) is compatible
+with GPL and as such, does not prevent use of this software in projects
+that use GPL.
+
+Some of the files may still include pointers to GPL version 2 license
+terms. However, such copyright and license notifications are maintained
+only for attribution purposes and any distribution of this software
+after February 11, 2012 is no longer under the GPL v2 option.
diff --git a/service/jni/README b/service/jni/README
new file mode 100644
index 0000000..8de14a6
--- /dev/null
+++ b/service/jni/README
@@ -0,0 +1,56 @@
+wpa_supplicant and hostapd
+--------------------------
+
+Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi> and contributors
+All Rights Reserved.
+
+These programs are licensed under the BSD license (the one with
+advertisement clause removed).
+
+If you are submitting changes to the project, please see CONTRIBUTIONS
+file for more instructions.
+
+
+This package may include either wpa_supplicant, hostapd, or both. See
+README file respective subdirectories (wpa_supplicant/README or
+hostapd/README) for more details.
+
+Source code files were moved around in v0.6.x releases and compared to
+earlier releases, the programs are now built by first going to a
+subdirectory (wpa_supplicant or hostapd) and creating build
+configuration (.config) and running 'make' there (for Linux/BSD/cygwin
+builds).
+
+
+License
+-------
+
+This software may be distributed, used, and modified under the terms of
+BSD license:
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+3. Neither the name(s) of the above-listed copyright holder(s) nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/service/jni/com_android_server_wifi_Gbk2Utf.cpp b/service/jni/com_android_server_wifi_Gbk2Utf.cpp
new file mode 100644
index 0000000..d28e0ba
--- /dev/null
+++ b/service/jni/com_android_server_wifi_Gbk2Utf.cpp
@@ -0,0 +1,605 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * wpa_supplicant/hostapd / common helper functions, etc.
+ * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#define LOG_TAG "wifi_gbk2utf"
+
+#include "jni.h"
+#include "com_android_server_wifi_Gbk2Utf.h"
+
+#define BUF_SIZE 256
+#define CONVERT_LINE_LEN 2048
+#define CHARSET_CN ("gbk")
+
+namespace android {
+
+static jint DBG = false;
+
+struct accessPointObjectItem *g_pItemList = NULL;
+struct accessPointObjectItem *g_pLastNode = NULL;
+pthread_mutex_t *g_pItemListMutex = NULL;
+
+static void addAPObjectItem(const char *ssid, const char *ssid_utf8)
+{
+ if (NULL == ssid || NULL == ssid_utf8) {
+ ALOGE("ssid or ssid_utf8 is NULL");
+ return;
+ }
+
+ struct accessPointObjectItem *pTmpItemNode = NULL;
+ struct accessPointObjectItem *pItemNode = NULL;
+ bool foundItem = false;
+
+ pthread_mutex_lock(g_pItemListMutex);
+ pTmpItemNode = g_pItemList;
+ while (pTmpItemNode) {
+ if (pTmpItemNode->ssid && (*(pTmpItemNode->ssid) == ssid)) {
+ foundItem = true;
+ break;
+ }
+ pTmpItemNode = pTmpItemNode->pNext;
+ }
+ if (foundItem) {
+ if (DBG)
+ ALOGD("Found AP %s", pTmpItemNode->ssid->string());
+ } else {
+ pItemNode = new struct accessPointObjectItem();
+ if (NULL == pItemNode) {
+ ALOGE("Failed to allocate memory for new item!");
+ goto EXIT;
+ }
+ memset(pItemNode, 0, sizeof(accessPointObjectItem));
+ pItemNode->ssid_utf8 = new String8(ssid_utf8);
+ if (NULL == pItemNode->ssid_utf8) {
+ ALOGE("Failed to allocate memory for new ssid_utf8!");
+ delete pItemNode;
+ goto EXIT;
+ }
+ pItemNode->ssid = new String8(ssid);
+ if (NULL == pItemNode->ssid) {
+ ALOGE("Failed to allocate memory for new ssid!");
+ delete pItemNode;
+ goto EXIT;
+ }
+
+ pItemNode->pNext = NULL;
+ if (DBG)
+ ALOGD("AP doesn't exist, new one for %s", ssid);
+ if (NULL == g_pItemList) {
+ g_pItemList = pItemNode;
+ g_pLastNode = g_pItemList;
+ } else {
+ g_pLastNode->pNext = pItemNode;
+ g_pLastNode = pItemNode;
+ }
+ }
+
+EXIT:
+ pthread_mutex_unlock(g_pItemListMutex);
+}
+
+static int hex2num(char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return -1;
+}
+
+
+static int hex2byte(const char *hex)
+{
+ int a, b;
+ a = hex2num(*hex++);
+ if (a < 0)
+ return -1;
+ b = hex2num(*hex++);
+ if (b < 0)
+ return -1;
+ return (a << 4) | b;
+}
+
+/* parse SSID string encoded from wpa_supplicant to normal string */
+static size_t ssid_decode(char *buf, size_t maxlen, const char *str)
+{
+ const char *pos = str;
+ size_t len = 0;
+ int val;
+
+ while (*pos) {
+ if (len == maxlen)
+ break;
+ switch (*pos) {
+ case '\\':
+ pos++;
+ switch (*pos) {
+ case '\\':
+ buf[len++] = '\\';
+ pos++;
+ break;
+ case '"':
+ buf[len++] = '"';
+ pos++;
+ break;
+ case 'n':
+ buf[len++] = '\n';
+ pos++;
+ break;
+ case 'r':
+ buf[len++] = '\r';
+ pos++;
+ break;
+ case 't':
+ buf[len++] = '\t';
+ pos++;
+ break;
+ case 'e':
+ buf[len++] = '\e';
+ pos++;
+ break;
+ case 'x':
+ pos++;
+ val = hex2byte(pos);
+ if (val < 0) {
+ val = hex2num(*pos);
+ if (val < 0)
+ break;
+ buf[len++] = val;
+ pos++;
+ } else {
+ buf[len++] = val;
+ pos += 2;
+ }
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ val = *pos++ - '0';
+ if (*pos >= '0' && *pos <= '7')
+ val = val * 8 + (*pos++ - '0');
+ if (*pos >= '0' && *pos <= '7')
+ val = val * 8 + (*pos++ - '0');
+ buf[len++] = val;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ buf[len++] = *pos++;
+ break;
+ }
+ }
+
+ return len;
+}
+
+/* This function can be used to convert SSIDs into printable form. Since wifi
+ * framework layer needs to parse printable form string.
+*/
+static void ssid_encode(char *txt, size_t maxlen, const char *data, unsigned int len)
+{
+ char *end = txt + maxlen;
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ if (txt + 4 > end)
+ break;
+
+ switch (data[i]) {
+ case '\"':
+ *txt++ = '\\';
+ *txt++ = '\"';
+ break;
+ case '\\':
+ *txt++ = '\\';
+ *txt++ = '\\';
+ break;
+ case '\e':
+ *txt++ = '\\';
+ *txt++ = 'e';
+ break;
+ case '\n':
+ *txt++ = '\\';
+ *txt++ = 'n';
+ break;
+ case '\r':
+ *txt++ = '\\';
+ *txt++ = 'r';
+ break;
+ case '\t':
+ *txt++ = '\\';
+ *txt++ = 't';
+ break;
+ default:
+ if (data[i] >= 32 && data[i] <= 127) {
+ *txt++ = data[i];
+ } else {
+ txt += snprintf(txt, end - txt, "\\x%02x",
+ data[i]);
+ }
+ break;
+ }
+ }
+ *txt = '\0';
+}
+
+/* check if the SSID string is UTF coded */
+static bool isUTF8String(const char* str, int length)
+{
+ unsigned int nBytes = 0;
+ unsigned char chr;
+ bool bAllAscii = true;
+ for (int i = 0; i < length; i++) {
+ chr = *(str+i);
+ if ((chr & 0x80) != 0) {
+ bAllAscii = false;
+ }
+ if (0 == nBytes) {
+ if (chr >= 0x80) {
+ if (chr >= 0xFC && chr <= 0xFD) {
+ nBytes = 6;
+ } else if (chr >= 0xF8) {
+ nBytes = 5;
+ } else if (chr >= 0xF0) {
+ nBytes = 4;
+ } else if (chr >= 0xE0) {
+ nBytes = 3;
+ } else if (chr >= 0xC0) {
+ nBytes = 2;
+ } else {
+ return false;
+ }
+ nBytes--;
+ }
+ } else {
+ if ((chr & 0xC0) != 0x80) {
+ return false;
+ }
+ nBytes--;
+ }
+ }
+
+ if (nBytes > 0 || bAllAscii) {
+ return false;
+ }
+ return true;
+}
+
+/*
+ * https://en.wikipedia.org/wiki/GBK
+ *
+ * GBK character is encoded as 1 or 2 bytes.
+ * - A single byte with range 0x00-0x7f is ASCII.
+ * - A byte with the high bit set indicates that it is
+ * the first of 2 bytes.
+ * byte1: (0x81-0xFE)
+ * byte2: (0x40-0xFE) except 0x7F
+ *
+ * This function only returns true only it is GBK string
+ * but not all character is ASCII.
+ */
+static bool isGBKString(const char *str, int length) {
+ unsigned char byte1;
+ unsigned char byte2;
+ bool isAllASCII = true;
+
+ for (int i = 0; i < length; i ++) {
+ byte1 = *(str+i);
+
+ if (byte1 >= 0x81 && byte1 < 0xFF && (i+1) < length) {
+ byte2 = *(str+i+1);
+ if (byte2 >= 0x40 && byte2 < 0xFF && byte2 != 0x7F) {
+ // GBK
+ isAllASCII = false;
+ i ++;
+ continue;
+ } else {
+ return false;
+ }
+ } else if (byte1 < 0x80){
+ // ASCII
+ continue;
+ } else {
+ return false;
+ }
+ }
+
+ if (isAllASCII)
+ return false;
+
+ return true;
+}
+
+static void createFromHex(char *buf, int maxlen, const char *str)
+{
+ const char *pos = str;
+ int len = 0;
+ int val;
+
+ while(*pos){
+ if (len == maxlen)
+ break;
+ val = hex2byte(pos);
+ if (val < 0) {
+ val = hex2num(*pos);
+ if (val < 0)
+ break;
+ buf[len++] = val;
+ } else {
+ buf[len++] = val;
+ pos += 2;
+ }
+ }
+}
+
+static size_t createToHex(char *buf, size_t buf_size, const char *str, unsigned int len)
+{
+ size_t i;
+ char *pos = buf, *end = buf + buf_size;
+ int ret;
+ if (buf_size == 0)
+ return 0;
+ for (i = 0; i < len; i++) {
+ ret = snprintf(pos, end - pos, "%02x", str[i]);
+ if (ret < 0 || ret >= end - pos) {
+ end[-1] = '\0';
+ return pos - buf;
+ }
+ pos += ret;
+ }
+ end[-1] = '\0';
+ return pos - buf;
+}
+
+void parseScanResults(String16& str, const char *reply)
+{
+ unsigned int lineBeg = 0, lineEnd = 0;
+ size_t replyLen = strlen(reply);
+ char ssid[BUF_SIZE] = {0};
+ char ssid_utf8[BUF_SIZE] = {0};
+ char ssid_txt[BUF_SIZE] = {0};
+ bool isUTF8 = false, isCh = false;
+ char buf[BUF_SIZE] = {0};
+ String8 line;
+
+ UConverterType conType = UCNV_UTF8;
+ char dest[CONVERT_LINE_LEN] = {0};
+ UErrorCode err = U_ZERO_ERROR;
+ UConverter* pConverter = ucnv_open(CHARSET_CN, &err);
+ if (U_FAILURE(err)) {
+ ALOGE("ucnv_open error");
+ return;
+ }
+
+ /* Parse every line of the reply to construct accessPointObjectItem list */
+ for (lineBeg = 0, lineEnd = 0; lineEnd <= replyLen; ++lineEnd) {
+ if (lineEnd == replyLen || '\n' == reply[lineEnd]) {
+ line.setTo(reply + lineBeg, lineEnd - lineBeg + 1);
+ if (DBG)
+ ALOGD("%s, line=%s ", __FUNCTION__, line.string());
+ if (strncmp(line.string(), "ssid=", 5) == 0) {
+ sscanf(line.string() + 5, "%[^\n]", ssid);
+ ssid_decode(buf,BUF_SIZE,ssid);
+ isUTF8 = isUTF8String(buf,sizeof(buf));
+ isCh = isGBKString(buf, sizeof(buf));
+ if (DBG)
+ ALOGD("%s, ssid = %s, buf = %s,isUTF8= %d, isCh = %d",
+ __FUNCTION__, ssid, buf ,isUTF8, isCh);
+ if (!isUTF8 && isCh) {
+ ucnv_toAlgorithmic(conType, pConverter, dest, CONVERT_LINE_LEN,
+ buf, strlen(buf), &err);
+ if (U_FAILURE(err)) {
+ ALOGE("ucnv_toUChars error");
+ goto EXIT;
+ }
+ ssid_encode(ssid_txt, BUF_SIZE, dest, strlen(dest));
+ if (DBG)
+ ALOGD("%s, ssid_txt = %s", __FUNCTION__,ssid_txt);
+ str += String16("ssid=");
+ str += String16(ssid_txt);
+ str += String16("\n");
+ memset(ssid_utf8, 0, BUF_SIZE);
+ strlcpy(ssid_utf8, dest, BUF_SIZE);
+ memset(dest, 0, CONVERT_LINE_LEN);
+ memset(ssid_txt, 0, BUF_SIZE);
+ } else {
+ memset(buf, 0, BUF_SIZE);
+ str += String16(line.string());
+ }
+ } else if (strncmp(line.string(), "====", 4) == 0) {
+ if (DBG)
+ ALOGD("After sscanf,ssid:%s, isCh:%d",
+ ssid, isCh);
+ if( !isUTF8 && isCh){
+ addAPObjectItem(buf, ssid_utf8);
+ memset(buf, 0, BUF_SIZE);
+ }
+ }
+ if (strncmp(line.string(), "ssid=", 5) != 0)
+ str += String16(line.string());
+ lineBeg = lineEnd + 1;
+ }
+ }
+
+EXIT:
+ ucnv_close(pConverter);
+}
+
+void constructSsid(String16& str, const char *reply)
+{
+ size_t replyLen = strlen(reply);
+ char ssid[BUF_SIZE] = {0};
+ char buf[BUF_SIZE] = {0};
+ char ssid_txt[BUF_SIZE] ={0};
+ bool isUTF8 = false, isCh = false;
+
+ char dest[CONVERT_LINE_LEN] = {0};
+ UConverterType conType = UCNV_UTF8;
+ UErrorCode err = U_ZERO_ERROR;
+ UConverter* pConverter = ucnv_open(CHARSET_CN, &err);
+ if (U_FAILURE(err)) {
+ ALOGE("ucnv_open error");
+ return;
+ }
+ sscanf(reply, "%[^\n]", ssid);
+ if (DBG)
+ ALOGD("%s, ssid = %s", __FUNCTION__, ssid);
+ createFromHex(buf, BUF_SIZE, ssid);
+ isUTF8 = isUTF8String(buf, sizeof(buf));
+ isCh = isGBKString(buf, sizeof(buf));
+ if (!isUTF8 && isCh) {
+ ucnv_toAlgorithmic(conType, pConverter, dest, CONVERT_LINE_LEN,
+ buf, strlen(buf), &err);
+ if (U_FAILURE(err)) {
+ ALOGE("ucnv_toUChars error");
+ goto EXIT;
+ }
+ createToHex(ssid_txt, strlen(dest)*2 + 1, dest, strlen(dest));
+ if (DBG)
+ ALOGD("%s, ssid_txt = %s, dest = %s \n" ,
+ __FUNCTION__, ssid_txt, dest);
+ str += String16(ssid_txt);
+ str += String16("\n");
+ memset(dest, 0, CONVERT_LINE_LEN);
+ memset(buf, 0, BUF_SIZE);
+ memset(ssid_txt, 0, BUF_SIZE);
+ } else {
+ memset(buf, 0, BUF_SIZE);
+ str += String16(reply);
+ }
+
+EXIT:
+ ucnv_close(pConverter);
+}
+
+jboolean setNetworkVariable(char *buf)
+{
+ struct accessPointObjectItem *pTmpItemNode = NULL;
+ char pos[BUF_SIZE] = {0};
+ bool isCh = false;
+ bool gbk_found = false;
+ int i;
+
+ unsigned int netId;
+ char name[BUF_SIZE] = {0};
+ char value[BUF_SIZE] = {0};
+ char interface[BUF_SIZE] = {0};
+ char dummy[BUF_SIZE] = {0};
+ char ssid[BUF_SIZE] = {0};
+ size_t utf8_len = 0;
+ if (strnlen(buf, BUF_SIZE) == BUF_SIZE) {
+ ALOGE("setNetworkVariable failed due to invalid length");
+ return JNI_FALSE;
+ }
+
+ /* parse SET_NETWORK command*/
+ sscanf(buf, "%s %s %d %s %s", interface, dummy, &netId, name, value);
+
+ /* L Framework will convert string to HEX, so we convert it back here for comparation */
+ if (0 == strncmp(name, "ssid", 4)) {
+ createFromHex(ssid, BUF_SIZE, value);
+ }
+
+ if (DBG)
+ ALOGD("parse SET_NETWORK command success, netId = %d, name = %s, value =%s, length=%d",
+ netId, name, value, strlen(value));
+
+ if (NULL == g_pItemListMutex) {
+ /* Driver is unloaded, g_pItemList, g_pItemListMutex are NULL */
+ return JNI_TRUE;
+ }
+ pthread_mutex_lock(g_pItemListMutex);
+ pTmpItemNode = g_pItemList;
+ if (NULL == pTmpItemNode) {
+ ALOGE("g_pItemList is NULL");
+ }
+ while (pTmpItemNode) {
+ if (pTmpItemNode->ssid_utf8) {
+ ALOGD("ssid_utf8 = %s, length=%d, value =%s, length=%d",
+ pTmpItemNode->ssid_utf8->string(),strlen(pTmpItemNode->ssid_utf8->string()), ssid, strlen(ssid));
+
+ if (0 == strcmp(pTmpItemNode->ssid_utf8->string(), ssid)) {
+ gbk_found = true;
+ break;
+ }
+ }
+ pTmpItemNode = pTmpItemNode->pNext;
+ }
+
+ if (0 == strncmp(name, "ssid", 4) && gbk_found) {
+ snprintf(buf, BUF_SIZE, "%s SET_NETWORK %d ssid \"%s\"", interface, netId, pTmpItemNode->ssid->string());
+ if (DBG)
+ ALOGD("new SET_NETWORK command is: %s", buf);
+ }
+
+ pthread_mutex_unlock(g_pItemListMutex);
+
+
+ return JNI_TRUE;
+}
+
+void constructEventSsid(char *eventstr)
+{
+ char *tmp = NULL;
+ char ssid[BUF_SIZE] = {0};
+ char ssid_txt[BUF_SIZE] = {0};
+ char buf[BUF_SIZE] = {0};
+ bool isUTF8 = false, isCh = false;
+
+ UConverterType conType = UCNV_UTF8;
+ char dest[CONVERT_LINE_LEN] = {0};
+ UErrorCode err = U_ZERO_ERROR;
+ UConverter* pConverter = ucnv_open(CHARSET_CN, &err);
+ if (U_FAILURE(err)) {
+ ALOGE("ucnv_open error");
+ return;
+ }
+
+ tmp = strstr(eventstr, " SSID");
+ if (tmp&&(strlen(tmp) > 6 )) {
+ if(!strstr(tmp,"="))
+ sscanf(tmp + 7, "%[^\']", ssid);
+ else
+ sscanf(tmp + 6, "%s", ssid);
+ if (DBG)
+ ALOGD("%s, SSID = %s", __FUNCTION__, ssid);
+ ssid_decode(buf,BUF_SIZE,ssid);
+ isUTF8 = isUTF8String(buf,sizeof(buf));
+ isCh = isGBKString(buf, sizeof(buf));
+ if (!isUTF8 && isCh) {
+ ucnv_toAlgorithmic(conType, pConverter, dest, CONVERT_LINE_LEN,
+ buf, strlen(buf), &err);
+ if (U_FAILURE(err)) {
+ ALOGE("ucnv_toUChars error");
+ goto EXIT;
+ }
+ ssid_encode(ssid_txt, BUF_SIZE, dest, strlen(dest));
+ if (!strstr(tmp,"="))
+ snprintf(eventstr + (strlen(eventstr) - strlen(tmp)), strlen(eventstr), " SSID \'%s\'", ssid_txt);
+ else
+ snprintf(eventstr + (strlen(eventstr) - strlen(tmp)), strlen(eventstr), " SSID=%s", ssid_txt);
+ if (DBG)
+ ALOGD("%s, ssid_txt = %s, eventsrt = %s", __FUNCTION__, ssid_txt, eventstr);
+ }
+ }
+
+EXIT:
+ ucnv_close(pConverter);
+}
+
+} //namespace android
diff --git a/service/jni/com_android_server_wifi_Gbk2Utf.h b/service/jni/com_android_server_wifi_Gbk2Utf.h
new file mode 100644
index 0000000..37e7a2b
--- /dev/null
+++ b/service/jni/com_android_server_wifi_Gbk2Utf.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <utils/String8.h>
+#include <utils/String16.h>
+#include <pthread.h>
+#include <unicode/ucnv.h>
+#include <unicode/ucsdet.h>
+#include <net/if.h>
+#include <sys/socket.h>
+#include <linux/wireless.h>
+#include <utils/misc.h>
+#include <utils/Log.h>
+
+namespace android {
+
+struct accessPointObjectItem {
+ String8 *ssid_utf8;
+ String8 *ssid;
+ struct accessPointObjectItem *pNext;
+};
+
+extern void parseScanResults(String16& str, const char *reply);
+
+extern void constructSsid(String16& str, const char *reply);
+
+extern void constructEventSsid(char *eventstr);
+
+extern jboolean setNetworkVariable(char *buf);
+
+} //namespace android
diff --git a/service/jni/com_android_server_wifi_WifiNative.cpp b/service/jni/com_android_server_wifi_WifiNative.cpp
index acc02d6..a6d4f4e 100644
--- a/service/jni/com_android_server_wifi_WifiNative.cpp
+++ b/service/jni/com_android_server_wifi_WifiNative.cpp
@@ -20,10 +20,10 @@
#include "JniConstants.h"
#include <ScopedUtfChars.h>
#include <ScopedBytes.h>
-#include <utils/misc.h>
+//#include <utils/misc.h>
#include <android_runtime/AndroidRuntime.h>
-#include <utils/Log.h>
-#include <utils/String16.h>
+//#include <utils/Log.h>
+//#include <utils/String16.h>
#include <ctype.h>
#include <sys/socket.h>
#include <linux/if.h>
@@ -35,6 +35,11 @@
#define REPLY_BUF_SIZE 4096 + 1 // wpa_supplicant's maximum size + 1 for nul
#define EVENT_BUF_SIZE 2048
+#define CONVERT_LINE_LEN 2048
+#define CHARSET_CN ("gbk")
+
+#include "com_android_server_wifi_Gbk2Utf.h"
+
namespace android {
static jint DBG = false;
@@ -100,13 +105,21 @@ int init_wifi_hal_func_table(wifi_hal_fn *hal_fn) {
return 0;
}
+extern struct accessPointObjectItem *g_pItemList;
+extern struct accessPointObjectItem *g_pLastNode;
+extern pthread_mutex_t *g_pItemListMutex;
+extern String8 *g_pCurrentSSID;
static bool doCommand(JNIEnv* env, jstring javaCommand,
char* reply, size_t reply_len) {
ScopedUtfChars command(env, javaCommand);
if (command.c_str() == NULL) {
return false; // ScopedUtfChars already threw on error.
}
-
+ if(strstr(command.c_str(), "SET_NETWORK")) {
+ if(!setNetworkVariable((char *)command.c_str())) {
+ return false;
+ }
+ }
if (DBG) {
ALOGD("doCommand: %s", command.c_str());
}
@@ -149,10 +162,30 @@ static jboolean doBooleanCommand(JNIEnv* env, jstring javaCommand) {
// Send a command to the supplicant, and return the reply as a String.
static jstring doStringCommand(JNIEnv* env, jstring javaCommand) {
char reply[REPLY_BUF_SIZE];
+ ScopedUtfChars command(env, javaCommand);
+ if (command.c_str() == NULL) {
+ return NULL;
+ }
if (!doCommand(env, javaCommand, reply, sizeof(reply))) {
return NULL;
}
- return env->NewStringUTF(reply);
+ if (DBG) ALOGD("cmd = %s, reply: %s", command.c_str(), reply);
+ String16 str;
+ if (strstr(command.c_str(),"BSS RANGE=")) {
+ parseScanResults(str,reply);
+ } else if (strstr(command.c_str(),"GET_NETWORK") &&
+ strstr(command.c_str(),"ssid") && !strstr(command.c_str(),"bssid")
+ && !strstr(command.c_str(),"scan_ssid")){
+ constructSsid(str, reply);
+ } else {
+ str += String16((char *)reply);
+ }
+ return env->NewString((const jchar *)str.string(), str.size());
+}
+
+static jboolean android_net_wifi_setMode(JNIEnv* env, jobject, jint type)
+{
+ return (jboolean)(::wifi_set_mode(type) == 0);
}
static jboolean android_net_wifi_isDriverLoaded(JNIEnv* env, jobject)
@@ -162,11 +195,41 @@ static jboolean android_net_wifi_isDriverLoaded(JNIEnv* env, jobject)
static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject)
{
+ g_pItemListMutex = new pthread_mutex_t;
+ if (NULL == g_pItemListMutex) {
+ ALOGE("Failed to allocate memory for g_pItemListMutex!");
+ return JNI_FALSE;
+ }
+ pthread_mutex_init(g_pItemListMutex, NULL);
return (::wifi_load_driver() == 0);
}
static jboolean android_net_wifi_unloadDriver(JNIEnv* env, jobject)
{
+ if (g_pItemListMutex != NULL) {
+ pthread_mutex_lock(g_pItemListMutex);
+ struct accessPointObjectItem *pCurrentNode = g_pItemList;
+ struct accessPointObjectItem *pNextNode = NULL;
+ while (pCurrentNode) {
+ pNextNode = pCurrentNode->pNext;
+ if (NULL != pCurrentNode->ssid) {
+ delete pCurrentNode->ssid;
+ pCurrentNode->ssid = NULL;
+ }
+ if (NULL != pCurrentNode->ssid_utf8) {
+ delete pCurrentNode->ssid_utf8;
+ pCurrentNode->ssid_utf8 = NULL;
+ }
+ delete pCurrentNode;
+ pCurrentNode = pNextNode;
+ }
+ g_pItemList = NULL;
+ g_pLastNode = NULL;
+ pthread_mutex_unlock(g_pItemListMutex);
+ pthread_mutex_destroy(g_pItemListMutex);
+ delete g_pItemListMutex;
+ g_pItemListMutex = NULL;
+ }
return (::wifi_unload_driver() == 0);
}
@@ -195,6 +258,9 @@ static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject)
char buf[EVENT_BUF_SIZE];
int nread = ::wifi_wait_for_event(buf, sizeof buf);
if (nread > 0) {
+ if (strstr(buf, " SSID=") || strstr(buf, " SSID ")){
+ constructEventSsid(buf);
+ }
return env->NewStringUTF(buf);
} else {
return NULL;
@@ -2181,6 +2247,7 @@ static JNINativeMethod gWifiMethods[] = {
{ "doIntCommandNative", "(Ljava/lang/String;)I", (void*)android_net_wifi_doIntCommand },
{ "doStringCommandNative", "(Ljava/lang/String;)Ljava/lang/String;",
(void*) android_net_wifi_doStringCommand },
+ { "setMode", "(I)Z", (void*) android_net_wifi_setMode},
{ "startHalNative", "()Z", (void*) android_net_wifi_startHal },
{ "stopHalNative", "()V", (void*) android_net_wifi_stopHal },
{ "waitForHalEventNative", "()V", (void*) android_net_wifi_waitForHalEvents },