diff options
-rw-r--r-- | core/java/android/net/DhcpStateMachine.java | 353 | ||||
-rw-r--r-- | core/java/android/net/NetworkUtils.java | 10 | ||||
-rw-r--r-- | core/jni/android_net_NetUtils.cpp | 35 | ||||
-rw-r--r-- | wifi/java/android/net/wifi/WifiStateMachine.java | 281 |
4 files changed, 134 insertions, 545 deletions
diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java deleted file mode 100644 index eaf087f..0000000 --- a/core/java/android/net/DhcpStateMachine.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import com.android.internal.util.Protocol; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.DhcpInfoInternal; -import android.net.NetworkUtils; -import android.os.Message; -import android.os.PowerManager; -import android.os.SystemClock; -import android.util.Log; - -/** - * StateMachine that interacts with the native DHCP client and can talk to - * a controller that also needs to be a StateMachine - * - * The Dhcp state machine provides the following features: - * - Wakeup and renewal using the native DHCP client (which will not renew - * on its own when the device is in suspend state and this can lead to device - * holding IP address beyond expiry) - * - A notification right before DHCP request or renewal is started. This - * can be used for any additional setup before DHCP. For example, wifi sets - * BT-Wifi coex settings right before DHCP is initiated - * - * @hide - */ -public class DhcpStateMachine extends StateMachine { - - private static final String TAG = "DhcpStateMachine"; - private static final boolean DBG = false; - - - /* A StateMachine that controls the DhcpStateMachine */ - private StateMachine mController; - - private Context mContext; - private BroadcastReceiver mBroadcastReceiver; - private AlarmManager mAlarmManager; - private PendingIntent mDhcpRenewalIntent; - private PowerManager.WakeLock mDhcpRenewWakeLock; - private static final String WAKELOCK_TAG = "DHCP"; - - private static final int DHCP_RENEW = 0; - private static final String ACTION_DHCP_RENEW = "android.net.wifi.DHCP_RENEW"; - - private enum DhcpAction { - START, - RENEW - }; - - private String mInterfaceName; - private boolean mRegisteredForPreDhcpNotification = false; - - private static final int BASE = Protocol.BASE_DHCP; - - /* Commands from controller to start/stop DHCP */ - public static final int CMD_START_DHCP = BASE + 1; - public static final int CMD_STOP_DHCP = BASE + 2; - public static final int CMD_RENEW_DHCP = BASE + 3; - - /* Notification from DHCP state machine prior to DHCP discovery/renewal */ - public static final int CMD_PRE_DHCP_ACTION = BASE + 4; - /* Notification from DHCP state machine post DHCP discovery/renewal. Indicates - * success/failure */ - public static final int CMD_POST_DHCP_ACTION = BASE + 5; - - /* Command from controller to indicate DHCP discovery/renewal can continue - * after pre DHCP action is complete */ - public static final int CMD_PRE_DHCP_ACTION_COMPLETE = BASE + 6; - - /* Message.arg1 arguments to CMD_POST_DHCP notification */ - public static final int DHCP_SUCCESS = 1; - public static final int DHCP_FAILURE = 2; - - private State mDefaultState = new DefaultState(); - private State mStoppedState = new StoppedState(); - private State mWaitBeforeStartState = new WaitBeforeStartState(); - private State mRunningState = new RunningState(); - private State mWaitBeforeRenewalState = new WaitBeforeRenewalState(); - - private DhcpStateMachine(Context context, StateMachine controller, String intf) { - super(TAG); - - mContext = context; - mController = controller; - mInterfaceName = intf; - - mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); - Intent dhcpRenewalIntent = new Intent(ACTION_DHCP_RENEW, null); - mDhcpRenewalIntent = PendingIntent.getBroadcast(mContext, DHCP_RENEW, dhcpRenewalIntent, 0); - - PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE); - mDhcpRenewWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG); - - mBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - //DHCP renew - if (DBG) Log.d(TAG, "Sending a DHCP renewal " + this); - //acquire a 40s wakelock to finish DHCP renewal - mDhcpRenewWakeLock.acquire(40000); - sendMessage(CMD_RENEW_DHCP); - } - }; - mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(ACTION_DHCP_RENEW)); - - addState(mDefaultState); - addState(mStoppedState, mDefaultState); - addState(mWaitBeforeStartState, mDefaultState); - addState(mRunningState, mDefaultState); - addState(mWaitBeforeRenewalState, mDefaultState); - - setInitialState(mStoppedState); - } - - public static DhcpStateMachine makeDhcpStateMachine(Context context, StateMachine controller, - String intf) { - DhcpStateMachine dsm = new DhcpStateMachine(context, controller, intf); - dsm.start(); - return dsm; - } - - /** - * This sends a notification right before DHCP request/renewal so that the - * controller can do certain actions before DHCP packets are sent out. - * When the controller is ready, it sends a CMD_PRE_DHCP_ACTION_COMPLETE message - * to indicate DHCP can continue - * - * This is used by Wifi at this time for the purpose of doing BT-Wifi coex - * handling during Dhcp - */ - public void registerForPreDhcpNotification() { - mRegisteredForPreDhcpNotification = true; - } - - class DefaultState extends State { - @Override - public boolean processMessage(Message message) { - if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); - switch (message.what) { - case CMD_RENEW_DHCP: - Log.e(TAG, "Error! Failed to handle a DHCP renewal on " + mInterfaceName); - break; - case SM_QUIT_CMD: - mContext.unregisterReceiver(mBroadcastReceiver); - //let parent kill the state machine - return NOT_HANDLED; - default: - Log.e(TAG, "Error! unhandled message " + message); - break; - } - return HANDLED; - } - } - - - class StoppedState extends State { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - } - - @Override - public boolean processMessage(Message message) { - boolean retValue = HANDLED; - if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); - switch (message.what) { - case CMD_START_DHCP: - if (mRegisteredForPreDhcpNotification) { - /* Notify controller before starting DHCP */ - mController.sendMessage(CMD_PRE_DHCP_ACTION); - transitionTo(mWaitBeforeStartState); - } else { - if (runDhcp(DhcpAction.START)) { - transitionTo(mRunningState); - } - } - break; - case CMD_STOP_DHCP: - //ignore - break; - default: - retValue = NOT_HANDLED; - break; - } - return retValue; - } - } - - class WaitBeforeStartState extends State { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - } - - @Override - public boolean processMessage(Message message) { - boolean retValue = HANDLED; - if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); - switch (message.what) { - case CMD_PRE_DHCP_ACTION_COMPLETE: - if (runDhcp(DhcpAction.START)) { - transitionTo(mRunningState); - } else { - transitionTo(mStoppedState); - } - break; - case CMD_STOP_DHCP: - transitionTo(mStoppedState); - break; - case CMD_START_DHCP: - //ignore - break; - default: - retValue = NOT_HANDLED; - break; - } - return retValue; - } - } - - class RunningState extends State { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - } - - @Override - public boolean processMessage(Message message) { - boolean retValue = HANDLED; - if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); - switch (message.what) { - case CMD_STOP_DHCP: - mAlarmManager.cancel(mDhcpRenewalIntent); - if (!NetworkUtils.stopDhcp(mInterfaceName)) { - Log.e(TAG, "Failed to stop Dhcp on " + mInterfaceName); - } - transitionTo(mStoppedState); - break; - case CMD_RENEW_DHCP: - if (mRegisteredForPreDhcpNotification) { - /* Notify controller before starting DHCP */ - mController.sendMessage(CMD_PRE_DHCP_ACTION); - transitionTo(mWaitBeforeRenewalState); - } else { - if (!runDhcp(DhcpAction.RENEW)) { - transitionTo(mStoppedState); - } - } - break; - case CMD_START_DHCP: - //ignore - break; - default: - retValue = NOT_HANDLED; - } - return retValue; - } - } - - class WaitBeforeRenewalState extends State { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - } - - @Override - public boolean processMessage(Message message) { - boolean retValue = HANDLED; - if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); - switch (message.what) { - case CMD_STOP_DHCP: - mAlarmManager.cancel(mDhcpRenewalIntent); - if (!NetworkUtils.stopDhcp(mInterfaceName)) { - Log.e(TAG, "Failed to stop Dhcp on " + mInterfaceName); - } - transitionTo(mStoppedState); - break; - case CMD_PRE_DHCP_ACTION_COMPLETE: - if (runDhcp(DhcpAction.RENEW)) { - transitionTo(mRunningState); - } else { - transitionTo(mStoppedState); - } - break; - case CMD_START_DHCP: - //ignore - break; - default: - retValue = NOT_HANDLED; - break; - } - return retValue; - } - } - - private boolean runDhcp(DhcpAction dhcpAction) { - boolean success = false; - DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal(); - - if (dhcpAction == DhcpAction.START) { - Log.d(TAG, "DHCP request on " + mInterfaceName); - success = NetworkUtils.runDhcp(mInterfaceName, dhcpInfoInternal); - } else if (dhcpAction == DhcpAction.RENEW) { - Log.d(TAG, "DHCP renewal on " + mInterfaceName); - success = NetworkUtils.runDhcpRenew(mInterfaceName, dhcpInfoInternal); - } - - if (success) { - Log.d(TAG, "DHCP succeeded on " + mInterfaceName); - //Do it a bit earlier than half the lease duration time - //to beat the native DHCP client and avoid extra packets - //48% for one hour lease time = 29 minutes - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - SystemClock.elapsedRealtime() + - dhcpInfoInternal.leaseDuration * 480, //in milliseconds - mDhcpRenewalIntent); - - mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, dhcpInfoInternal) - .sendToTarget(); - } else { - Log.d(TAG, "DHCP failed on " + mInterfaceName + ": " + - NetworkUtils.getDhcpError()); - NetworkUtils.stopDhcp(mInterfaceName); - mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_FAILURE, 0) - .sendToTarget(); - } - return success; - } -} diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index 8a678d6..cb9caf8 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -54,16 +54,6 @@ public class NetworkUtils { public native static boolean runDhcp(String interfaceName, DhcpInfoInternal ipInfo); /** - * Initiate renewal on the Dhcp client daemon. This call blocks until it obtains - * a result (either success or failure) from the daemon. - * @param interfaceName the name of the interface to configure - * @param ipInfo if the request succeeds, this object is filled in with - * the IP address information. - * @return {@code true} for success, {@code false} for failure - */ - public native static boolean runDhcpRenew(String interfaceName, DhcpInfoInternal ipInfo); - - /** * Shut down the DHCP client daemon. * @param interfaceName the name of the interface for which the daemon * should be stopped diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp index 68d1b3a..f11c81d 100644 --- a/core/jni/android_net_NetUtils.cpp +++ b/core/jni/android_net_NetUtils.cpp @@ -36,16 +36,6 @@ int dhcp_do_request(const char *ifname, const char *dns2, const char *server, uint32_t *lease); - -int dhcp_do_request_renew(const char *ifname, - const char *ipaddr, - const char *gateway, - uint32_t *prefixLength, - const char *dns1, - const char *dns2, - const char *server, - uint32_t *lease); - int dhcp_stop(const char *ifname); int dhcp_release_lease(const char *ifname); char *dhcp_get_errmsg(); @@ -101,8 +91,7 @@ static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz, jstri return (jint)result; } -static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstring ifname, - jobject info, bool renew) +static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info) { int result; char ipaddr[PROPERTY_VALUE_MAX]; @@ -116,14 +105,8 @@ static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstr const char *nameStr = env->GetStringUTFChars(ifname, NULL); if (nameStr == NULL) return (jboolean)false; - if (renew) { - result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength, - dns1, dns2, server, &lease); - } else { - result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength, - dns1, dns2, server, &lease); - } - + result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength, + dns1, dns2, server, &lease); env->ReleaseStringUTFChars(ifname, nameStr); if (result == 0 && dhcpInfoInternalFieldIds.dhcpInfoInternalClass != NULL) { env->SetObjectField(info, dhcpInfoInternalFieldIds.ipaddress, env->NewStringUTF(ipaddr)); @@ -161,17 +144,6 @@ static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstr return (jboolean)(result == 0); } -static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info) -{ - return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false); -} - -static jboolean android_net_utils_runDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname, jobject info) -{ - return android_net_utils_runDhcpCommon(env, clazz, ifname, info, true); -} - - static jboolean android_net_utils_stopDhcp(JNIEnv* env, jobject clazz, jstring ifname) { int result; @@ -209,7 +181,6 @@ static JNINativeMethod gNetworkUtilMethods[] = { { "disableInterface", "(Ljava/lang/String;)I", (void *)android_net_utils_disableInterface }, { "resetConnections", "(Ljava/lang/String;)I", (void *)android_net_utils_resetConnections }, { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z", (void *)android_net_utils_runDhcp }, - { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z", (void *)android_net_utils_runDhcpRenew }, { "stopDhcp", "(Ljava/lang/String;)Z", (void *)android_net_utils_stopDhcp }, { "releaseDhcpLease", "(Ljava/lang/String;)Z", (void *)android_net_utils_releaseDhcpLease }, { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError }, diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index d10a5d8..ce441aa 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -48,7 +48,6 @@ import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.DhcpInfo; import android.net.DhcpInfoInternal; -import android.net.DhcpStateMachine; import android.net.InterfaceConfiguration; import android.net.LinkAddress; import android.net.LinkProperties; @@ -153,7 +152,6 @@ public class WifiStateMachine extends StateMachine { private NetworkInfo mNetworkInfo; private SupplicantStateTracker mSupplicantStateTracker; private WpsStateMachine mWpsStateMachine; - private DhcpStateMachine mDhcpStateMachine; private AlarmManager mAlarmManager; private PendingIntent mScanIntent; @@ -191,10 +189,10 @@ public class WifiStateMachine extends StateMachine { static final int CMD_START_DRIVER = BASE + 13; /* Start the driver */ static final int CMD_STOP_DRIVER = BASE + 14; - /* Indicates Static IP succeded */ - static final int CMD_STATIC_IP_SUCCESS = BASE + 15; - /* Indicates Static IP failed */ - static final int CMD_STATIC_IP_FAILURE = BASE + 16; + /* Indicates DHCP succeded */ + static final int CMD_IP_CONFIG_SUCCESS = BASE + 15; + /* Indicates DHCP failed */ + static final int CMD_IP_CONFIG_FAILURE = BASE + 16; /* Start the soft access point */ static final int CMD_START_AP = BASE + 21; @@ -344,11 +342,8 @@ public class WifiStateMachine extends StateMachine { */ private static final int DEFAULT_MAX_DHCP_RETRIES = 9; - static final int POWER_MODE_ACTIVE = 1; - static final int POWER_MODE_AUTO = 0; - - /* Tracks the power mode for restoration after a DHCP request/renewal goes through */ - private int mPowerMode = POWER_MODE_AUTO; + private static final int POWER_MODE_ACTIVE = 1; + private static final int POWER_MODE_AUTO = 0; /** * See {@link Settings.Secure#WIFI_SCAN_INTERVAL_MS}. This is the default value if a @@ -1415,10 +1410,10 @@ public class WifiStateMachine extends StateMachine { /* * stop DHCP */ - if (mDhcpStateMachine != null) { - mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP); - mDhcpStateMachine.quit(); - mDhcpStateMachine = null; + NetworkUtils.resetConnections(mInterfaceName); + + if (!NetworkUtils.stopDhcp(mInterfaceName)) { + Log.e(TAG, "Could not stop DHCP"); } /* Disable interface */ @@ -1447,99 +1442,7 @@ public class WifiStateMachine extends StateMachine { mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; } - void handlePreDhcpSetup() { - 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 - WifiNative.setBluetoothCoexistenceModeCommand( - WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED); - } - - mPowerMode = WifiNative.getPowerModeCommand(); - if (mPowerMode < 0) { - // Handle the case where supplicant driver does not support - // getPowerModeCommand. - mPowerMode = WifiStateMachine.POWER_MODE_AUTO; - } - if (mPowerMode != WifiStateMachine.POWER_MODE_ACTIVE) { - WifiNative.setPowerModeCommand(WifiStateMachine.POWER_MODE_ACTIVE); - } - } - - - void handlePostDhcpSetup() { - /* restore power mode */ - WifiNative.setPowerModeCommand(mPowerMode); - - // Set the coexistence mode back to its default value - WifiNative.setBluetoothCoexistenceModeCommand( - WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE); - } - - private void handleSuccessfulIpConfiguration(DhcpInfoInternal dhcpInfoInternal) { - synchronized (mDhcpInfoInternal) { - mDhcpInfoInternal = dhcpInfoInternal; - } - mLastSignalLevel = -1; // force update of signal strength - WifiConfigStore.setIpConfiguration(mLastNetworkId, dhcpInfoInternal); - InetAddress addr = NetworkUtils.numericToInetAddress(dhcpInfoInternal.ipAddress); - mWifiInfo.setInetAddress(addr); - if (getNetworkDetailedState() == DetailedState.CONNECTED) { - //DHCP renewal in connected state - LinkProperties linkProperties = dhcpInfoInternal.makeLinkProperties(); - linkProperties.setHttpProxy(WifiConfigStore.getProxyProperties(mLastNetworkId)); - linkProperties.setInterfaceName(mInterfaceName); - if (!linkProperties.equals(mLinkProperties)) { - Log.d(TAG, "Link configuration changed for netId: " + mLastNetworkId - + " old: " + mLinkProperties + "new: " + linkProperties); - mLinkProperties = linkProperties; - sendLinkConfigurationChangedBroadcast(); - } - } else { - configureLinkProperties(); - setNetworkDetailedState(DetailedState.CONNECTED); - sendNetworkStateChangeBroadcast(mLastBssid); - } - } - - private void handleFailedIpConfiguration() { - Log.e(TAG, "IP configuration failed"); - - mWifiInfo.setInetAddress(null); - /** - * If we've exceeded the maximum number of retries for DHCP - * to a given network, disable the network - */ - if (++mReconnectCount > getMaxDhcpRetries()) { - Log.e(TAG, "Failed " + - mReconnectCount + " times, Disabling " + mLastNetworkId); - WifiConfigStore.disableNetwork(mLastNetworkId); - mReconnectCount = 0; - } - - /* DHCP times out after about 30 seconds, we do a - * disconnect and an immediate reconnect to try again - */ - WifiNative.disconnectCommand(); - WifiNative.reconnectCommand(); - } - - private boolean startSoftApWithConfig(WifiConfiguration config, int currentStatus) { + private boolean startSoftApWithConfig(WifiConfiguration config, int currentStatus) { if (config == null) { config = WifiApConfigStore.getApConfiguration(); } else { @@ -1564,7 +1467,6 @@ public class WifiStateMachine extends StateMachine { return true; } - /********************************************************* * Notifications from WifiMonitor ********************************************************/ @@ -1742,8 +1644,6 @@ public class WifiStateMachine extends StateMachine { case CMD_FORGET_NETWORK: case CMD_RSSI_POLL: case CMD_ENABLE_ALL_NETWORKS: - case DhcpStateMachine.CMD_PRE_DHCP_ACTION: - case DhcpStateMachine.CMD_POST_DHCP_ACTION: break; case CMD_START_WPS: /* Return failure when the state machine cannot handle WPS initiation*/ @@ -2609,18 +2509,74 @@ public class WifiStateMachine extends StateMachine { } class ConnectingState extends State { + boolean mModifiedBluetoothCoexistenceMode; + int mPowerMode; + boolean mUseStaticIp; + Thread mDhcpThread; @Override public void enter() { if (DBG) Log.d(TAG, getName() + "\n"); EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); + mUseStaticIp = WifiConfigStore.isUsingStaticIp(mLastNetworkId); + if (!mUseStaticIp) { + mDhcpThread = null; + mModifiedBluetoothCoexistenceMode = false; + mPowerMode = POWER_MODE_AUTO; + + 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. + */ + mModifiedBluetoothCoexistenceMode = true; + + // Disable the coexistence mode + WifiNative.setBluetoothCoexistenceModeCommand( + WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED); + } - if (!WifiConfigStore.isUsingStaticIp(mLastNetworkId)) { - //start DHCP - mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine( - mContext, WifiStateMachine.this, mInterfaceName); - mDhcpStateMachine.registerForPreDhcpNotification(); - mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP); + mPowerMode = WifiNative.getPowerModeCommand(); + if (mPowerMode < 0) { + // Handle the case where supplicant driver does not support + // getPowerModeCommand. + mPowerMode = POWER_MODE_AUTO; + } + if (mPowerMode != POWER_MODE_ACTIVE) { + WifiNative.setPowerModeCommand(POWER_MODE_ACTIVE); + } + + Log.d(TAG, "DHCP request started"); + mDhcpThread = new Thread(new Runnable() { + public void run() { + DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal(); + if (NetworkUtils.runDhcp(mInterfaceName, dhcpInfoInternal)) { + Log.d(TAG, "DHCP request succeeded"); + synchronized (mDhcpInfoInternal) { + mDhcpInfoInternal = dhcpInfoInternal; + } + WifiConfigStore.setIpConfiguration(mLastNetworkId, dhcpInfoInternal); + sendMessage(CMD_IP_CONFIG_SUCCESS); + } else { + Log.d(TAG, "DHCP request failed: " + + NetworkUtils.getDhcpError()); + sendMessage(CMD_IP_CONFIG_FAILURE); + } + } + }); + mDhcpThread.start(); } else { DhcpInfoInternal dhcpInfoInternal = WifiConfigStore.getIpConfiguration( mLastNetworkId); @@ -2632,13 +2588,16 @@ public class WifiStateMachine extends StateMachine { try { netd.setInterfaceConfig(mInterfaceName, ifcg); Log.v(TAG, "Static IP configuration succeeded"); - sendMessage(CMD_STATIC_IP_SUCCESS, dhcpInfoInternal); + synchronized (mDhcpInfoInternal) { + mDhcpInfoInternal = dhcpInfoInternal; + } + sendMessage(CMD_IP_CONFIG_SUCCESS); } catch (RemoteException re) { Log.v(TAG, "Static IP configuration failed: " + re); - sendMessage(CMD_STATIC_IP_FAILURE); + sendMessage(CMD_IP_CONFIG_FAILURE); } catch (IllegalStateException e) { Log.v(TAG, "Static IP configuration failed: " + e); - sendMessage(CMD_STATIC_IP_FAILURE); + sendMessage(CMD_IP_CONFIG_FAILURE); } } } @@ -2647,26 +2606,44 @@ public class WifiStateMachine extends StateMachine { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); switch(message.what) { - case DhcpStateMachine.CMD_PRE_DHCP_ACTION: - handlePreDhcpSetup(); - mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE); - break; - case DhcpStateMachine.CMD_POST_DHCP_ACTION: - handlePostDhcpSetup(); - if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS) { - handleSuccessfulIpConfiguration((DhcpInfoInternal) message.obj); - transitionTo(mConnectedState); - } else if (message.arg1 == DhcpStateMachine.DHCP_FAILURE) { - handleFailedIpConfiguration(); - transitionTo(mDisconnectingState); + case CMD_IP_CONFIG_SUCCESS: + mLastSignalLevel = -1; // force update of signal strength + InetAddress addr; + synchronized (mDhcpInfoInternal) { + addr = NetworkUtils.numericToInetAddress(mDhcpInfoInternal.ipAddress); } - break; - case CMD_STATIC_IP_SUCCESS: - handleSuccessfulIpConfiguration((DhcpInfoInternal) message.obj); + mWifiInfo.setInetAddress(addr); + configureLinkProperties(); + if (getNetworkDetailedState() == DetailedState.CONNECTED) { + sendLinkConfigurationChangedBroadcast(); + } else { + setNetworkDetailedState(DetailedState.CONNECTED); + sendNetworkStateChangeBroadcast(mLastBssid); + } + //TODO: The framework is not detecting a DHCP renewal and a possible + //IP change. we should detect this and send out a config change broadcast transitionTo(mConnectedState); break; - case CMD_STATIC_IP_FAILURE: - handleFailedIpConfiguration(); + case CMD_IP_CONFIG_FAILURE: + mWifiInfo.setInetAddress(null); + + Log.e(TAG, "IP configuration failed"); + /** + * If we've exceeded the maximum number of retries for DHCP + * to a given network, disable the network + */ + if (++mReconnectCount > getMaxDhcpRetries()) { + Log.e(TAG, "Failed " + + mReconnectCount + " times, Disabling " + mLastNetworkId); + WifiConfigStore.disableNetwork(mLastNetworkId); + mReconnectCount = 0; + } + + /* DHCP times out after about 30 seconds, we do a + * disconnect and an immediate reconnect to try again + */ + WifiNative.disconnectCommand(); + WifiNative.reconnectCommand(); transitionTo(mDisconnectingState); break; case CMD_DISCONNECT: @@ -2710,6 +2687,23 @@ public class WifiStateMachine extends StateMachine { EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); return HANDLED; } + + @Override + public void exit() { + /* reset power state & bluetooth coexistence if on DHCP */ + if (!mUseStaticIp) { + if (mPowerMode != POWER_MODE_ACTIVE) { + WifiNative.setPowerModeCommand(mPowerMode); + } + + if (mModifiedBluetoothCoexistenceMode) { + // Set the coexistence mode back to its default value + WifiNative.setBluetoothCoexistenceModeCommand( + WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE); + } + } + + } } class ConnectedState extends State { @@ -2727,19 +2721,6 @@ public class WifiStateMachine extends StateMachine { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); boolean eventLoggingEnabled = true; switch (message.what) { - case DhcpStateMachine.CMD_PRE_DHCP_ACTION: - handlePreDhcpSetup(); - mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE); - break; - case DhcpStateMachine.CMD_POST_DHCP_ACTION: - handlePostDhcpSetup(); - if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS) { - handleSuccessfulIpConfiguration((DhcpInfoInternal) message.obj); - } else if (message.arg1 == DhcpStateMachine.DHCP_FAILURE) { - handleFailedIpConfiguration(); - transitionTo(mDisconnectingState); - } - break; case CMD_DISCONNECT: WifiNative.disconnectCommand(); transitionTo(mDisconnectingState); |