diff options
-rw-r--r-- | services/java/com/android/server/WifiService.java | 19 | ||||
-rw-r--r-- | wifi/java/android/net/wifi/IWifiManager.aidl | 8 | ||||
-rw-r--r-- | wifi/java/android/net/wifi/WifiManager.java | 93 | ||||
-rw-r--r-- | wifi/java/android/net/wifi/WifiStateMachine.java | 132 |
4 files changed, 248 insertions, 4 deletions
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index b43b33e..3ab6553 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -766,6 +766,25 @@ public class WifiService extends IWifiManager.Stub { mWifiStateMachine.clearBlacklist(); } + public void connectNetworkWithId(int networkId) { + enforceChangePermission(); + mWifiStateMachine.connectNetwork(networkId); + } + + public void connectNetworkWithConfig(WifiConfiguration config) { + enforceChangePermission(); + mWifiStateMachine.connectNetwork(config); + } + + public void saveNetwork(WifiConfiguration config) { + enforceChangePermission(); + mWifiStateMachine.saveNetwork(config); + } + + public void forgetNetwork(int netId) { + enforceChangePermission(); + mWifiStateMachine.forgetNetwork(netId); + } private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 3426af7..cd07f0e 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -93,5 +93,13 @@ interface IWifiManager void addToBlacklist(String bssid); void clearBlacklist(); + + void connectNetworkWithConfig(in WifiConfiguration wifiConfig); + + void connectNetworkWithId(int networkId); + + void saveNetwork(in WifiConfiguration wifiConfig); + + void forgetNetwork(int networkId); } diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 339763a..a774c12 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -274,7 +274,14 @@ public class WifiManager { * @see #ERROR_AUTHENTICATING */ public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError"; - + /** + * Broadcast intent action indicating that the supplicant configuration changed. + * This can be as a result of adding/updating/deleting a network + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String SUPPLICANT_CONFIG_CHANGED_ACTION = + "android.net.wifi.supplicant.CONFIG_CHANGE"; /** * An access point scan has completed, and results are available from the supplicant. * Call {@link #getScanResults()} to obtain the results. @@ -929,6 +936,90 @@ public class WifiManager { } } + /* TODO: deprecate synchronous API and open up the following API */ + /** + * Connect to a network with the given configuration. The network also + * gets added to the supplicant configuration. + * + * For a new network, this function is used instead of a + * sequence of addNetwork(), enableNetwork(), saveConfiguration() and + * reconnect() + * + * @param config the set of variables that describe the configuration, + * contained in a {@link WifiConfiguration} object. + * @hide + */ + public void connectNetwork(WifiConfiguration config) { + if (config == null) { + return; + } + try { + mService.connectNetworkWithConfig(config); + } catch (RemoteException e) { } + } + + /** + * Connect to a network with the given networkId. + * + * This function is used instead of a enableNetwork(), saveConfiguration() and + * reconnect() + * + * @param networkId the network id identifiying the network in the + * supplicant configuration list + * @hide + */ + public void connectNetwork(int networkId) { + if (networkId < 0) { + return; + } + try { + mService.connectNetworkWithId(networkId); + } catch (RemoteException e) { } + } + + /** + * Save the given network in the supplicant config. If the network already + * exists, the configuration is updated. A new network is enabled + * by default. + * + * For a new network, this function is used instead of a + * sequence of addNetwork(), enableNetwork() and saveConfiguration(). + * + * For an existing network, it accomplishes the task of updateNetwork() + * and saveConfiguration() + * + * @param config the set of variables that describe the configuration, + * contained in a {@link WifiConfiguration} object. + * @hide + */ + public void saveNetwork(WifiConfiguration config) { + if (config == null) { + return; + } + try { + mService.saveNetwork(config); + } catch (RemoteException e) { } + } + + /** + * Delete the network in the supplicant config. + * + * This function is used instead of a sequence of removeNetwork() + * and saveConfiguration(). + * + * @param config the set of variables that describe the configuration, + * contained in a {@link WifiConfiguration} object. + * @hide + */ + public void forgetNetwork(int netId) { + if (netId < 0) { + return; + } + try { + mService.forgetNetwork(netId); + } catch (RemoteException e) { } + } + /** * Allows an application to keep the Wi-Fi radio awake. * Normally the Wi-Fi radio may turn off when the user has not used the device in a while. diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 845508b..360b642 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -44,6 +44,7 @@ import android.net.NetworkUtils; import android.net.ConnectivityManager; import android.net.NetworkInfo.DetailedState; import android.net.NetworkProperties; +import android.net.wifi.WifiConfiguration.Status; import android.os.Binder; import android.os.Message; import android.os.Parcelable; @@ -151,6 +152,10 @@ public class WifiStateMachine extends HierarchicalStateMachine { private WifiInfo mWifiInfo; private NetworkInfo mNetworkInfo; private SupplicantStateTracker mSupplicantStateTracker; + /* Tracks the highest priority of configured networks */ + private int mLastPriority = -1; + /* Tracks if all networks need to be enabled */ + private boolean mEnableAllNetworks = false; // Event log tags (must be in sync with event-log-tags) private static final int EVENTLOG_WIFI_STATE_CHANGED = 50021; @@ -283,6 +288,27 @@ public class WifiStateMachine extends HierarchicalStateMachine { private static final int CMD_START_PACKET_FILTERING = 88; /* Clear packet filter */ private static final int CMD_STOP_PACKET_FILTERING = 89; + /* Connect to a specified network (network id + * or WifiConfiguration) This involves increasing + * the priority of the network, enabling the network + * (while disabling others) and issuing a reconnect. + * Note that CMD_RECONNECT just does a reconnect to + * an existing network. All the networks get enabled + * upon a successful connection or a failure. + */ + private static final int CMD_CONNECT_NETWORK = 90; + /* Save the specified network. This involves adding + * an enabled network (if new) and updating the + * config and issuing a save on supplicant config. + */ + private static final int CMD_SAVE_NETWORK = 91; + /* Delete the specified network. This involves + * removing the network and issuing a save on + * supplicant config. + */ + private static final int CMD_FORGET_NETWORK = 92; + + /** * Interval in milliseconds between polling for connection @@ -704,6 +730,22 @@ public class WifiStateMachine extends HierarchicalStateMachine { sendMessage(obtainMessage(CMD_CLEAR_BLACKLIST)); } + public void connectNetwork(int netId) { + sendMessage(obtainMessage(CMD_CONNECT_NETWORK, netId, 0)); + } + + public void connectNetwork(WifiConfiguration wifiConfig) { + sendMessage(obtainMessage(CMD_CONNECT_NETWORK, wifiConfig)); + } + + public void saveNetwork(WifiConfiguration wifiConfig) { + sendMessage(obtainMessage(CMD_SAVE_NETWORK, wifiConfig)); + } + + public void forgetNetwork(int netId) { + sendMessage(obtainMessage(CMD_FORGET_NETWORK, netId, 0)); + } + /** * Get detailed status of the connection * @@ -1354,6 +1396,11 @@ public class WifiStateMachine extends HierarchicalStateMachine { mContext.sendStickyBroadcast(intent); } + private void sendSupplicantConfigChangedBroadcast() { + Intent intent = new Intent(WifiManager.SUPPLICANT_CONFIG_CHANGED_ACTION); + mContext.sendBroadcast(intent); + } + private void sendSupplicantConnectionChangedBroadcast(boolean connected) { if (!ActivityManagerNative.isSystemReady()) return; @@ -1420,6 +1467,20 @@ public class WifiStateMachine extends HierarchicalStateMachine { return -1; } + private void enableAllNetworks() { + if (mEnableAllNetworks) { + mEnableAllNetworks = false; + List<WifiConfiguration> configList = getConfiguredNetworksNative(); + for (WifiConfiguration config : configList) { + if(config != null && config.status == Status.DISABLED) { + WifiNative.enableNetworkCommand(config.networkId, false); + } + } + WifiNative.saveConfigCommand(); + sendSupplicantConfigChangedBroadcast(); + } + } + private int addOrUpdateNetworkNative(WifiConfiguration config) { /* * If the supplied networkId is -1, we create a new empty @@ -1613,7 +1674,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { private List<WifiConfiguration> getConfiguredNetworksNative() { String listStr = WifiNative.listNetworksCommand(); - + mLastPriority = 0; List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>(); if (listStr == null) @@ -1641,6 +1702,9 @@ public class WifiStateMachine extends HierarchicalStateMachine { config.status = WifiConfiguration.Status.ENABLED; } readNetworkVariables(config); + if (config.priority > mLastPriority) { + mLastPriority = config.priority; + } networks.add(config); } return networks; @@ -2048,6 +2112,9 @@ public class WifiStateMachine extends HierarchicalStateMachine { case CMD_SET_BLUETOOTH_SCAN_MODE: case CMD_SET_NUM_ALLOWED_CHANNELS: case CMD_REQUEST_CM_WAKELOCK: + case CMD_CONNECT_NETWORK: + case CMD_SAVE_NETWORK: + case CMD_FORGET_NETWORK: break; default: Log.e(TAG, "Error! unhandled message" + message); @@ -2397,6 +2464,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { public boolean processMessage(Message message) { if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); SyncParams syncParams; + WifiConfiguration config; switch(message.what) { case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */ Log.d(TAG, "Stop supplicant received"); @@ -2434,9 +2502,10 @@ public class WifiStateMachine extends HierarchicalStateMachine { case CMD_ADD_OR_UPDATE_NETWORK: EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); syncParams = (SyncParams) message.obj; - WifiConfiguration config = (WifiConfiguration) syncParams.mParameter; + config = (WifiConfiguration) syncParams.mParameter; syncParams.mSyncReturn.intValue = addOrUpdateNetworkNative(config); notifyOnMsgObject(message); + sendSupplicantConfigChangedBroadcast(); break; case CMD_REMOVE_NETWORK: EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); @@ -2449,6 +2518,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { /* asynchronous handling */ WifiNative.removeNetworkCommand(message.arg1); } + sendSupplicantConfigChangedBroadcast(); break; case CMD_ENABLE_NETWORK: EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); @@ -2462,6 +2532,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { /* asynchronous handling */ WifiNative.enableNetworkCommand(message.arg1, message.arg2 == 1); } + sendSupplicantConfigChangedBroadcast(); break; case CMD_DISABLE_NETWORK: EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); @@ -2474,6 +2545,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { /* asynchronous handling */ WifiNative.disableNetworkCommand(message.arg1); } + sendSupplicantConfigChangedBroadcast(); break; case CMD_BLACKLIST_NETWORK: EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); @@ -2526,6 +2598,21 @@ public class WifiStateMachine extends HierarchicalStateMachine { case CMD_SET_SCAN_MODE: mIsScanMode = (message.arg1 == SCAN_ONLY_MODE); break; + case CMD_SAVE_NETWORK: + config = (WifiConfiguration) message.obj; + int netId = addOrUpdateNetworkNative(config); + /* enable a new network */ + if (config.networkId < 0) { + WifiNative.enableNetworkCommand(netId, false); + } + WifiNative.saveConfigCommand(); + sendSupplicantConfigChangedBroadcast(); + break; + case CMD_FORGET_NETWORK: + WifiNative.removeNetworkCommand(message.arg1); + WifiNative.saveConfigCommand(); + sendSupplicantConfigChangedBroadcast(); + break; default: return NOT_HANDLED; } @@ -2836,6 +2923,41 @@ public class WifiStateMachine extends HierarchicalStateMachine { WifiNative.reassociateCommand(); } break; + case CMD_CONNECT_NETWORK: + int netId = message.arg1; + WifiConfiguration config = (WifiConfiguration) message.obj; + if (config != null) { + netId = addOrUpdateNetworkNative(config); + } + // Reset the priority of each network at start or if it goes too high. + if (mLastPriority == -1 || mLastPriority > 1000000) { + List<WifiConfiguration> configList = getConfiguredNetworksNative(); + for (WifiConfiguration conf : configList) { + if (conf.networkId != -1) { + conf.priority = 0; + addOrUpdateNetworkNative(conf); + } + } + mLastPriority = 0; + } + + // Set to the highest priority and save the configuration. + config = new WifiConfiguration(); + config.networkId = netId; + config.priority = ++mLastPriority; + + addOrUpdateNetworkNative(config); + WifiNative.saveConfigCommand(); + + // Connect to network by disabling others. + WifiNative.enableNetworkCommand(netId, true); + WifiNative.reconnectCommand(); + mEnableAllNetworks = true; + /* Dont send a supplicant config change broadcast here + * as it is better to not expose the temporary disabling + * of all networks + */ + break; case SCAN_RESULTS_EVENT: /* Set the scan setting back to "connect" mode */ WifiNative.setScanResultHandlingCommand(CONNECT_MODE); @@ -2848,7 +2970,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { mWifiInfo.setBSSID(mLastBssid = stateChangeResult.BSSID); mWifiInfo.setNetworkId(stateChangeResult.networkId); mLastNetworkId = stateChangeResult.networkId; - + enableAllNetworks(); /* send event to CM & network change broadcast */ setDetailedState(DetailedState.OBTAINING_IPADDR); sendNetworkStateChangeBroadcast(mLastBssid); @@ -2857,6 +2979,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { break; case NETWORK_DISCONNECTION_EVENT: Log.d(TAG,"Network connection lost"); + enableAllNetworks(); handleNetworkDisconnect(); transitionTo(mDisconnectedState); break; @@ -2991,6 +3114,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { Log.e(TAG, "Failed " + mReconnectCount + " times, Disabling " + mLastNetworkId); WifiNative.disableNetworkCommand(mLastNetworkId); + sendSupplicantConfigChangedBroadcast(); } /* DHCP times out after about 30 seconds, we do a @@ -3419,6 +3543,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { WifiNative.disableNetworkCommand(mWifiInfo.getNetworkId()); mPasswordKeyMayBeIncorrect = false; sendSupplicantStateChangedBroadcast(stateChangeResult, true); + sendSupplicantConfigChangedBroadcast(); } else { sendSupplicantStateChangedBroadcast(stateChangeResult, false); @@ -3478,6 +3603,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { } if (mLoopDetectCount > MAX_SUPPLICANT_LOOP_ITERATIONS) { WifiNative.disableNetworkCommand(stateChangeResult.networkId); + sendSupplicantConfigChangedBroadcast(); mLoopDetectCount = 0; } |