diff options
Diffstat (limited to 'service/java/com/android')
13 files changed, 1677 insertions, 283 deletions
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; + } + } + } /** |