summaryrefslogtreecommitdiffstats
path: root/wifi/java
diff options
context:
space:
mode:
authorVinit Deshapnde <vinitd@google.com>2013-12-06 15:12:41 -0800
committerVinit Deshapnde <vinitd@google.com>2013-12-11 16:06:49 -0800
commitffadfb9ffdced62db215319d3edc7717802088fb (patch)
treeb33f1b8d1d9cba0c9de8bed3c18859a7e72d8d5a /wifi/java
parentf7a38a09ff4d7b3cf7f2e975e18562335e0cbcf3 (diff)
downloadframeworks_base-ffadfb9ffdced62db215319d3edc7717802088fb.zip
frameworks_base-ffadfb9ffdced62db215319d3edc7717802088fb.tar.gz
frameworks_base-ffadfb9ffdced62db215319d3edc7717802088fb.tar.bz2
Move Wifi/P2p service components under services
Some methods need to be public, since frameworks/base complies before frameworks/base/services; and services takes build dependency on base. Similar issue exists with WifiEnterpriseConfig constants. Bug: 9907308 Change-Id: Ied0e3dee0b25c939067dbc66867a9814b3b3b68e
Diffstat (limited to 'wifi/java')
-rw-r--r--wifi/java/android/net/wifi/NetworkUpdateResult.java70
-rw-r--r--wifi/java/android/net/wifi/StateChangeResult.java38
-rw-r--r--wifi/java/android/net/wifi/SupplicantState.java6
-rw-r--r--wifi/java/android/net/wifi/SupplicantStateTracker.java361
-rw-r--r--wifi/java/android/net/wifi/WifiApConfigStore.java211
-rw-r--r--wifi/java/android/net/wifi/WifiConfigStore.java2022
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java2
-rw-r--r--wifi/java/android/net/wifi/WifiEnterpriseConfig.java134
-rw-r--r--wifi/java/android/net/wifi/WifiInfo.java27
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java3
-rw-r--r--wifi/java/android/net/wifi/WifiMonitor.java936
-rw-r--r--wifi/java/android/net/wifi/WifiNative.java970
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java4408
-rw-r--r--wifi/java/android/net/wifi/WifiWatchdogStateMachine.java1209
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pConfig.java3
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pDevice.java2
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java6
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java27
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pService.java2949
19 files changed, 145 insertions, 13239 deletions
diff --git a/wifi/java/android/net/wifi/NetworkUpdateResult.java b/wifi/java/android/net/wifi/NetworkUpdateResult.java
deleted file mode 100644
index 234bbe1..0000000
--- a/wifi/java/android/net/wifi/NetworkUpdateResult.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2010 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.wifi;
-
-import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID;
-
-class NetworkUpdateResult {
- int netId;
- boolean ipChanged;
- boolean proxyChanged;
- boolean isNewNetwork = false;
-
- public NetworkUpdateResult(int id) {
- netId = id;
- ipChanged = false;
- proxyChanged = false;
- }
-
- public NetworkUpdateResult(boolean ip, boolean proxy) {
- netId = INVALID_NETWORK_ID;
- ipChanged = ip;
- proxyChanged = proxy;
- }
-
- public void setNetworkId(int id) {
- netId = id;
- }
-
- public int getNetworkId() {
- return netId;
- }
-
- public void setIpChanged(boolean ip) {
- ipChanged = ip;
- }
-
- public boolean hasIpChanged() {
- return ipChanged;
- }
-
- public void setProxyChanged(boolean proxy) {
- proxyChanged = proxy;
- }
-
- public boolean hasProxyChanged() {
- return proxyChanged;
- }
-
- public boolean isNewNetwork() {
- return isNewNetwork;
- }
-
- public void setIsNewNetwork(boolean isNew) {
- isNewNetwork = isNew;
- }
-}
diff --git a/wifi/java/android/net/wifi/StateChangeResult.java b/wifi/java/android/net/wifi/StateChangeResult.java
deleted file mode 100644
index c334b91..0000000
--- a/wifi/java/android/net/wifi/StateChangeResult.java
+++ /dev/null
@@ -1,38 +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.wifi;
-
-/**
- * Stores supplicant state change information passed from WifiMonitor to
- * a state machine. WifiStateMachine, SupplicantStateTracker and WpsStateMachine
- * are example state machines that handle it.
- * @hide
- */
-public class StateChangeResult {
- StateChangeResult(int networkId, WifiSsid wifiSsid, String BSSID,
- SupplicantState state) {
- this.state = state;
- this.wifiSsid= wifiSsid;
- this.BSSID = BSSID;
- this.networkId = networkId;
- }
-
- int networkId;
- WifiSsid wifiSsid;
- String BSSID;
- SupplicantState state;
-}
diff --git a/wifi/java/android/net/wifi/SupplicantState.java b/wifi/java/android/net/wifi/SupplicantState.java
index 4a2037d..369d3a8 100644
--- a/wifi/java/android/net/wifi/SupplicantState.java
+++ b/wifi/java/android/net/wifi/SupplicantState.java
@@ -194,7 +194,8 @@ public enum SupplicantState implements Parcelable {
}
}
- static boolean isConnecting(SupplicantState state) {
+ /** @hide */
+ public static boolean isConnecting(SupplicantState state) {
switch(state) {
case AUTHENTICATING:
case ASSOCIATING:
@@ -216,7 +217,8 @@ public enum SupplicantState implements Parcelable {
}
}
- static boolean isDriverActive(SupplicantState state) {
+ /** @hide */
+ public static boolean isDriverActive(SupplicantState state) {
switch(state) {
case DISCONNECTED:
case DORMANT:
diff --git a/wifi/java/android/net/wifi/SupplicantStateTracker.java b/wifi/java/android/net/wifi/SupplicantStateTracker.java
deleted file mode 100644
index e76eb17..0000000
--- a/wifi/java/android/net/wifi/SupplicantStateTracker.java
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * Copyright (C) 2010 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.wifi;
-
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-
-import android.net.wifi.StateChangeResult;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Parcelable;
-import android.os.UserHandle;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-/**
- * Tracks the state changes in supplicant and provides functionality
- * that is based on these state changes:
- * - detect a failed WPA handshake that loops indefinitely
- * - authentication failure handling
- */
-class SupplicantStateTracker extends StateMachine {
-
- private static final String TAG = "SupplicantStateTracker";
- private static final boolean DBG = false;
-
- private WifiStateMachine mWifiStateMachine;
- private WifiConfigStore mWifiConfigStore;
- private int mAuthenticationFailuresCount = 0;
- private int mAssociationRejectCount = 0;
- /* Indicates authentication failure in supplicant broadcast.
- * TODO: enhance auth failure reporting to include notification
- * for all type of failures: EAP, WPS & WPA networks */
- private boolean mAuthFailureInSupplicantBroadcast = false;
-
- /* Maximum retries on a authentication failure notification */
- private static final int MAX_RETRIES_ON_AUTHENTICATION_FAILURE = 2;
-
- /* Maximum retries on assoc rejection events */
- private static final int MAX_RETRIES_ON_ASSOCIATION_REJECT = 16;
-
- /* Tracks if networks have been disabled during a connection */
- private boolean mNetworksDisabledDuringConnect = false;
-
- private Context mContext;
-
- private State mUninitializedState = new UninitializedState();
- private State mDefaultState = new DefaultState();
- private State mInactiveState = new InactiveState();
- private State mDisconnectState = new DisconnectedState();
- private State mScanState = new ScanState();
- private State mHandshakeState = new HandshakeState();
- private State mCompletedState = new CompletedState();
- private State mDormantState = new DormantState();
-
- public SupplicantStateTracker(Context c, WifiStateMachine wsm, WifiConfigStore wcs, Handler t) {
- super(TAG, t.getLooper());
-
- mContext = c;
- mWifiStateMachine = wsm;
- mWifiConfigStore = wcs;
- addState(mDefaultState);
- addState(mUninitializedState, mDefaultState);
- addState(mInactiveState, mDefaultState);
- addState(mDisconnectState, mDefaultState);
- addState(mScanState, mDefaultState);
- addState(mHandshakeState, mDefaultState);
- addState(mCompletedState, mDefaultState);
- addState(mDormantState, mDefaultState);
-
- setInitialState(mUninitializedState);
- setLogRecSize(50);
- setLogOnlyTransitions(true);
- //start the state machine
- start();
- }
-
- private void handleNetworkConnectionFailure(int netId, int disableReason) {
- /* If other networks disabled during connection, enable them */
- if (mNetworksDisabledDuringConnect) {
- mWifiConfigStore.enableAllNetworks();
- mNetworksDisabledDuringConnect = false;
- }
- /* Disable failed network */
- mWifiConfigStore.disableNetwork(netId, disableReason);
- }
-
- private void transitionOnSupplicantStateChange(StateChangeResult stateChangeResult) {
- SupplicantState supState = (SupplicantState) stateChangeResult.state;
-
- if (DBG) Log.d(TAG, "Supplicant state: " + supState.toString() + "\n");
-
- switch (supState) {
- case DISCONNECTED:
- transitionTo(mDisconnectState);
- break;
- case INTERFACE_DISABLED:
- //we should have received a disconnection already, do nothing
- break;
- case SCANNING:
- transitionTo(mScanState);
- break;
- case AUTHENTICATING:
- case ASSOCIATING:
- case ASSOCIATED:
- case FOUR_WAY_HANDSHAKE:
- case GROUP_HANDSHAKE:
- transitionTo(mHandshakeState);
- break;
- case COMPLETED:
- transitionTo(mCompletedState);
- break;
- case DORMANT:
- transitionTo(mDormantState);
- break;
- case INACTIVE:
- transitionTo(mInactiveState);
- break;
- case UNINITIALIZED:
- case INVALID:
- transitionTo(mUninitializedState);
- break;
- default:
- Log.e(TAG, "Unknown supplicant state " + supState);
- break;
- }
- }
-
- private void sendSupplicantStateChangedBroadcast(SupplicantState state, boolean failedAuth) {
- Intent intent = new Intent(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
- | Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra(WifiManager.EXTRA_NEW_STATE, (Parcelable) state);
- if (failedAuth) {
- intent.putExtra(
- WifiManager.EXTRA_SUPPLICANT_ERROR,
- WifiManager.ERROR_AUTHENTICATING);
- }
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- /********************************************************
- * HSM states
- *******************************************************/
-
- class DefaultState extends State {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch (message.what) {
- case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
- mAuthenticationFailuresCount++;
- mAuthFailureInSupplicantBroadcast = true;
- break;
- case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
- StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
- SupplicantState state = stateChangeResult.state;
- sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast);
- mAuthFailureInSupplicantBroadcast = false;
- transitionOnSupplicantStateChange(stateChangeResult);
- break;
- case WifiStateMachine.CMD_RESET_SUPPLICANT_STATE:
- transitionTo(mUninitializedState);
- break;
- case WifiManager.CONNECT_NETWORK:
- mNetworksDisabledDuringConnect = true;
- mAssociationRejectCount = 0;
- break;
- case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
- mAssociationRejectCount++;
- break;
- default:
- Log.e(TAG, "Ignoring " + message);
- break;
- }
- return HANDLED;
- }
- }
-
- /*
- * This indicates that the supplicant state as seen
- * by the framework is not initialized yet. We are
- * in this state right after establishing a control
- * channel connection before any supplicant events
- * or after we have lost the control channel
- * connection to the supplicant
- */
- class UninitializedState extends State {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- }
- }
-
- class InactiveState extends State {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- }
- }
-
- class DisconnectedState extends State {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- /* If a disconnect event happens after authentication failure
- * exceeds maximum retries, disable the network
- */
- Message message = getCurrentMessage();
- StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-
- if (mAuthenticationFailuresCount >= MAX_RETRIES_ON_AUTHENTICATION_FAILURE) {
- Log.d(TAG, "Failed to authenticate, disabling network " +
- stateChangeResult.networkId);
- handleNetworkConnectionFailure(stateChangeResult.networkId,
- WifiConfiguration.DISABLED_AUTH_FAILURE);
- mAuthenticationFailuresCount = 0;
- }
- else if (mAssociationRejectCount >= MAX_RETRIES_ON_ASSOCIATION_REJECT) {
- Log.d(TAG, "Association getting rejected, disabling network " +
- stateChangeResult.networkId);
- handleNetworkConnectionFailure(stateChangeResult.networkId,
- WifiConfiguration.DISABLED_ASSOCIATION_REJECT);
- mAssociationRejectCount = 0;
- }
- }
- }
-
- class ScanState extends State {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- }
- }
-
- class HandshakeState extends State {
- /**
- * The max number of the WPA supplicant loop iterations before we
- * decide that the loop should be terminated:
- */
- private static final int MAX_SUPPLICANT_LOOP_ITERATIONS = 4;
- private int mLoopDetectIndex;
- private int mLoopDetectCount;
-
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- mLoopDetectIndex = 0;
- mLoopDetectCount = 0;
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch (message.what) {
- case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
- StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
- SupplicantState state = stateChangeResult.state;
- if (SupplicantState.isHandshakeState(state)) {
- if (mLoopDetectIndex > state.ordinal()) {
- mLoopDetectCount++;
- }
- if (mLoopDetectCount > MAX_SUPPLICANT_LOOP_ITERATIONS) {
- Log.d(TAG, "Supplicant loop detected, disabling network " +
- stateChangeResult.networkId);
- handleNetworkConnectionFailure(stateChangeResult.networkId,
- WifiConfiguration.DISABLED_AUTH_FAILURE);
- }
- mLoopDetectIndex = state.ordinal();
- sendSupplicantStateChangedBroadcast(state,
- mAuthFailureInSupplicantBroadcast);
- } else {
- //Have the DefaultState handle the transition
- return NOT_HANDLED;
- }
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class CompletedState extends State {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- /* Reset authentication failure count */
- mAuthenticationFailuresCount = 0;
- mAssociationRejectCount = 0;
- if (mNetworksDisabledDuringConnect) {
- mWifiConfigStore.enableAllNetworks();
- mNetworksDisabledDuringConnect = false;
- }
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch(message.what) {
- case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
- StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
- SupplicantState state = stateChangeResult.state;
- sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast);
- /* Ignore any connecting state in completed state. Group re-keying
- * events and other auth events that do not affect connectivity are
- * ignored
- */
- if (SupplicantState.isConnecting(state)) {
- break;
- }
- transitionOnSupplicantStateChange(stateChangeResult);
- break;
- case WifiStateMachine.CMD_RESET_SUPPLICANT_STATE:
- sendSupplicantStateChangedBroadcast(SupplicantState.DISCONNECTED, false);
- transitionTo(mUninitializedState);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- //TODO: remove after getting rid of the state in supplicant
- class DormantState extends State {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- }
- }
-
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- super.dump(fd, pw, args);
- pw.println("mAuthenticationFailuresCount " + mAuthenticationFailuresCount);
- pw.println("mAuthFailureInSupplicantBroadcast " + mAuthFailureInSupplicantBroadcast);
- pw.println("mNetworksDisabledDuringConnect " + mNetworksDisabledDuringConnect);
- pw.println();
- }
-}
diff --git a/wifi/java/android/net/wifi/WifiApConfigStore.java b/wifi/java/android/net/wifi/WifiApConfigStore.java
deleted file mode 100644
index e675ad4..0000000
--- a/wifi/java/android/net/wifi/WifiApConfigStore.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2010 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.wifi;
-
-import android.content.Context;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
-import android.os.Environment;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Messenger;
-import android.util.Log;
-
-import com.android.internal.util.AsyncChannel;
-import com.android.internal.R;
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.UUID;
-
-/**
- * Provides API to the WifiStateMachine for doing read/write access
- * to soft access point configuration
- */
-class WifiApConfigStore extends StateMachine {
-
- private Context mContext;
- private static final String TAG = "WifiApConfigStore";
-
- private static final String AP_CONFIG_FILE = Environment.getDataDirectory() +
- "/misc/wifi/softap.conf";
-
- private static final int AP_CONFIG_FILE_VERSION = 1;
-
- private State mDefaultState = new DefaultState();
- private State mInactiveState = new InactiveState();
- private State mActiveState = new ActiveState();
-
- private WifiConfiguration mWifiApConfig = null;
- private AsyncChannel mReplyChannel = new AsyncChannel();
-
- WifiApConfigStore(Context context, Handler target) {
- super(TAG, target.getLooper());
-
- mContext = context;
- addState(mDefaultState);
- addState(mInactiveState, mDefaultState);
- addState(mActiveState, mDefaultState);
-
- setInitialState(mInactiveState);
- }
-
- public static WifiApConfigStore makeWifiApConfigStore(Context context, Handler target) {
- WifiApConfigStore s = new WifiApConfigStore(context, target);
- s.start();
- return s;
- }
-
- class DefaultState extends State {
- public boolean processMessage(Message message) {
- switch (message.what) {
- case WifiStateMachine.CMD_SET_AP_CONFIG:
- case WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED:
- Log.e(TAG, "Unexpected message: " + message);
- break;
- case WifiStateMachine.CMD_REQUEST_AP_CONFIG:
- mReplyChannel.replyToMessage(message,
- WifiStateMachine.CMD_RESPONSE_AP_CONFIG, mWifiApConfig);
- break;
- default:
- Log.e(TAG, "Failed to handle " + message);
- break;
- }
- return HANDLED;
- }
- }
-
- class InactiveState extends State {
- public boolean processMessage(Message message) {
- switch (message.what) {
- case WifiStateMachine.CMD_SET_AP_CONFIG:
- mWifiApConfig = (WifiConfiguration) message.obj;
- transitionTo(mActiveState);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class ActiveState extends State {
- public void enter() {
- new Thread(new Runnable() {
- public void run() {
- writeApConfiguration(mWifiApConfig);
- sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED);
- }
- }).start();
- }
-
- public boolean processMessage(Message message) {
- switch (message.what) {
- //TODO: have feedback to the user when we do this
- //to indicate the write is currently in progress
- case WifiStateMachine.CMD_SET_AP_CONFIG:
- deferMessage(message);
- break;
- case WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED:
- transitionTo(mInactiveState);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- void loadApConfiguration() {
- DataInputStream in = null;
- try {
- WifiConfiguration config = new WifiConfiguration();
- in = new DataInputStream(new BufferedInputStream(new FileInputStream(
- AP_CONFIG_FILE)));
-
- int version = in.readInt();
- if (version != 1) {
- Log.e(TAG, "Bad version on hotspot configuration file, set defaults");
- setDefaultApConfiguration();
- return;
- }
- config.SSID = in.readUTF();
- int authType = in.readInt();
- config.allowedKeyManagement.set(authType);
- if (authType != KeyMgmt.NONE) {
- config.preSharedKey = in.readUTF();
- }
- mWifiApConfig = config;
- } catch (IOException ignore) {
- setDefaultApConfiguration();
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {}
- }
- }
- }
-
- Messenger getMessenger() {
- return new Messenger(getHandler());
- }
-
- private void writeApConfiguration(final WifiConfiguration config) {
- DataOutputStream out = null;
- try {
- out = new DataOutputStream(new BufferedOutputStream(
- new FileOutputStream(AP_CONFIG_FILE)));
-
- out.writeInt(AP_CONFIG_FILE_VERSION);
- out.writeUTF(config.SSID);
- int authType = config.getAuthType();
- out.writeInt(authType);
- if(authType != KeyMgmt.NONE) {
- out.writeUTF(config.preSharedKey);
- }
- } catch (IOException e) {
- Log.e(TAG, "Error writing hotspot configuration" + e);
- } finally {
- if (out != null) {
- try {
- out.close();
- } catch (IOException e) {}
- }
- }
- }
-
- /* Generate a default WPA2 based configuration with a random password.
- We are changing the Wifi Ap configuration storage from secure settings to a
- flat file accessible only by the system. A WPA2 based default configuration
- 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);
- sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG, config);
- }
-}
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
deleted file mode 100644
index e45c2e7..0000000
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ /dev/null
@@ -1,2022 +0,0 @@
-/*
- * Copyright (C) 2010 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.wifi;
-
-import android.content.Context;
-import android.content.Intent;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-import android.net.NetworkUtils;
-import android.net.NetworkInfo.DetailedState;
-import android.net.ProxyProperties;
-import android.net.RouteInfo;
-import android.net.wifi.WifiConfiguration.IpAssignment;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
-import android.net.wifi.WifiConfiguration.ProxySettings;
-import android.net.wifi.WifiConfiguration.Status;
-import android.net.wifi.NetworkUpdateResult;
-import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID;
-
-import android.os.Environment;
-import android.os.FileObserver;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Process;
-import android.os.UserHandle;
-import android.security.Credentials;
-import android.security.KeyChain;
-import android.security.KeyStore;
-import android.text.TextUtils;
-import android.util.LocalLog;
-import android.util.Log;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.EOFException;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.InetAddress;
-import java.security.PrivateKey;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * This class provides the API to manage configured
- * wifi networks. The API is not thread safe is being
- * used only from WifiStateMachine.
- *
- * It deals with the following
- * - Add/update/remove a WifiConfiguration
- * The configuration contains two types of information.
- * = IP and proxy configuration that is handled by WifiConfigStore and
- * is saved to disk on any change.
- *
- * The format of configuration file is as follows:
- * <version>
- * <netA_key1><netA_value1><netA_key2><netA_value2>...<EOS>
- * <netB_key1><netB_value1><netB_key2><netB_value2>...<EOS>
- * ..
- *
- * (key, value) pairs for a given network are grouped together and can
- * be in any order. A EOS at the end of a set of (key, value) pairs
- * indicates that the next set of (key, value) pairs are for a new
- * network. A network is identified by a unique ID_KEY. If there is no
- * ID_KEY in the (key, value) pairs, the data is discarded.
- *
- * An invalid version on read would result in discarding the contents of
- * the file. On the next write, the latest version is written to file.
- *
- * Any failures during read or write to the configuration file are ignored
- * without reporting to the user since the likelihood of these errors are
- * low and the impact on connectivity is low.
- *
- * = SSID & security details that is pushed to the supplicant.
- * supplicant saves these details to the disk on calling
- * saveConfigCommand().
- *
- * We have two kinds of APIs exposed:
- * > public API calls that provide fine grained control
- * - enableNetwork, disableNetwork, addOrUpdateNetwork(),
- * removeNetwork(). For these calls, the config is not persisted
- * to the disk. (TODO: deprecate these calls in WifiManager)
- * > The new API calls - selectNetwork(), saveNetwork() & forgetNetwork().
- * These calls persist the supplicant config to disk.
- *
- * - Maintain a list of configured networks for quick access
- *
- */
-class WifiConfigStore {
-
- private Context mContext;
- private static final String TAG = "WifiConfigStore";
- private static final boolean DBG = true;
- private static final boolean VDBG = false;
-
- private static final String SUPPLICANT_CONFIG_FILE = "/data/misc/wifi/wpa_supplicant.conf";
-
- /* configured networks with network id as the key */
- private HashMap<Integer, WifiConfiguration> mConfiguredNetworks =
- new HashMap<Integer, WifiConfiguration>();
-
- /* A network id is a unique identifier for a network configured in the
- * supplicant. Network ids are generated when the supplicant reads
- * the configuration file at start and can thus change for networks.
- * We store the IP configuration for networks along with a unique id
- * that is generated from SSID and security type of the network. A mapping
- * from the generated unique id to network id of the network is needed to
- * map supplicant config to IP configuration. */
- private HashMap<Integer, Integer> mNetworkIds =
- new HashMap<Integer, Integer>();
-
- /* Tracks the highest priority of configured networks */
- private int mLastPriority = -1;
-
- private static final String ipConfigFile = Environment.getDataDirectory() +
- "/misc/wifi/ipconfig.txt";
-
- private static final int IPCONFIG_FILE_VERSION = 2;
-
- /* IP and proxy configuration keys */
- private static final String ID_KEY = "id";
- private static final String IP_ASSIGNMENT_KEY = "ipAssignment";
- private static final String LINK_ADDRESS_KEY = "linkAddress";
- private static final String GATEWAY_KEY = "gateway";
- private static final String DNS_KEY = "dns";
- private static final String PROXY_SETTINGS_KEY = "proxySettings";
- private static final String PROXY_HOST_KEY = "proxyHost";
- private static final String PROXY_PORT_KEY = "proxyPort";
- private static final String PROXY_PAC_FILE = "proxyPac";
- private static final String EXCLUSION_LIST_KEY = "exclusionList";
- private static final String EOS = "eos";
-
-
- /* Enterprise configuration keys */
- /**
- * In old configurations, the "private_key" field was used. However, newer
- * configurations use the key_id field with the engine_id set to "keystore".
- * If this field is found in the configuration, the migration code is
- * triggered.
- */
- public static final String OLD_PRIVATE_KEY_NAME = "private_key";
-
- /**
- * String representing the keystore OpenSSL ENGINE's ID.
- */
- public static final String ENGINE_ID_KEYSTORE = "keystore";
-
- /**
- * String representing the keystore URI used for wpa_supplicant.
- */
- public static final String KEYSTORE_URI = "keystore://";
-
- /**
- * String to set the engine value to when it should be enabled.
- */
- public static final String ENGINE_ENABLE = "1";
-
- /**
- * String to set the engine value to when it should be disabled.
- */
- public static final String ENGINE_DISABLE = "0";
-
- public static final String CA_CERT_PREFIX = KEYSTORE_URI + Credentials.CA_CERTIFICATE;
- public static final String CLIENT_CERT_PREFIX = KEYSTORE_URI + Credentials.USER_CERTIFICATE;
- public static final String EAP_KEY = "eap";
- public static final String PHASE2_KEY = "phase2";
- public static final String IDENTITY_KEY = "identity";
- public static final String ANON_IDENTITY_KEY = "anonymous_identity";
- public static final String PASSWORD_KEY = "password";
- public static final String CLIENT_CERT_KEY = "client_cert";
- public static final String CA_CERT_KEY = "ca_cert";
- public static final String SUBJECT_MATCH_KEY = "subject_match";
- public static final String ENGINE_KEY = "engine";
- public static final String ENGINE_ID_KEY = "engine_id";
- public static final String PRIVATE_KEY_ID_KEY = "key_id";
- public static final String OPP_KEY_CACHING = "proactive_key_caching";
-
- /** This represents an empty value of an enterprise field.
- * NULL is used at wpa_supplicant to indicate an empty value
- */
- static final String EMPTY_VALUE = "NULL";
-
- /** Internal use only */
- private static final String[] ENTERPRISE_CONFIG_SUPPLICANT_KEYS = new String[] { EAP_KEY,
- PHASE2_KEY, IDENTITY_KEY, ANON_IDENTITY_KEY, PASSWORD_KEY, CLIENT_CERT_KEY,
- CA_CERT_KEY, SUBJECT_MATCH_KEY, ENGINE_KEY, ENGINE_ID_KEY, PRIVATE_KEY_ID_KEY };
-
- private final LocalLog mLocalLog;
- private final WpaConfigFileObserver mFileObserver;
-
- private WifiNative mWifiNative;
- private final KeyStore mKeyStore = KeyStore.getInstance();
-
- WifiConfigStore(Context c, WifiNative wn) {
- mContext = c;
- mWifiNative = wn;
-
- if (VDBG) {
- mLocalLog = mWifiNative.getLocalLog();
- mFileObserver = new WpaConfigFileObserver();
- mFileObserver.startWatching();
- } else {
- mLocalLog = null;
- mFileObserver = null;
- }
- }
-
- class WpaConfigFileObserver extends FileObserver {
-
- public WpaConfigFileObserver() {
- super(SUPPLICANT_CONFIG_FILE, CLOSE_WRITE);
- }
-
- @Override
- public void onEvent(int event, String path) {
- if (event == CLOSE_WRITE) {
- File file = new File(SUPPLICANT_CONFIG_FILE);
- if (VDBG) localLog("wpa_supplicant.conf changed; new size = " + file.length());
- }
- }
- }
-
-
- /**
- * Fetch the list of configured networks
- * and enable all stored networks in supplicant.
- */
- void loadAndEnableAllNetworks() {
- if (DBG) log("Loading config and enabling all networks");
- loadConfiguredNetworks();
- enableAllNetworks();
- }
-
- /**
- * Fetch the list of currently configured networks
- * @return List of networks
- */
- List<WifiConfiguration> getConfiguredNetworks() {
- List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
- for(WifiConfiguration config : mConfiguredNetworks.values()) {
- networks.add(new WifiConfiguration(config));
- }
- return networks;
- }
-
- /**
- * enable all networks and save config. This will be a no-op if the list
- * of configured networks indicates all networks as being enabled
- */
- void enableAllNetworks() {
- boolean networkEnabledStateChanged = false;
- for(WifiConfiguration config : mConfiguredNetworks.values()) {
- if(config != null && config.status == Status.DISABLED) {
- if(mWifiNative.enableNetwork(config.networkId, false)) {
- networkEnabledStateChanged = true;
- config.status = Status.ENABLED;
- } else {
- loge("Enable network failed on " + config.networkId);
- }
- }
- }
-
- if (networkEnabledStateChanged) {
- mWifiNative.saveConfig();
- sendConfiguredNetworksChangedBroadcast();
- }
- }
-
-
- /**
- * Selects the specified network for connection. This involves
- * updating the priority of all the networks and enabling the given
- * network while disabling others.
- *
- * Selecting a network will leave the other networks disabled and
- * a call to enableAllNetworks() needs to be issued upon a connection
- * or a failure event from supplicant
- *
- * @param netId network to select for connection
- * @return false if the network id is invalid
- */
- boolean selectNetwork(int netId) {
- if (VDBG) localLog("selectNetwork", netId);
- if (netId == 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 config : mConfiguredNetworks.values()) {
- if (config.networkId != INVALID_NETWORK_ID) {
- config.priority = 0;
- addOrUpdateNetworkNative(config);
- }
- }
- mLastPriority = 0;
- }
-
- // Set to the highest priority and save the configuration.
- WifiConfiguration config = new WifiConfiguration();
- config.networkId = netId;
- config.priority = ++mLastPriority;
-
- addOrUpdateNetworkNative(config);
- mWifiNative.saveConfig();
-
- /* Enable the given network while disabling all other networks */
- enableNetworkWithoutBroadcast(netId, true);
-
- /* Avoid saving the config & sending a broadcast to prevent settings
- * from displaying a disabled list of networks */
- return true;
- }
-
- /**
- * Add/update the specified configuration and save config
- *
- * @param config WifiConfiguration to be saved
- * @return network update result
- */
- NetworkUpdateResult saveNetwork(WifiConfiguration config) {
- if (VDBG) localLog("saveNetwork", config.networkId);
- // A new network cannot have null SSID
- if (config == null || (config.networkId == INVALID_NETWORK_ID &&
- config.SSID == null)) {
- return new NetworkUpdateResult(INVALID_NETWORK_ID);
- }
-
- boolean newNetwork = (config.networkId == INVALID_NETWORK_ID);
- NetworkUpdateResult result = addOrUpdateNetworkNative(config);
- int netId = result.getNetworkId();
- /* enable a new network */
- if (newNetwork && netId != INVALID_NETWORK_ID) {
- mWifiNative.enableNetwork(netId, false);
- mConfiguredNetworks.get(netId).status = Status.ENABLED;
- }
- mWifiNative.saveConfig();
- sendConfiguredNetworksChangedBroadcast(config, result.isNewNetwork() ?
- WifiManager.CHANGE_REASON_ADDED : WifiManager.CHANGE_REASON_CONFIG_CHANGE);
- return result;
- }
-
- void updateStatus(int netId, DetailedState state) {
- if (netId != INVALID_NETWORK_ID) {
- WifiConfiguration config = mConfiguredNetworks.get(netId);
- if (config == null) return;
- switch (state) {
- case CONNECTED:
- config.status = Status.CURRENT;
- break;
- case DISCONNECTED:
- //If network is already disabled, keep the status
- if (config.status == Status.CURRENT) {
- config.status = Status.ENABLED;
- }
- break;
- default:
- //do nothing, retain the existing state
- break;
- }
- }
- }
-
- /**
- * Forget the specified network and save config
- *
- * @param netId network to forget
- * @return {@code true} if it succeeds, {@code false} otherwise
- */
- boolean forgetNetwork(int netId) {
- if (VDBG) localLog("forgetNetwork", netId);
- if (mWifiNative.removeNetwork(netId)) {
- mWifiNative.saveConfig();
- removeConfigAndSendBroadcastIfNeeded(netId);
- return true;
- } else {
- loge("Failed to remove network " + netId);
- return false;
- }
- }
-
- /**
- * Add/update a network. Note that there is no saveConfig operation.
- * This function is retained for compatibility with the public
- * API. The more powerful saveNetwork() is used by the
- * state machine
- *
- * @param config wifi configuration to add/update
- * @return network Id
- */
- int addOrUpdateNetwork(WifiConfiguration config) {
- if (VDBG) localLog("addOrUpdateNetwork", config.networkId);
- NetworkUpdateResult result = addOrUpdateNetworkNative(config);
- if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) {
- sendConfiguredNetworksChangedBroadcast(mConfiguredNetworks.get(result.getNetworkId()),
- result.isNewNetwork ? WifiManager.CHANGE_REASON_ADDED :
- WifiManager.CHANGE_REASON_CONFIG_CHANGE);
- }
- return result.getNetworkId();
- }
-
- /**
- * Remove a network. Note that there is no saveConfig operation.
- * This function is retained for compatibility with the public
- * API. The more powerful forgetNetwork() is used by the
- * state machine for network removal
- *
- * @param netId network to be removed
- * @return {@code true} if it succeeds, {@code false} otherwise
- */
- boolean removeNetwork(int netId) {
- if (VDBG) localLog("removeNetwork", netId);
- boolean ret = mWifiNative.removeNetwork(netId);
- if (ret) {
- removeConfigAndSendBroadcastIfNeeded(netId);
- }
- return ret;
- }
-
- private void removeConfigAndSendBroadcastIfNeeded(int netId) {
- WifiConfiguration config = mConfiguredNetworks.get(netId);
- if (config != null) {
- // Remove any associated keys
- if (config.enterpriseConfig != null) {
- removeKeys(config.enterpriseConfig);
- }
- mConfiguredNetworks.remove(netId);
- mNetworkIds.remove(configKey(config));
-
- writeIpAndProxyConfigurations();
- sendConfiguredNetworksChangedBroadcast(config, WifiManager.CHANGE_REASON_REMOVED);
- }
- }
-
- /**
- * Enable a network. Note that there is no saveConfig operation.
- * This function is retained for compatibility with the public
- * API. The more powerful selectNetwork()/saveNetwork() is used by the
- * state machine for connecting to a network
- *
- * @param netId network to be enabled
- * @return {@code true} if it succeeds, {@code false} otherwise
- */
- boolean enableNetwork(int netId, boolean disableOthers) {
- boolean ret = enableNetworkWithoutBroadcast(netId, disableOthers);
- if (disableOthers) {
- if (VDBG) localLog("enableNetwork(disableOthers=true) ", netId);
- sendConfiguredNetworksChangedBroadcast();
- } else {
- if (VDBG) localLog("enableNetwork(disableOthers=false) ", netId);
- WifiConfiguration enabledNetwork = null;
- synchronized(mConfiguredNetworks) {
- enabledNetwork = mConfiguredNetworks.get(netId);
- }
- // check just in case the network was removed by someone else.
- if (enabledNetwork != null) {
- sendConfiguredNetworksChangedBroadcast(enabledNetwork,
- WifiManager.CHANGE_REASON_CONFIG_CHANGE);
- }
- }
- return ret;
- }
-
- boolean enableNetworkWithoutBroadcast(int netId, boolean disableOthers) {
- boolean ret = mWifiNative.enableNetwork(netId, disableOthers);
-
- WifiConfiguration config = mConfiguredNetworks.get(netId);
- if (config != null) config.status = Status.ENABLED;
-
- if (disableOthers) {
- markAllNetworksDisabledExcept(netId);
- }
- return ret;
- }
-
- void disableAllNetworks() {
- if (VDBG) localLog("disableAllNetworks");
- boolean networkDisabled = false;
- for(WifiConfiguration config : mConfiguredNetworks.values()) {
- if(config != null && config.status != Status.DISABLED) {
- if(mWifiNative.disableNetwork(config.networkId)) {
- networkDisabled = true;
- config.status = Status.DISABLED;
- } else {
- loge("Disable network failed on " + config.networkId);
- }
- }
- }
-
- if (networkDisabled) {
- sendConfiguredNetworksChangedBroadcast();
- }
- }
- /**
- * Disable a network. Note that there is no saveConfig operation.
- * @param netId network to be disabled
- * @return {@code true} if it succeeds, {@code false} otherwise
- */
- boolean disableNetwork(int netId) {
- return disableNetwork(netId, WifiConfiguration.DISABLED_UNKNOWN_REASON);
- }
-
- /**
- * Disable a network. Note that there is no saveConfig operation.
- * @param netId network to be disabled
- * @param reason reason code network was disabled
- * @return {@code true} if it succeeds, {@code false} otherwise
- */
- boolean disableNetwork(int netId, int reason) {
- if (VDBG) localLog("disableNetwork", netId);
- boolean ret = mWifiNative.disableNetwork(netId);
- WifiConfiguration network = null;
- WifiConfiguration config = mConfiguredNetworks.get(netId);
- /* Only change the reason if the network was not previously disabled */
- if (config != null && config.status != Status.DISABLED) {
- config.status = Status.DISABLED;
- config.disableReason = reason;
- network = config;
- }
- if (network != null) {
- sendConfiguredNetworksChangedBroadcast(network,
- WifiManager.CHANGE_REASON_CONFIG_CHANGE);
- }
- return ret;
- }
-
- /**
- * Save the configured networks in supplicant to disk
- * @return {@code true} if it succeeds, {@code false} otherwise
- */
- boolean saveConfig() {
- return mWifiNative.saveConfig();
- }
-
- /**
- * Start WPS pin method configuration with pin obtained
- * from the access point
- * @param config WPS configuration
- * @return Wps result containing status and pin
- */
- WpsResult startWpsWithPinFromAccessPoint(WpsInfo config) {
- WpsResult result = new WpsResult();
- if (mWifiNative.startWpsRegistrar(config.BSSID, config.pin)) {
- /* WPS leaves all networks disabled */
- markAllNetworksDisabled();
- result.status = WpsResult.Status.SUCCESS;
- } else {
- loge("Failed to start WPS pin method configuration");
- result.status = WpsResult.Status.FAILURE;
- }
- return result;
- }
-
- /**
- * Start WPS pin method configuration with pin obtained
- * from the device
- * @return WpsResult indicating status and pin
- */
- WpsResult startWpsWithPinFromDevice(WpsInfo config) {
- WpsResult result = new WpsResult();
- result.pin = mWifiNative.startWpsPinDisplay(config.BSSID);
- /* WPS leaves all networks disabled */
- if (!TextUtils.isEmpty(result.pin)) {
- markAllNetworksDisabled();
- result.status = WpsResult.Status.SUCCESS;
- } else {
- loge("Failed to start WPS pin method configuration");
- result.status = WpsResult.Status.FAILURE;
- }
- return result;
- }
-
- /**
- * Start WPS push button configuration
- * @param config WPS configuration
- * @return WpsResult indicating status and pin
- */
- WpsResult startWpsPbc(WpsInfo config) {
- WpsResult result = new WpsResult();
- if (mWifiNative.startWpsPbc(config.BSSID)) {
- /* WPS leaves all networks disabled */
- markAllNetworksDisabled();
- result.status = WpsResult.Status.SUCCESS;
- } else {
- loge("Failed to start WPS push button configuration");
- result.status = WpsResult.Status.FAILURE;
- }
- return result;
- }
-
- /**
- * Fetch the link properties for a given network id
- * @return LinkProperties for the given network id
- */
- LinkProperties getLinkProperties(int netId) {
- WifiConfiguration config = mConfiguredNetworks.get(netId);
- if (config != null) return new LinkProperties(config.linkProperties);
- return null;
- }
-
- /**
- * set IP configuration for a given network id
- */
- void setLinkProperties(int netId, LinkProperties linkProperties) {
- WifiConfiguration config = mConfiguredNetworks.get(netId);
- if (config != null) {
- // add old proxy details - TODO - is this still needed?
- if(config.linkProperties != null) {
- linkProperties.setHttpProxy(config.linkProperties.getHttpProxy());
- }
- config.linkProperties = linkProperties;
- }
- }
-
- /**
- * clear IP configuration for a given network id
- * @param network id
- */
- void clearLinkProperties(int netId) {
- WifiConfiguration config = mConfiguredNetworks.get(netId);
- if (config != null && config.linkProperties != null) {
- // Clear everything except proxy
- ProxyProperties proxy = config.linkProperties.getHttpProxy();
- config.linkProperties.clear();
- config.linkProperties.setHttpProxy(proxy);
- }
- }
-
-
- /**
- * Fetch the proxy properties for a given network id
- * @param network id
- * @return ProxyProperties for the network id
- */
- ProxyProperties getProxyProperties(int netId) {
- LinkProperties linkProperties = getLinkProperties(netId);
- if (linkProperties != null) {
- return new ProxyProperties(linkProperties.getHttpProxy());
- }
- return null;
- }
-
- /**
- * Return if the specified network is using static IP
- * @param network id
- * @return {@code true} if using static ip for netId
- */
- boolean isUsingStaticIp(int netId) {
- WifiConfiguration config = mConfiguredNetworks.get(netId);
- if (config != null && config.ipAssignment == IpAssignment.STATIC) {
- return true;
- }
- return false;
- }
-
- /**
- * Should be called when a single network configuration is made.
- * @param network The network configuration that changed.
- * @param reason The reason for the change, should be one of WifiManager.CHANGE_REASON_ADDED,
- * WifiManager.CHANGE_REASON_REMOVED, or WifiManager.CHANGE_REASON_CHANGE.
- */
- private void sendConfiguredNetworksChangedBroadcast(WifiConfiguration network,
- int reason) {
- Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, false);
- intent.putExtra(WifiManager.EXTRA_WIFI_CONFIGURATION, network);
- intent.putExtra(WifiManager.EXTRA_CHANGE_REASON, reason);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- /**
- * Should be called when multiple network configuration changes are made.
- */
- private void sendConfiguredNetworksChangedBroadcast() {
- Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, true);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- void loadConfiguredNetworks() {
- String listStr = mWifiNative.listNetworks();
- mLastPriority = 0;
-
- mConfiguredNetworks.clear();
- mNetworkIds.clear();
-
- if (listStr == null)
- return;
-
- String[] lines = listStr.split("\n");
- // Skip the first line, which is a header
- for (int i = 1; i < lines.length; i++) {
- String[] result = lines[i].split("\t");
- // network-id | ssid | bssid | flags
- WifiConfiguration config = new WifiConfiguration();
- try {
- config.networkId = Integer.parseInt(result[0]);
- } catch(NumberFormatException e) {
- loge("Failed to read network-id '" + result[0] + "'");
- continue;
- }
- if (result.length > 3) {
- if (result[3].indexOf("[CURRENT]") != -1)
- config.status = WifiConfiguration.Status.CURRENT;
- else if (result[3].indexOf("[DISABLED]") != -1)
- config.status = WifiConfiguration.Status.DISABLED;
- else
- config.status = WifiConfiguration.Status.ENABLED;
- } else {
- config.status = WifiConfiguration.Status.ENABLED;
- }
- readNetworkVariables(config);
- if (config.priority > mLastPriority) {
- mLastPriority = config.priority;
- }
- config.ipAssignment = IpAssignment.DHCP;
- config.proxySettings = ProxySettings.NONE;
-
- if (mNetworkIds.containsKey(configKey(config))) {
- // That SSID is already known, just ignore this duplicate entry
- if (VDBG) localLog("discarded duplicate network", config.networkId);
- } else {
- mConfiguredNetworks.put(config.networkId, config);
- mNetworkIds.put(configKey(config), config.networkId);
- if (VDBG) localLog("loaded configured network", config.networkId);
- }
- }
-
- readIpAndProxyConfigurations();
- sendConfiguredNetworksChangedBroadcast();
-
- if (VDBG) localLog("loadConfiguredNetworks loaded " + mNetworkIds.size() + " networks");
-
- if (mNetworkIds.size() == 0) {
- // no networks? Lets log if the wpa_supplicant.conf file contents
- BufferedReader reader = null;
- try {
- reader = new BufferedReader(new FileReader(SUPPLICANT_CONFIG_FILE));
- if (VDBG) localLog("--- Begin wpa_supplicant.conf Contents ---");
- for (String line = reader.readLine(); line != null; line = reader.readLine()) {
- if (VDBG) localLog(line);
- }
- if (VDBG) localLog("--- End wpa_supplicant.conf Contents ---");
- } catch (FileNotFoundException e) {
- if (VDBG) localLog("Could not open " + SUPPLICANT_CONFIG_FILE + ", " + e);
- } catch (IOException e) {
- if (VDBG) localLog("Could not read " + SUPPLICANT_CONFIG_FILE + ", " + e);
- } finally {
- try {
- if (reader != null) {
- reader.close();
- }
- } catch (IOException e) {
- // Just ignore the fact that we couldn't close
- }
- }
- }
- }
-
- /* Mark all networks except specified netId as disabled */
- private void markAllNetworksDisabledExcept(int netId) {
- for(WifiConfiguration config : mConfiguredNetworks.values()) {
- if(config != null && config.networkId != netId) {
- if (config.status != Status.DISABLED) {
- config.status = Status.DISABLED;
- config.disableReason = WifiConfiguration.DISABLED_UNKNOWN_REASON;
- }
- }
- }
- }
-
- private void markAllNetworksDisabled() {
- markAllNetworksDisabledExcept(INVALID_NETWORK_ID);
- }
-
- boolean needsUnlockedKeyStore() {
-
- // Any network using certificates to authenticate access requires
- // unlocked key store; unless the certificates can be stored with
- // hardware encryption
-
- for(WifiConfiguration config : mConfiguredNetworks.values()) {
-
- if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP)
- && config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
-
- if (needsSoftwareBackedKeyStore(config.enterpriseConfig)) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- private void writeIpAndProxyConfigurations() {
-
- /* Make a copy */
- List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
- for(WifiConfiguration config : mConfiguredNetworks.values()) {
- networks.add(new WifiConfiguration(config));
- }
-
- DelayedDiskWrite.write(networks);
- }
-
- private static class DelayedDiskWrite {
-
- private static HandlerThread sDiskWriteHandlerThread;
- private static Handler sDiskWriteHandler;
- /* Tracks multiple writes on the same thread */
- private static int sWriteSequence = 0;
- private static final String TAG = "DelayedDiskWrite";
-
- static void write (final List<WifiConfiguration> networks) {
-
- /* Do a delayed write to disk on a seperate handler thread */
- synchronized (DelayedDiskWrite.class) {
- if (++sWriteSequence == 1) {
- sDiskWriteHandlerThread = new HandlerThread("WifiConfigThread");
- sDiskWriteHandlerThread.start();
- sDiskWriteHandler = new Handler(sDiskWriteHandlerThread.getLooper());
- }
- }
-
- sDiskWriteHandler.post(new Runnable() {
- @Override
- public void run() {
- onWriteCalled(networks);
- }
- });
- }
-
- private static void onWriteCalled(List<WifiConfiguration> networks) {
-
- DataOutputStream out = null;
- try {
- out = new DataOutputStream(new BufferedOutputStream(
- new FileOutputStream(ipConfigFile)));
-
- out.writeInt(IPCONFIG_FILE_VERSION);
-
- for(WifiConfiguration config : networks) {
- boolean writeToFile = false;
-
- try {
- LinkProperties linkProperties = config.linkProperties;
- switch (config.ipAssignment) {
- case STATIC:
- out.writeUTF(IP_ASSIGNMENT_KEY);
- out.writeUTF(config.ipAssignment.toString());
- for (LinkAddress linkAddr : linkProperties.getLinkAddresses()) {
- out.writeUTF(LINK_ADDRESS_KEY);
- out.writeUTF(linkAddr.getAddress().getHostAddress());
- out.writeInt(linkAddr.getNetworkPrefixLength());
- }
- for (RouteInfo route : linkProperties.getRoutes()) {
- out.writeUTF(GATEWAY_KEY);
- LinkAddress dest = route.getDestination();
- if (dest != null) {
- out.writeInt(1);
- out.writeUTF(dest.getAddress().getHostAddress());
- out.writeInt(dest.getNetworkPrefixLength());
- } else {
- out.writeInt(0);
- }
- if (route.getGateway() != null) {
- out.writeInt(1);
- out.writeUTF(route.getGateway().getHostAddress());
- } else {
- out.writeInt(0);
- }
- }
- for (InetAddress inetAddr : linkProperties.getDnses()) {
- out.writeUTF(DNS_KEY);
- out.writeUTF(inetAddr.getHostAddress());
- }
- writeToFile = true;
- break;
- case DHCP:
- out.writeUTF(IP_ASSIGNMENT_KEY);
- out.writeUTF(config.ipAssignment.toString());
- writeToFile = true;
- break;
- case UNASSIGNED:
- /* Ignore */
- break;
- default:
- loge("Ignore invalid ip assignment while writing");
- break;
- }
-
- switch (config.proxySettings) {
- case STATIC:
- ProxyProperties proxyProperties = linkProperties.getHttpProxy();
- String exclusionList = proxyProperties.getExclusionList();
- out.writeUTF(PROXY_SETTINGS_KEY);
- out.writeUTF(config.proxySettings.toString());
- out.writeUTF(PROXY_HOST_KEY);
- out.writeUTF(proxyProperties.getHost());
- out.writeUTF(PROXY_PORT_KEY);
- out.writeInt(proxyProperties.getPort());
- out.writeUTF(EXCLUSION_LIST_KEY);
- out.writeUTF(exclusionList);
- writeToFile = true;
- break;
- case PAC:
- ProxyProperties proxyPacProperties = linkProperties.getHttpProxy();
- out.writeUTF(PROXY_SETTINGS_KEY);
- out.writeUTF(config.proxySettings.toString());
- out.writeUTF(PROXY_PAC_FILE);
- out.writeUTF(proxyPacProperties.getPacFileUrl());
- writeToFile = true;
- break;
- case NONE:
- out.writeUTF(PROXY_SETTINGS_KEY);
- out.writeUTF(config.proxySettings.toString());
- writeToFile = true;
- break;
- case UNASSIGNED:
- /* Ignore */
- break;
- default:
- loge("Ignthisore invalid proxy settings while writing");
- break;
- }
- if (writeToFile) {
- out.writeUTF(ID_KEY);
- out.writeInt(configKey(config));
- }
- } catch (NullPointerException e) {
- loge("Failure in writing " + config.linkProperties + e);
- }
- out.writeUTF(EOS);
- }
-
- } catch (IOException e) {
- loge("Error writing data file");
- } finally {
- if (out != null) {
- try {
- out.close();
- } catch (Exception e) {}
- }
-
- //Quit if no more writes sent
- synchronized (DelayedDiskWrite.class) {
- if (--sWriteSequence == 0) {
- sDiskWriteHandler.getLooper().quit();
- sDiskWriteHandler = null;
- sDiskWriteHandlerThread = null;
- }
- }
- }
- }
-
- private static void loge(String s) {
- Log.e(TAG, s);
- }
- }
-
- private void readIpAndProxyConfigurations() {
-
- DataInputStream in = null;
- try {
- in = new DataInputStream(new BufferedInputStream(new FileInputStream(
- ipConfigFile)));
-
- int version = in.readInt();
- if (version != 2 && version != 1) {
- loge("Bad version on IP configuration file, ignore read");
- return;
- }
-
- while (true) {
- int id = -1;
- // Default is DHCP with no proxy
- IpAssignment ipAssignment = IpAssignment.DHCP;
- ProxySettings proxySettings = ProxySettings.NONE;
- LinkProperties linkProperties = new LinkProperties();
- String proxyHost = null;
- String pacFileUrl = null;
- int proxyPort = -1;
- String exclusionList = null;
- String key;
-
- do {
- key = in.readUTF();
- try {
- if (key.equals(ID_KEY)) {
- id = in.readInt();
- } else if (key.equals(IP_ASSIGNMENT_KEY)) {
- ipAssignment = IpAssignment.valueOf(in.readUTF());
- } else if (key.equals(LINK_ADDRESS_KEY)) {
- LinkAddress linkAddr = new LinkAddress(
- NetworkUtils.numericToInetAddress(in.readUTF()), in.readInt());
- linkProperties.addLinkAddress(linkAddr);
- } else if (key.equals(GATEWAY_KEY)) {
- LinkAddress dest = null;
- InetAddress gateway = null;
- if (version == 1) {
- // only supported default gateways - leave the dest/prefix empty
- gateway = NetworkUtils.numericToInetAddress(in.readUTF());
- } else {
- if (in.readInt() == 1) {
- dest = new LinkAddress(
- NetworkUtils.numericToInetAddress(in.readUTF()),
- in.readInt());
- }
- if (in.readInt() == 1) {
- gateway = NetworkUtils.numericToInetAddress(in.readUTF());
- }
- }
- linkProperties.addRoute(new RouteInfo(dest, gateway));
- } else if (key.equals(DNS_KEY)) {
- linkProperties.addDns(
- NetworkUtils.numericToInetAddress(in.readUTF()));
- } else if (key.equals(PROXY_SETTINGS_KEY)) {
- proxySettings = ProxySettings.valueOf(in.readUTF());
- } else if (key.equals(PROXY_HOST_KEY)) {
- proxyHost = in.readUTF();
- } else if (key.equals(PROXY_PORT_KEY)) {
- proxyPort = in.readInt();
- } else if (key.equals(PROXY_PAC_FILE)) {
- pacFileUrl = in.readUTF();
- } else if (key.equals(EXCLUSION_LIST_KEY)) {
- exclusionList = in.readUTF();
- } else if (key.equals(EOS)) {
- break;
- } else {
- loge("Ignore unknown key " + key + "while reading");
- }
- } catch (IllegalArgumentException e) {
- loge("Ignore invalid address while reading" + e);
- }
- } while (true);
-
- if (id != -1) {
- WifiConfiguration config = mConfiguredNetworks.get(
- mNetworkIds.get(id));
-
- if (config == null) {
- loge("configuration found for missing network, ignored");
- } else {
- config.linkProperties = linkProperties;
- switch (ipAssignment) {
- case STATIC:
- case DHCP:
- config.ipAssignment = ipAssignment;
- break;
- case UNASSIGNED:
- loge("BUG: Found UNASSIGNED IP on file, use DHCP");
- config.ipAssignment = IpAssignment.DHCP;
- break;
- default:
- loge("Ignore invalid ip assignment while reading");
- break;
- }
-
- switch (proxySettings) {
- case STATIC:
- config.proxySettings = proxySettings;
- ProxyProperties proxyProperties =
- new ProxyProperties(proxyHost, proxyPort, exclusionList);
- linkProperties.setHttpProxy(proxyProperties);
- break;
- case PAC:
- config.proxySettings = proxySettings;
- ProxyProperties proxyPacProperties =
- new ProxyProperties(pacFileUrl);
- linkProperties.setHttpProxy(proxyPacProperties);
- break;
- case NONE:
- config.proxySettings = proxySettings;
- break;
- case UNASSIGNED:
- loge("BUG: Found UNASSIGNED proxy on file, use NONE");
- config.proxySettings = ProxySettings.NONE;
- break;
- default:
- loge("Ignore invalid proxy settings while reading");
- break;
- }
- }
- } else {
- if (DBG) log("Missing id while parsing configuration");
- }
- }
- } catch (EOFException ignore) {
- } catch (IOException e) {
- loge("Error parsing configuration" + e);
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (Exception e) {}
- }
- }
- }
-
- private NetworkUpdateResult addOrUpdateNetworkNative(WifiConfiguration config) {
- /*
- * If the supplied networkId is INVALID_NETWORK_ID, we create a new empty
- * network configuration. Otherwise, the networkId should
- * refer to an existing configuration.
- */
-
- if (VDBG) localLog("addOrUpdateNetworkNative " + config.getPrintableSsid());
-
- int netId = config.networkId;
- boolean newNetwork = false;
- // networkId of INVALID_NETWORK_ID means we want to create a new network
- if (netId == INVALID_NETWORK_ID) {
- Integer savedNetId = mNetworkIds.get(configKey(config));
- if (savedNetId != null) {
- netId = savedNetId;
- } else {
- newNetwork = true;
- netId = mWifiNative.addNetwork();
- if (netId < 0) {
- loge("Failed to add a network!");
- return new NetworkUpdateResult(INVALID_NETWORK_ID);
- }
- }
- }
-
- boolean updateFailed = true;
-
- setVariables: {
-
- if (config.SSID != null &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.ssidVarName,
- config.SSID)) {
- loge("failed to set SSID: "+config.SSID);
- break setVariables;
- }
-
- if (config.BSSID != null &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.bssidVarName,
- config.BSSID)) {
- loge("failed to set BSSID: "+config.BSSID);
- break setVariables;
- }
-
- String allowedKeyManagementString =
- makeString(config.allowedKeyManagement, WifiConfiguration.KeyMgmt.strings);
- if (config.allowedKeyManagement.cardinality() != 0 &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.KeyMgmt.varName,
- allowedKeyManagementString)) {
- loge("failed to set key_mgmt: "+
- allowedKeyManagementString);
- break setVariables;
- }
-
- String allowedProtocolsString =
- makeString(config.allowedProtocols, WifiConfiguration.Protocol.strings);
- if (config.allowedProtocols.cardinality() != 0 &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.Protocol.varName,
- allowedProtocolsString)) {
- loge("failed to set proto: "+
- allowedProtocolsString);
- break setVariables;
- }
-
- String allowedAuthAlgorithmsString =
- makeString(config.allowedAuthAlgorithms, WifiConfiguration.AuthAlgorithm.strings);
- if (config.allowedAuthAlgorithms.cardinality() != 0 &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.AuthAlgorithm.varName,
- allowedAuthAlgorithmsString)) {
- loge("failed to set auth_alg: "+
- allowedAuthAlgorithmsString);
- break setVariables;
- }
-
- String allowedPairwiseCiphersString =
- makeString(config.allowedPairwiseCiphers,
- WifiConfiguration.PairwiseCipher.strings);
- if (config.allowedPairwiseCiphers.cardinality() != 0 &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.PairwiseCipher.varName,
- allowedPairwiseCiphersString)) {
- loge("failed to set pairwise: "+
- allowedPairwiseCiphersString);
- break setVariables;
- }
-
- String allowedGroupCiphersString =
- makeString(config.allowedGroupCiphers, WifiConfiguration.GroupCipher.strings);
- if (config.allowedGroupCiphers.cardinality() != 0 &&
- !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.GroupCipher.varName,
- allowedGroupCiphersString)) {
- loge("failed to set group: "+
- allowedGroupCiphersString);
- break setVariables;
- }
-
- // 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(
- netId,
- WifiConfiguration.pskVarName,
- config.preSharedKey)) {
- loge("failed to set psk");
- break setVariables;
- }
-
- boolean hasSetKey = false;
- if (config.wepKeys != null) {
- 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(
- netId,
- WifiConfiguration.wepKeyVarNames[i],
- config.wepKeys[i])) {
- loge("failed to set wep_key" + i + ": " + config.wepKeys[i]);
- break setVariables;
- }
- hasSetKey = true;
- }
- }
- }
-
- if (hasSetKey) {
- if (!mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.wepTxKeyIdxVarName,
- Integer.toString(config.wepTxKeyIndex))) {
- loge("failed to set wep_tx_keyidx: " + config.wepTxKeyIndex);
- break setVariables;
- }
- }
-
- if (!mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.priorityVarName,
- Integer.toString(config.priority))) {
- loge(config.SSID + ": failed to set priority: "
- +config.priority);
- break setVariables;
- }
-
- if (config.hiddenSSID && !mWifiNative.setNetworkVariable(
- netId,
- WifiConfiguration.hiddenSSIDVarName,
- Integer.toString(config.hiddenSSID ? 1 : 0))) {
- loge(config.SSID + ": failed to set hiddenSSID: "+
- config.hiddenSSID);
- break setVariables;
- }
-
- if (config.enterpriseConfig != null &&
- config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE) {
-
- WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig;
-
- if (needsKeyStore(enterpriseConfig)) {
- /**
- * Keyguard settings may eventually be controlled by device policy.
- * We check here if keystore is unlocked before installing
- * credentials.
- * TODO: Do we need a dialog here ?
- */
- if (mKeyStore.state() != KeyStore.State.UNLOCKED) {
- loge(config.SSID + ": key store is locked");
- break setVariables;
- }
-
- try {
- /* config passed may include only fields being updated.
- * In order to generate the key id, fetch uninitialized
- * fields from the currently tracked configuration
- */
- WifiConfiguration currentConfig = mConfiguredNetworks.get(netId);
- String keyId = config.getKeyIdForCredentials(currentConfig);
-
- if (!installKeys(enterpriseConfig, keyId)) {
- loge(config.SSID + ": failed to install keys");
- break setVariables;
- }
- } catch (IllegalStateException e) {
- loge(config.SSID + " invalid config for key installation");
- break setVariables;
- }
- }
-
- HashMap<String, String> enterpriseFields = enterpriseConfig.getFields();
- for (String key : enterpriseFields.keySet()) {
- String value = enterpriseFields.get(key);
- if (!mWifiNative.setNetworkVariable(
- netId,
- key,
- value)) {
- removeKeys(enterpriseConfig);
- loge(config.SSID + ": failed to set " + key +
- ": " + value);
- break setVariables;
- }
- }
- }
- updateFailed = false;
- } //end of setVariables
-
- if (updateFailed) {
- if (newNetwork) {
- mWifiNative.removeNetwork(netId);
- loge("Failed to set a network variable, removed network: " + netId);
- }
- return new NetworkUpdateResult(INVALID_NETWORK_ID);
- }
-
- /* An update of the network variables requires reading them
- * back from the supplicant to update mConfiguredNetworks.
- * This is because some of the variables (SSID, wep keys &
- * passphrases) reflect different values when read back than
- * when written. For example, wep key is stored as * irrespective
- * of the value sent to the supplicant
- */
- WifiConfiguration currentConfig = mConfiguredNetworks.get(netId);
- if (currentConfig == null) {
- currentConfig = new WifiConfiguration();
- currentConfig.ipAssignment = IpAssignment.DHCP;
- currentConfig.proxySettings = ProxySettings.NONE;
- currentConfig.networkId = netId;
- }
-
- readNetworkVariables(currentConfig);
-
- mConfiguredNetworks.put(netId, currentConfig);
- mNetworkIds.put(configKey(currentConfig), netId);
-
- NetworkUpdateResult result = writeIpAndProxyConfigurationsOnChange(currentConfig, config);
- result.setIsNewNetwork(newNetwork);
- result.setNetworkId(netId);
- return result;
- }
-
- /* Compare current and new configuration and write to file on change */
- private NetworkUpdateResult writeIpAndProxyConfigurationsOnChange(
- WifiConfiguration currentConfig,
- WifiConfiguration newConfig) {
- boolean ipChanged = false;
- boolean proxyChanged = false;
- LinkProperties linkProperties = null;
-
- switch (newConfig.ipAssignment) {
- case STATIC:
- Collection<LinkAddress> currentLinkAddresses = currentConfig.linkProperties
- .getLinkAddresses();
- Collection<LinkAddress> newLinkAddresses = newConfig.linkProperties
- .getLinkAddresses();
- Collection<InetAddress> currentDnses = currentConfig.linkProperties.getDnses();
- Collection<InetAddress> newDnses = newConfig.linkProperties.getDnses();
- Collection<RouteInfo> currentRoutes = currentConfig.linkProperties.getRoutes();
- Collection<RouteInfo> newRoutes = newConfig.linkProperties.getRoutes();
-
- boolean linkAddressesDiffer =
- (currentLinkAddresses.size() != newLinkAddresses.size()) ||
- !currentLinkAddresses.containsAll(newLinkAddresses);
- boolean dnsesDiffer = (currentDnses.size() != newDnses.size()) ||
- !currentDnses.containsAll(newDnses);
- boolean routesDiffer = (currentRoutes.size() != newRoutes.size()) ||
- !currentRoutes.containsAll(newRoutes);
-
- if ((currentConfig.ipAssignment != newConfig.ipAssignment) ||
- linkAddressesDiffer ||
- dnsesDiffer ||
- routesDiffer) {
- ipChanged = true;
- }
- break;
- case DHCP:
- if (currentConfig.ipAssignment != newConfig.ipAssignment) {
- ipChanged = true;
- }
- break;
- case UNASSIGNED:
- /* Ignore */
- break;
- default:
- loge("Ignore invalid ip assignment during write");
- break;
- }
-
- switch (newConfig.proxySettings) {
- case STATIC:
- case PAC:
- ProxyProperties newHttpProxy = newConfig.linkProperties.getHttpProxy();
- ProxyProperties currentHttpProxy = currentConfig.linkProperties.getHttpProxy();
-
- if (newHttpProxy != null) {
- proxyChanged = !newHttpProxy.equals(currentHttpProxy);
- } else {
- proxyChanged = (currentHttpProxy != null);
- }
- break;
- case NONE:
- if (currentConfig.proxySettings != newConfig.proxySettings) {
- proxyChanged = true;
- }
- break;
- case UNASSIGNED:
- /* Ignore */
- break;
- default:
- loge("Ignore invalid proxy configuration during write");
- break;
- }
-
- if (!ipChanged) {
- linkProperties = copyIpSettingsFromConfig(currentConfig);
- } else {
- currentConfig.ipAssignment = newConfig.ipAssignment;
- linkProperties = copyIpSettingsFromConfig(newConfig);
- log("IP config changed SSID = " + currentConfig.SSID + " linkProperties: " +
- linkProperties.toString());
- }
-
-
- if (!proxyChanged) {
- linkProperties.setHttpProxy(currentConfig.linkProperties.getHttpProxy());
- } else {
- currentConfig.proxySettings = newConfig.proxySettings;
- linkProperties.setHttpProxy(newConfig.linkProperties.getHttpProxy());
- log("proxy changed SSID = " + currentConfig.SSID);
- if (linkProperties.getHttpProxy() != null) {
- log(" proxyProperties: " + linkProperties.getHttpProxy().toString());
- }
- }
-
- if (ipChanged || proxyChanged) {
- currentConfig.linkProperties = linkProperties;
- writeIpAndProxyConfigurations();
- sendConfiguredNetworksChangedBroadcast(currentConfig,
- WifiManager.CHANGE_REASON_CONFIG_CHANGE);
- }
- return new NetworkUpdateResult(ipChanged, proxyChanged);
- }
-
- private LinkProperties copyIpSettingsFromConfig(WifiConfiguration config) {
- LinkProperties linkProperties = new LinkProperties();
- linkProperties.setInterfaceName(config.linkProperties.getInterfaceName());
- for (LinkAddress linkAddr : config.linkProperties.getLinkAddresses()) {
- linkProperties.addLinkAddress(linkAddr);
- }
- for (RouteInfo route : config.linkProperties.getRoutes()) {
- linkProperties.addRoute(route);
- }
- for (InetAddress dns : config.linkProperties.getDnses()) {
- linkProperties.addDns(dns);
- }
- return linkProperties;
- }
-
- /**
- * Read the variables from the supplicant daemon that are needed to
- * fill in the WifiConfiguration object.
- *
- * @param config the {@link WifiConfiguration} object to be filled in.
- */
- private void readNetworkVariables(WifiConfiguration config) {
-
- int netId = config.networkId;
- if (netId < 0)
- return;
-
- /*
- * TODO: maybe should have a native method that takes an array of
- * variable names and returns an array of values. But we'd still
- * be doing a round trip to the supplicant daemon for each variable.
- */
- String value;
-
- value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.ssidVarName);
- if (!TextUtils.isEmpty(value)) {
- if (value.charAt(0) != '"') {
- config.SSID = "\"" + WifiSsid.createFromHex(value).toString() + "\"";
- //TODO: convert a hex string that is not UTF-8 decodable to a P-formatted
- //supplicant string
- } else {
- config.SSID = value;
- }
- } else {
- config.SSID = null;
- }
-
- value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.bssidVarName);
- if (!TextUtils.isEmpty(value)) {
- config.BSSID = value;
- } else {
- config.BSSID = null;
- }
-
- value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.priorityVarName);
- config.priority = -1;
- if (!TextUtils.isEmpty(value)) {
- try {
- config.priority = Integer.parseInt(value);
- } catch (NumberFormatException ignore) {
- }
- }
-
- value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.hiddenSSIDVarName);
- config.hiddenSSID = false;
- if (!TextUtils.isEmpty(value)) {
- try {
- config.hiddenSSID = Integer.parseInt(value) != 0;
- } catch (NumberFormatException ignore) {
- }
- }
-
- value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.wepTxKeyIdxVarName);
- config.wepTxKeyIndex = -1;
- if (!TextUtils.isEmpty(value)) {
- try {
- config.wepTxKeyIndex = Integer.parseInt(value);
- } catch (NumberFormatException ignore) {
- }
- }
-
- for (int i = 0; i < 4; i++) {
- value = mWifiNative.getNetworkVariable(netId,
- WifiConfiguration.wepKeyVarNames[i]);
- if (!TextUtils.isEmpty(value)) {
- config.wepKeys[i] = value;
- } else {
- config.wepKeys[i] = null;
- }
- }
-
- value = mWifiNative.getNetworkVariable(netId, WifiConfiguration.pskVarName);
- if (!TextUtils.isEmpty(value)) {
- config.preSharedKey = value;
- } else {
- config.preSharedKey = null;
- }
-
- value = mWifiNative.getNetworkVariable(config.networkId,
- WifiConfiguration.Protocol.varName);
- if (!TextUtils.isEmpty(value)) {
- String vals[] = value.split(" ");
- for (String val : vals) {
- int index =
- lookupString(val, WifiConfiguration.Protocol.strings);
- if (0 <= index) {
- config.allowedProtocols.set(index);
- }
- }
- }
-
- value = mWifiNative.getNetworkVariable(config.networkId,
- WifiConfiguration.KeyMgmt.varName);
- if (!TextUtils.isEmpty(value)) {
- String vals[] = value.split(" ");
- for (String val : vals) {
- int index =
- lookupString(val, WifiConfiguration.KeyMgmt.strings);
- if (0 <= index) {
- config.allowedKeyManagement.set(index);
- }
- }
- }
-
- value = mWifiNative.getNetworkVariable(config.networkId,
- WifiConfiguration.AuthAlgorithm.varName);
- if (!TextUtils.isEmpty(value)) {
- String vals[] = value.split(" ");
- for (String val : vals) {
- int index =
- lookupString(val, WifiConfiguration.AuthAlgorithm.strings);
- if (0 <= index) {
- config.allowedAuthAlgorithms.set(index);
- }
- }
- }
-
- value = mWifiNative.getNetworkVariable(config.networkId,
- WifiConfiguration.PairwiseCipher.varName);
- if (!TextUtils.isEmpty(value)) {
- String vals[] = value.split(" ");
- for (String val : vals) {
- int index =
- lookupString(val, WifiConfiguration.PairwiseCipher.strings);
- if (0 <= index) {
- config.allowedPairwiseCiphers.set(index);
- }
- }
- }
-
- value = mWifiNative.getNetworkVariable(config.networkId,
- WifiConfiguration.GroupCipher.varName);
- if (!TextUtils.isEmpty(value)) {
- String vals[] = value.split(" ");
- for (String val : vals) {
- int index =
- lookupString(val, WifiConfiguration.GroupCipher.strings);
- if (0 <= index) {
- config.allowedGroupCiphers.set(index);
- }
- }
- }
-
- if (config.enterpriseConfig == null) {
- config.enterpriseConfig = new WifiEnterpriseConfig();
- }
- HashMap<String, String> enterpriseFields = config.enterpriseConfig.getFields();
- for (String key : ENTERPRISE_CONFIG_SUPPLICANT_KEYS) {
- value = mWifiNative.getNetworkVariable(netId, key);
- if (!TextUtils.isEmpty(value)) {
- enterpriseFields.put(key, removeDoubleQuotes(value));
- } else {
- enterpriseFields.put(key, EMPTY_VALUE);
- }
- }
-
- if (migrateOldEapTlsNative(config.enterpriseConfig, netId)) {
- saveConfig();
- }
-
- migrateCerts(config.enterpriseConfig);
- // initializeSoftwareKeystoreFlag(config.enterpriseConfig, mKeyStore);
- }
-
- private String removeDoubleQuotes(String string) {
- int length = string.length();
- if ((length > 1) && (string.charAt(0) == '"')
- && (string.charAt(length - 1) == '"')) {
- return string.substring(1, length - 1);
- }
- return string;
- }
-
- private String convertToQuotedString(String string) {
- return "\"" + string + "\"";
- }
-
- private String makeString(BitSet set, String[] strings) {
- StringBuffer buf = new StringBuffer();
- int nextSetBit = -1;
-
- /* Make sure all set bits are in [0, strings.length) to avoid
- * going out of bounds on strings. (Shouldn't happen, but...) */
- set = set.get(0, strings.length);
-
- while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) {
- buf.append(strings[nextSetBit].replace('_', '-')).append(' ');
- }
-
- // remove trailing space
- if (set.cardinality() > 0) {
- buf.setLength(buf.length() - 1);
- }
-
- return buf.toString();
- }
-
- private int lookupString(String string, String[] strings) {
- int size = strings.length;
-
- string = string.replace('-', '_');
-
- for (int i = 0; i < size; i++)
- if (string.equals(strings[i]))
- return i;
-
- // if we ever get here, we should probably add the
- // value to WifiConfiguration to reflect that it's
- // supported by the WPA supplicant
- loge("Failed to look-up a string: " + string);
-
- return -1;
- }
-
- /* Returns a unique for a given configuration */
- private static int configKey(WifiConfiguration config) {
- String key;
-
- if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
- key = config.SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK];
- } else if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
- config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
- key = config.SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP];
- } else if (config.wepKeys[0] != null) {
- key = config.SSID + "WEP";
- } else {
- key = config.SSID + KeyMgmt.strings[KeyMgmt.NONE];
- }
-
- return key.hashCode();
- }
-
- void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("WifiConfigStore");
- pw.println("mLastPriority " + mLastPriority);
- pw.println("Configured networks");
- for (WifiConfiguration conf : getConfiguredNetworks()) {
- pw.println(conf);
- }
- pw.println();
-
- if (mLocalLog != null) {
- pw.println("WifiConfigStore - Log Begin ----");
- mLocalLog.dump(fd, pw, args);
- pw.println("WifiConfigStore - Log End ----");
- }
- }
-
- public String getConfigFile() {
- return ipConfigFile;
- }
-
- private void loge(String s) {
- Log.e(TAG, s);
- }
-
- private void log(String s) {
- Log.d(TAG, s);
- }
-
- private void localLog(String s) {
- if (mLocalLog != null) {
- mLocalLog.log(s);
- }
- }
-
- private void localLog(String s, int netId) {
- if (mLocalLog == null) {
- return;
- }
-
- WifiConfiguration config;
- synchronized(mConfiguredNetworks) {
- config = mConfiguredNetworks.get(netId);
- }
-
- if (config != null) {
- mLocalLog.log(s + " " + config.getPrintableSsid());
- } else {
- mLocalLog.log(s + " " + netId);
- }
- }
-
- // Certificate and privake key management for EnterpriseConfig
- boolean needsKeyStore(WifiEnterpriseConfig config) {
- // Has no keys to be installed
- if (config.getClientCertificate() == null && config.getCaCertificate() == null)
- return false;
- return true;
- }
-
- static boolean isHardwareBackedKey(PrivateKey key) {
- return KeyChain.isBoundKeyAlgorithm(key.getAlgorithm());
- }
-
- static boolean hasHardwareBackedKey(Certificate certificate) {
- return KeyChain.isBoundKeyAlgorithm(certificate.getPublicKey().getAlgorithm());
- }
-
- boolean needsSoftwareBackedKeyStore(WifiEnterpriseConfig config) {
- String client = config.getClientCertificateAlias();
- if (!TextUtils.isEmpty(client)) {
- // a valid client certificate is configured
-
- // BUGBUG: keyStore.get() never returns certBytes; because it is not
- // taking WIFI_UID as a parameter. It always looks for certificate
- // with SYSTEM_UID, and never finds any Wifi certificates. Assuming that
- // all certificates need software keystore until we get the get() API
- // fixed.
-
- return true;
- }
-
- /*
- try {
-
- if (DBG) Slog.d(TAG, "Loading client certificate " + Credentials
- .USER_CERTIFICATE + client);
-
- CertificateFactory factory = CertificateFactory.getInstance("X.509");
- if (factory == null) {
- Slog.e(TAG, "Error getting certificate factory");
- return;
- }
-
- byte[] certBytes = keyStore.get(Credentials.USER_CERTIFICATE + client);
- if (certBytes != null) {
- Certificate cert = (X509Certificate) factory.generateCertificate(
- new ByteArrayInputStream(certBytes));
-
- if (cert != null) {
- mNeedsSoftwareKeystore = hasHardwareBackedKey(cert);
-
- if (DBG) Slog.d(TAG, "Loaded client certificate " + Credentials
- .USER_CERTIFICATE + client);
- if (DBG) Slog.d(TAG, "It " + (mNeedsSoftwareKeystore ? "needs" :
- "does not need" ) + " software key store");
- } else {
- Slog.d(TAG, "could not generate certificate");
- }
- } else {
- Slog.e(TAG, "Could not load client certificate " + Credentials
- .USER_CERTIFICATE + client);
- mNeedsSoftwareKeystore = true;
- }
-
- } catch(CertificateException e) {
- Slog.e(TAG, "Could not read certificates");
- mCaCert = null;
- mClientCertificate = null;
- }
- */
-
- return false;
- }
-
- boolean installKeys(WifiEnterpriseConfig config, String name) {
- boolean ret = true;
- String privKeyName = Credentials.USER_PRIVATE_KEY + name;
- String userCertName = Credentials.USER_CERTIFICATE + name;
- String caCertName = Credentials.CA_CERTIFICATE + name;
- if (config.getClientCertificate() != null) {
- byte[] privKeyData = config.getClientPrivateKey().getEncoded();
- if (isHardwareBackedKey(config.getClientPrivateKey())) {
- // Hardware backed key store is secure enough to store keys un-encrypted, this
- // removes the need for user to punch a PIN to get access to these keys
- if (DBG) Log.d(TAG, "importing keys " + name + " in hardware backed store");
- ret = mKeyStore.importKey(privKeyName, privKeyData, android.os.Process.WIFI_UID,
- KeyStore.FLAG_NONE);
- } else {
- // Software backed key store is NOT secure enough to store keys un-encrypted.
- // Save keys encrypted so they are protected with user's PIN. User will
- // have to unlock phone before being able to use these keys and connect to
- // networks.
- if (DBG) Log.d(TAG, "importing keys " + name + " in software backed store");
- ret = mKeyStore.importKey(privKeyName, privKeyData, Process.WIFI_UID,
- KeyStore.FLAG_ENCRYPTED);
- }
- if (ret == false) {
- return ret;
- }
-
- ret = putCertInKeyStore(userCertName, config.getClientCertificate());
- if (ret == false) {
- // Remove private key installed
- mKeyStore.delKey(privKeyName, Process.WIFI_UID);
- return ret;
- }
- }
-
- if (config.getCaCertificate() != null) {
- ret = putCertInKeyStore(caCertName, config.getCaCertificate());
- if (ret == false) {
- if (config.getClientCertificate() != null) {
- // Remove client key+cert
- mKeyStore.delKey(privKeyName, Process.WIFI_UID);
- mKeyStore.delete(userCertName, Process.WIFI_UID);
- }
- return ret;
- }
- }
-
- // Set alias names
- if (config.getClientCertificate() != null) {
- config.setClientCertificateAlias(name);
- config.resetClientKeyEntry();
- }
-
- if (config.getCaCertificate() != null) {
- config.setCaCertificateAlias(name);
- config.resetCaCertificate();
- }
-
- return ret;
- }
-
- private boolean putCertInKeyStore(String name, Certificate cert) {
- try {
- byte[] certData = Credentials.convertToPem(cert);
- if (DBG) Log.d(TAG, "putting certificate " + name + " in keystore");
- return mKeyStore.put(name, certData, Process.WIFI_UID, KeyStore.FLAG_NONE);
-
- } catch (IOException e1) {
- return false;
- } catch (CertificateException e2) {
- return false;
- }
- }
-
- void removeKeys(WifiEnterpriseConfig config) {
- String client = config.getClientCertificateAlias();
- // a valid client certificate is configured
- if (!TextUtils.isEmpty(client)) {
- if (DBG) Log.d(TAG, "removing client private key and user cert");
- mKeyStore.delKey(Credentials.USER_PRIVATE_KEY + client, Process.WIFI_UID);
- mKeyStore.delete(Credentials.USER_CERTIFICATE + client, Process.WIFI_UID);
- }
-
- String ca = config.getCaCertificateAlias();
- // a valid ca certificate is configured
- if (!TextUtils.isEmpty(ca)) {
- if (DBG) Log.d(TAG, "removing CA cert");
- mKeyStore.delete(Credentials.CA_CERTIFICATE + ca, Process.WIFI_UID);
- }
- }
-
-
- /** Migrates the old style TLS config to the new config style. This should only be used
- * when restoring an old wpa_supplicant.conf or upgrading from a previous
- * platform version.
- * @return true if the config was updated
- * @hide
- */
- boolean migrateOldEapTlsNative(WifiEnterpriseConfig config, int netId) {
- String oldPrivateKey = mWifiNative.getNetworkVariable(netId, OLD_PRIVATE_KEY_NAME);
- /*
- * If the old configuration value is not present, then there is nothing
- * to do.
- */
- if (TextUtils.isEmpty(oldPrivateKey)) {
- return false;
- } else {
- // Also ignore it if it's empty quotes.
- oldPrivateKey = removeDoubleQuotes(oldPrivateKey);
- if (TextUtils.isEmpty(oldPrivateKey)) {
- return false;
- }
- }
-
- config.setFieldValue(ENGINE_KEY, ENGINE_ENABLE);
- config.setFieldValue(ENGINE_ID_KEY, ENGINE_ID_KEYSTORE);
-
- /*
- * The old key started with the keystore:// URI prefix, but we don't
- * need that anymore. Trim it off if it exists.
- */
- final String keyName;
- if (oldPrivateKey.startsWith(KEYSTORE_URI)) {
- keyName = new String(oldPrivateKey.substring(KEYSTORE_URI.length()));
- } else {
- keyName = oldPrivateKey;
- }
- config.setFieldValue(PRIVATE_KEY_ID_KEY, keyName);
-
- mWifiNative.setNetworkVariable(netId, ENGINE_KEY, config.getFieldValue(ENGINE_KEY, ""));
-
- mWifiNative.setNetworkVariable(netId, ENGINE_ID_KEY,
- config.getFieldValue(ENGINE_ID_KEY, ""));
-
- mWifiNative.setNetworkVariable(netId, PRIVATE_KEY_ID_KEY,
- config.getFieldValue(PRIVATE_KEY_ID_KEY, ""));
-
- // Remove old private_key string so we don't run this again.
- mWifiNative.setNetworkVariable(netId, OLD_PRIVATE_KEY_NAME, EMPTY_VALUE);
-
- return true;
- }
-
- /** Migrate certs from global pool to wifi UID if not already done */
- void migrateCerts(WifiEnterpriseConfig config) {
- String client = config.getClientCertificateAlias();
- // a valid client certificate is configured
- if (!TextUtils.isEmpty(client)) {
- if (!mKeyStore.contains(Credentials.USER_PRIVATE_KEY + client, Process.WIFI_UID)) {
- mKeyStore.duplicate(Credentials.USER_PRIVATE_KEY + client, -1,
- Credentials.USER_PRIVATE_KEY + client, Process.WIFI_UID);
- mKeyStore.duplicate(Credentials.USER_CERTIFICATE + client, -1,
- Credentials.USER_CERTIFICATE + client, Process.WIFI_UID);
- }
- }
-
- String ca = config.getCaCertificateAlias();
- // a valid ca certificate is configured
- if (!TextUtils.isEmpty(ca)) {
- if (!mKeyStore.contains(Credentials.CA_CERTIFICATE + ca, Process.WIFI_UID)) {
- mKeyStore.duplicate(Credentials.CA_CERTIFICATE + ca, -1,
- Credentials.CA_CERTIFICATE + ca, Process.WIFI_UID);
- }
- }
- }
-}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 87afa88..6562462 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -499,7 +499,7 @@ public class WifiConfiguration implements Parcelable {
* @throws IllegalStateException if config is invalid for key id generation
* @hide
*/
- String getKeyIdForCredentials(WifiConfiguration current) {
+ public String getKeyIdForCredentials(WifiConfiguration current) {
String keyMgmt = null;
try {
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 452d84b..69be2cf 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -33,12 +33,67 @@ import java.security.spec.PKCS8EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
-/**
+/**
* Enterprise configuration details for Wi-Fi. Stores details about the EAP method
* and any associated credentials.
*/
public class WifiEnterpriseConfig implements Parcelable {
+ /** @hide */
+ public static final String EMPTY_VALUE = "NULL";
+ /** @hide */
+ public static final String EAP_KEY = "eap";
+ /** @hide */
+ public static final String PHASE2_KEY = "phase2";
+ /** @hide */
+ public static final String IDENTITY_KEY = "identity";
+ /** @hide */
+ public static final String ANON_IDENTITY_KEY = "anonymous_identity";
+ /** @hide */
+ public static final String PASSWORD_KEY = "password";
+ /** @hide */
+ public static final String SUBJECT_MATCH_KEY = "subject_match";
+ /** @hide */
+ public static final String OPP_KEY_CACHING = "proactive_key_caching";
+ /**
+ * String representing the keystore OpenSSL ENGINE's ID.
+ * @hide
+ */
+ public static final String ENGINE_ID_KEYSTORE = "keystore";
+
+ /**
+ * String representing the keystore URI used for wpa_supplicant.
+ * @hide
+ */
+ public static final String KEYSTORE_URI = "keystore://";
+
+ /**
+ * String to set the engine value to when it should be enabled.
+ * @hide
+ */
+ public static final String ENGINE_ENABLE = "1";
+
+ /**
+ * String to set the engine value to when it should be disabled.
+ * @hide
+ */
+ public static final String ENGINE_DISABLE = "0";
+
+ /** @hide */
+ public static final String CA_CERT_PREFIX = KEYSTORE_URI + Credentials.CA_CERTIFICATE;
+ /** @hide */
+ public static final String CLIENT_CERT_PREFIX = KEYSTORE_URI + Credentials.USER_CERTIFICATE;
+ /** @hide */
+ public static final String CLIENT_CERT_KEY = "client_cert";
+ /** @hide */
+ public static final String CA_CERT_KEY = "ca_cert";
+ /** @hide */
+ public static final String ENGINE_KEY = "engine";
+ /** @hide */
+ public static final String ENGINE_ID_KEY = "engine_id";
+ /** @hide */
+ public static final String PRIVATE_KEY_ID_KEY = "key_id";
+
private HashMap<String, String> mFields = new HashMap<String, String>();
private X509Certificate mCaCert;
private PrivateKey mClientPrivateKey;
@@ -189,15 +244,17 @@ public class WifiEnterpriseConfig implements Parcelable {
public static final int GTC = 4;
private static final String PREFIX = "auth=";
/** @hide */
- public static final String[] strings = {WifiConfigStore.EMPTY_VALUE, "PAP", "MSCHAP",
+ public static final String[] strings = {EMPTY_VALUE, "PAP", "MSCHAP",
"MSCHAPV2", "GTC" };
/** Prevent initialization */
private Phase2() {}
}
- /** Internal use only */
- HashMap<String, String> getFields() {
+ /** Internal use only
+ * @hide
+ */
+ public HashMap<String, String> getFields() {
return mFields;
}
@@ -214,8 +271,8 @@ public class WifiEnterpriseConfig implements Parcelable {
case Eap.PWD:
case Eap.TLS:
case Eap.TTLS:
- mFields.put(WifiConfigStore.EAP_KEY, Eap.strings[eapMethod]);
- mFields.put(WifiConfigStore.OPP_KEY_CACHING, "1");
+ mFields.put(EAP_KEY, Eap.strings[eapMethod]);
+ mFields.put(OPP_KEY_CACHING, "1");
break;
default:
throw new IllegalArgumentException("Unknown EAP method");
@@ -227,7 +284,7 @@ public class WifiEnterpriseConfig implements Parcelable {
* @return eap method configured
*/
public int getEapMethod() {
- String eapMethod = mFields.get(WifiConfigStore.EAP_KEY);
+ String eapMethod = mFields.get(EAP_KEY);
return getStringIndex(Eap.strings, eapMethod, Eap.NONE);
}
@@ -243,14 +300,14 @@ public class WifiEnterpriseConfig implements Parcelable {
public void setPhase2Method(int phase2Method) {
switch (phase2Method) {
case Phase2.NONE:
- mFields.put(WifiConfigStore.PHASE2_KEY, WifiConfigStore.EMPTY_VALUE);
+ mFields.put(PHASE2_KEY, EMPTY_VALUE);
break;
/** Valid methods */
case Phase2.PAP:
case Phase2.MSCHAP:
case Phase2.MSCHAPV2:
case Phase2.GTC:
- mFields.put(WifiConfigStore.PHASE2_KEY, convertToQuotedString(
+ mFields.put(PHASE2_KEY, convertToQuotedString(
Phase2.PREFIX + Phase2.strings[phase2Method]));
break;
default:
@@ -263,7 +320,7 @@ public class WifiEnterpriseConfig implements Parcelable {
* @return a phase 2 method defined at {@link Phase2}
* */
public int getPhase2Method() {
- String phase2Method = removeDoubleQuotes(mFields.get(WifiConfigStore.PHASE2_KEY));
+ String phase2Method = removeDoubleQuotes(mFields.get(PHASE2_KEY));
// Remove auth= prefix
if (phase2Method.startsWith(Phase2.PREFIX)) {
phase2Method = phase2Method.substring(Phase2.PREFIX.length());
@@ -276,7 +333,7 @@ public class WifiEnterpriseConfig implements Parcelable {
* @param identity
*/
public void setIdentity(String identity) {
- setFieldValue(WifiConfigStore.IDENTITY_KEY, identity, "");
+ setFieldValue(IDENTITY_KEY, identity, "");
}
/**
@@ -284,7 +341,7 @@ public class WifiEnterpriseConfig implements Parcelable {
* @return the identity
*/
public String getIdentity() {
- return getFieldValue(WifiConfigStore.IDENTITY_KEY, "");
+ return getFieldValue(IDENTITY_KEY, "");
}
/**
@@ -293,14 +350,14 @@ public class WifiEnterpriseConfig implements Parcelable {
* @param anonymousIdentity the anonymous identity
*/
public void setAnonymousIdentity(String anonymousIdentity) {
- setFieldValue(WifiConfigStore.ANON_IDENTITY_KEY, anonymousIdentity, "");
+ setFieldValue(ANON_IDENTITY_KEY, anonymousIdentity, "");
}
/** Get the anonymous identity
* @return anonymous identity
*/
public String getAnonymousIdentity() {
- return getFieldValue(WifiConfigStore.ANON_IDENTITY_KEY, "");
+ return getFieldValue(ANON_IDENTITY_KEY, "");
}
/**
@@ -308,7 +365,7 @@ public class WifiEnterpriseConfig implements Parcelable {
* @param password the password
*/
public void setPassword(String password) {
- setFieldValue(WifiConfigStore.PASSWORD_KEY, password, "");
+ setFieldValue(PASSWORD_KEY, password, "");
}
/**
@@ -318,7 +375,7 @@ public class WifiEnterpriseConfig implements Parcelable {
* framework, returns "*".
*/
public String getPassword() {
- return getFieldValue(WifiConfigStore.PASSWORD_KEY, "");
+ return getFieldValue(PASSWORD_KEY, "");
}
/**
@@ -331,7 +388,7 @@ public class WifiEnterpriseConfig implements Parcelable {
* @hide
*/
public void setCaCertificateAlias(String alias) {
- setFieldValue(WifiConfigStore.CA_CERT_KEY, alias, WifiConfigStore.CA_CERT_PREFIX);
+ setFieldValue(CA_CERT_KEY, alias, CA_CERT_PREFIX);
}
/**
@@ -340,7 +397,7 @@ public class WifiEnterpriseConfig implements Parcelable {
* @hide
*/
public String getCaCertificateAlias() {
- return getFieldValue(WifiConfigStore.CA_CERT_KEY, WifiConfigStore.CA_CERT_PREFIX);
+ return getFieldValue(CA_CERT_KEY, CA_CERT_PREFIX);
}
/**
@@ -381,8 +438,7 @@ public class WifiEnterpriseConfig implements Parcelable {
mCaCert = null;
}
- /**
- * Set Client certificate alias.
+ /** Set Client certificate alias.
*
* <p> See the {@link android.security.KeyChain} for details on installing or choosing
* a certificate
@@ -391,16 +447,15 @@ public class WifiEnterpriseConfig implements Parcelable {
* @hide
*/
public void setClientCertificateAlias(String alias) {
- setFieldValue(WifiConfigStore.CLIENT_CERT_KEY, alias, WifiConfigStore.CLIENT_CERT_PREFIX);
- setFieldValue(WifiConfigStore.PRIVATE_KEY_ID_KEY, alias, Credentials.USER_PRIVATE_KEY);
+ setFieldValue(CLIENT_CERT_KEY, alias, CLIENT_CERT_PREFIX);
+ setFieldValue(PRIVATE_KEY_ID_KEY, alias, Credentials.USER_PRIVATE_KEY);
// Also, set engine parameters
if (TextUtils.isEmpty(alias)) {
- mFields.put(WifiConfigStore.ENGINE_KEY, WifiConfigStore.ENGINE_DISABLE);
- mFields.put(WifiConfigStore.ENGINE_ID_KEY, WifiConfigStore.EMPTY_VALUE);
+ mFields.put(ENGINE_KEY, ENGINE_DISABLE);
+ mFields.put(ENGINE_ID_KEY, EMPTY_VALUE);
} else {
- mFields.put(WifiConfigStore.ENGINE_KEY, WifiConfigStore.ENGINE_ENABLE);
- mFields.put(WifiConfigStore.ENGINE_ID_KEY,
- convertToQuotedString(WifiConfigStore.ENGINE_ID_KEYSTORE));
+ mFields.put(ENGINE_KEY, ENGINE_ENABLE);
+ mFields.put(ENGINE_ID_KEY, convertToQuotedString(ENGINE_ID_KEYSTORE));
}
}
@@ -410,7 +465,7 @@ public class WifiEnterpriseConfig implements Parcelable {
* @hide
*/
public String getClientCertificateAlias() {
- return getFieldValue(WifiConfigStore.CLIENT_CERT_KEY, WifiConfigStore.CLIENT_CERT_PREFIX);
+ return getFieldValue(CLIENT_CERT_KEY, CLIENT_CERT_PREFIX);
}
/**
@@ -472,7 +527,7 @@ public class WifiEnterpriseConfig implements Parcelable {
* @param subjectMatch substring to be matched
*/
public void setSubjectMatch(String subjectMatch) {
- setFieldValue(WifiConfigStore.SUBJECT_MATCH_KEY, subjectMatch, "");
+ setFieldValue(SUBJECT_MATCH_KEY, subjectMatch, "");
}
/**
@@ -480,20 +535,20 @@ public class WifiEnterpriseConfig implements Parcelable {
* @return the subject match string
*/
public String getSubjectMatch() {
- return getFieldValue(WifiConfigStore.SUBJECT_MATCH_KEY, "");
+ return getFieldValue(SUBJECT_MATCH_KEY, "");
}
/** See {@link WifiConfiguration#getKeyIdForCredentials} @hide */
String getKeyId(WifiEnterpriseConfig current) {
- String eap = mFields.get(WifiConfigStore.EAP_KEY);
- String phase2 = mFields.get(WifiConfigStore.PHASE2_KEY);
+ String eap = mFields.get(EAP_KEY);
+ String phase2 = mFields.get(PHASE2_KEY);
// If either eap or phase2 are not initialized, use current config details
if (TextUtils.isEmpty((eap))) {
- eap = current.mFields.get(WifiConfigStore.EAP_KEY);
+ eap = current.mFields.get(EAP_KEY);
}
if (TextUtils.isEmpty(phase2)) {
- phase2 = current.mFields.get(WifiConfigStore.PHASE2_KEY);
+ phase2 = current.mFields.get(PHASE2_KEY);
}
return eap + "_" + phase2;
}
@@ -532,10 +587,10 @@ public class WifiEnterpriseConfig implements Parcelable {
* @return value
* @hide
*/
- String getFieldValue(String key, String prefix) {
+ public String getFieldValue(String key, String prefix) {
String value = mFields.get(key);
// Uninitialized or known to be empty after reading from supplicant
- if (TextUtils.isEmpty(value) || WifiConfigStore.EMPTY_VALUE.equals(value)) return "";
+ if (TextUtils.isEmpty(value) || EMPTY_VALUE.equals(value)) return "";
value = removeDoubleQuotes(value);
if (value.startsWith(prefix)) {
@@ -549,10 +604,11 @@ public class WifiEnterpriseConfig implements Parcelable {
* @param key into the hash
* @param value to be set
* @param prefix an optional value to be prefixed to actual value
+ * @hide
*/
- private void setFieldValue(String key, String value, String prefix) {
+ public void setFieldValue(String key, String value, String prefix) {
if (TextUtils.isEmpty(value)) {
- mFields.put(key, WifiConfigStore.EMPTY_VALUE);
+ mFields.put(key, EMPTY_VALUE);
} else {
mFields.put(key, convertToQuotedString(prefix + value));
}
@@ -567,7 +623,7 @@ public class WifiEnterpriseConfig implements Parcelable {
*/
public void setFieldValue(String key, String value) {
if (TextUtils.isEmpty(value)) {
- mFields.put(key, WifiConfigStore.EMPTY_VALUE);
+ mFields.put(key, EMPTY_VALUE);
} else {
mFields.put(key, convertToQuotedString(value));
}
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index dea0c6c..6a13067 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -78,7 +78,8 @@ public class WifiInfo implements Parcelable {
*/
private boolean mMeteredHint;
- WifiInfo() {
+ /** @hide */
+ public WifiInfo() {
mWifiSsid = null;
mBSSID = null;
mNetworkId = -1;
@@ -105,7 +106,8 @@ public class WifiInfo implements Parcelable {
}
}
- void setSSID(WifiSsid wifiSsid) {
+ /** @hide */
+ public void setSSID(WifiSsid wifiSsid) {
mWifiSsid = wifiSsid;
}
@@ -133,7 +135,8 @@ public class WifiInfo implements Parcelable {
return mWifiSsid;
}
- void setBSSID(String BSSID) {
+ /** @hide */
+ public void setBSSID(String BSSID) {
mBSSID = BSSID;
}
@@ -156,7 +159,8 @@ public class WifiInfo implements Parcelable {
return mRssi;
}
- void setRssi(int rssi) {
+ /** @hide */
+ public void setRssi(int rssi) {
mRssi = rssi;
}
@@ -169,15 +173,17 @@ public class WifiInfo implements Parcelable {
return mLinkSpeed;
}
- void setLinkSpeed(int linkSpeed) {
+ /** @hide */
+ public void setLinkSpeed(int linkSpeed) {
this.mLinkSpeed = linkSpeed;
}
/**
* Record the MAC address of the WLAN interface
* @param macAddress the MAC address in {@code XX:XX:XX:XX:XX:XX} form
+ * @hide
*/
- void setMacAddress(String macAddress) {
+ public void setMacAddress(String macAddress) {
this.mMacAddress = macAddress;
}
@@ -195,7 +201,8 @@ public class WifiInfo implements Parcelable {
return mMeteredHint;
}
- void setNetworkId(int id) {
+ /** @hide */
+ public void setNetworkId(int id) {
mNetworkId = id;
}
@@ -218,11 +225,13 @@ public class WifiInfo implements Parcelable {
return mSupplicantState;
}
- void setSupplicantState(SupplicantState state) {
+ /** @hide */
+ public void setSupplicantState(SupplicantState state) {
mSupplicantState = state;
}
- void setInetAddress(InetAddress address) {
+ /** @hide */
+ public void setInetAddress(InetAddress address) {
mIpAddress = address;
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index ae1fbf7..aabe007 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -522,6 +522,9 @@ public class WifiManager {
/** @hide */
public static final int DATA_ACTIVITY_INOUT = 0x03;
+ /** @hide */
+ public static final boolean DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED = false;
+
/* Maximum number of active locks we allow.
* This limit was added to prevent apps from creating a ridiculous number
* of locks and crashing the system by overflowing the global ref table.
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
deleted file mode 100644
index a18954c..0000000
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ /dev/null
@@ -1,936 +0,0 @@
-/*
- * Copyright (C) 2008 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.wifi;
-
-import android.net.NetworkInfo;
-import android.net.wifi.p2p.WifiP2pConfig;
-import android.net.wifi.p2p.WifiP2pDevice;
-import android.net.wifi.p2p.WifiP2pGroup;
-import android.net.wifi.p2p.WifiP2pProvDiscEvent;
-import android.net.wifi.p2p.WifiP2pService.P2pStatus;
-import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
-import android.os.Message;
-import android.util.Log;
-
-import com.android.internal.util.Protocol;
-import com.android.internal.util.StateMachine;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Listens for events from the wpa_supplicant server, and passes them on
- * to the {@link StateMachine} for handling. Runs in its own thread.
- *
- * @hide
- */
-public class WifiMonitor {
-
- private static final boolean DBG = false;
- private static final String TAG = "WifiMonitor";
-
- /** Events we receive from the supplicant daemon */
-
- private static final int CONNECTED = 1;
- private static final int DISCONNECTED = 2;
- private static final int STATE_CHANGE = 3;
- private static final int SCAN_RESULTS = 4;
- private static final int LINK_SPEED = 5;
- private static final int TERMINATING = 6;
- private static final int DRIVER_STATE = 7;
- private static final int EAP_FAILURE = 8;
- private static final int ASSOC_REJECT = 9;
- private static final int UNKNOWN = 10;
-
- /** All events coming from the supplicant start with this prefix */
- private static final String EVENT_PREFIX_STR = "CTRL-EVENT-";
- private static final int EVENT_PREFIX_LEN_STR = EVENT_PREFIX_STR.length();
-
- /** All WPA events coming from the supplicant start with this prefix */
- private static final String WPA_EVENT_PREFIX_STR = "WPA:";
- private static final String PASSWORD_MAY_BE_INCORRECT_STR =
- "pre-shared key may be incorrect";
-
- /* WPS events */
- private static final String WPS_SUCCESS_STR = "WPS-SUCCESS";
-
- /* Format: WPS-FAIL msg=%d [config_error=%d] [reason=%d (%s)] */
- private static final String WPS_FAIL_STR = "WPS-FAIL";
- private static final String WPS_FAIL_PATTERN =
- "WPS-FAIL msg=\\d+(?: config_error=(\\d+))?(?: reason=(\\d+))?";
-
- /* config error code values for config_error=%d */
- private static final int CONFIG_MULTIPLE_PBC_DETECTED = 12;
- private static final int CONFIG_AUTH_FAILURE = 18;
-
- /* reason code values for reason=%d */
- private static final int REASON_TKIP_ONLY_PROHIBITED = 1;
- private static final int REASON_WEP_PROHIBITED = 2;
-
- private static final String WPS_OVERLAP_STR = "WPS-OVERLAP-DETECTED";
- private static final String WPS_TIMEOUT_STR = "WPS-TIMEOUT";
-
- /**
- * Names of events from wpa_supplicant (minus the prefix). In the
- * format descriptions, * &quot;<code>x</code>&quot;
- * designates a dynamic value that needs to be parsed out from the event
- * string
- */
- /**
- * <pre>
- * CTRL-EVENT-CONNECTED - Connection to xx:xx:xx:xx:xx:xx completed
- * </pre>
- * <code>xx:xx:xx:xx:xx:xx</code> is the BSSID of the associated access point
- */
- private static final String CONNECTED_STR = "CONNECTED";
- /**
- * <pre>
- * CTRL-EVENT-DISCONNECTED - Disconnect event - remove keys
- * </pre>
- */
- private static final String DISCONNECTED_STR = "DISCONNECTED";
- /**
- * <pre>
- * CTRL-EVENT-STATE-CHANGE x
- * </pre>
- * <code>x</code> is the numerical value of the new state.
- */
- private static final String STATE_CHANGE_STR = "STATE-CHANGE";
- /**
- * <pre>
- * CTRL-EVENT-SCAN-RESULTS ready
- * </pre>
- */
- private static final String SCAN_RESULTS_STR = "SCAN-RESULTS";
-
- /**
- * <pre>
- * CTRL-EVENT-LINK-SPEED x Mb/s
- * </pre>
- * {@code x} is the link speed in Mb/sec.
- */
- private static final String LINK_SPEED_STR = "LINK-SPEED";
- /**
- * <pre>
- * CTRL-EVENT-TERMINATING - signal x
- * </pre>
- * <code>x</code> is the signal that caused termination.
- */
- private static final String TERMINATING_STR = "TERMINATING";
- /**
- * <pre>
- * CTRL-EVENT-DRIVER-STATE state
- * </pre>
- * <code>state</code> can be HANGED
- */
- private static final String DRIVER_STATE_STR = "DRIVER-STATE";
- /**
- * <pre>
- * CTRL-EVENT-EAP-FAILURE EAP authentication failed
- * </pre>
- */
- private static final String EAP_FAILURE_STR = "EAP-FAILURE";
-
- /**
- * This indicates an authentication failure on EAP FAILURE event
- */
- private static final String EAP_AUTH_FAILURE_STR = "EAP authentication failed";
-
- /**
- * This indicates an assoc reject event
- */
- private static final String ASSOC_REJECT_STR = "ASSOC-REJECT";
-
- /**
- * Regex pattern for extracting an Ethernet-style MAC address from a string.
- * Matches a strings like the following:<pre>
- * CTRL-EVENT-CONNECTED - Connection to 00:1e:58:ec:d5:6d completed (reauth) [id=1 id_str=]</pre>
- */
- private static Pattern mConnectedEventPattern =
- Pattern.compile("((?:[0-9a-f]{2}:){5}[0-9a-f]{2}) .* \\[id=([0-9]+) ");
-
- /** P2P events */
- private static final String P2P_EVENT_PREFIX_STR = "P2P";
-
- /* P2P-DEVICE-FOUND fa:7b:7a:42:02:13 p2p_dev_addr=fa:7b:7a:42:02:13 pri_dev_type=1-0050F204-1
- name='p2p-TEST1' config_methods=0x188 dev_capab=0x27 group_capab=0x0 */
- private static final String P2P_DEVICE_FOUND_STR = "P2P-DEVICE-FOUND";
-
- /* P2P-DEVICE-LOST p2p_dev_addr=42:fc:89:e1:e2:27 */
- private static final String P2P_DEVICE_LOST_STR = "P2P-DEVICE-LOST";
-
- /* P2P-FIND-STOPPED */
- private static final String P2P_FIND_STOPPED_STR = "P2P-FIND-STOPPED";
-
- /* P2P-GO-NEG-REQUEST 42:fc:89:a8:96:09 dev_passwd_id=4 */
- private static final String P2P_GO_NEG_REQUEST_STR = "P2P-GO-NEG-REQUEST";
-
- private static final String P2P_GO_NEG_SUCCESS_STR = "P2P-GO-NEG-SUCCESS";
-
- /* P2P-GO-NEG-FAILURE status=x */
- private static final String P2P_GO_NEG_FAILURE_STR = "P2P-GO-NEG-FAILURE";
-
- private static final String P2P_GROUP_FORMATION_SUCCESS_STR =
- "P2P-GROUP-FORMATION-SUCCESS";
-
- private static final String P2P_GROUP_FORMATION_FAILURE_STR =
- "P2P-GROUP-FORMATION-FAILURE";
-
- /* P2P-GROUP-STARTED p2p-wlan0-0 [client|GO] ssid="DIRECT-W8" freq=2437
- [psk=2182b2e50e53f260d04f3c7b25ef33c965a3291b9b36b455a82d77fd82ca15bc|passphrase="fKG4jMe3"]
- go_dev_addr=fa:7b:7a:42:02:13 [PERSISTENT] */
- private static final String P2P_GROUP_STARTED_STR = "P2P-GROUP-STARTED";
-
- /* P2P-GROUP-REMOVED p2p-wlan0-0 [client|GO] reason=REQUESTED */
- private static final String P2P_GROUP_REMOVED_STR = "P2P-GROUP-REMOVED";
-
- /* P2P-INVITATION-RECEIVED sa=fa:7b:7a:42:02:13 go_dev_addr=f8:7b:7a:42:02:13
- bssid=fa:7b:7a:42:82:13 unknown-network */
- private static final String P2P_INVITATION_RECEIVED_STR = "P2P-INVITATION-RECEIVED";
-
- /* P2P-INVITATION-RESULT status=1 */
- private static final String P2P_INVITATION_RESULT_STR = "P2P-INVITATION-RESULT";
-
- /* P2P-PROV-DISC-PBC-REQ 42:fc:89:e1:e2:27 p2p_dev_addr=42:fc:89:e1:e2:27
- pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27
- group_capab=0x0 */
- private static final String P2P_PROV_DISC_PBC_REQ_STR = "P2P-PROV-DISC-PBC-REQ";
-
- /* P2P-PROV-DISC-PBC-RESP 02:12:47:f2:5a:36 */
- private static final String P2P_PROV_DISC_PBC_RSP_STR = "P2P-PROV-DISC-PBC-RESP";
-
- /* P2P-PROV-DISC-ENTER-PIN 42:fc:89:e1:e2:27 p2p_dev_addr=42:fc:89:e1:e2:27
- pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27
- group_capab=0x0 */
- private static final String P2P_PROV_DISC_ENTER_PIN_STR = "P2P-PROV-DISC-ENTER-PIN";
- /* P2P-PROV-DISC-SHOW-PIN 42:fc:89:e1:e2:27 44490607 p2p_dev_addr=42:fc:89:e1:e2:27
- pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27
- group_capab=0x0 */
- private static final String P2P_PROV_DISC_SHOW_PIN_STR = "P2P-PROV-DISC-SHOW-PIN";
- /* P2P-PROV-DISC-FAILURE p2p_dev_addr=42:fc:89:e1:e2:27 */
- private static final String P2P_PROV_DISC_FAILURE_STR = "P2P-PROV-DISC-FAILURE";
-
- /*
- * Protocol format is as follows.<br>
- * See the Table.62 in the WiFi Direct specification for the detail.
- * ______________________________________________________________
- * | Length(2byte) | Type(1byte) | TransId(1byte)}|
- * ______________________________________________________________
- * | status(1byte) | vendor specific(variable) |
- *
- * P2P-SERV-DISC-RESP 42:fc:89:e1:e2:27 1 0300000101
- * length=3, service type=0(ALL Service), transaction id=1,
- * status=1(service protocol type not available)<br>
- *
- * P2P-SERV-DISC-RESP 42:fc:89:e1:e2:27 1 0300020201
- * length=3, service type=2(UPnP), transaction id=2,
- * status=1(service protocol type not available)
- *
- * P2P-SERV-DISC-RESP 42:fc:89:e1:e2:27 1 990002030010757569643a3131323
- * 2646534652d383537342d353961622d393332322d3333333435363738393034343a3
- * a75726e3a736368656d61732d75706e702d6f72673a736572766963653a436f6e746
- * 56e744469726563746f72793a322c757569643a36383539646564652d383537342d3
- * 53961622d393333322d3132333435363738393031323a3a75706e703a726f6f74646
- * 576696365
- * length=153,type=2(UPnP),transaction id=3,status=0
- *
- * UPnP Protocol format is as follows.
- * ______________________________________________________
- * | Version (1) | USN (Variable) |
- *
- * version=0x10(UPnP1.0) data=usn:uuid:1122de4e-8574-59ab-9322-33345678
- * 9044::urn:schemas-upnp-org:service:ContentDirectory:2,usn:uuid:6859d
- * ede-8574-59ab-9332-123456789012::upnp:rootdevice
- *
- * P2P-SERV-DISC-RESP 58:17:0c:bc:dd:ca 21 1900010200045f6970
- * 70c00c000c01094d795072696e746572c027
- * length=25, type=1(Bonjour),transaction id=2,status=0
- *
- * Bonjour Protocol format is as follows.
- * __________________________________________________________
- * |DNS Name(Variable)|DNS Type(1)|Version(1)|RDATA(Variable)|
- *
- * DNS Name=_ipp._tcp.local.,DNS type=12(PTR), Version=1,
- * RDATA=MyPrinter._ipp._tcp.local.
- *
- */
- private static final String P2P_SERV_DISC_RESP_STR = "P2P-SERV-DISC-RESP";
-
- 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";
- /* AP-STA-DISCONNECTED 42:fc:89:a8:96:09 */
- private static final String AP_STA_DISCONNECTED_STR = "AP-STA-DISCONNECTED";
-
- /* Supplicant events reported to a state machine */
- private static final int BASE = Protocol.BASE_WIFI_MONITOR;
-
- /* Connection to supplicant established */
- public static final int SUP_CONNECTION_EVENT = BASE + 1;
- /* Connection to supplicant lost */
- public static final int SUP_DISCONNECTION_EVENT = BASE + 2;
- /* Network connection completed */
- public static final int NETWORK_CONNECTION_EVENT = BASE + 3;
- /* Network disconnection completed */
- public static final int NETWORK_DISCONNECTION_EVENT = BASE + 4;
- /* Scan results are available */
- public static final int SCAN_RESULTS_EVENT = BASE + 5;
- /* Supplicate state changed */
- public static final int SUPPLICANT_STATE_CHANGE_EVENT = BASE + 6;
- /* Password failure and EAP authentication failure */
- public static final int AUTHENTICATION_FAILURE_EVENT = BASE + 7;
- /* WPS success detected */
- public static final int WPS_SUCCESS_EVENT = BASE + 8;
- /* WPS failure detected */
- public static final int WPS_FAIL_EVENT = BASE + 9;
- /* WPS overlap detected */
- public static final int WPS_OVERLAP_EVENT = BASE + 10;
- /* WPS timeout detected */
- public static final int WPS_TIMEOUT_EVENT = BASE + 11;
- /* Driver was hung */
- public static final int DRIVER_HUNG_EVENT = BASE + 12;
-
- /* P2P events */
- public static final int P2P_DEVICE_FOUND_EVENT = BASE + 21;
- public static final int P2P_DEVICE_LOST_EVENT = BASE + 22;
- public static final int P2P_GO_NEGOTIATION_REQUEST_EVENT = BASE + 23;
- public static final int P2P_GO_NEGOTIATION_SUCCESS_EVENT = BASE + 25;
- public static final int P2P_GO_NEGOTIATION_FAILURE_EVENT = BASE + 26;
- public static final int P2P_GROUP_FORMATION_SUCCESS_EVENT = BASE + 27;
- public static final int P2P_GROUP_FORMATION_FAILURE_EVENT = BASE + 28;
- public static final int P2P_GROUP_STARTED_EVENT = BASE + 29;
- public static final int P2P_GROUP_REMOVED_EVENT = BASE + 30;
- public static final int P2P_INVITATION_RECEIVED_EVENT = BASE + 31;
- public static final int P2P_INVITATION_RESULT_EVENT = BASE + 32;
- public static final int P2P_PROV_DISC_PBC_REQ_EVENT = BASE + 33;
- public static final int P2P_PROV_DISC_PBC_RSP_EVENT = BASE + 34;
- public static final int P2P_PROV_DISC_ENTER_PIN_EVENT = BASE + 35;
- public static final int P2P_PROV_DISC_SHOW_PIN_EVENT = BASE + 36;
- 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;
-
- /* hostap events */
- public static final int AP_STA_DISCONNECTED_EVENT = BASE + 41;
- public static final int AP_STA_CONNECTED_EVENT = BASE + 42;
-
- /* Indicates assoc reject event */
- public static final int ASSOCIATION_REJECTION_EVENT = BASE + 43;
-
- /**
- * This indicates a read error on the monitor socket conenction
- */
- private static final String WPA_RECV_ERROR_STR = "recv error";
-
- /**
- * Max errors before we close supplicant connection
- */
- private static final int MAX_RECV_ERRORS = 10;
-
- private final String mInterfaceName;
- private final WifiNative mWifiNative;
- private final StateMachine mStateMachine;
- private boolean mMonitoring;
-
- // This is a global counter, since it's not monitor specific. However, the existing
- // implementation forwards all "global" control events like CTRL-EVENT-TERMINATING
- // to the p2p0 monitor. Is that expected ? It seems a bit surprising.
- //
- // TODO: If the p2p0 monitor isn't registered, the behaviour is even more surprising.
- // The event will be dispatched to all monitors, and each of them will end up incrementing
- // it in their dispatchXXX method. If we have 5 registered monitors (say), 2 consecutive
- // recv errors will cause us to disconnect from the supplicant (instead of the intended 10).
- //
- // This variable is always accessed and modified under a WifiMonitorSingleton lock.
- private static int sRecvErrors;
-
- public WifiMonitor(StateMachine wifiStateMachine, WifiNative wifiNative) {
- if (DBG) Log.d(TAG, "Creating WifiMonitor");
- mWifiNative = wifiNative;
- mInterfaceName = wifiNative.mInterfaceName;
- mStateMachine = wifiStateMachine;
- mMonitoring = false;
-
- WifiMonitorSingleton.sInstance.registerInterfaceMonitor(mInterfaceName, this);
- }
-
- public void startMonitoring() {
- WifiMonitorSingleton.sInstance.startMonitoring(mInterfaceName);
- }
-
- public void stopMonitoring() {
- WifiMonitorSingleton.sInstance.stopMonitoring(mInterfaceName);
- }
-
- public void stopSupplicant() {
- WifiMonitorSingleton.sInstance.stopSupplicant();
- }
-
- public void killSupplicant(boolean p2pSupported) {
- WifiMonitorSingleton.sInstance.killSupplicant(p2pSupported);
- }
-
- private static class WifiMonitorSingleton {
- private static final WifiMonitorSingleton sInstance = new WifiMonitorSingleton();
-
- private final HashMap<String, WifiMonitor> mIfaceMap = new HashMap<String, WifiMonitor>();
- private boolean mConnected = false;
- private WifiNative mWifiNative;
-
- private WifiMonitorSingleton() {
- }
-
- public synchronized void startMonitoring(String iface) {
- WifiMonitor m = mIfaceMap.get(iface);
- if (m == null) {
- Log.e(TAG, "startMonitor called with unknown iface=" + iface);
- return;
- }
-
- Log.d(TAG, "startMonitoring(" + iface + ") with mConnected = " + mConnected);
-
- if (mConnected) {
- m.mMonitoring = true;
- m.mStateMachine.sendMessage(SUP_CONNECTION_EVENT);
- } else {
- if (DBG) Log.d(TAG, "connecting to supplicant");
- int connectTries = 0;
- while (true) {
- if (mWifiNative.connectToSupplicant()) {
- m.mMonitoring = true;
- m.mStateMachine.sendMessage(SUP_CONNECTION_EVENT);
- new MonitorThread(mWifiNative, this).start();
- mConnected = true;
- break;
- }
- if (connectTries++ < 5) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException ignore) {
- }
- } else {
- mIfaceMap.remove(iface);
- m.mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
- Log.e(TAG, "startMonitoring(" + iface + ") failed!");
- break;
- }
- }
- }
- }
-
- public synchronized void stopMonitoring(String iface) {
- WifiMonitor m = mIfaceMap.get(iface);
- if (DBG) Log.d(TAG, "stopMonitoring(" + iface + ") = " + m.mStateMachine);
- m.mMonitoring = false;
- m.mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
- }
-
- public synchronized void registerInterfaceMonitor(String iface, WifiMonitor m) {
- if (DBG) Log.d(TAG, "registerInterface(" + iface + "+" + m.mStateMachine + ")");
- mIfaceMap.put(iface, m);
- if (mWifiNative == null) {
- mWifiNative = m.mWifiNative;
- }
- }
-
- public synchronized void unregisterInterfaceMonitor(String iface) {
- // REVIEW: When should we call this? If this isn't called, then WifiMonitor
- // objects will remain in the mIfaceMap; and won't ever get deleted
-
- WifiMonitor m = mIfaceMap.remove(iface);
- if (DBG) Log.d(TAG, "unregisterInterface(" + iface + "+" + m.mStateMachine + ")");
- }
-
- public synchronized void stopSupplicant() {
- mWifiNative.stopSupplicant();
- }
-
- public synchronized void killSupplicant(boolean p2pSupported) {
- WifiNative.killSupplicant(p2pSupported);
- mConnected = false;
- for (WifiMonitor m : mIfaceMap.values()) {
- m.mMonitoring = false;
- }
- }
-
- private synchronized boolean dispatchEvent(String eventStr) {
- String iface;
- if (eventStr.startsWith("IFNAME=")) {
- int space = eventStr.indexOf(' ');
- if (space != -1) {
- iface = eventStr.substring(7, space);
- 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
- // for it explicitly, and send messages there ..
- iface = "p2p0";
- }
- eventStr = eventStr.substring(space + 1);
- } else {
- // No point dispatching this event to any interface, the dispatched
- // event string will begin with "IFNAME=" which dispatchEvent can't really
- // do anything about.
- Log.e(TAG, "Dropping malformed event (unparsable iface): " + eventStr);
- return false;
- }
- } else {
- // events without prefix belong to p2p0 monitor
- iface = "p2p0";
- }
-
- if (DBG) Log.d(TAG, "Dispatching event to interface: " + iface);
-
- WifiMonitor m = mIfaceMap.get(iface);
- if (m != null) {
- if (m.mMonitoring) {
- if (m.dispatchEvent(eventStr)) {
- mConnected = false;
- return true;
- }
-
- return false;
- } else {
- if (DBG) Log.d(TAG, "Dropping event because (" + iface + ") is stopped");
- return false;
- }
- } else {
- if (DBG) Log.d(TAG, "Sending to all monitors because there's no matching iface");
- boolean done = false;
- for (WifiMonitor monitor : mIfaceMap.values()) {
- if (monitor.mMonitoring && monitor.dispatchEvent(eventStr)) {
- done = true;
- }
- }
-
- if (done) {
- mConnected = false;
- }
-
- return done;
- }
- }
- }
-
- private static class MonitorThread extends Thread {
- private final WifiNative mWifiNative;
- private final WifiMonitorSingleton mWifiMonitorSingleton;
-
- public MonitorThread(WifiNative wifiNative, WifiMonitorSingleton wifiMonitorSingleton) {
- super("WifiMonitor");
- mWifiNative = wifiNative;
- mWifiMonitorSingleton = wifiMonitorSingleton;
- }
-
- public void run() {
- //noinspection InfiniteLoopStatement
- for (;;) {
- String eventStr = mWifiNative.waitForEvent();
-
- // Skip logging the common but mostly uninteresting scan-results event
- if (DBG && eventStr.indexOf(SCAN_RESULTS_STR) == -1) {
- Log.d(TAG, "Event [" + eventStr + "]");
- }
-
- if (mWifiMonitorSingleton.dispatchEvent(eventStr)) {
- if (DBG) Log.d(TAG, "Disconnecting from the supplicant, no more events");
- break;
- }
- }
- }
- }
-
- /* @return true if the event was supplicant disconnection */
- private boolean dispatchEvent(String eventStr) {
-
- if (!eventStr.startsWith(EVENT_PREFIX_STR)) {
- if (eventStr.startsWith(WPA_EVENT_PREFIX_STR) &&
- 0 < eventStr.indexOf(PASSWORD_MAY_BE_INCORRECT_STR)) {
- mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
- } else if (eventStr.startsWith(WPS_SUCCESS_STR)) {
- mStateMachine.sendMessage(WPS_SUCCESS_EVENT);
- } else if (eventStr.startsWith(WPS_FAIL_STR)) {
- handleWpsFailEvent(eventStr);
- } else if (eventStr.startsWith(WPS_OVERLAP_STR)) {
- mStateMachine.sendMessage(WPS_OVERLAP_EVENT);
- } else if (eventStr.startsWith(WPS_TIMEOUT_STR)) {
- mStateMachine.sendMessage(WPS_TIMEOUT_EVENT);
- } else if (eventStr.startsWith(P2P_EVENT_PREFIX_STR)) {
- handleP2pEvents(eventStr);
- } else if (eventStr.startsWith(HOST_AP_EVENT_PREFIX_STR)) {
- handleHostApEvents(eventStr);
- }
- else {
- if (DBG) Log.w(TAG, "couldn't identify event type - " + eventStr);
- }
- return false;
- }
-
- String eventName = eventStr.substring(EVENT_PREFIX_LEN_STR);
- int nameEnd = eventName.indexOf(' ');
- if (nameEnd != -1)
- eventName = eventName.substring(0, nameEnd);
- if (eventName.length() == 0) {
- if (DBG) Log.i(TAG, "Received wpa_supplicant event with empty event name");
- return false;
- }
- /*
- * Map event name into event enum
- */
- int event;
- if (eventName.equals(CONNECTED_STR))
- event = CONNECTED;
- else if (eventName.equals(DISCONNECTED_STR))
- event = DISCONNECTED;
- else if (eventName.equals(STATE_CHANGE_STR))
- event = STATE_CHANGE;
- else if (eventName.equals(SCAN_RESULTS_STR))
- event = SCAN_RESULTS;
- else if (eventName.equals(LINK_SPEED_STR))
- event = LINK_SPEED;
- else if (eventName.equals(TERMINATING_STR))
- event = TERMINATING;
- else if (eventName.equals(DRIVER_STATE_STR))
- event = DRIVER_STATE;
- else if (eventName.equals(EAP_FAILURE_STR))
- event = EAP_FAILURE;
- else if (eventName.equals(ASSOC_REJECT_STR))
- event = ASSOC_REJECT;
- else
- event = UNKNOWN;
-
- String eventData = eventStr;
- if (event == DRIVER_STATE || event == LINK_SPEED)
- eventData = eventData.split(" ")[1];
- else if (event == STATE_CHANGE || event == EAP_FAILURE) {
- int ind = eventStr.indexOf(" ");
- if (ind != -1) {
- eventData = eventStr.substring(ind + 1);
- }
- } else {
- int ind = eventStr.indexOf(" - ");
- if (ind != -1) {
- eventData = eventStr.substring(ind + 3);
- }
- }
-
- if (event == STATE_CHANGE) {
- handleSupplicantStateChange(eventData);
- } else if (event == DRIVER_STATE) {
- handleDriverEvent(eventData);
- } else if (event == TERMINATING) {
- /**
- * Close the supplicant connection if we see
- * too many recv errors
- */
- if (eventData.startsWith(WPA_RECV_ERROR_STR)) {
- if (++sRecvErrors > MAX_RECV_ERRORS) {
- if (DBG) {
- Log.d(TAG, "too many recv errors, closing connection");
- }
- } else {
- return false;
- }
- }
-
- // notify and exit
- mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
- return true;
- } else if (event == EAP_FAILURE) {
- if (eventData.startsWith(EAP_AUTH_FAILURE_STR)) {
- mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
- }
- } else if (event == ASSOC_REJECT) {
- mStateMachine.sendMessage(ASSOCIATION_REJECTION_EVENT);
- } else {
- handleEvent(event, eventData);
- }
- sRecvErrors = 0;
- return false;
- }
-
- private void handleDriverEvent(String state) {
- if (state == null) {
- return;
- }
- if (state.equals("HANGED")) {
- mStateMachine.sendMessage(DRIVER_HUNG_EVENT);
- }
- }
-
- /**
- * Handle all supplicant events except STATE-CHANGE
- * @param event the event type
- * @param remainder the rest of the string following the
- * event name and &quot;&#8195;&#8212;&#8195;&quot;
- */
- void handleEvent(int event, String remainder) {
- switch (event) {
- case DISCONNECTED:
- handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED, remainder);
- break;
-
- case CONNECTED:
- handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED, remainder);
- break;
-
- case SCAN_RESULTS:
- mStateMachine.sendMessage(SCAN_RESULTS_EVENT);
- break;
-
- case UNKNOWN:
- break;
- }
- }
-
- private void handleWpsFailEvent(String dataString) {
- final Pattern p = Pattern.compile(WPS_FAIL_PATTERN);
- Matcher match = p.matcher(dataString);
- if (match.find()) {
- String cfgErr = match.group(1);
- String reason = match.group(2);
-
- if (reason != null) {
- switch(Integer.parseInt(reason)) {
- case REASON_TKIP_ONLY_PROHIBITED:
- mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
- WifiManager.WPS_TKIP_ONLY_PROHIBITED, 0));
- return;
- case REASON_WEP_PROHIBITED:
- mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
- WifiManager.WPS_WEP_PROHIBITED, 0));
- return;
- }
- }
- if (cfgErr != null) {
- switch(Integer.parseInt(cfgErr)) {
- case CONFIG_AUTH_FAILURE:
- mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
- WifiManager.WPS_AUTH_FAILURE, 0));
- return;
- case CONFIG_MULTIPLE_PBC_DETECTED:
- mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
- WifiManager.WPS_OVERLAP_ERROR, 0));
- return;
- }
- }
- }
- //For all other errors, return a generic internal error
- mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
- WifiManager.ERROR, 0));
- }
-
- /* <event> status=<err> and the special case of <event> reason=FREQ_CONFLICT */
- private P2pStatus p2pError(String dataString) {
- P2pStatus err = P2pStatus.UNKNOWN;
- String[] tokens = dataString.split(" ");
- if (tokens.length < 2) return err;
- String[] nameValue = tokens[1].split("=");
- if (nameValue.length != 2) return err;
-
- /* Handle the special case of reason=FREQ+CONFLICT */
- if (nameValue[1].equals("FREQ_CONFLICT")) {
- return P2pStatus.NO_COMMON_CHANNEL;
- }
- try {
- err = P2pStatus.valueOf(Integer.parseInt(nameValue[1]));
- } catch (NumberFormatException e) {
- e.printStackTrace();
- }
- return err;
- }
-
- /**
- * Handle p2p events
- */
- private void handleP2pEvents(String dataString) {
- if (dataString.startsWith(P2P_DEVICE_FOUND_STR)) {
- mStateMachine.sendMessage(P2P_DEVICE_FOUND_EVENT, new WifiP2pDevice(dataString));
- } else if (dataString.startsWith(P2P_DEVICE_LOST_STR)) {
- mStateMachine.sendMessage(P2P_DEVICE_LOST_EVENT, new WifiP2pDevice(dataString));
- } else if (dataString.startsWith(P2P_FIND_STOPPED_STR)) {
- mStateMachine.sendMessage(P2P_FIND_STOPPED_EVENT);
- } else if (dataString.startsWith(P2P_GO_NEG_REQUEST_STR)) {
- mStateMachine.sendMessage(P2P_GO_NEGOTIATION_REQUEST_EVENT,
- new WifiP2pConfig(dataString));
- } else if (dataString.startsWith(P2P_GO_NEG_SUCCESS_STR)) {
- mStateMachine.sendMessage(P2P_GO_NEGOTIATION_SUCCESS_EVENT);
- } else if (dataString.startsWith(P2P_GO_NEG_FAILURE_STR)) {
- mStateMachine.sendMessage(P2P_GO_NEGOTIATION_FAILURE_EVENT, p2pError(dataString));
- } else if (dataString.startsWith(P2P_GROUP_FORMATION_SUCCESS_STR)) {
- mStateMachine.sendMessage(P2P_GROUP_FORMATION_SUCCESS_EVENT);
- } else if (dataString.startsWith(P2P_GROUP_FORMATION_FAILURE_STR)) {
- mStateMachine.sendMessage(P2P_GROUP_FORMATION_FAILURE_EVENT, p2pError(dataString));
- } else if (dataString.startsWith(P2P_GROUP_STARTED_STR)) {
- mStateMachine.sendMessage(P2P_GROUP_STARTED_EVENT, new WifiP2pGroup(dataString));
- } else if (dataString.startsWith(P2P_GROUP_REMOVED_STR)) {
- mStateMachine.sendMessage(P2P_GROUP_REMOVED_EVENT, new WifiP2pGroup(dataString));
- } else if (dataString.startsWith(P2P_INVITATION_RECEIVED_STR)) {
- mStateMachine.sendMessage(P2P_INVITATION_RECEIVED_EVENT,
- new WifiP2pGroup(dataString));
- } else if (dataString.startsWith(P2P_INVITATION_RESULT_STR)) {
- mStateMachine.sendMessage(P2P_INVITATION_RESULT_EVENT, p2pError(dataString));
- } else if (dataString.startsWith(P2P_PROV_DISC_PBC_REQ_STR)) {
- mStateMachine.sendMessage(P2P_PROV_DISC_PBC_REQ_EVENT,
- new WifiP2pProvDiscEvent(dataString));
- } else if (dataString.startsWith(P2P_PROV_DISC_PBC_RSP_STR)) {
- mStateMachine.sendMessage(P2P_PROV_DISC_PBC_RSP_EVENT,
- new WifiP2pProvDiscEvent(dataString));
- } else if (dataString.startsWith(P2P_PROV_DISC_ENTER_PIN_STR)) {
- mStateMachine.sendMessage(P2P_PROV_DISC_ENTER_PIN_EVENT,
- new WifiP2pProvDiscEvent(dataString));
- } else if (dataString.startsWith(P2P_PROV_DISC_SHOW_PIN_STR)) {
- mStateMachine.sendMessage(P2P_PROV_DISC_SHOW_PIN_EVENT,
- new WifiP2pProvDiscEvent(dataString));
- } else if (dataString.startsWith(P2P_PROV_DISC_FAILURE_STR)) {
- mStateMachine.sendMessage(P2P_PROV_DISC_FAILURE_EVENT);
- } else if (dataString.startsWith(P2P_SERV_DISC_RESP_STR)) {
- List<WifiP2pServiceResponse> list = WifiP2pServiceResponse.newInstance(dataString);
- if (list != null) {
- mStateMachine.sendMessage(P2P_SERV_DISC_RESP_EVENT, list);
- } else {
- Log.e(TAG, "Null service resp " + dataString);
- }
- }
- }
-
- /**
- * Handle hostap events
- */
- private void handleHostApEvents(String dataString) {
- String[] tokens = dataString.split(" ");
- /* AP-STA-CONNECTED 42:fc:89:a8:96:09 p2p_dev_addr=02:90:4c:a0:92:54 */
- if (tokens[0].equals(AP_STA_CONNECTED_STR)) {
- mStateMachine.sendMessage(AP_STA_CONNECTED_EVENT, new WifiP2pDevice(dataString));
- /* AP-STA-DISCONNECTED 42:fc:89:a8:96:09 p2p_dev_addr=02:90:4c:a0:92:54 */
- } else if (tokens[0].equals(AP_STA_DISCONNECTED_STR)) {
- mStateMachine.sendMessage(AP_STA_DISCONNECTED_EVENT, new WifiP2pDevice(dataString));
- }
- }
-
- /**
- * Handle the supplicant STATE-CHANGE event
- * @param dataString New supplicant state string in the format:
- * id=network-id state=new-state
- */
- private void handleSupplicantStateChange(String dataString) {
- WifiSsid wifiSsid = null;
- int index = dataString.lastIndexOf("SSID=");
- if (index != -1) {
- wifiSsid = WifiSsid.createFromAsciiEncoded(
- dataString.substring(index + 5));
- }
- String[] dataTokens = dataString.split(" ");
-
- String BSSID = null;
- int networkId = -1;
- int newState = -1;
- for (String token : dataTokens) {
- String[] nameValue = token.split("=");
- if (nameValue.length != 2) {
- continue;
- }
-
- if (nameValue[0].equals("BSSID")) {
- BSSID = nameValue[1];
- continue;
- }
-
- int value;
- try {
- value = Integer.parseInt(nameValue[1]);
- } catch (NumberFormatException e) {
- continue;
- }
-
- if (nameValue[0].equals("id")) {
- networkId = value;
- } else if (nameValue[0].equals("state")) {
- newState = value;
- }
- }
-
- if (newState == -1) return;
-
- SupplicantState newSupplicantState = SupplicantState.INVALID;
- for (SupplicantState state : SupplicantState.values()) {
- if (state.ordinal() == newState) {
- newSupplicantState = state;
- break;
- }
- }
- if (newSupplicantState == SupplicantState.INVALID) {
- Log.w(TAG, "Invalid supplicant state: " + newState);
- }
- notifySupplicantStateChange(networkId, wifiSsid, BSSID, newSupplicantState);
- }
-
- private void handleNetworkStateChange(NetworkInfo.DetailedState newState, String data) {
- String BSSID = null;
- int networkId = -1;
- if (newState == NetworkInfo.DetailedState.CONNECTED) {
- Matcher match = mConnectedEventPattern.matcher(data);
- if (!match.find()) {
- if (DBG) Log.d(TAG, "Could not find BSSID in CONNECTED event string");
- } else {
- BSSID = match.group(1);
- try {
- networkId = Integer.parseInt(match.group(2));
- } catch (NumberFormatException e) {
- networkId = -1;
- }
- }
- notifyNetworkStateChange(newState, BSSID, networkId);
- }
- }
-
- /**
- * Send the state machine a notification that the state of Wifi connectivity
- * has changed.
- * @param newState the new network state
- * @param BSSID when the new state is {@link NetworkInfo.DetailedState#CONNECTED},
- * this is the MAC address of the access point. Otherwise, it
- * is {@code null}.
- * @param netId the configured network on which the state change occurred
- */
- void notifyNetworkStateChange(NetworkInfo.DetailedState newState, String BSSID, int netId) {
- if (newState == NetworkInfo.DetailedState.CONNECTED) {
- Message m = mStateMachine.obtainMessage(NETWORK_CONNECTION_EVENT,
- netId, 0, BSSID);
- mStateMachine.sendMessage(m);
- } else {
- Message m = mStateMachine.obtainMessage(NETWORK_DISCONNECTION_EVENT,
- netId, 0, BSSID);
- mStateMachine.sendMessage(m);
- }
- }
-
- /**
- * Send the state machine a notification that the state of the supplicant
- * has changed.
- * @param networkId the configured network on which the state change occurred
- * @param wifiSsid network name
- * @param BSSID network address
- * @param newState the new {@code SupplicantState}
- */
- void notifySupplicantStateChange(int networkId, WifiSsid wifiSsid, String BSSID,
- SupplicantState newState) {
- mStateMachine.sendMessage(mStateMachine.obtainMessage(SUPPLICANT_STATE_CHANGE_EVENT,
- new StateChangeResult(networkId, wifiSsid, BSSID, newState)));
- }
-}
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
deleted file mode 100644
index c2f278a..0000000
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ /dev/null
@@ -1,970 +0,0 @@
-/*
- * Copyright (C) 2008 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.wifi;
-
-import android.net.wifi.p2p.WifiP2pConfig;
-import android.net.wifi.p2p.WifiP2pGroup;
-import android.text.TextUtils;
-import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
-import android.util.LocalLog;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * Native calls for bring up/shut down of the supplicant daemon and for
- * sending requests to the supplicant daemon
- *
- * waitForEvent() is called on the monitor thread for events. All other methods
- * must be serialized from the framework.
- *
- * {@hide}
- */
-public class WifiNative {
-
- private static final boolean DBG = false;
- private final String mTAG;
- private static final int DEFAULT_GROUP_OWNER_INTENT = 6;
-
- static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED = 0;
- static final int BLUETOOTH_COEXISTENCE_MODE_DISABLED = 1;
- static final int BLUETOOTH_COEXISTENCE_MODE_SENSE = 2;
-
- static final int SCAN_WITHOUT_CONNECTION_SETUP = 1;
- static final int SCAN_WITH_CONNECTION_SETUP = 2;
-
- // Hold this lock before calling supplicant - it is required to
- // mutually exclude access from Wifi and P2p state machines
- static final Object mLock = new Object();
-
- public final String mInterfaceName;
- public final String mInterfacePrefix;
-
- private boolean mSuspendOptEnabled = false;
-
- public native static boolean loadDriver();
-
- public native static boolean isDriverLoaded();
-
- public native static boolean unloadDriver();
-
- public native static boolean startSupplicant(boolean p2pSupported);
-
- /* Sends a kill signal to supplicant. To be used when we have lost connection
- or when the supplicant is hung */
- public native static boolean killSupplicant(boolean p2pSupported);
-
- private native boolean connectToSupplicantNative();
-
- private native void closeSupplicantConnectionNative();
-
- /**
- * Wait for the supplicant to send an event, returning the event string.
- * @return the event string sent by the supplicant.
- */
- private native String waitForEventNative();
-
- private native boolean doBooleanCommandNative(String command);
-
- private native int doIntCommandNative(String command);
-
- private native String doStringCommandNative(String command);
-
- public WifiNative(String interfaceName) {
- mInterfaceName = interfaceName;
- mTAG = "WifiNative-" + interfaceName;
- if (!interfaceName.equals("p2p0")) {
- mInterfacePrefix = "IFNAME=" + interfaceName + " ";
- } else {
- // commands for p2p0 interface don't need prefix
- mInterfacePrefix = "";
- }
- }
-
- private static final LocalLog mLocalLog = new LocalLog(1024);
-
- // hold mLock before accessing mCmdIdLock
- private int mCmdId;
-
- public LocalLog getLocalLog() {
- return mLocalLog;
- }
-
- private int getNewCmdIdLocked() {
- return mCmdId++;
- }
-
- private void localLog(String s) {
- if (mLocalLog != null)
- mLocalLog.log(mInterfaceName + ": " + s);
- }
-
- public boolean connectToSupplicant() {
- // No synchronization necessary .. it is implemented in WifiMonitor
- localLog(mInterfacePrefix + "connectToSupplicant");
- return connectToSupplicantNative();
- }
-
- public void closeSupplicantConnection() {
- localLog(mInterfacePrefix + "closeSupplicantConnection");
- closeSupplicantConnectionNative();
- }
-
- public String waitForEvent() {
- // No synchronization necessary .. it is implemented in WifiMonitor
- return waitForEventNative();
- }
-
- private boolean doBooleanCommand(String command) {
- if (DBG) Log.d(mTAG, "doBoolean: " + command);
- synchronized (mLock) {
- int cmdId = getNewCmdIdLocked();
- localLog(cmdId + "->" + mInterfacePrefix + command);
- boolean result = doBooleanCommandNative(mInterfacePrefix + command);
- localLog(cmdId + "<-" + result);
- if (DBG) Log.d(mTAG, " returned " + result);
- return result;
- }
- }
-
- private int doIntCommand(String command) {
- if (DBG) Log.d(mTAG, "doInt: " + command);
- synchronized (mLock) {
- int cmdId = getNewCmdIdLocked();
- localLog(cmdId + "->" + mInterfacePrefix + command);
- int result = doIntCommandNative(mInterfacePrefix + command);
- localLog(cmdId + "<-" + result);
- if (DBG) Log.d(mTAG, " returned " + result);
- return result;
- }
- }
-
- private String doStringCommand(String command) {
- if (DBG) Log.d(mTAG, "doString: " + command);
- synchronized (mLock) {
- int cmdId = getNewCmdIdLocked();
- localLog(cmdId + "->" + mInterfacePrefix + command);
- String result = doStringCommandNative(mInterfacePrefix + command);
- localLog(cmdId + "<-" + result);
- if (DBG) Log.d(mTAG, " returned " + result);
- return result;
- }
- }
-
- private String doStringCommandWithoutLogging(String command) {
- if (DBG) Log.d(mTAG, "doString: " + command);
- synchronized (mLock) {
- return doStringCommandNative(mInterfacePrefix + command);
- }
- }
-
- public boolean ping() {
- String pong = doStringCommand("PING");
- return (pong != null && pong.equals("PONG"));
- }
-
- public boolean scan(int type) {
- if (type == SCAN_WITHOUT_CONNECTION_SETUP) {
- return doBooleanCommand("SCAN TYPE=ONLY");
- } else if (type == SCAN_WITH_CONNECTION_SETUP) {
- return doBooleanCommand("SCAN");
- } else {
- throw new IllegalArgumentException("Invalid scan type");
- }
- }
-
- /* Does a graceful shutdown of supplicant. Is a common stop function for both p2p and sta.
- *
- * Note that underneath we use a harsh-sounding "terminate" supplicant command
- * for a graceful stop and a mild-sounding "stop" interface
- * to kill the process
- */
- public boolean stopSupplicant() {
- return doBooleanCommand("TERMINATE");
- }
-
- public String listNetworks() {
- return doStringCommand("LIST_NETWORKS");
- }
-
- public int addNetwork() {
- return doIntCommand("ADD_NETWORK");
- }
-
- public boolean setNetworkVariable(int netId, String name, String value) {
- if (TextUtils.isEmpty(name) || TextUtils.isEmpty(value)) return false;
- return doBooleanCommand("SET_NETWORK " + netId + " " + name + " " + value);
- }
-
- public String getNetworkVariable(int netId, String name) {
- if (TextUtils.isEmpty(name)) return null;
-
- // GET_NETWORK will likely flood the logs ...
- return doStringCommandWithoutLogging("GET_NETWORK " + netId + " " + name);
- }
-
- public boolean removeNetwork(int netId) {
- return doBooleanCommand("REMOVE_NETWORK " + netId);
- }
-
- public boolean enableNetwork(int netId, boolean disableOthers) {
- if (disableOthers) {
- return doBooleanCommand("SELECT_NETWORK " + netId);
- } else {
- return doBooleanCommand("ENABLE_NETWORK " + netId);
- }
- }
-
- public boolean disableNetwork(int netId) {
- return doBooleanCommand("DISABLE_NETWORK " + netId);
- }
-
- public boolean reconnect() {
- return doBooleanCommand("RECONNECT");
- }
-
- public boolean reassociate() {
- return doBooleanCommand("REASSOCIATE");
- }
-
- public boolean disconnect() {
- return doBooleanCommand("DISCONNECT");
- }
-
- public String status() {
- return doStringCommand("STATUS");
- }
-
- public String getMacAddress() {
- //Macaddr = XX.XX.XX.XX.XX.XX
- String ret = doStringCommand("DRIVER MACADDR");
- if (!TextUtils.isEmpty(ret)) {
- String[] tokens = ret.split(" = ");
- if (tokens.length == 2) return tokens[1];
- }
- return null;
- }
-
- /**
- * Format of results:
- * =================
- * id=1
- * bssid=68:7f:74:d7:1b:6e
- * freq=2412
- * level=-43
- * tsf=1344621975160944
- * age=2623
- * flags=[WPA2-PSK-CCMP][WPS][ESS]
- * ssid=zubyb
- * ====
- *
- * RANGE=ALL gets all scan results
- * RANGE=ID- gets results from ID
- * MASK=<N> see wpa_supplicant/src/common/wpa_ctrl.h for details
- */
- public String scanResults(int sid) {
- return doStringCommandWithoutLogging("BSS RANGE=" + sid + "- MASK=0x21987");
- }
-
- /**
- * Format of command
- * DRIVER WLS_BATCHING SET SCANFREQ=x MSCAN=r BESTN=y CHANNEL=<z, w, t> RTT=s
- * where x is an ascii representation of an integer number of seconds between scans
- * r is an ascii representation of an integer number of scans per batch
- * y is an ascii representation of an integer number of the max AP to remember per scan
- * z, w, t represent a 1..n size list of channel numbers and/or 'A', 'B' values
- * indicating entire ranges of channels
- * s is an ascii representation of an integer number of highest-strength AP
- * for which we'd like approximate distance reported
- *
- * The return value is an ascii integer representing a guess of the number of scans
- * the firmware can remember before it runs out of buffer space or -1 on error
- */
- public String setBatchedScanSettings(BatchedScanSettings settings) {
- if (settings == null) {
- return doStringCommand("DRIVER WLS_BATCHING STOP");
- }
- String cmd = "DRIVER WLS_BATCHING SET SCANFREQ=" + settings.scanIntervalSec;
- cmd += " MSCAN=" + settings.maxScansPerBatch;
- if (settings.maxApPerScan != BatchedScanSettings.UNSPECIFIED) {
- cmd += " BESTN=" + settings.maxApPerScan;
- }
- if (settings.channelSet != null && !settings.channelSet.isEmpty()) {
- cmd += " CHANNEL=<";
- int i = 0;
- for (String channel : settings.channelSet) {
- cmd += (i > 0 ? "," : "") + channel;
- ++i;
- }
- cmd += ">";
- }
- if (settings.maxApForDistance != BatchedScanSettings.UNSPECIFIED) {
- cmd += " RTT=" + settings.maxApForDistance;
- }
- return doStringCommand(cmd);
- }
-
- public String getBatchedScanResults() {
- return doStringCommand("DRIVER WLS_BATCHING GET");
- }
-
- public boolean startDriver() {
- return doBooleanCommand("DRIVER START");
- }
-
- public boolean stopDriver() {
- return doBooleanCommand("DRIVER STOP");
- }
-
-
- /**
- * Start filtering out Multicast V4 packets
- * @return {@code true} if the operation succeeded, {@code false} otherwise
- *
- * Multicast filtering rules work as follows:
- *
- * The driver can filter multicast (v4 and/or v6) and broadcast packets when in
- * a power optimized mode (typically when screen goes off).
- *
- * In order to prevent the driver from filtering the multicast/broadcast packets, we have to
- * add a DRIVER RXFILTER-ADD rule followed by DRIVER RXFILTER-START to make the rule effective
- *
- * DRIVER RXFILTER-ADD Num
- * where Num = 0 - Unicast, 1 - Broadcast, 2 - Mutil4 or 3 - Multi6
- *
- * and DRIVER RXFILTER-START
- * In order to stop the usage of these rules, we do
- *
- * DRIVER RXFILTER-STOP
- * DRIVER RXFILTER-REMOVE Num
- * where Num is as described for RXFILTER-ADD
- *
- * The SETSUSPENDOPT driver command overrides the filtering rules
- */
- public boolean startFilteringMulticastV4Packets() {
- return doBooleanCommand("DRIVER RXFILTER-STOP")
- && doBooleanCommand("DRIVER RXFILTER-REMOVE 2")
- && doBooleanCommand("DRIVER RXFILTER-START");
- }
-
- /**
- * Stop filtering out Multicast V4 packets.
- * @return {@code true} if the operation succeeded, {@code false} otherwise
- */
- public boolean stopFilteringMulticastV4Packets() {
- return doBooleanCommand("DRIVER RXFILTER-STOP")
- && doBooleanCommand("DRIVER RXFILTER-ADD 2")
- && doBooleanCommand("DRIVER RXFILTER-START");
- }
-
- /**
- * Start filtering out Multicast V6 packets
- * @return {@code true} if the operation succeeded, {@code false} otherwise
- */
- public boolean startFilteringMulticastV6Packets() {
- return doBooleanCommand("DRIVER RXFILTER-STOP")
- && doBooleanCommand("DRIVER RXFILTER-REMOVE 3")
- && doBooleanCommand("DRIVER RXFILTER-START");
- }
-
- /**
- * Stop filtering out Multicast V6 packets.
- * @return {@code true} if the operation succeeded, {@code false} otherwise
- */
- public boolean stopFilteringMulticastV6Packets() {
- return doBooleanCommand("DRIVER RXFILTER-STOP")
- && doBooleanCommand("DRIVER RXFILTER-ADD 3")
- && doBooleanCommand("DRIVER RXFILTER-START");
- }
-
- public int getBand() {
- String ret = doStringCommand("DRIVER GETBAND");
- if (!TextUtils.isEmpty(ret)) {
- //reply is "BAND X" where X is the band
- String[] tokens = ret.split(" ");
- try {
- if (tokens.length == 2) return Integer.parseInt(tokens[1]);
- } catch (NumberFormatException e) {
- return -1;
- }
- }
- return -1;
- }
-
- public boolean setBand(int band) {
- return doBooleanCommand("DRIVER SETBAND " + band);
- }
-
- /**
- * Sets the bluetooth coexistence mode.
- *
- * @param mode One of {@link #BLUETOOTH_COEXISTENCE_MODE_DISABLED},
- * {@link #BLUETOOTH_COEXISTENCE_MODE_ENABLED}, or
- * {@link #BLUETOOTH_COEXISTENCE_MODE_SENSE}.
- * @return Whether the mode was successfully set.
- */
- public boolean setBluetoothCoexistenceMode(int mode) {
- return doBooleanCommand("DRIVER BTCOEXMODE " + mode);
- }
-
- /**
- * Enable or disable Bluetooth coexistence scan mode. When this mode is on,
- * some of the low-level scan parameters used by the driver are changed to
- * reduce interference with A2DP streaming.
- *
- * @param isSet whether to enable or disable this mode
- * @return {@code true} if the command succeeded, {@code false} otherwise.
- */
- public boolean setBluetoothCoexistenceScanMode(boolean setCoexScanMode) {
- if (setCoexScanMode) {
- return doBooleanCommand("DRIVER BTCOEXSCAN-START");
- } else {
- return doBooleanCommand("DRIVER BTCOEXSCAN-STOP");
- }
- }
-
- public boolean saveConfig() {
- return doBooleanCommand("SAVE_CONFIG");
- }
-
- public boolean addToBlacklist(String bssid) {
- if (TextUtils.isEmpty(bssid)) return false;
- return doBooleanCommand("BLACKLIST " + bssid);
- }
-
- public boolean clearBlacklist() {
- return doBooleanCommand("BLACKLIST clear");
- }
-
- public boolean setSuspendOptimizations(boolean enabled) {
- if (mSuspendOptEnabled == enabled) return true;
- mSuspendOptEnabled = enabled;
- if (enabled) {
- return doBooleanCommand("DRIVER SETSUSPENDMODE 1");
- } else {
- return doBooleanCommand("DRIVER SETSUSPENDMODE 0");
- }
- }
-
- public boolean setCountryCode(String countryCode) {
- return doBooleanCommand("DRIVER COUNTRY " + countryCode.toUpperCase(Locale.ROOT));
- }
-
- public void enableBackgroundScan(boolean enable) {
- if (enable) {
- doBooleanCommand("SET pno 1");
- } else {
- doBooleanCommand("SET pno 0");
- }
- }
-
- public void setScanInterval(int scanInterval) {
- doBooleanCommand("SCAN_INTERVAL " + scanInterval);
- }
-
- public void startTdls(String macAddr, boolean enable) {
- if (enable) {
- doBooleanCommand("TDLS_DISCOVER " + macAddr);
- doBooleanCommand("TDLS_SETUP " + macAddr);
- } else {
- doBooleanCommand("TDLS_TEARDOWN " + macAddr);
- }
- }
-
- /** Example output:
- * RSSI=-65
- * LINKSPEED=48
- * NOISE=9999
- * FREQUENCY=0
- */
- public String signalPoll() {
- return doStringCommandWithoutLogging("SIGNAL_POLL");
- }
-
- /** Example outout:
- * TXGOOD=396
- * TXBAD=1
- */
- public String pktcntPoll() {
- return doStringCommand("PKTCNT_POLL");
- }
-
- public void bssFlush() {
- doBooleanCommand("BSS_FLUSH 0");
- }
-
- public boolean startWpsPbc(String bssid) {
- if (TextUtils.isEmpty(bssid)) {
- return doBooleanCommand("WPS_PBC");
- } else {
- return doBooleanCommand("WPS_PBC " + bssid);
- }
- }
-
- public boolean startWpsPbc(String iface, String bssid) {
- synchronized (mLock) {
- if (TextUtils.isEmpty(bssid)) {
- return doBooleanCommandNative("IFNAME=" + iface + " WPS_PBC");
- } else {
- return doBooleanCommandNative("IFNAME=" + iface + " WPS_PBC " + bssid);
- }
- }
- }
-
- public boolean startWpsPinKeypad(String pin) {
- if (TextUtils.isEmpty(pin)) return false;
- return doBooleanCommand("WPS_PIN any " + pin);
- }
-
- public boolean startWpsPinKeypad(String iface, String pin) {
- if (TextUtils.isEmpty(pin)) return false;
- synchronized (mLock) {
- return doBooleanCommandNative("IFNAME=" + iface + " WPS_PIN any " + pin);
- }
- }
-
-
- public String startWpsPinDisplay(String bssid) {
- if (TextUtils.isEmpty(bssid)) {
- return doStringCommand("WPS_PIN any");
- } else {
- return doStringCommand("WPS_PIN " + bssid);
- }
- }
-
- public String startWpsPinDisplay(String iface, String bssid) {
- synchronized (mLock) {
- if (TextUtils.isEmpty(bssid)) {
- return doStringCommandNative("IFNAME=" + iface + " WPS_PIN any");
- } else {
- return doStringCommandNative("IFNAME=" + iface + " WPS_PIN " + bssid);
- }
- }
- }
-
- /* Configures an access point connection */
- public boolean startWpsRegistrar(String bssid, String pin) {
- if (TextUtils.isEmpty(bssid) || TextUtils.isEmpty(pin)) return false;
- return doBooleanCommand("WPS_REG " + bssid + " " + pin);
- }
-
- public boolean cancelWps() {
- return doBooleanCommand("WPS_CANCEL");
- }
-
- public boolean setPersistentReconnect(boolean enabled) {
- int value = (enabled == true) ? 1 : 0;
- return doBooleanCommand("SET persistent_reconnect " + value);
- }
-
- public boolean setDeviceName(String name) {
- return doBooleanCommand("SET device_name " + name);
- }
-
- public boolean setDeviceType(String type) {
- return doBooleanCommand("SET device_type " + type);
- }
-
- public boolean setConfigMethods(String cfg) {
- return doBooleanCommand("SET config_methods " + cfg);
- }
-
- public boolean setManufacturer(String value) {
- return doBooleanCommand("SET manufacturer " + value);
- }
-
- public boolean setModelName(String value) {
- return doBooleanCommand("SET model_name " + value);
- }
-
- public boolean setModelNumber(String value) {
- return doBooleanCommand("SET model_number " + value);
- }
-
- public boolean setSerialNumber(String value) {
- return doBooleanCommand("SET serial_number " + value);
- }
-
- public boolean setP2pSsidPostfix(String postfix) {
- return doBooleanCommand("SET p2p_ssid_postfix " + postfix);
- }
-
- public boolean setP2pGroupIdle(String iface, int time) {
- synchronized (mLock) {
- return doBooleanCommandNative("IFNAME=" + iface + " SET p2p_group_idle " + time);
- }
- }
-
- public void setPowerSave(boolean enabled) {
- if (enabled) {
- doBooleanCommand("SET ps 1");
- } else {
- doBooleanCommand("SET ps 0");
- }
- }
-
- public boolean setP2pPowerSave(String iface, boolean enabled) {
- synchronized (mLock) {
- if (enabled) {
- return doBooleanCommandNative("IFNAME=" + iface + " P2P_SET ps 1");
- } else {
- return doBooleanCommandNative("IFNAME=" + iface + " P2P_SET ps 0");
- }
- }
- }
-
- public boolean setWfdEnable(boolean enable) {
- return doBooleanCommand("SET wifi_display " + (enable ? "1" : "0"));
- }
-
- public boolean setWfdDeviceInfo(String hex) {
- return doBooleanCommand("WFD_SUBELEM_SET 0 " + hex);
- }
-
- /**
- * "sta" prioritizes STA connection over P2P and "p2p" prioritizes
- * P2P connection over STA
- */
- public boolean setConcurrencyPriority(String s) {
- return doBooleanCommand("P2P_SET conc_pref " + s);
- }
-
- public boolean p2pFind() {
- return doBooleanCommand("P2P_FIND");
- }
-
- public boolean p2pFind(int timeout) {
- if (timeout <= 0) {
- return p2pFind();
- }
- return doBooleanCommand("P2P_FIND " + timeout);
- }
-
- public boolean p2pStopFind() {
- return doBooleanCommand("P2P_STOP_FIND");
- }
-
- public boolean p2pListen() {
- return doBooleanCommand("P2P_LISTEN");
- }
-
- public boolean p2pListen(int timeout) {
- if (timeout <= 0) {
- return p2pListen();
- }
- return doBooleanCommand("P2P_LISTEN " + timeout);
- }
-
- public boolean p2pExtListen(boolean enable, int period, int interval) {
- if (enable && interval < period) {
- return false;
- }
- return doBooleanCommand("P2P_EXT_LISTEN"
- + (enable ? (" " + period + " " + interval) : ""));
- }
-
- public boolean p2pSetChannel(int lc, int oc) {
- if (DBG) Log.d(mTAG, "p2pSetChannel: lc="+lc+", oc="+oc);
-
- if (lc >=1 && lc <= 11) {
- if (!doBooleanCommand("P2P_SET listen_channel " + lc)) {
- return false;
- }
- } else if (lc != 0) {
- return false;
- }
-
- if (oc >= 1 && oc <= 165 ) {
- int freq = (oc <= 14 ? 2407 : 5000) + oc * 5;
- return doBooleanCommand("P2P_SET disallow_freq 1000-"
- + (freq - 5) + "," + (freq + 5) + "-6000");
- } else if (oc == 0) {
- /* oc==0 disables "P2P_SET disallow_freq" (enables all freqs) */
- return doBooleanCommand("P2P_SET disallow_freq \"\"");
- }
-
- return false;
- }
-
- public boolean p2pFlush() {
- return doBooleanCommand("P2P_FLUSH");
- }
-
- /* p2p_connect <peer device address> <pbc|pin|PIN#> [label|display|keypad]
- [persistent] [join|auth] [go_intent=<0..15>] [freq=<in MHz>] */
- public String p2pConnect(WifiP2pConfig config, boolean joinExistingGroup) {
- if (config == null) return null;
- List<String> args = new ArrayList<String>();
- WpsInfo wps = config.wps;
- args.add(config.deviceAddress);
-
- switch (wps.setup) {
- case WpsInfo.PBC:
- args.add("pbc");
- break;
- case WpsInfo.DISPLAY:
- if (TextUtils.isEmpty(wps.pin)) {
- args.add("pin");
- } else {
- args.add(wps.pin);
- }
- args.add("display");
- break;
- case WpsInfo.KEYPAD:
- args.add(wps.pin);
- args.add("keypad");
- break;
- case WpsInfo.LABEL:
- args.add(wps.pin);
- args.add("label");
- default:
- break;
- }
-
- if (config.netId == WifiP2pGroup.PERSISTENT_NET_ID) {
- args.add("persistent");
- }
-
- if (joinExistingGroup) {
- args.add("join");
- } else {
- //TODO: This can be adapted based on device plugged in state and
- //device battery state
- int groupOwnerIntent = config.groupOwnerIntent;
- if (groupOwnerIntent < 0 || groupOwnerIntent > 15) {
- groupOwnerIntent = DEFAULT_GROUP_OWNER_INTENT;
- }
- args.add("go_intent=" + groupOwnerIntent);
- }
-
- String command = "P2P_CONNECT ";
- for (String s : args) command += s + " ";
-
- return doStringCommand(command);
- }
-
- public boolean p2pCancelConnect() {
- return doBooleanCommand("P2P_CANCEL");
- }
-
- public boolean p2pProvisionDiscovery(WifiP2pConfig config) {
- if (config == null) return false;
-
- switch (config.wps.setup) {
- case WpsInfo.PBC:
- return doBooleanCommand("P2P_PROV_DISC " + config.deviceAddress + " pbc");
- case WpsInfo.DISPLAY:
- //We are doing display, so provision discovery is keypad
- return doBooleanCommand("P2P_PROV_DISC " + config.deviceAddress + " keypad");
- case WpsInfo.KEYPAD:
- //We are doing keypad, so provision discovery is display
- return doBooleanCommand("P2P_PROV_DISC " + config.deviceAddress + " display");
- default:
- break;
- }
- return false;
- }
-
- public boolean p2pGroupAdd(boolean persistent) {
- if (persistent) {
- return doBooleanCommand("P2P_GROUP_ADD persistent");
- }
- return doBooleanCommand("P2P_GROUP_ADD");
- }
-
- public boolean p2pGroupAdd(int netId) {
- return doBooleanCommand("P2P_GROUP_ADD persistent=" + netId);
- }
-
- public boolean p2pGroupRemove(String iface) {
- if (TextUtils.isEmpty(iface)) return false;
- synchronized (mLock) {
- return doBooleanCommandNative("IFNAME=" + iface + " P2P_GROUP_REMOVE " + iface);
- }
- }
-
- public boolean p2pReject(String deviceAddress) {
- return doBooleanCommand("P2P_REJECT " + deviceAddress);
- }
-
- /* Invite a peer to a group */
- public boolean p2pInvite(WifiP2pGroup group, String deviceAddress) {
- if (TextUtils.isEmpty(deviceAddress)) return false;
-
- if (group == null) {
- return doBooleanCommand("P2P_INVITE peer=" + deviceAddress);
- } else {
- return doBooleanCommand("P2P_INVITE group=" + group.getInterface()
- + " peer=" + deviceAddress + " go_dev_addr=" + group.getOwner().deviceAddress);
- }
- }
-
- /* Reinvoke a persistent connection */
- public boolean p2pReinvoke(int netId, String deviceAddress) {
- if (TextUtils.isEmpty(deviceAddress) || netId < 0) return false;
-
- return doBooleanCommand("P2P_INVITE persistent=" + netId + " peer=" + deviceAddress);
- }
-
- public String p2pGetSsid(String deviceAddress) {
- return p2pGetParam(deviceAddress, "oper_ssid");
- }
-
- public String p2pGetDeviceAddress() {
- String status = status();
- if (status == null) return "";
-
- String[] tokens = status.split("\n");
- for (String token : tokens) {
- if (token.startsWith("p2p_device_address=")) {
- String[] nameValue = token.split("=");
- if (nameValue.length != 2) break;
- return nameValue[1];
- }
- }
- return "";
- }
-
- public int getGroupCapability(String deviceAddress) {
- int gc = 0;
- if (TextUtils.isEmpty(deviceAddress)) return gc;
- String peerInfo = p2pPeer(deviceAddress);
- if (TextUtils.isEmpty(peerInfo)) return gc;
-
- String[] tokens = peerInfo.split("\n");
- for (String token : tokens) {
- if (token.startsWith("group_capab=")) {
- String[] nameValue = token.split("=");
- if (nameValue.length != 2) break;
- try {
- return Integer.decode(nameValue[1]);
- } catch(NumberFormatException e) {
- return gc;
- }
- }
- }
- return gc;
- }
-
- public String p2pPeer(String deviceAddress) {
- return doStringCommand("P2P_PEER " + deviceAddress);
- }
-
- private String p2pGetParam(String deviceAddress, String key) {
- if (deviceAddress == null) return null;
-
- String peerInfo = p2pPeer(deviceAddress);
- if (peerInfo == null) return null;
- String[] tokens= peerInfo.split("\n");
-
- key += "=";
- for (String token : tokens) {
- if (token.startsWith(key)) {
- String[] nameValue = token.split("=");
- if (nameValue.length != 2) break;
- return nameValue[1];
- }
- }
- return null;
- }
-
- public boolean p2pServiceAdd(WifiP2pServiceInfo servInfo) {
- /*
- * P2P_SERVICE_ADD bonjour <query hexdump> <RDATA hexdump>
- * P2P_SERVICE_ADD upnp <version hex> <service>
- *
- * e.g)
- * [Bonjour]
- * # IP Printing over TCP (PTR) (RDATA=MyPrinter._ipp._tcp.local.)
- * P2P_SERVICE_ADD bonjour 045f697070c00c000c01 094d795072696e746572c027
- * # IP Printing over TCP (TXT) (RDATA=txtvers=1,pdl=application/postscript)
- * P2P_SERVICE_ADD bonjour 096d797072696e746572045f697070c00c001001
- * 09747874766572733d311a70646c3d6170706c69636174696f6e2f706f7374736372797074
- *
- * [UPnP]
- * P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012
- * P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::upnp:rootdevice
- * P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::urn:schemas-upnp
- * -org:device:InternetGatewayDevice:1
- * P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9322-123456789012::urn:schemas-upnp
- * -org:service:ContentDirectory:2
- */
- for (String s : servInfo.getSupplicantQueryList()) {
- String command = "P2P_SERVICE_ADD";
- command += (" " + s);
- if (!doBooleanCommand(command)) {
- return false;
- }
- }
- return true;
- }
-
- public boolean p2pServiceDel(WifiP2pServiceInfo servInfo) {
- /*
- * P2P_SERVICE_DEL bonjour <query hexdump>
- * P2P_SERVICE_DEL upnp <version hex> <service>
- */
- for (String s : servInfo.getSupplicantQueryList()) {
- String command = "P2P_SERVICE_DEL ";
-
- String[] data = s.split(" ");
- if (data.length < 2) {
- return false;
- }
- if ("upnp".equals(data[0])) {
- command += s;
- } else if ("bonjour".equals(data[0])) {
- command += data[0];
- command += (" " + data[1]);
- } else {
- return false;
- }
- if (!doBooleanCommand(command)) {
- return false;
- }
- }
- return true;
- }
-
- public boolean p2pServiceFlush() {
- return doBooleanCommand("P2P_SERVICE_FLUSH");
- }
-
- public String p2pServDiscReq(String addr, String query) {
- String command = "P2P_SERV_DISC_REQ";
- command += (" " + addr);
- command += (" " + query);
-
- return doStringCommand(command);
- }
-
- public boolean p2pServDiscCancelReq(String id) {
- return doBooleanCommand("P2P_SERV_DISC_CANCEL_REQ " + id);
- }
-
- /* Set the current mode of miracast operation.
- * 0 = disabled
- * 1 = operating as source
- * 2 = operating as sink
- */
- public void setMiracastMode(int mode) {
- // Note: optional feature on the driver. It is ok for this to fail.
- doBooleanCommand("DRIVER MIRACAST " + mode);
- }
-}
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
deleted file mode 100644
index 149f08d..0000000
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ /dev/null
@@ -1,4408 +0,0 @@
-/*
- * Copyright (C) 2010 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.wifi;
-
-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;
-import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
-
-/**
- * TODO:
- * Deprecate WIFI_STATE_UNKNOWN
- */
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
-import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.app.backup.IBackupManager;
-import android.bluetooth.BluetoothAdapter;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.database.ContentObserver;
-import android.net.ConnectivityManager;
-import android.net.DhcpResults;
-import android.net.DhcpStateMachine;
-import android.net.InterfaceConfiguration;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-import android.net.NetworkInfo;
-import android.net.NetworkInfo.DetailedState;
-import android.net.NetworkUtils;
-import android.net.RouteInfo;
-import android.net.wifi.WpsResult.Status;
-import android.net.wifi.p2p.WifiP2pManager;
-import android.net.wifi.p2p.WifiP2pService;
-import android.os.BatteryStats;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.INetworkManagementService;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.os.WorkSource;
-import android.provider.Settings;
-import android.util.LruCache;
-import android.text.TextUtils;
-
-import com.android.internal.R;
-import com.android.internal.app.IBatteryStats;
-import com.android.internal.util.AsyncChannel;
-import com.android.internal.util.Protocol;
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-
-import com.android.server.net.BaseNetworkObserver;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.Iterator;
-import java.util.regex.Pattern;
-
-/**
- * Track the state of Wifi connectivity. All event handling is done here,
- * and all changes in connectivity state are initiated here.
- *
- * Wi-Fi now supports three modes of operation: Client, SoftAp and p2p
- * In the current implementation, we support concurrent wifi p2p and wifi operation.
- * The WifiStateMachine handles SoftAp and Client operations while WifiP2pService
- * handles p2p operation.
- *
- * @hide
- */
-public class WifiStateMachine extends StateMachine {
-
- private static final String NETWORKTYPE = "WIFI";
- private static final boolean DBG = false;
-
- private WifiMonitor mWifiMonitor;
- private WifiNative mWifiNative;
- private WifiConfigStore mWifiConfigStore;
- private INetworkManagementService mNwService;
- private ConnectivityManager mCm;
-
- private final boolean mP2pSupported;
- private final AtomicBoolean mP2pConnected = new AtomicBoolean(false);
- private boolean mTemporarilyDisconnectWifi = false;
- private final String mPrimaryDeviceType;
-
- /* Scan results handling */
- private List<ScanResult> mScanResults = new ArrayList<ScanResult>();
- private static final Pattern scanResultPattern = Pattern.compile("\t+");
- private static final int SCAN_RESULT_CACHE_SIZE = 80;
- private final LruCache<String, ScanResult> mScanResultCache;
-
- /* Batch scan results */
- private final List<BatchedScanResult> mBatchedScanResults =
- new ArrayList<BatchedScanResult>();
- private int mBatchedScanOwnerUid = UNKNOWN_SCAN_SOURCE;
- private int mExpectedBatchedScans = 0;
- private long mBatchedScanMinPollTime = 0;
-
- /* Chipset supports background scan */
- private final boolean mBackgroundScanSupported;
-
- private String mInterfaceName;
- /* Tethering interface could be separate from wlan interface */
- private String mTetherInterfaceName;
-
- private int mLastSignalLevel = -1;
- private String mLastBssid;
- private int mLastNetworkId;
- private boolean mEnableRssiPolling = false;
- private boolean mEnableBackgroundScan = false;
- private int mRssiPollToken = 0;
- private int mReconnectCount = 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
- * In SCAN_ONLY_MODE, the STA can only scan for access points
- * In SCAN_ONLY_WIFI_OFF_MODE, the STA can only scan for access points with wifi toggle being off
- */
- private int mOperationalMode = CONNECT_MODE;
- private boolean mScanResultIsPending = false;
- private WorkSource mScanWorkSource = null;
- private static final int UNKNOWN_SCAN_SOURCE = -1;
- /* Tracks if state machine has received any screen state change broadcast yet.
- * We can miss one of these at boot.
- */
- private AtomicBoolean mScreenBroadcastReceived = new AtomicBoolean(false);
-
- private boolean mBluetoothConnectionActive = false;
-
- private PowerManager.WakeLock mSuspendWakeLock;
-
- /**
- * Interval in milliseconds between polling for RSSI
- * and linkspeed information
- */
- private static final int POLL_RSSI_INTERVAL_MSECS = 3000;
-
- /**
- * Delay between supplicant restarts upon failure to establish connection
- */
- private static final int SUPPLICANT_RESTART_INTERVAL_MSECS = 5000;
-
- /**
- * Number of times we attempt to restart supplicant
- */
- private static final int SUPPLICANT_RESTART_TRIES = 5;
-
- private int mSupplicantRestartCount = 0;
- /* Tracks sequence number on stop failure message */
- private int mSupplicantStopFailureToken = 0;
-
- /**
- * Tether state change notification time out
- */
- private static final int TETHER_NOTIFICATION_TIME_OUT_MSECS = 5000;
-
- /* Tracks sequence number on a tether notification time out */
- private int mTetherToken = 0;
-
- /**
- * Driver start time out.
- */
- private static final int DRIVER_START_TIME_OUT_MSECS = 10000;
-
- /* Tracks sequence number on a driver time out */
- private int mDriverStartToken = 0;
-
- /**
- * The link properties of the wifi interface.
- * Do not modify this directly; use updateLinkProperties instead.
- */
- private LinkProperties mLinkProperties;
-
- /**
- * Subset of link properties coming from netlink.
- * Currently includes IPv4 and IPv6 addresses. In the future will also include IPv6 DNS servers
- * and domains obtained from router advertisements (RFC 6106).
- */
- private final LinkProperties mNetlinkLinkProperties;
-
- /* Tracks sequence number on a periodic scan message */
- private int mPeriodicScanToken = 0;
-
- // Wakelock held during wifi start/stop and driver load/unload
- private PowerManager.WakeLock mWakeLock;
-
- private Context mContext;
-
- private final Object mDhcpResultsLock = new Object();
- private DhcpResults mDhcpResults;
- private WifiInfo mWifiInfo;
- private NetworkInfo mNetworkInfo;
- private SupplicantStateTracker mSupplicantStateTracker;
- private DhcpStateMachine mDhcpStateMachine;
- private boolean mDhcpActive = false;
-
- private class InterfaceObserver extends BaseNetworkObserver {
- private WifiStateMachine mWifiStateMachine;
-
- InterfaceObserver(WifiStateMachine wifiStateMachine) {
- super();
- mWifiStateMachine = wifiStateMachine;
- }
-
- private void maybeLog(String operation, String iface, LinkAddress address) {
- if (DBG) {
- log(operation + ": " + address + " on " + iface +
- " flags " + address.getFlags() + " scope " + address.getScope());
- }
- }
-
- @Override
- public void addressUpdated(String iface, LinkAddress address) {
- if (mWifiStateMachine.mInterfaceName.equals(iface)) {
- maybeLog("addressUpdated", iface, address);
- mWifiStateMachine.sendMessage(CMD_IP_ADDRESS_UPDATED, address);
- }
- }
-
- @Override
- public void addressRemoved(String iface, LinkAddress address) {
- if (mWifiStateMachine.mInterfaceName.equals(iface)) {
- maybeLog("addressRemoved", iface, address);
- mWifiStateMachine.sendMessage(CMD_IP_ADDRESS_REMOVED, address);
- }
- }
- }
-
- private InterfaceObserver mInterfaceObserver;
-
- private AlarmManager mAlarmManager;
- private PendingIntent mScanIntent;
- private PendingIntent mDriverStopIntent;
- private PendingIntent mBatchedScanIntervalIntent;
-
- /* Tracks current frequency mode */
- private AtomicInteger mFrequencyBand = new AtomicInteger(WifiManager.WIFI_FREQUENCY_BAND_AUTO);
-
- /* Tracks if we are filtering Multicast v4 packets. Default is to filter. */
- private AtomicBoolean mFilteringMulticastV4Packets = new AtomicBoolean(true);
-
- // Channel for sending replies.
- private AsyncChannel mReplyChannel = new AsyncChannel();
-
- private WifiP2pManager mWifiP2pManager;
- //Used to initiate a connection with WifiP2pService
- private AsyncChannel mWifiP2pChannel;
- private AsyncChannel mWifiApConfigChannel;
-
- /* The base for wifi message types */
- static final int BASE = Protocol.BASE_WIFI;
- /* Start the supplicant */
- static final int CMD_START_SUPPLICANT = BASE + 11;
- /* Stop the supplicant */
- static final int CMD_STOP_SUPPLICANT = BASE + 12;
- /* Start the driver */
- static final int CMD_START_DRIVER = BASE + 13;
- /* Stop the driver */
- static final int CMD_STOP_DRIVER = BASE + 14;
- /* Indicates Static IP succeeded */
- static final int CMD_STATIC_IP_SUCCESS = BASE + 15;
- /* Indicates Static IP failed */
- static final int CMD_STATIC_IP_FAILURE = BASE + 16;
- /* Indicates supplicant stop failed */
- static final int CMD_STOP_SUPPLICANT_FAILED = BASE + 17;
- /* Delayed stop to avoid shutting down driver too quick*/
- static final int CMD_DELAYED_STOP_DRIVER = BASE + 18;
- /* A delayed message sent to start driver when it fail to come up */
- static final int CMD_DRIVER_START_TIMED_OUT = BASE + 19;
-
- /* Start the soft access point */
- static final int CMD_START_AP = BASE + 21;
- /* Indicates soft ap start succeeded */
- static final int CMD_START_AP_SUCCESS = BASE + 22;
- /* Indicates soft ap start failed */
- static final int CMD_START_AP_FAILURE = BASE + 23;
- /* Stop the soft access point */
- static final int CMD_STOP_AP = BASE + 24;
- /* Set the soft access point configuration */
- static final int CMD_SET_AP_CONFIG = BASE + 25;
- /* Soft access point configuration set completed */
- static final int CMD_SET_AP_CONFIG_COMPLETED = BASE + 26;
- /* Request the soft access point configuration */
- static final int CMD_REQUEST_AP_CONFIG = BASE + 27;
- /* Response to access point configuration request */
- static final int CMD_RESPONSE_AP_CONFIG = BASE + 28;
- /* Invoked when getting a tether state change notification */
- static final int CMD_TETHER_STATE_CHANGE = BASE + 29;
- /* A delayed message sent to indicate tether state change failed to arrive */
- static final int CMD_TETHER_NOTIFICATION_TIMED_OUT = BASE + 30;
-
- static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 31;
-
- /* Supplicant commands */
- /* Is supplicant alive ? */
- static final int CMD_PING_SUPPLICANT = BASE + 51;
- /* Add/update a network configuration */
- static final int CMD_ADD_OR_UPDATE_NETWORK = BASE + 52;
- /* Delete a network */
- static final int CMD_REMOVE_NETWORK = BASE + 53;
- /* Enable a network. The device will attempt a connection to the given network. */
- static final int CMD_ENABLE_NETWORK = BASE + 54;
- /* Enable all networks */
- static final int CMD_ENABLE_ALL_NETWORKS = BASE + 55;
- /* Blacklist network. De-prioritizes the given BSSID for connection. */
- static final int CMD_BLACKLIST_NETWORK = BASE + 56;
- /* Clear the blacklist network list */
- static final int CMD_CLEAR_BLACKLIST = BASE + 57;
- /* Save configuration */
- static final int CMD_SAVE_CONFIG = BASE + 58;
- /* Get configured networks*/
- static final int CMD_GET_CONFIGURED_NETWORKS = BASE + 59;
-
- /* Supplicant commands after driver start*/
- /* Initiate a scan */
- static final int CMD_START_SCAN = BASE + 71;
- /* Set operational mode. CONNECT, SCAN ONLY, SCAN_ONLY with Wi-Fi off mode */
- static final int CMD_SET_OPERATIONAL_MODE = BASE + 72;
- /* Disconnect from a network */
- static final int CMD_DISCONNECT = BASE + 73;
- /* Reconnect to a network */
- static final int CMD_RECONNECT = BASE + 74;
- /* Reassociate to a network */
- static final int CMD_REASSOCIATE = BASE + 75;
- /* Controls suspend mode optimizations
- *
- * When high perf mode is enabled, suspend mode optimizations are disabled
- *
- * When high perf mode is disabled, suspend mode optimizations are enabled
- *
- * Suspend mode optimizations include:
- * - packet filtering
- * - turn off roaming
- * - DTIM wake up settings
- */
- static final int CMD_SET_HIGH_PERF_MODE = BASE + 77;
- /* Set the country code */
- static final int CMD_SET_COUNTRY_CODE = BASE + 80;
- /* Enables RSSI poll */
- static final int CMD_ENABLE_RSSI_POLL = BASE + 82;
- /* RSSI poll */
- static final int CMD_RSSI_POLL = BASE + 83;
- /* Set up packet filtering */
- static final int CMD_START_PACKET_FILTERING = BASE + 84;
- /* Clear packet filter */
- static final int CMD_STOP_PACKET_FILTERING = BASE + 85;
- /* Enable suspend mode optimizations in the driver */
- static final int CMD_SET_SUSPEND_OPT_ENABLED = BASE + 86;
- /* When there are no saved networks, we do a periodic scan to notify user of
- * an open network */
- static final int CMD_NO_NETWORKS_PERIODIC_SCAN = BASE + 88;
-
- /* arg1 values to CMD_STOP_PACKET_FILTERING and CMD_START_PACKET_FILTERING */
- static final int MULTICAST_V6 = 1;
- static final int MULTICAST_V4 = 0;
-
- /* Set the frequency band */
- static final int CMD_SET_FREQUENCY_BAND = BASE + 90;
- /* Enable background scan for configured networks */
- static final int CMD_ENABLE_BACKGROUND_SCAN = BASE + 91;
- /* Enable TDLS on a specific MAC address */
- static final int CMD_ENABLE_TDLS = BASE + 92;
-
- /* Commands from/to the SupplicantStateTracker */
- /* Reset the supplicant state tracker */
- static final int CMD_RESET_SUPPLICANT_STATE = BASE + 111;
-
- /* P2p commands */
- /* We are ok with no response here since we wont do much with it anyway */
- public static final int CMD_ENABLE_P2P = BASE + 131;
- /* In order to shut down supplicant cleanly, we wait till p2p has
- * been disabled */
- public static final int CMD_DISABLE_P2P_REQ = BASE + 132;
- public static final int CMD_DISABLE_P2P_RSP = BASE + 133;
-
- public static final int CMD_BOOT_COMPLETED = BASE + 134;
-
- /* change the batch scan settings.
- * arg1 = responsible UID
- * arg2 = csph (channel scans per hour)
- * obj = bundle with the new settings and the optional worksource
- */
- public static final int CMD_SET_BATCHED_SCAN = BASE + 135;
- public static final int CMD_START_NEXT_BATCHED_SCAN = BASE + 136;
- public static final int CMD_POLL_BATCHED_SCAN = BASE + 137;
-
- /* Link configuration (IP address, DNS, ...) changes */
- /* An new IP address was added to our interface, or an existing IP address was updated */
- static final int CMD_IP_ADDRESS_UPDATED = BASE + 140;
- /* An IP address was removed from our interface */
- static final int CMD_IP_ADDRESS_REMOVED = BASE + 141;
- /* Reload all networks and reconnect */
- static final int CMD_RELOAD_TLS_AND_RECONNECT = BASE + 142;
-
- /* Wifi state machine modes of operation */
- /* CONNECT_MODE - connect to any 'known' AP when it becomes available */
- public static final int CONNECT_MODE = 1;
- /* SCAN_ONLY_MODE - don't connect to any APs; scan, but only while apps hold lock */
- public static final int SCAN_ONLY_MODE = 2;
- /* SCAN_ONLY_WITH_WIFI_OFF - scan, but don't connect to any APs */
- public static final int SCAN_ONLY_WITH_WIFI_OFF_MODE = 3;
-
- private static final int SUCCESS = 1;
- private static final int FAILURE = -1;
-
- /**
- * The maximum number of times we will retry a connection to an access point
- * for which we have failed in acquiring an IP address from DHCP. A value of
- * N means that we will make N+1 connection attempts in all.
- * <p>
- * See {@link Settings.Secure#WIFI_MAX_DHCP_RETRY_COUNT}. This is the default
- * value if a Settings value is not present.
- */
- private static final int DEFAULT_MAX_DHCP_RETRIES = 9;
-
- /* Tracks if suspend optimizations need to be disabled by DHCP,
- * screen or due to high perf mode.
- * When any of them needs to disable it, we keep the suspend optimizations
- * disabled
- */
- private int mSuspendOptNeedsDisabled = 0;
-
- private static final int SUSPEND_DUE_TO_DHCP = 1;
- private static final int SUSPEND_DUE_TO_HIGH_PERF = 1<<1;
- private static final int SUSPEND_DUE_TO_SCREEN = 1<<2;
-
- /* Tracks if user has enabled suspend optimizations through settings */
- private AtomicBoolean mUserWantsSuspendOpt = new AtomicBoolean(true);
-
- /**
- * Default framework scan interval in milliseconds. This is used in the scenario in which
- * wifi chipset does not support background scanning to set up a
- * periodic wake up scan so that the device can connect to a new access
- * point on the move. {@link Settings.Global#WIFI_FRAMEWORK_SCAN_INTERVAL_MS} can
- * override this.
- */
- private final int mDefaultFrameworkScanIntervalMs;
-
- /**
- * Supplicant scan interval in milliseconds.
- * Comes from {@link Settings.Global#WIFI_SUPPLICANT_SCAN_INTERVAL_MS} or
- * from the default config if the setting is not set
- */
- private long mSupplicantScanIntervalMs;
-
- /**
- * Minimum time interval between enabling all networks.
- * A device can end up repeatedly connecting to a bad network on screen on/off toggle
- * due to enabling every time. We add a threshold to avoid this.
- */
- private static final int MIN_INTERVAL_ENABLE_ALL_NETWORKS_MS = 10 * 60 * 1000; /* 10 minutes */
- private long mLastEnableAllNetworksTime;
-
- /**
- * Starting and shutting down driver too quick causes problems leading to driver
- * being in a bad state. Delay driver stop.
- */
- private final int mDriverStopDelayMs;
- private int mDelayedStopCounter;
- private boolean mInDelayedStop = false;
-
- // sometimes telephony gives us this data before boot is complete and we can't store it
- // until after, so the write is deferred
- private volatile String mPersistedCountryCode;
-
- // Supplicant doesn't like setting the same country code multiple times (it may drop
- // currently connected network), so we save the country code here to avoid redundency
- private String mLastSetCountryCode;
-
- private static final int MIN_RSSI = -200;
- private static final int MAX_RSSI = 256;
-
- /* Default parent state */
- private State mDefaultState = new DefaultState();
- /* Temporary initial state */
- private State mInitialState = new InitialState();
- /* Driver loaded, waiting for supplicant to start */
- private State mSupplicantStartingState = new SupplicantStartingState();
- /* Driver loaded and supplicant ready */
- private State mSupplicantStartedState = new SupplicantStartedState();
- /* Waiting for supplicant to stop and monitor to exit */
- private State mSupplicantStoppingState = new SupplicantStoppingState();
- /* Driver start issued, waiting for completed event */
- private State mDriverStartingState = new DriverStartingState();
- /* Driver started */
- private State mDriverStartedState = new DriverStartedState();
- /* Wait until p2p is disabled
- * This is a special state which is entered right after we exit out of DriverStartedState
- * before transitioning to another state.
- */
- private State mWaitForP2pDisableState = new WaitForP2pDisableState();
- /* Driver stopping */
- private State mDriverStoppingState = new DriverStoppingState();
- /* Driver stopped */
- private State mDriverStoppedState = new DriverStoppedState();
- /* Scan for networks, no connection will be established */
- private State mScanModeState = new ScanModeState();
- /* Connecting to an access point */
- private State mConnectModeState = new ConnectModeState();
- /* Connected at 802.11 (L2) level */
- private State mL2ConnectedState = new L2ConnectedState();
- /* fetching IP after connection to access point (assoc+auth complete) */
- private State mObtainingIpState = new ObtainingIpState();
- /* Waiting for link quality verification to be complete */
- private State mVerifyingLinkState = new VerifyingLinkState();
- /* Connected with IP addr */
- private State mConnectedState = new ConnectedState();
- /* disconnect issued, waiting for network disconnect confirmation */
- private State mDisconnectingState = new DisconnectingState();
- /* Network is not connected, supplicant assoc+auth is not complete */
- private State mDisconnectedState = new DisconnectedState();
- /* Waiting for WPS to be completed*/
- private State mWpsRunningState = new WpsRunningState();
-
- /* Soft ap is starting up */
- private State mSoftApStartingState = new SoftApStartingState();
- /* Soft ap is running */
- private State mSoftApStartedState = new SoftApStartedState();
- /* Soft ap is running and we are waiting for tether notification */
- private State mTetheringState = new TetheringState();
- /* Soft ap is running and we are tethered through connectivity service */
- private State mTetheredState = new TetheredState();
- /* Waiting for untether confirmation before stopping soft Ap */
- private State mUntetheringState = new UntetheringState();
-
- private class TetherStateChange {
- ArrayList<String> available;
- ArrayList<String> active;
- TetherStateChange(ArrayList<String> av, ArrayList<String> ac) {
- available = av;
- active = ac;
- }
- }
-
-
- /**
- * One of {@link WifiManager#WIFI_STATE_DISABLED},
- * {@link WifiManager#WIFI_STATE_DISABLING},
- * {@link WifiManager#WIFI_STATE_ENABLED},
- * {@link WifiManager#WIFI_STATE_ENABLING},
- * {@link WifiManager#WIFI_STATE_UNKNOWN}
- *
- */
- private final AtomicInteger mWifiState = new AtomicInteger(WIFI_STATE_DISABLED);
-
- /**
- * One of {@link WifiManager#WIFI_AP_STATE_DISABLED},
- * {@link WifiManager#WIFI_AP_STATE_DISABLING},
- * {@link WifiManager#WIFI_AP_STATE_ENABLED},
- * {@link WifiManager#WIFI_AP_STATE_ENABLING},
- * {@link WifiManager#WIFI_AP_STATE_FAILED}
- *
- */
- private final AtomicInteger mWifiApState = new AtomicInteger(WIFI_AP_STATE_DISABLED);
-
- private static final int SCAN_REQUEST = 0;
- private static final String ACTION_START_SCAN =
- "com.android.server.WifiManager.action.START_SCAN";
-
- private static final String DELAYED_STOP_COUNTER = "DelayedStopCounter";
- private static final int DRIVER_STOP_REQUEST = 0;
- private static final String ACTION_DELAYED_DRIVER_STOP =
- "com.android.server.WifiManager.action.DELAYED_DRIVER_STOP";
-
- private static final String ACTION_REFRESH_BATCHED_SCAN =
- "com.android.server.WifiManager.action.REFRESH_BATCHED_SCAN";
- /**
- * Keep track of whether WIFI is running.
- */
- private boolean mIsRunning = false;
-
- /**
- * Keep track of whether we last told the battery stats we had started.
- */
- private boolean mReportedRunning = false;
-
- /**
- * Most recently set source of starting WIFI.
- */
- private final WorkSource mRunningWifiUids = new WorkSource();
-
- /**
- * The last reported UIDs that were responsible for starting WIFI.
- */
- private final WorkSource mLastRunningWifiUids = new WorkSource();
-
- private final IBatteryStats mBatteryStats;
-
- private BatchedScanSettings mBatchedScanSettings = null;
-
- /**
- * Track the worksource/cost of the current settings and track what's been noted
- * to the battery stats, so we can mark the end of the previous when changing.
- */
- private WorkSource mBatchedScanWorkSource = null;
- private int mBatchedScanCsph = 0;
- private WorkSource mNotedBatchedScanWorkSource = null;
- private int mNotedBatchedScanCsph = 0;
-
-
- public WifiStateMachine(Context context, String wlanInterface) {
- super("WifiStateMachine");
- mContext = context;
- mInterfaceName = wlanInterface;
-
- mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
- mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
- BatteryStats.SERVICE_NAME));
-
- IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
- mNwService = INetworkManagementService.Stub.asInterface(b);
-
- mP2pSupported = mContext.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_WIFI_DIRECT);
-
- mWifiNative = new WifiNative(mInterfaceName);
- mWifiConfigStore = new WifiConfigStore(context, mWifiNative);
- mWifiMonitor = new WifiMonitor(this, mWifiNative);
- mWifiInfo = new WifiInfo();
- mSupplicantStateTracker = new SupplicantStateTracker(context, this, mWifiConfigStore,
- getHandler());
- mLinkProperties = new LinkProperties();
- mNetlinkLinkProperties = new LinkProperties();
-
- mWifiP2pManager = (WifiP2pManager) mContext.getSystemService(Context.WIFI_P2P_SERVICE);
-
- mNetworkInfo.setIsAvailable(false);
- mLastBssid = null;
- mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
- mLastSignalLevel = -1;
-
- mInterfaceObserver = new InterfaceObserver(this);
- try {
- mNwService.registerObserver(mInterfaceObserver);
- } catch (RemoteException e) {
- loge("Couldn't register interface observer: " + e.toString());
- }
-
- mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
- Intent scanIntent = new Intent(ACTION_START_SCAN, null);
- mScanIntent = PendingIntent.getBroadcast(mContext, SCAN_REQUEST, scanIntent, 0);
-
- Intent batchedIntent = new Intent(ACTION_REFRESH_BATCHED_SCAN, null);
- mBatchedScanIntervalIntent = PendingIntent.getBroadcast(mContext, 0, batchedIntent, 0);
-
- mDefaultFrameworkScanIntervalMs = mContext.getResources().getInteger(
- R.integer.config_wifi_framework_scan_interval);
-
- mDriverStopDelayMs = mContext.getResources().getInteger(
- R.integer.config_wifi_driver_stop_delay);
-
- mBackgroundScanSupported = mContext.getResources().getBoolean(
- R.bool.config_wifi_background_scan_support);
-
- mPrimaryDeviceType = mContext.getResources().getString(
- R.string.config_wifi_p2p_device_type);
-
- mUserWantsSuspendOpt.set(Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);
-
- mContext.registerReceiver(
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- ArrayList<String> available = intent.getStringArrayListExtra(
- ConnectivityManager.EXTRA_AVAILABLE_TETHER);
- ArrayList<String> active = intent.getStringArrayListExtra(
- ConnectivityManager.EXTRA_ACTIVE_TETHER);
- sendMessage(CMD_TETHER_STATE_CHANGE, new TetherStateChange(available, active));
- }
- },new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
-
- mContext.registerReceiver(
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final WorkSource workSource = null;
- startScan(UNKNOWN_SCAN_SOURCE, workSource);
- }
- },
- new IntentFilter(ACTION_START_SCAN));
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_SCREEN_ON);
- filter.addAction(Intent.ACTION_SCREEN_OFF);
- filter.addAction(ACTION_REFRESH_BATCHED_SCAN);
- mContext.registerReceiver(
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
-
- if (action.equals(Intent.ACTION_SCREEN_ON)) {
- handleScreenStateChanged(true);
- } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
- handleScreenStateChanged(false);
- } else if (action.equals(ACTION_REFRESH_BATCHED_SCAN)) {
- startNextBatchedScanAsync();
- }
- }
- }, filter);
-
- mContext.registerReceiver(
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- int counter = intent.getIntExtra(DELAYED_STOP_COUNTER, 0);
- sendMessage(CMD_DELAYED_STOP_DRIVER, counter, 0);
- }
- },
- new IntentFilter(ACTION_DELAYED_DRIVER_STOP));
-
- mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
- Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED), false,
- new ContentObserver(getHandler()) {
- @Override
- public void onChange(boolean selfChange) {
- mUserWantsSuspendOpt.set(Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);
- }
- });
-
- mContext.registerReceiver(
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- sendMessage(CMD_BOOT_COMPLETED);
- }
- },
- new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
-
- mScanResultCache = new LruCache<String, ScanResult>(SCAN_RESULT_CACHE_SIZE);
-
- PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
- mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getName());
-
- mSuspendWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WifiSuspend");
- mSuspendWakeLock.setReferenceCounted(false);
-
- addState(mDefaultState);
- addState(mInitialState, mDefaultState);
- addState(mSupplicantStartingState, mDefaultState);
- addState(mSupplicantStartedState, mDefaultState);
- addState(mDriverStartingState, mSupplicantStartedState);
- addState(mDriverStartedState, mSupplicantStartedState);
- addState(mScanModeState, mDriverStartedState);
- addState(mConnectModeState, mDriverStartedState);
- addState(mL2ConnectedState, mConnectModeState);
- addState(mObtainingIpState, mL2ConnectedState);
- addState(mVerifyingLinkState, mL2ConnectedState);
- addState(mConnectedState, mL2ConnectedState);
- addState(mDisconnectingState, mConnectModeState);
- addState(mDisconnectedState, mConnectModeState);
- addState(mWpsRunningState, mConnectModeState);
- addState(mWaitForP2pDisableState, mSupplicantStartedState);
- addState(mDriverStoppingState, mSupplicantStartedState);
- addState(mDriverStoppedState, mSupplicantStartedState);
- addState(mSupplicantStoppingState, mDefaultState);
- addState(mSoftApStartingState, mDefaultState);
- addState(mSoftApStartedState, mDefaultState);
- addState(mTetheringState, mSoftApStartedState);
- addState(mTetheredState, mSoftApStartedState);
- addState(mUntetheringState, mSoftApStartedState);
-
- setInitialState(mInitialState);
-
- setLogRecSize(2000);
- setLogOnlyTransitions(false);
- if (DBG) setDbg(true);
-
- //start the state machine
- start();
-
- final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED);
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- /*********************************************************
- * Methods exposed for public use
- ********************************************************/
-
- public Messenger getMessenger() {
- return new Messenger(getHandler());
- }
- /**
- * TODO: doc
- */
- public boolean syncPingSupplicant(AsyncChannel channel) {
- Message resultMsg = channel.sendMessageSynchronously(CMD_PING_SUPPLICANT);
- boolean result = (resultMsg.arg1 != FAILURE);
- resultMsg.recycle();
- return result;
- }
-
- /**
- * Initiate a wifi scan. If workSource is not null, blame is given to it,
- * otherwise blame is given to callingUid.
- *
- * @param callingUid The uid initiating the wifi scan. Blame will be given
- * here unless workSource is specified.
- * @param workSource If not null, blame is given to workSource.
- */
- public void startScan(int callingUid, WorkSource workSource) {
- sendMessage(CMD_START_SCAN, callingUid, 0, workSource);
- }
-
- /**
- * start or stop batched scanning using the given settings
- */
- private static final String BATCHED_SETTING = "batched_settings";
- private static final String BATCHED_WORKSOURCE = "batched_worksource";
- public void setBatchedScanSettings(BatchedScanSettings settings, int callingUid, int csph,
- WorkSource workSource) {
- Bundle bundle = new Bundle();
- bundle.putParcelable(BATCHED_SETTING, settings);
- bundle.putParcelable(BATCHED_WORKSOURCE, workSource);
- sendMessage(CMD_SET_BATCHED_SCAN, callingUid, csph, bundle);
- }
-
- public List<BatchedScanResult> syncGetBatchedScanResultsList() {
- synchronized (mBatchedScanResults) {
- List<BatchedScanResult> batchedScanList =
- new ArrayList<BatchedScanResult>(mBatchedScanResults.size());
- for(BatchedScanResult result: mBatchedScanResults) {
- batchedScanList.add(new BatchedScanResult(result));
- }
- return batchedScanList;
- }
- }
-
- public void requestBatchedScanPoll() {
- sendMessage(CMD_POLL_BATCHED_SCAN);
- }
-
- private void startBatchedScan() {
- if (mBatchedScanSettings == null) return;
-
- if (mDhcpActive) {
- if (DBG) log("not starting Batched Scans due to DHCP");
- return;
- }
-
- // first grab any existing data
- retrieveBatchedScanData();
-
- mAlarmManager.cancel(mBatchedScanIntervalIntent);
-
- String scansExpected = mWifiNative.setBatchedScanSettings(mBatchedScanSettings);
- try {
- mExpectedBatchedScans = Integer.parseInt(scansExpected);
- setNextBatchedAlarm(mExpectedBatchedScans);
- if (mExpectedBatchedScans > 0) noteBatchedScanStart();
- } catch (NumberFormatException e) {
- stopBatchedScan();
- loge("Exception parsing WifiNative.setBatchedScanSettings response " + e);
- }
- }
-
- // called from BroadcastListener
- private void startNextBatchedScanAsync() {
- sendMessage(CMD_START_NEXT_BATCHED_SCAN);
- }
-
- private void startNextBatchedScan() {
- // first grab any existing data
- retrieveBatchedScanData();
-
- setNextBatchedAlarm(mExpectedBatchedScans);
- }
-
- private void handleBatchedScanPollRequest() {
- if (DBG) {
- log("handleBatchedScanPoll Request - mBatchedScanMinPollTime=" +
- mBatchedScanMinPollTime + " , mBatchedScanSettings=" +
- mBatchedScanSettings);
- }
- // if there is no appropriate PollTime that's because we either aren't
- // batching or we've already set a time for a poll request
- if (mBatchedScanMinPollTime == 0) return;
- if (mBatchedScanSettings == null) return;
-
- long now = System.currentTimeMillis();
-
- if (now > mBatchedScanMinPollTime) {
- // do the poll and reset our timers
- startNextBatchedScan();
- } else {
- mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, mBatchedScanMinPollTime,
- mBatchedScanIntervalIntent);
- mBatchedScanMinPollTime = 0;
- }
- }
-
- // return true if new/different
- private boolean recordBatchedScanSettings(int responsibleUid, int csph, Bundle bundle) {
- BatchedScanSettings settings = bundle.getParcelable(BATCHED_SETTING);
- WorkSource responsibleWorkSource = bundle.getParcelable(BATCHED_WORKSOURCE);
-
- if (DBG) {
- log("set batched scan to " + settings + " for uid=" + responsibleUid +
- ", worksource=" + responsibleWorkSource);
- }
- if (settings != null) {
- if (settings.equals(mBatchedScanSettings)) return false;
- } else {
- if (mBatchedScanSettings == null) return false;
- }
- mBatchedScanSettings = settings;
- if (responsibleWorkSource == null) responsibleWorkSource = new WorkSource(responsibleUid);
- mBatchedScanWorkSource = responsibleWorkSource;
- mBatchedScanCsph = csph;
- return true;
- }
-
- private void stopBatchedScan() {
- mAlarmManager.cancel(mBatchedScanIntervalIntent);
- retrieveBatchedScanData();
- mWifiNative.setBatchedScanSettings(null);
- noteBatchedScanStop();
- }
-
- private void setNextBatchedAlarm(int scansExpected) {
-
- if (mBatchedScanSettings == null || scansExpected < 1) return;
-
- mBatchedScanMinPollTime = System.currentTimeMillis() +
- mBatchedScanSettings.scanIntervalSec * 1000;
-
- if (mBatchedScanSettings.maxScansPerBatch < scansExpected) {
- scansExpected = mBatchedScanSettings.maxScansPerBatch;
- }
-
- int secToFull = mBatchedScanSettings.scanIntervalSec;
- secToFull *= scansExpected;
-
- int debugPeriod = SystemProperties.getInt("wifi.batchedScan.pollPeriod", 0);
- if (debugPeriod > 0) secToFull = debugPeriod;
-
- // set the alarm to do the next poll. We set it a little short as we'd rather
- // wake up wearly than miss a scan due to buffer overflow
- mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
- + ((secToFull - (mBatchedScanSettings.scanIntervalSec / 2)) * 1000),
- mBatchedScanIntervalIntent);
- }
-
- /**
- * Start reading new scan data
- * Data comes in as:
- * "scancount=5\n"
- * "nextcount=5\n"
- * "apcount=3\n"
- * "trunc\n" (optional)
- * "bssid=...\n"
- * "ssid=...\n"
- * "freq=...\n" (in Mhz)
- * "level=...\n"
- * "dist=...\n" (in cm)
- * "distsd=...\n" (standard deviation, in cm)
- * "===="
- * "bssid=...\n"
- * etc
- * "===="
- * "bssid=...\n"
- * etc
- * "%%%%"
- * "apcount=2\n"
- * "bssid=...\n"
- * etc
- * "%%%%
- * etc
- * "----"
- */
- private final static boolean DEBUG_PARSE = false;
- private void retrieveBatchedScanData() {
- String rawData = mWifiNative.getBatchedScanResults();
- if (DEBUG_PARSE) log("rawData = " + rawData);
- mBatchedScanMinPollTime = 0;
- if (rawData == null || rawData.equalsIgnoreCase("OK")) {
- loge("Unexpected BatchedScanResults :" + rawData);
- return;
- }
-
- int scanCount = 0;
- final String END_OF_BATCHES = "----";
- final String SCANCOUNT = "scancount=";
- final String TRUNCATED = "trunc";
- final String AGE = "age=";
- final String DIST = "dist=";
- final String DISTSD = "distSd=";
-
- String splitData[] = rawData.split("\n");
- int n = 0;
- if (splitData[n].startsWith(SCANCOUNT)) {
- try {
- scanCount = Integer.parseInt(splitData[n++].substring(SCANCOUNT.length()));
- } catch (NumberFormatException e) {
- loge("scancount parseInt Exception from " + splitData[n]);
- }
- } else log("scancount not found");
- if (scanCount == 0) {
- loge("scanCount==0 - aborting");
- return;
- }
-
- final Intent intent = new Intent(WifiManager.BATCHED_SCAN_RESULTS_AVAILABLE_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-
- synchronized (mBatchedScanResults) {
- mBatchedScanResults.clear();
- BatchedScanResult batchedScanResult = new BatchedScanResult();
-
- String bssid = null;
- WifiSsid wifiSsid = null;
- int level = 0;
- int freq = 0;
- int dist, distSd;
- long tsf = 0;
- dist = distSd = ScanResult.UNSPECIFIED;
- final long now = SystemClock.elapsedRealtime();
- final int bssidStrLen = BSSID_STR.length();
-
- while (true) {
- while (n < splitData.length) {
- if (DEBUG_PARSE) logd("parsing " + splitData[n]);
- if (splitData[n].equals(END_OF_BATCHES)) {
- if (n+1 != splitData.length) {
- loge("didn't consume " + (splitData.length-n));
- }
- if (mBatchedScanResults.size() > 0) {
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- }
- logd("retrieveBatchedScanResults X");
- return;
- }
- if ((splitData[n].equals(END_STR)) || splitData[n].equals(DELIMITER_STR)) {
- if (bssid != null) {
- batchedScanResult.scanResults.add(new ScanResult(
- wifiSsid, bssid, "", level, freq, tsf, dist, distSd));
- wifiSsid = null;
- bssid = null;
- level = 0;
- freq = 0;
- tsf = 0;
- dist = distSd = ScanResult.UNSPECIFIED;
- }
- if (splitData[n].equals(END_STR)) {
- if (batchedScanResult.scanResults.size() != 0) {
- mBatchedScanResults.add(batchedScanResult);
- batchedScanResult = new BatchedScanResult();
- } else {
- logd("Found empty batch");
- }
- }
- } else if (splitData[n].equals(TRUNCATED)) {
- batchedScanResult.truncated = true;
- } else if (splitData[n].startsWith(BSSID_STR)) {
- bssid = new String(splitData[n].getBytes(), bssidStrLen,
- splitData[n].length() - bssidStrLen);
- } else if (splitData[n].startsWith(FREQ_STR)) {
- try {
- freq = Integer.parseInt(splitData[n].substring(FREQ_STR.length()));
- } catch (NumberFormatException e) {
- loge("Invalid freqency: " + splitData[n]);
- freq = 0;
- }
- } else if (splitData[n].startsWith(AGE)) {
- try {
- tsf = now - Long.parseLong(splitData[n].substring(AGE.length()));
- tsf *= 1000; // convert mS -> uS
- } catch (NumberFormatException e) {
- loge("Invalid timestamp: " + splitData[n]);
- tsf = 0;
- }
- } else if (splitData[n].startsWith(SSID_STR)) {
- wifiSsid = WifiSsid.createFromAsciiEncoded(
- splitData[n].substring(SSID_STR.length()));
- } else if (splitData[n].startsWith(LEVEL_STR)) {
- try {
- level = Integer.parseInt(splitData[n].substring(LEVEL_STR.length()));
- if (level > 0) level -= 256;
- } catch (NumberFormatException e) {
- loge("Invalid level: " + splitData[n]);
- level = 0;
- }
- } else if (splitData[n].startsWith(DIST)) {
- try {
- dist = Integer.parseInt(splitData[n].substring(DIST.length()));
- } catch (NumberFormatException e) {
- loge("Invalid distance: " + splitData[n]);
- dist = ScanResult.UNSPECIFIED;
- }
- } else if (splitData[n].startsWith(DISTSD)) {
- try {
- distSd = Integer.parseInt(splitData[n].substring(DISTSD.length()));
- } catch (NumberFormatException e) {
- loge("Invalid distanceSd: " + splitData[n]);
- distSd = ScanResult.UNSPECIFIED;
- }
- } else {
- loge("Unable to parse batched scan result line: " + splitData[n]);
- }
- n++;
- }
- rawData = mWifiNative.getBatchedScanResults();
- if (DEBUG_PARSE) log("reading more data:\n" + rawData);
- if (rawData == null) {
- loge("Unexpected null BatchedScanResults");
- return;
- }
- splitData = rawData.split("\n");
- if (splitData.length == 0 || splitData[0].equals("ok")) {
- loge("batch scan results just ended!");
- if (mBatchedScanResults.size() > 0) {
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
- return;
- }
- n = 0;
- }
- }
- }
-
- // If workSource is not null, blame is given to it, otherwise blame is given to callingUid.
- private void noteScanStart(int callingUid, WorkSource workSource) {
- if (mScanWorkSource == null && (callingUid != UNKNOWN_SCAN_SOURCE || workSource != null)) {
- mScanWorkSource = workSource != null ? workSource : new WorkSource(callingUid);
- try {
- mBatteryStats.noteWifiScanStartedFromSource(mScanWorkSource);
- } catch (RemoteException e) {
- log(e.toString());
- }
- }
- }
-
- private void noteScanEnd() {
- if (mScanWorkSource != null) {
- try {
- mBatteryStats.noteWifiScanStoppedFromSource(mScanWorkSource);
- } catch (RemoteException e) {
- log(e.toString());
- } finally {
- mScanWorkSource = null;
- }
- }
- }
-
- private void noteBatchedScanStart() {
- // note the end of a previous scan set
- if (mNotedBatchedScanWorkSource != null &&
- (mNotedBatchedScanWorkSource.equals(mBatchedScanWorkSource) == false ||
- mNotedBatchedScanCsph != mBatchedScanCsph)) {
- try {
- mBatteryStats.noteWifiBatchedScanStoppedFromSource(mNotedBatchedScanWorkSource);
- } catch (RemoteException e) {
- log(e.toString());
- } finally {
- mNotedBatchedScanWorkSource = null;
- mNotedBatchedScanCsph = 0;
- }
- }
- // note the start of the new
- try {
- mBatteryStats.noteWifiBatchedScanStartedFromSource(mBatchedScanWorkSource,
- mBatchedScanCsph);
- mNotedBatchedScanWorkSource = mBatchedScanWorkSource;
- mNotedBatchedScanCsph = mBatchedScanCsph;
- } catch (RemoteException e) {
- log(e.toString());
- }
- }
-
- private void noteBatchedScanStop() {
- if (mNotedBatchedScanWorkSource != null) {
- try {
- mBatteryStats.noteWifiBatchedScanStoppedFromSource(mNotedBatchedScanWorkSource);
- } catch (RemoteException e) {
- log(e.toString());
- } finally {
- mNotedBatchedScanWorkSource = null;
- mNotedBatchedScanCsph = 0;
- }
- }
- }
-
- private void startScanNative(int type) {
- mWifiNative.scan(type);
- mScanResultIsPending = true;
- }
-
- /**
- * TODO: doc
- */
- public void setSupplicantRunning(boolean enable) {
- if (enable) {
- sendMessage(CMD_START_SUPPLICANT);
- } else {
- sendMessage(CMD_STOP_SUPPLICANT);
- }
- }
-
- /**
- * TODO: doc
- */
- public void setHostApRunning(WifiConfiguration wifiConfig, boolean enable) {
- if (enable) {
- sendMessage(CMD_START_AP, wifiConfig);
- } else {
- sendMessage(CMD_STOP_AP);
- }
- }
-
- public void setWifiApConfiguration(WifiConfiguration config) {
- mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);
- }
-
- public WifiConfiguration syncGetWifiApConfiguration() {
- Message resultMsg = mWifiApConfigChannel.sendMessageSynchronously(CMD_REQUEST_AP_CONFIG);
- WifiConfiguration ret = (WifiConfiguration) resultMsg.obj;
- resultMsg.recycle();
- return ret;
- }
-
- /**
- * TODO: doc
- */
- public int syncGetWifiState() {
- return mWifiState.get();
- }
-
- /**
- * TODO: doc
- */
- public String syncGetWifiStateByName() {
- switch (mWifiState.get()) {
- case WIFI_STATE_DISABLING:
- return "disabling";
- case WIFI_STATE_DISABLED:
- return "disabled";
- case WIFI_STATE_ENABLING:
- return "enabling";
- case WIFI_STATE_ENABLED:
- return "enabled";
- case WIFI_STATE_UNKNOWN:
- return "unknown state";
- default:
- return "[invalid state]";
- }
- }
-
- /**
- * TODO: doc
- */
- public int syncGetWifiApState() {
- return mWifiApState.get();
- }
-
- /**
- * TODO: doc
- */
- public String syncGetWifiApStateByName() {
- switch (mWifiApState.get()) {
- case WIFI_AP_STATE_DISABLING:
- return "disabling";
- case WIFI_AP_STATE_DISABLED:
- return "disabled";
- case WIFI_AP_STATE_ENABLING:
- return "enabling";
- case WIFI_AP_STATE_ENABLED:
- return "enabled";
- case WIFI_AP_STATE_FAILED:
- return "failed";
- default:
- return "[invalid state]";
- }
- }
-
- /**
- * Get status information for the current connection, if any.
- * @return a {@link WifiInfo} object containing information about the current connection
- *
- */
- public WifiInfo syncRequestConnectionInfo() {
- return mWifiInfo;
- }
-
- public DhcpResults syncGetDhcpResults() {
- synchronized (mDhcpResultsLock) {
- return new DhcpResults(mDhcpResults);
- }
- }
-
- /**
- * TODO: doc
- */
- public void setDriverStart(boolean enable) {
- if (enable) {
- sendMessage(CMD_START_DRIVER);
- } else {
- sendMessage(CMD_STOP_DRIVER);
- }
- }
-
- /**
- * TODO: doc
- */
- public void setOperationalMode(int mode) {
- if (DBG) log("setting operational mode to " + String.valueOf(mode));
- sendMessage(CMD_SET_OPERATIONAL_MODE, mode, 0);
- }
-
- /**
- * TODO: doc
- */
- public List<ScanResult> syncGetScanResultsList() {
- synchronized (mScanResultCache) {
- List<ScanResult> scanList = new ArrayList<ScanResult>();
- for(ScanResult result: mScanResults) {
- scanList.add(new ScanResult(result));
- }
- return scanList;
- }
- }
-
- /**
- * Disconnect from Access Point
- */
- public void disconnectCommand() {
- sendMessage(CMD_DISCONNECT);
- }
-
- /**
- * Initiate a reconnection to AP
- */
- public void reconnectCommand() {
- sendMessage(CMD_RECONNECT);
- }
-
- /**
- * Initiate a re-association to AP
- */
- public void reassociateCommand() {
- sendMessage(CMD_REASSOCIATE);
- }
-
- /**
- * Reload networks and then reconnect; helps load correct data for TLS networks
- */
-
- public void reloadTlsNetworksAndReconnect() {
- sendMessage(CMD_RELOAD_TLS_AND_RECONNECT);
- }
-
- /**
- * Add a network synchronously
- *
- * @return network id of the new network
- */
- public int syncAddOrUpdateNetwork(AsyncChannel channel, WifiConfiguration config) {
- Message resultMsg = channel.sendMessageSynchronously(CMD_ADD_OR_UPDATE_NETWORK, config);
- int result = resultMsg.arg1;
- resultMsg.recycle();
- return result;
- }
-
- public List<WifiConfiguration> syncGetConfiguredNetworks(AsyncChannel channel) {
- Message resultMsg = channel.sendMessageSynchronously(CMD_GET_CONFIGURED_NETWORKS);
- List<WifiConfiguration> result = (List<WifiConfiguration>) resultMsg.obj;
- resultMsg.recycle();
- return result;
- }
-
- /**
- * Delete a network
- *
- * @param networkId id of the network to be removed
- */
- public boolean syncRemoveNetwork(AsyncChannel channel, int networkId) {
- Message resultMsg = channel.sendMessageSynchronously(CMD_REMOVE_NETWORK, networkId);
- boolean result = (resultMsg.arg1 != FAILURE);
- resultMsg.recycle();
- return result;
- }
-
- /**
- * Enable a network
- *
- * @param netId network id of the network
- * @param disableOthers true, if all other networks have to be disabled
- * @return {@code true} if the operation succeeds, {@code false} otherwise
- */
- public boolean syncEnableNetwork(AsyncChannel channel, int netId, boolean disableOthers) {
- Message resultMsg = channel.sendMessageSynchronously(CMD_ENABLE_NETWORK, netId,
- disableOthers ? 1 : 0);
- boolean result = (resultMsg.arg1 != FAILURE);
- resultMsg.recycle();
- return result;
- }
-
- /**
- * Disable a network
- *
- * @param netId network id of the network
- * @return {@code true} if the operation succeeds, {@code false} otherwise
- */
- public boolean syncDisableNetwork(AsyncChannel channel, int netId) {
- Message resultMsg = channel.sendMessageSynchronously(WifiManager.DISABLE_NETWORK, netId);
- boolean result = (resultMsg.arg1 != WifiManager.DISABLE_NETWORK_FAILED);
- resultMsg.recycle();
- return result;
- }
-
- /**
- * Blacklist a BSSID. This will avoid the AP if there are
- * alternate APs to connect
- *
- * @param bssid BSSID of the network
- */
- public void addToBlacklist(String bssid) {
- sendMessage(CMD_BLACKLIST_NETWORK, bssid);
- }
-
- /**
- * Clear the blacklist list
- *
- */
- public void clearBlacklist() {
- sendMessage(CMD_CLEAR_BLACKLIST);
- }
-
- public void enableRssiPolling(boolean enabled) {
- sendMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0);
- }
-
- public void enableBackgroundScanCommand(boolean enabled) {
- sendMessage(CMD_ENABLE_BACKGROUND_SCAN, enabled ? 1 : 0, 0);
- }
-
- public void enableAllNetworks() {
- sendMessage(CMD_ENABLE_ALL_NETWORKS);
- }
-
- /**
- * Start filtering Multicast v4 packets
- */
- public void startFilteringMulticastV4Packets() {
- mFilteringMulticastV4Packets.set(true);
- sendMessage(CMD_START_PACKET_FILTERING, MULTICAST_V4, 0);
- }
-
- /**
- * Stop filtering Multicast v4 packets
- */
- public void stopFilteringMulticastV4Packets() {
- mFilteringMulticastV4Packets.set(false);
- sendMessage(CMD_STOP_PACKET_FILTERING, MULTICAST_V4, 0);
- }
-
- /**
- * Start filtering Multicast v4 packets
- */
- public void startFilteringMulticastV6Packets() {
- sendMessage(CMD_START_PACKET_FILTERING, MULTICAST_V6, 0);
- }
-
- /**
- * Stop filtering Multicast v4 packets
- */
- public void stopFilteringMulticastV6Packets() {
- sendMessage(CMD_STOP_PACKET_FILTERING, MULTICAST_V6, 0);
- }
-
- /**
- * Set high performance mode of operation.
- * Enabling would set active power mode and disable suspend optimizations;
- * disabling would set auto power mode and enable suspend optimizations
- * @param enable true if enable, false otherwise
- */
- public void setHighPerfModeEnabled(boolean enable) {
- sendMessage(CMD_SET_HIGH_PERF_MODE, enable ? 1 : 0, 0);
- }
-
- /**
- * Set the country code
- * @param countryCode following ISO 3166 format
- * @param persist {@code true} if the setting should be remembered.
- */
- public void setCountryCode(String countryCode, boolean persist) {
- if (persist) {
- mPersistedCountryCode = countryCode;
- Settings.Global.putString(mContext.getContentResolver(),
- Settings.Global.WIFI_COUNTRY_CODE,
- countryCode);
- }
- sendMessage(CMD_SET_COUNTRY_CODE, countryCode);
- mWifiP2pChannel.sendMessage(WifiP2pService.SET_COUNTRY_CODE, countryCode);
- }
-
- /**
- * Set the operational frequency band
- * @param band
- * @param persist {@code true} if the setting should be remembered.
- */
- public void setFrequencyBand(int band, boolean persist) {
- if (persist) {
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.WIFI_FREQUENCY_BAND,
- band);
- }
- sendMessage(CMD_SET_FREQUENCY_BAND, band, 0);
- }
-
- /**
- * Enable TDLS for a specific MAC address
- */
- public void enableTdls(String remoteMacAddress, boolean enable) {
- int enabler = enable ? 1 : 0;
- sendMessage(CMD_ENABLE_TDLS, enabler, 0, remoteMacAddress);
- }
-
- /**
- * Returns the operational frequency band
- */
- public int getFrequencyBand() {
- return mFrequencyBand.get();
- }
-
- /**
- * Returns the wifi configuration file
- */
- public String getConfigFile() {
- return mWifiConfigStore.getConfigFile();
- }
-
- /**
- * Send a message indicating bluetooth adapter connection state changed
- */
- public void sendBluetoothAdapterStateChange(int state) {
- sendMessage(CMD_BLUETOOTH_ADAPTER_STATE_CHANGE, state, 0);
- }
-
- /**
- * Save configuration on supplicant
- *
- * @return {@code true} if the operation succeeds, {@code false} otherwise
- *
- * TODO: deprecate this
- */
- public boolean syncSaveConfig(AsyncChannel channel) {
- Message resultMsg = channel.sendMessageSynchronously(CMD_SAVE_CONFIG);
- boolean result = (resultMsg.arg1 != FAILURE);
- resultMsg.recycle();
- return result;
- }
-
- public void updateBatteryWorkSource(WorkSource newSource) {
- synchronized (mRunningWifiUids) {
- try {
- if (newSource != null) {
- mRunningWifiUids.set(newSource);
- }
- if (mIsRunning) {
- if (mReportedRunning) {
- // If the work source has changed since last time, need
- // to remove old work from battery stats.
- if (mLastRunningWifiUids.diff(mRunningWifiUids)) {
- mBatteryStats.noteWifiRunningChanged(mLastRunningWifiUids,
- mRunningWifiUids);
- mLastRunningWifiUids.set(mRunningWifiUids);
- }
- } else {
- // Now being started, report it.
- mBatteryStats.noteWifiRunning(mRunningWifiUids);
- mLastRunningWifiUids.set(mRunningWifiUids);
- mReportedRunning = true;
- }
- } else {
- if (mReportedRunning) {
- // Last reported we were running, time to stop.
- mBatteryStats.noteWifiStopped(mLastRunningWifiUids);
- mLastRunningWifiUids.clear();
- mReportedRunning = false;
- }
- }
- mWakeLock.setWorkSource(newSource);
- } catch (RemoteException ignore) {
- }
- }
- }
-
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- super.dump(fd, pw, args);
- mSupplicantStateTracker.dump(fd, pw, args);
- pw.println("mLinkProperties " + mLinkProperties);
- pw.println("mWifiInfo " + mWifiInfo);
- pw.println("mDhcpResults " + mDhcpResults);
- pw.println("mNetworkInfo " + mNetworkInfo);
- pw.println("mLastSignalLevel " + mLastSignalLevel);
- pw.println("mLastBssid " + mLastBssid);
- pw.println("mLastNetworkId " + mLastNetworkId);
- pw.println("mReconnectCount " + mReconnectCount);
- pw.println("mOperationalMode " + mOperationalMode);
- pw.println("mUserWantsSuspendOpt " + mUserWantsSuspendOpt);
- pw.println("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled);
- pw.println("Supplicant status " + mWifiNative.status());
- pw.println("mEnableBackgroundScan " + mEnableBackgroundScan);
- pw.println();
- mWifiConfigStore.dump(fd, pw, args);
- }
-
- /*********************************************************
- * Internal private functions
- ********************************************************/
-
- private void handleScreenStateChanged(boolean screenOn) {
- if (DBG) log("handleScreenStateChanged: " + screenOn);
- enableRssiPolling(screenOn);
- if (mBackgroundScanSupported) {
- enableBackgroundScanCommand(screenOn == false);
- }
-
- if (screenOn) enableAllNetworks();
- if (mUserWantsSuspendOpt.get()) {
- if (screenOn) {
- sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 0, 0);
- } else {
- //Allow 2s for suspend optimizations to be set
- mSuspendWakeLock.acquire(2000);
- sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 1, 0);
- }
- }
- mScreenBroadcastReceived.set(true);
- }
-
- private void checkAndSetConnectivityInstance() {
- if (mCm == null) {
- mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- }
- }
-
- private boolean startTethering(ArrayList<String> available) {
-
- boolean wifiAvailable = false;
-
- checkAndSetConnectivityInstance();
-
- String[] wifiRegexs = mCm.getTetherableWifiRegexs();
-
- for (String intf : available) {
- for (String regex : wifiRegexs) {
- if (intf.matches(regex)) {
-
- InterfaceConfiguration ifcg = null;
- try {
- ifcg = mNwService.getInterfaceConfig(intf);
- if (ifcg != null) {
- /* IP/netmask: 192.168.43.1/255.255.255.0 */
- ifcg.setLinkAddress(new LinkAddress(
- NetworkUtils.numericToInetAddress("192.168.43.1"), 24));
- ifcg.setInterfaceUp();
-
- mNwService.setInterfaceConfig(intf, ifcg);
- }
- } catch (Exception e) {
- loge("Error configuring interface " + intf + ", :" + e);
- return false;
- }
-
- if(mCm.tether(intf) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
- loge("Error tethering on " + intf);
- return false;
- }
- mTetherInterfaceName = intf;
- return true;
- }
- }
- }
- // We found no interfaces to tether
- return false;
- }
-
- private void stopTethering() {
-
- checkAndSetConnectivityInstance();
-
- /* Clear the interface config to allow dhcp correctly configure new
- ip settings */
- InterfaceConfiguration ifcg = null;
- try {
- ifcg = mNwService.getInterfaceConfig(mTetherInterfaceName);
- if (ifcg != null) {
- ifcg.setLinkAddress(
- new LinkAddress(NetworkUtils.numericToInetAddress("0.0.0.0"), 0));
- mNwService.setInterfaceConfig(mTetherInterfaceName, ifcg);
- }
- } catch (Exception e) {
- loge("Error resetting interface " + mTetherInterfaceName + ", :" + e);
- }
-
- if (mCm.untether(mTetherInterfaceName) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
- loge("Untether initiate failed!");
- }
- }
-
- private boolean isWifiTethered(ArrayList<String> active) {
-
- checkAndSetConnectivityInstance();
-
- String[] wifiRegexs = mCm.getTetherableWifiRegexs();
- for (String intf : active) {
- for (String regex : wifiRegexs) {
- if (intf.matches(regex)) {
- return true;
- }
- }
- }
- // We found no interfaces that are tethered
- return false;
- }
-
- /**
- * Set the country code from the system setting value, if any.
- */
- private void setCountryCode() {
- String countryCode = Settings.Global.getString(mContext.getContentResolver(),
- Settings.Global.WIFI_COUNTRY_CODE);
- if (countryCode != null && !countryCode.isEmpty()) {
- setCountryCode(countryCode, false);
- } else {
- //use driver default
- }
- }
-
- /**
- * Set the frequency band from the system setting value, if any.
- */
- private void setFrequencyBand() {
- int band = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.WIFI_FREQUENCY_BAND, WifiManager.WIFI_FREQUENCY_BAND_AUTO);
- setFrequencyBand(band, false);
- }
-
- private void setSuspendOptimizationsNative(int reason, boolean enabled) {
- if (DBG) log("setSuspendOptimizationsNative: " + reason + " " + enabled);
- if (enabled) {
- mSuspendOptNeedsDisabled &= ~reason;
- /* None of dhcp, screen or highperf need it disabled and user wants it enabled */
- if (mSuspendOptNeedsDisabled == 0 && mUserWantsSuspendOpt.get()) {
- mWifiNative.setSuspendOptimizations(true);
- }
- } else {
- mSuspendOptNeedsDisabled |= reason;
- mWifiNative.setSuspendOptimizations(false);
- }
- }
-
- private void setSuspendOptimizations(int reason, boolean enabled) {
- if (DBG) log("setSuspendOptimizations: " + reason + " " + enabled);
- if (enabled) {
- mSuspendOptNeedsDisabled &= ~reason;
- } else {
- mSuspendOptNeedsDisabled |= reason;
- }
- if (DBG) log("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled);
- }
-
- private void setWifiState(int wifiState) {
- final int previousWifiState = mWifiState.get();
-
- try {
- if (wifiState == WIFI_STATE_ENABLED) {
- mBatteryStats.noteWifiOn();
- } else if (wifiState == WIFI_STATE_DISABLED) {
- mBatteryStats.noteWifiOff();
- }
- } catch (RemoteException e) {
- loge("Failed to note battery stats in wifi");
- }
-
- mWifiState.set(wifiState);
-
- if (DBG) log("setWifiState: " + syncGetWifiStateByName());
-
- final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState);
- intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState);
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- private void setWifiApState(int wifiApState) {
- final int previousWifiApState = mWifiApState.get();
-
- try {
- if (wifiApState == WIFI_AP_STATE_ENABLED) {
- mBatteryStats.noteWifiOn();
- } else if (wifiApState == WIFI_AP_STATE_DISABLED) {
- mBatteryStats.noteWifiOff();
- }
- } catch (RemoteException e) {
- loge("Failed to note battery stats in wifi");
- }
-
- // Update state
- mWifiApState.set(wifiApState);
-
- if (DBG) log("setWifiApState: " + syncGetWifiApStateByName());
-
- final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, wifiApState);
- intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, previousWifiApState);
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- private static final String ID_STR = "id=";
- private static final String BSSID_STR = "bssid=";
- private static final String FREQ_STR = "freq=";
- private static final String LEVEL_STR = "level=";
- private static final String TSF_STR = "tsf=";
- private static final String FLAGS_STR = "flags=";
- private static final String SSID_STR = "ssid=";
- private static final String DELIMITER_STR = "====";
- private static final String END_STR = "####";
-
- /**
- * Format:
- *
- * id=1
- * bssid=68:7f:76:d7:1a:6e
- * freq=2412
- * level=-44
- * tsf=1344626243700342
- * flags=[WPA2-PSK-CCMP][WPS][ESS]
- * ssid=zfdy
- * ====
- * id=2
- * bssid=68:5f:74:d7:1a:6f
- * freq=5180
- * level=-73
- * tsf=1344626243700373
- * flags=[WPA2-PSK-CCMP][WPS][ESS]
- * ssid=zuby
- * ====
- */
- private void setScanResults() {
- String bssid = "";
- int level = 0;
- int freq = 0;
- long tsf = 0;
- String flags = "";
- WifiSsid wifiSsid = null;
- String scanResults;
- String tmpResults;
- StringBuffer scanResultsBuf = new StringBuffer();
- int sid = 0;
-
- while (true) {
- tmpResults = mWifiNative.scanResults(sid);
- if (TextUtils.isEmpty(tmpResults)) break;
- scanResultsBuf.append(tmpResults);
- scanResultsBuf.append("\n");
- String[] lines = tmpResults.split("\n");
- sid = -1;
- for (int i=lines.length - 1; i >= 0; i--) {
- if (lines[i].startsWith(END_STR)) {
- break;
- } else if (lines[i].startsWith(ID_STR)) {
- try {
- sid = Integer.parseInt(lines[i].substring(ID_STR.length())) + 1;
- } catch (NumberFormatException e) {
- // Nothing to do
- }
- break;
- }
- }
- if (sid == -1) break;
- }
-
- scanResults = scanResultsBuf.toString();
- if (TextUtils.isEmpty(scanResults)) {
- return;
- }
-
- // note that all these splits and substrings keep references to the original
- // huge string buffer while the amount we really want is generally pretty small
- // so make copies instead (one example b/11087956 wasted 400k of heap here).
- synchronized(mScanResultCache) {
- mScanResults = new ArrayList<ScanResult>();
- String[] lines = scanResults.split("\n");
- final int bssidStrLen = BSSID_STR.length();
- final int flagLen = FLAGS_STR.length();
-
- for (String line : lines) {
- if (line.startsWith(BSSID_STR)) {
- bssid = new String(line.getBytes(), bssidStrLen, line.length() - bssidStrLen);
- } else if (line.startsWith(FREQ_STR)) {
- try {
- freq = Integer.parseInt(line.substring(FREQ_STR.length()));
- } catch (NumberFormatException e) {
- freq = 0;
- }
- } else if (line.startsWith(LEVEL_STR)) {
- try {
- level = Integer.parseInt(line.substring(LEVEL_STR.length()));
- /* some implementations avoid negative values by adding 256
- * so we need to adjust for that here.
- */
- if (level > 0) level -= 256;
- } catch(NumberFormatException e) {
- level = 0;
- }
- } else if (line.startsWith(TSF_STR)) {
- try {
- tsf = Long.parseLong(line.substring(TSF_STR.length()));
- } catch (NumberFormatException e) {
- tsf = 0;
- }
- } else if (line.startsWith(FLAGS_STR)) {
- flags = new String(line.getBytes(), flagLen, line.length() - flagLen);
- } else if (line.startsWith(SSID_STR)) {
- wifiSsid = WifiSsid.createFromAsciiEncoded(
- line.substring(SSID_STR.length()));
- } else if (line.startsWith(DELIMITER_STR) || line.startsWith(END_STR)) {
- if (bssid != null) {
- String ssid = (wifiSsid != null) ? wifiSsid.toString() : WifiSsid.NONE;
- String key = bssid + ssid;
- ScanResult scanResult = mScanResultCache.get(key);
- if (scanResult != null) {
- scanResult.level = level;
- scanResult.wifiSsid = wifiSsid;
- // Keep existing API
- scanResult.SSID = (wifiSsid != null) ? wifiSsid.toString() :
- WifiSsid.NONE;
- scanResult.capabilities = flags;
- scanResult.frequency = freq;
- scanResult.timestamp = tsf;
- } else {
- scanResult =
- new ScanResult(
- wifiSsid, bssid, flags, level, freq, tsf);
- mScanResultCache.put(key, scanResult);
- }
- mScanResults.add(scanResult);
- }
- bssid = null;
- level = 0;
- freq = 0;
- tsf = 0;
- flags = "";
- wifiSsid = null;
- }
- }
- }
- }
-
- /*
- * Fetch RSSI and linkspeed on current connection
- */
- private void fetchRssiAndLinkSpeedNative() {
- int newRssi = -1;
- int newLinkSpeed = -1;
-
- String signalPoll = mWifiNative.signalPoll();
-
- if (signalPoll != null) {
- String[] lines = signalPoll.split("\n");
- for (String line : lines) {
- String[] prop = line.split("=");
- if (prop.length < 2) continue;
- try {
- if (prop[0].equals("RSSI")) {
- newRssi = Integer.parseInt(prop[1]);
- } else if (prop[0].equals("LINKSPEED")) {
- newLinkSpeed = Integer.parseInt(prop[1]);
- }
- } catch (NumberFormatException e) {
- //Ignore, defaults on rssi and linkspeed are assigned
- }
- }
- }
-
- if (newRssi != -1 && MIN_RSSI < newRssi && newRssi < MAX_RSSI) { // screen out invalid values
- /* some implementations avoid negative values by adding 256
- * so we need to adjust for that here.
- */
- if (newRssi > 0) newRssi -= 256;
- mWifiInfo.setRssi(newRssi);
- /*
- * Rather then sending the raw RSSI out every time it
- * changes, we precalculate the signal level that would
- * be displayed in the status bar, and only send the
- * broadcast if that much more coarse-grained number
- * changes. This cuts down greatly on the number of
- * broadcasts, at the cost of not informing others
- * interested in RSSI of all the changes in signal
- * level.
- */
- int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, WifiManager.RSSI_LEVELS);
- if (newSignalLevel != mLastSignalLevel) {
- sendRssiChangeBroadcast(newRssi);
- }
- mLastSignalLevel = newSignalLevel;
- } else {
- mWifiInfo.setRssi(MIN_RSSI);
- }
-
- if (newLinkSpeed != -1) {
- mWifiInfo.setLinkSpeed(newLinkSpeed);
- }
- }
-
- /*
- * Fetch TX packet counters on current connection
- */
- private void fetchPktcntNative(RssiPacketCountInfo info) {
- String pktcntPoll = mWifiNative.pktcntPoll();
-
- if (pktcntPoll != null) {
- String[] lines = pktcntPoll.split("\n");
- for (String line : lines) {
- String[] prop = line.split("=");
- if (prop.length < 2) continue;
- try {
- if (prop[0].equals("TXGOOD")) {
- info.txgood = Integer.parseInt(prop[1]);
- } else if (prop[0].equals("TXBAD")) {
- info.txbad = Integer.parseInt(prop[1]);
- }
- } catch (NumberFormatException e) {
- //Ignore
- }
- }
- }
- }
-
- /**
- * Updates mLinkProperties by merging information from various sources.
- *
- * This is needed because the information in mLinkProperties comes from multiple sources (DHCP,
- * netlink, static configuration, ...). When one of these sources of information has updated
- * link properties, we can't just assign them to mLinkProperties or we'd lose track of the
- * information that came from other sources. Instead, when one of those sources has new
- * information, we update the object that tracks the information from that source and then
- * call this method to apply the change to mLinkProperties.
- *
- * The information in mLinkProperties is currently obtained as follows:
- * - Interface name: set in the constructor.
- * - IPv4 and IPv6 addresses: netlink, via mInterfaceObserver.
- * - IPv4 routes, DNS servers, and domains: DHCP.
- * - HTTP proxy: the wifi config store.
- */
- private void updateLinkProperties() {
- LinkProperties newLp = new LinkProperties();
-
- // Interface name and proxy are locally configured.
- newLp.setInterfaceName(mInterfaceName);
- newLp.setHttpProxy(mWifiConfigStore.getProxyProperties(mLastNetworkId));
-
- // IPv4 and IPv6 addresses come from netlink.
- newLp.setLinkAddresses(mNetlinkLinkProperties.getLinkAddresses());
-
- // For now, routing and DNS only come from DHCP or static configuration. In the future,
- // we'll need to merge IPv6 DNS servers and domains coming from netlink.
- synchronized (mDhcpResultsLock) {
- // 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) && (mDhcpResults.linkProperties != null)) {
- LinkProperties lp = mDhcpResults.linkProperties;
- for (RouteInfo route: lp.getRoutes()) {
- newLp.addRoute(route);
- }
- for (InetAddress dns: lp.getDnses()) {
- newLp.addDns(dns);
- }
- newLp.setDomains(lp.getDomains());
- }
- }
-
- // If anything has changed, and we're already connected, send out a notification.
- // If we're still connecting, apps will be notified when we connect.
- if (!newLp.equals(mLinkProperties)) {
- if (DBG) {
- log("Link configuration changed for netId: " + mLastNetworkId
- + " old: " + mLinkProperties + "new: " + newLp);
- }
- mLinkProperties = newLp;
- if (getNetworkDetailedState() == DetailedState.CONNECTED) {
- sendLinkConfigurationChangedBroadcast();
- }
- }
- }
-
- /**
- * Clears all our link properties.
- */
- private void clearLinkProperties() {
- // If the network used DHCP, clear the LinkProperties we stored in the config store.
- if (!mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
- mWifiConfigStore.clearLinkProperties(mLastNetworkId);
- }
-
- // Clear the link properties obtained from DHCP and netlink.
- synchronized(mDhcpResultsLock) {
- if (mDhcpResults != null && mDhcpResults.linkProperties != null) {
- mDhcpResults.linkProperties.clear();
- }
- }
- mNetlinkLinkProperties.clear();
-
- // Now clear the merged link properties.
- mLinkProperties.clear();
- }
-
- private int getMaxDhcpRetries() {
- return Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
- DEFAULT_MAX_DHCP_RETRIES);
- }
-
- private void sendScanResultsAvailableBroadcast() {
- noteScanEnd();
- Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- private void sendRssiChangeBroadcast(final int newRssi) {
- Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(WifiManager.EXTRA_NEW_RSSI, newRssi);
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- private void sendNetworkStateChangeBroadcast(String bssid) {
- Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo));
- intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties (mLinkProperties));
- if (bssid != null)
- intent.putExtra(WifiManager.EXTRA_BSSID, bssid);
- if (mNetworkInfo.getDetailedState() == DetailedState.VERIFYING_POOR_LINK ||
- mNetworkInfo.getDetailedState() == DetailedState.CONNECTED) {
- intent.putExtra(WifiManager.EXTRA_WIFI_INFO, new WifiInfo(mWifiInfo));
- }
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- private void sendLinkConfigurationChangedBroadcast() {
- Intent intent = new Intent(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties));
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- private void sendSupplicantConnectionChangedBroadcast(boolean connected) {
- Intent intent = new Intent(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, connected);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- /**
- * Record the detailed state of a network.
- * @param state the new {@code DetailedState}
- */
- private void setNetworkDetailedState(NetworkInfo.DetailedState state) {
- if (DBG) {
- log("setDetailed state, old ="
- + mNetworkInfo.getDetailedState() + " and new state=" + state);
- }
-
- if (state != mNetworkInfo.getDetailedState()) {
- mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());
- }
- }
-
- private DetailedState getNetworkDetailedState() {
- return mNetworkInfo.getDetailedState();
- }
-
-
- private SupplicantState handleSupplicantStateChange(Message message) {
- StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
- SupplicantState state = stateChangeResult.state;
- // Supplicant state change
- // [31-13] Reserved for future use
- // [8 - 0] Supplicant state (as defined in SupplicantState.java)
- // 50023 supplicant_state_changed (custom|1|5)
- mWifiInfo.setSupplicantState(state);
- // Network id is only valid when we start connecting
- if (SupplicantState.isConnecting(state)) {
- mWifiInfo.setNetworkId(stateChangeResult.networkId);
- } else {
- mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
- }
-
- mWifiInfo.setBSSID(stateChangeResult.BSSID);
- mWifiInfo.setSSID(stateChangeResult.wifiSsid);
-
- mSupplicantStateTracker.sendMessage(Message.obtain(message));
-
- return state;
- }
-
- /**
- * Resets the Wi-Fi Connections by clearing any state, resetting any sockets
- * using the interface, stopping DHCP & disabling interface
- */
- private void handleNetworkDisconnect() {
- if (DBG) log("Stopping DHCP and clearing IP");
-
- stopDhcp();
-
- try {
- mNwService.clearInterfaceAddresses(mInterfaceName);
- mNwService.disableIpv6(mInterfaceName);
- } catch (Exception e) {
- loge("Failed to clear addresses or disable ipv6" + e);
- }
-
- /* Reset data structures */
- mWifiInfo.setInetAddress(null);
- mWifiInfo.setBSSID(null);
- mWifiInfo.setSSID(null);
- mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
- mWifiInfo.setRssi(MIN_RSSI);
- mWifiInfo.setLinkSpeed(-1);
- mWifiInfo.setMeteredHint(false);
-
- setNetworkDetailedState(DetailedState.DISCONNECTED);
- mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.DISCONNECTED);
-
- /* Clear network properties */
- clearLinkProperties();
-
- /* send event to CM & network change broadcast */
- sendNetworkStateChangeBroadcast(mLastBssid);
-
- mLastBssid= null;
- mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
- }
-
- private void handleSupplicantConnectionLoss() {
- /* Socket connection can be lost when we do a graceful shutdown
- * or when the driver is hung. Ensure supplicant is stopped here.
- */
- mWifiMonitor.killSupplicant(mP2pSupported);
- sendSupplicantConnectionChangedBroadcast(false);
- setWifiState(WIFI_STATE_DISABLED);
- }
-
- 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 power save and suspend optimizations during DHCP */
- // Note: The order here is important for now. Brcm driver changes
- // power settings when we control suspend mode optimizations.
- // TODO: Remove this comment when the driver is fixed.
- setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, false);
- mWifiNative.setPowerSave(false);
-
- stopBatchedScan();
-
- /* P2p discovery breaks dhcp, shut it down in order to get through this */
- Message msg = new Message();
- msg.what = WifiP2pService.BLOCK_DISCOVERY;
- msg.arg1 = WifiP2pService.ENABLED;
- msg.arg2 = DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE;
- msg.obj = mDhcpStateMachine;
- mWifiP2pChannel.sendMessage(msg);
- }
-
-
- void startDhcp() {
- if (mDhcpStateMachine == null) {
- mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(
- mContext, WifiStateMachine.this, mInterfaceName);
-
- }
- mDhcpStateMachine.registerForPreDhcpNotification();
- mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
- }
-
- void stopDhcp() {
- if (mDhcpStateMachine != null) {
- /* In case we were in middle of DHCP operation restore back powermode */
- handlePostDhcpSetup();
- mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
- }
- }
-
- void handlePostDhcpSetup() {
- /* Restore power save and suspend optimizations */
- setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, true);
- mWifiNative.setPowerSave(true);
-
- mWifiP2pChannel.sendMessage(WifiP2pService.BLOCK_DISCOVERY, WifiP2pService.DISABLED);
-
- // Set the coexistence mode back to its default value
- mWifiNative.setBluetoothCoexistenceMode(
- mWifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE);
-
- mDhcpActive = false;
-
- startBatchedScan();
- }
-
- private void handleSuccessfulIpConfiguration(DhcpResults dhcpResults) {
- mLastSignalLevel = -1; // force update of signal strength
- mReconnectCount = 0; //Reset IP failure tracking
- synchronized (mDhcpResultsLock) {
- mDhcpResults = dhcpResults;
- }
- LinkProperties linkProperties = dhcpResults.linkProperties;
- mWifiConfigStore.setLinkProperties(mLastNetworkId, new LinkProperties(linkProperties));
- InetAddress addr = null;
- Iterator<InetAddress> addrs = linkProperties.getAddresses().iterator();
- if (addrs.hasNext()) {
- addr = addrs.next();
- }
- mWifiInfo.setInetAddress(addr);
- mWifiInfo.setMeteredHint(dhcpResults.hasMeteredHint());
- updateLinkProperties();
- }
-
- private void handleFailedIpConfiguration() {
- loge("IP configuration failed");
-
- mWifiInfo.setInetAddress(null);
- mWifiInfo.setMeteredHint(false);
- /**
- * If we've exceeded the maximum number of retries for DHCP
- * to a given network, disable the network
- */
- int maxRetries = getMaxDhcpRetries();
- // maxRetries == 0 means keep trying forever
- if (maxRetries > 0 && ++mReconnectCount > maxRetries) {
- loge("Failed " +
- mReconnectCount + " times, Disabling " + mLastNetworkId);
- mWifiConfigStore.disableNetwork(mLastNetworkId,
- WifiConfiguration.DISABLED_DHCP_FAILURE);
- mReconnectCount = 0;
- }
-
- /* DHCP times out after about 30 seconds, we do a
- * disconnect and an immediate reconnect to try again
- */
- mWifiNative.disconnect();
- mWifiNative.reconnect();
- }
-
- /* Current design is to not set the config on a running hostapd but instead
- * stop and start tethering when user changes config on a running access point
- *
- * TODO: Add control channel setup through hostapd that allows changing config
- * on a running daemon
- */
- private void startSoftApWithConfig(final WifiConfiguration config) {
- // start hostapd on a seperate thread
- new Thread(new Runnable() {
- public void run() {
- try {
- mNwService.startAccessPoint(config, mInterfaceName);
- } catch (Exception e) {
- loge("Exception in softap start " + e);
- try {
- mNwService.stopAccessPoint(mInterfaceName);
- mNwService.startAccessPoint(config, mInterfaceName);
- } catch (Exception e1) {
- loge("Exception in softap re-start " + e1);
- sendMessage(CMD_START_AP_FAILURE);
- return;
- }
- }
- if (DBG) log("Soft AP start successful");
- sendMessage(CMD_START_AP_SUCCESS);
- }
- }).start();
- }
-
- /********************************************************
- * HSM states
- *******************************************************/
-
- class DefaultState extends State {
- @Override
- public boolean processMessage(Message message) {
- switch (message.what) {
- case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
- if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
- mWifiP2pChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
- } else {
- loge("WifiP2pService connection failure, error=" + message.arg1);
- }
- break;
- case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
- loge("WifiP2pService channel lost, message.arg1 =" + message.arg1);
- //TODO: Re-establish connection to state machine after a delay
- //mWifiP2pChannel.connect(mContext, getHandler(), mWifiP2pManager.getMessenger());
- break;
- case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE:
- mBluetoothConnectionActive = (message.arg1 !=
- BluetoothAdapter.STATE_DISCONNECTED);
- break;
- /* Synchronous call returns */
- case CMD_PING_SUPPLICANT:
- case CMD_ENABLE_NETWORK:
- case CMD_ADD_OR_UPDATE_NETWORK:
- case CMD_REMOVE_NETWORK:
- case CMD_SAVE_CONFIG:
- replyToMessage(message, message.what, FAILURE);
- break;
- case CMD_GET_CONFIGURED_NETWORKS:
- replyToMessage(message, message.what, (List<WifiConfiguration>) null);
- break;
- case CMD_ENABLE_RSSI_POLL:
- mEnableRssiPolling = (message.arg1 == 1);
- break;
- case CMD_ENABLE_BACKGROUND_SCAN:
- mEnableBackgroundScan = (message.arg1 == 1);
- break;
- case CMD_SET_HIGH_PERF_MODE:
- if (message.arg1 == 1) {
- setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, false);
- } else {
- setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, true);
- }
- break;
- case CMD_BOOT_COMPLETED:
- String countryCode = mPersistedCountryCode;
- if (TextUtils.isEmpty(countryCode) == false) {
- Settings.Global.putString(mContext.getContentResolver(),
- Settings.Global.WIFI_COUNTRY_CODE,
- countryCode);
- // it may be that the state transition that should send this info
- // to the driver happened between mPersistedCountryCode getting set
- // and now, so simply persisting it here would mean we have sent
- // nothing to the driver. Send the cmd so it might be set now.
- sendMessageAtFrontOfQueue(CMD_SET_COUNTRY_CODE, countryCode);
- }
- break;
- case CMD_SET_BATCHED_SCAN:
- recordBatchedScanSettings(message.arg1, message.arg2, (Bundle)message.obj);
- break;
- case CMD_POLL_BATCHED_SCAN:
- handleBatchedScanPollRequest();
- break;
- case CMD_START_NEXT_BATCHED_SCAN:
- startNextBatchedScan();
- break;
- /* Discard */
- case CMD_START_SCAN:
- case CMD_START_SUPPLICANT:
- case CMD_STOP_SUPPLICANT:
- case CMD_STOP_SUPPLICANT_FAILED:
- case CMD_START_DRIVER:
- case CMD_STOP_DRIVER:
- case CMD_DELAYED_STOP_DRIVER:
- case CMD_DRIVER_START_TIMED_OUT:
- case CMD_START_AP:
- case CMD_START_AP_SUCCESS:
- case CMD_START_AP_FAILURE:
- case CMD_STOP_AP:
- case CMD_TETHER_STATE_CHANGE:
- case CMD_TETHER_NOTIFICATION_TIMED_OUT:
- case CMD_DISCONNECT:
- case CMD_RECONNECT:
- case CMD_REASSOCIATE:
- case CMD_RELOAD_TLS_AND_RECONNECT:
- case WifiMonitor.SUP_CONNECTION_EVENT:
- case WifiMonitor.SUP_DISCONNECTION_EVENT:
- case WifiMonitor.NETWORK_CONNECTION_EVENT:
- case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
- case WifiMonitor.SCAN_RESULTS_EVENT:
- case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
- case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
- case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
- case WifiMonitor.WPS_OVERLAP_EVENT:
- case CMD_BLACKLIST_NETWORK:
- case CMD_CLEAR_BLACKLIST:
- case CMD_SET_OPERATIONAL_MODE:
- case CMD_SET_COUNTRY_CODE:
- case CMD_SET_FREQUENCY_BAND:
- case CMD_RSSI_POLL:
- case CMD_ENABLE_ALL_NETWORKS:
- case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
- case DhcpStateMachine.CMD_POST_DHCP_ACTION:
- /* Handled by WifiApConfigStore */
- case CMD_SET_AP_CONFIG:
- case CMD_SET_AP_CONFIG_COMPLETED:
- case CMD_REQUEST_AP_CONFIG:
- case CMD_RESPONSE_AP_CONFIG:
- case WifiWatchdogStateMachine.POOR_LINK_DETECTED:
- case WifiWatchdogStateMachine.GOOD_LINK_DETECTED:
- case CMD_NO_NETWORKS_PERIODIC_SCAN:
- case CMD_DISABLE_P2P_RSP:
- break;
- case DhcpStateMachine.CMD_ON_QUIT:
- mDhcpStateMachine = null;
- break;
- case CMD_SET_SUSPEND_OPT_ENABLED:
- if (message.arg1 == 1) {
- mSuspendWakeLock.release();
- setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, true);
- } else {
- setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, false);
- }
- break;
- case WifiMonitor.DRIVER_HUNG_EVENT:
- setSupplicantRunning(false);
- setSupplicantRunning(true);
- break;
- case WifiManager.CONNECT_NETWORK:
- replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED,
- WifiManager.BUSY);
- break;
- case WifiManager.FORGET_NETWORK:
- replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED,
- WifiManager.BUSY);
- break;
- case WifiManager.SAVE_NETWORK:
- replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED,
- WifiManager.BUSY);
- break;
- case WifiManager.START_WPS:
- replyToMessage(message, WifiManager.WPS_FAILED,
- WifiManager.BUSY);
- break;
- case WifiManager.CANCEL_WPS:
- replyToMessage(message, WifiManager.CANCEL_WPS_FAILED,
- WifiManager.BUSY);
- break;
- case WifiManager.DISABLE_NETWORK:
- replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED,
- WifiManager.BUSY);
- break;
- case WifiManager.RSSI_PKTCNT_FETCH:
- replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_FAILED,
- WifiManager.BUSY);
- break;
- case WifiP2pService.P2P_CONNECTION_CHANGED:
- NetworkInfo info = (NetworkInfo) message.obj;
- mP2pConnected.set(info.isConnected());
- break;
- case WifiP2pService.DISCONNECT_WIFI_REQUEST:
- mTemporarilyDisconnectWifi = (message.arg1 == 1);
- replyToMessage(message, WifiP2pService.DISCONNECT_WIFI_RESPONSE);
- break;
- case CMD_IP_ADDRESS_UPDATED:
- // addLinkAddress is a no-op if called more than once with the same address.
- if (mNetlinkLinkProperties.addLinkAddress((LinkAddress) message.obj)) {
- updateLinkProperties();
- }
- break;
- case CMD_IP_ADDRESS_REMOVED:
- if (mNetlinkLinkProperties.removeLinkAddress((LinkAddress) message.obj)) {
- updateLinkProperties();
- }
- break;
- default:
- loge("Error! unhandled message" + message);
- break;
- }
- return HANDLED;
- }
- }
-
- class InitialState extends State {
- @Override
- public void enter() {
- mWifiNative.unloadDriver();
-
- if (mWifiP2pChannel == null) {
- mWifiP2pChannel = new AsyncChannel();
- mWifiP2pChannel.connect(mContext, getHandler(), mWifiP2pManager.getMessenger());
- }
-
- if (mWifiApConfigChannel == null) {
- mWifiApConfigChannel = new AsyncChannel();
- WifiApConfigStore wifiApConfigStore = WifiApConfigStore.makeWifiApConfigStore(
- mContext, getHandler());
- wifiApConfigStore.loadApConfiguration();
- mWifiApConfigChannel.connectSync(mContext, getHandler(),
- wifiApConfigStore.getMessenger());
- }
- }
- @Override
- public boolean processMessage(Message message) {
- switch (message.what) {
- case CMD_START_SUPPLICANT:
- if (mWifiNative.loadDriver()) {
- try {
- mNwService.wifiFirmwareReload(mInterfaceName, "STA");
- } catch (Exception e) {
- loge("Failed to reload STA firmware " + e);
- // continue
- }
-
- try {
- // A runtime crash can leave the interface up and
- // this affects connectivity when supplicant starts up.
- // Ensure interface is down before a supplicant start.
- mNwService.setInterfaceDown(mInterfaceName);
- // Set privacy extensions
- mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, 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);
- } 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(mWifiNative.startSupplicant(mP2pSupported)) {
- setWifiState(WIFI_STATE_ENABLING);
- if (DBG) log("Supplicant start successful");
- mWifiMonitor.startMonitoring();
- transitionTo(mSupplicantStartingState);
- } else {
- loge("Failed to start supplicant!");
- }
- } else {
- loge("Failed to load driver");
- }
- break;
- case CMD_START_AP:
- if (mWifiNative.loadDriver()) {
- setWifiApState(WIFI_AP_STATE_ENABLING);
- transitionTo(mSoftApStartingState);
- } else {
- loge("Failed to load driver for softap");
- }
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class SupplicantStartingState extends State {
- private void initializeWpsDetails() {
- String detail;
- detail = SystemProperties.get("ro.product.name", "");
- if (!mWifiNative.setDeviceName(detail)) {
- loge("Failed to set device name " + detail);
- }
- detail = SystemProperties.get("ro.product.manufacturer", "");
- if (!mWifiNative.setManufacturer(detail)) {
- loge("Failed to set manufacturer " + detail);
- }
- detail = SystemProperties.get("ro.product.model", "");
- if (!mWifiNative.setModelName(detail)) {
- loge("Failed to set model name " + detail);
- }
- detail = SystemProperties.get("ro.product.model", "");
- if (!mWifiNative.setModelNumber(detail)) {
- loge("Failed to set model number " + detail);
- }
- detail = SystemProperties.get("ro.serialno", "");
- if (!mWifiNative.setSerialNumber(detail)) {
- loge("Failed to set serial number " + detail);
- }
- if (!mWifiNative.setConfigMethods("physical_display virtual_push_button")) {
- loge("Failed to set WPS config methods");
- }
- if (!mWifiNative.setDeviceType(mPrimaryDeviceType)) {
- loge("Failed to set primary device type " + mPrimaryDeviceType);
- }
- }
-
- @Override
- public boolean processMessage(Message message) {
- switch(message.what) {
- case WifiMonitor.SUP_CONNECTION_EVENT:
- if (DBG) log("Supplicant connection established");
- setWifiState(WIFI_STATE_ENABLED);
- mSupplicantRestartCount = 0;
- /* Reset the supplicant state to indicate the supplicant
- * state is not known at this time */
- mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
- /* Initialize data structures */
- mLastBssid = null;
- mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
- mLastSignalLevel = -1;
-
- mWifiInfo.setMacAddress(mWifiNative.getMacAddress());
- mWifiConfigStore.loadAndEnableAllNetworks();
- initializeWpsDetails();
-
- sendSupplicantConnectionChangedBroadcast(true);
- transitionTo(mDriverStartedState);
- break;
- case WifiMonitor.SUP_DISCONNECTION_EVENT:
- if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) {
- loge("Failed to setup control channel, restart supplicant");
- mWifiMonitor.killSupplicant(mP2pSupported);
- transitionTo(mInitialState);
- sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
- } else {
- loge("Failed " + mSupplicantRestartCount +
- " times to start supplicant, unload driver");
- mSupplicantRestartCount = 0;
- setWifiState(WIFI_STATE_UNKNOWN);
- transitionTo(mInitialState);
- }
- break;
- case CMD_START_SUPPLICANT:
- case CMD_STOP_SUPPLICANT:
- case CMD_START_AP:
- case CMD_STOP_AP:
- case CMD_START_DRIVER:
- case CMD_STOP_DRIVER:
- case CMD_SET_OPERATIONAL_MODE:
- case CMD_SET_COUNTRY_CODE:
- case CMD_SET_FREQUENCY_BAND:
- case CMD_START_PACKET_FILTERING:
- case CMD_STOP_PACKET_FILTERING:
- deferMessage(message);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class SupplicantStartedState extends State {
- @Override
- public void enter() {
- /* Wifi is available as long as we have a connection to supplicant */
- mNetworkInfo.setIsAvailable(true);
-
- int defaultInterval = mContext.getResources().getInteger(
- R.integer.config_wifi_supplicant_scan_interval);
-
- mSupplicantScanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),
- Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS,
- defaultInterval);
-
- mWifiNative.setScanInterval((int)mSupplicantScanIntervalMs / 1000);
- }
- @Override
- public boolean processMessage(Message message) {
- switch(message.what) {
- case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */
- if (mP2pSupported) {
- transitionTo(mWaitForP2pDisableState);
- } else {
- transitionTo(mSupplicantStoppingState);
- }
- break;
- case WifiMonitor.SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */
- loge("Connection lost, restart supplicant");
- handleSupplicantConnectionLoss();
- handleNetworkDisconnect();
- mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
- if (mP2pSupported) {
- transitionTo(mWaitForP2pDisableState);
- } else {
- transitionTo(mInitialState);
- }
- sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
- break;
- case WifiMonitor.SCAN_RESULTS_EVENT:
- setScanResults();
- sendScanResultsAvailableBroadcast();
- mScanResultIsPending = false;
- break;
- case CMD_PING_SUPPLICANT:
- boolean ok = mWifiNative.ping();
- replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
- break;
- /* Cannot start soft AP while in client mode */
- case CMD_START_AP:
- loge("Failed to start soft AP with a running supplicant");
- setWifiApState(WIFI_AP_STATE_FAILED);
- break;
- case CMD_SET_OPERATIONAL_MODE:
- mOperationalMode = message.arg1;
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
-
- @Override
- public void exit() {
- mNetworkInfo.setIsAvailable(false);
- }
- }
-
- class SupplicantStoppingState extends State {
- @Override
- public void enter() {
- /* Send any reset commands to supplicant before shutting it down */
- handleNetworkDisconnect();
- if (mDhcpStateMachine != null) {
- mDhcpStateMachine.doQuit();
- }
-
- if (DBG) log("stopping supplicant");
- mWifiMonitor.stopSupplicant();
-
- /* Send ourselves a delayed message to indicate failure after a wait time */
- sendMessageDelayed(obtainMessage(CMD_STOP_SUPPLICANT_FAILED,
- ++mSupplicantStopFailureToken, 0), SUPPLICANT_RESTART_INTERVAL_MSECS);
- setWifiState(WIFI_STATE_DISABLING);
- mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
- }
- @Override
- public boolean processMessage(Message message) {
- switch(message.what) {
- case WifiMonitor.SUP_CONNECTION_EVENT:
- loge("Supplicant connection received while stopping");
- break;
- case WifiMonitor.SUP_DISCONNECTION_EVENT:
- if (DBG) log("Supplicant connection lost");
- handleSupplicantConnectionLoss();
- transitionTo(mInitialState);
- break;
- case CMD_STOP_SUPPLICANT_FAILED:
- if (message.arg1 == mSupplicantStopFailureToken) {
- loge("Timed out on a supplicant stop, kill and proceed");
- handleSupplicantConnectionLoss();
- transitionTo(mInitialState);
- }
- break;
- case CMD_START_SUPPLICANT:
- case CMD_STOP_SUPPLICANT:
- case CMD_START_AP:
- case CMD_STOP_AP:
- case CMD_START_DRIVER:
- case CMD_STOP_DRIVER:
- case CMD_SET_OPERATIONAL_MODE:
- case CMD_SET_COUNTRY_CODE:
- case CMD_SET_FREQUENCY_BAND:
- case CMD_START_PACKET_FILTERING:
- case CMD_STOP_PACKET_FILTERING:
- deferMessage(message);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class DriverStartingState extends State {
- private int mTries;
- @Override
- public void enter() {
- mTries = 1;
- /* Send ourselves a delayed message to start driver a second time */
- sendMessageDelayed(obtainMessage(CMD_DRIVER_START_TIMED_OUT,
- ++mDriverStartToken, 0), DRIVER_START_TIME_OUT_MSECS);
- }
- @Override
- public boolean processMessage(Message message) {
- switch(message.what) {
- case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
- SupplicantState state = handleSupplicantStateChange(message);
- /* If suplicant is exiting out of INTERFACE_DISABLED state into
- * a state that indicates driver has started, it is ready to
- * receive driver commands
- */
- if (SupplicantState.isDriverActive(state)) {
- transitionTo(mDriverStartedState);
- }
- break;
- case CMD_DRIVER_START_TIMED_OUT:
- if (message.arg1 == mDriverStartToken) {
- if (mTries >= 2) {
- loge("Failed to start driver after " + mTries);
- transitionTo(mDriverStoppedState);
- } else {
- loge("Driver start failed, retrying");
- mWakeLock.acquire();
- mWifiNative.startDriver();
- mWakeLock.release();
-
- ++mTries;
- /* Send ourselves a delayed message to start driver again */
- sendMessageDelayed(obtainMessage(CMD_DRIVER_START_TIMED_OUT,
- ++mDriverStartToken, 0), DRIVER_START_TIME_OUT_MSECS);
- }
- }
- break;
- /* Queue driver commands & connection events */
- case CMD_START_DRIVER:
- case CMD_STOP_DRIVER:
- case WifiMonitor.NETWORK_CONNECTION_EVENT:
- case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
- case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
- case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
- case WifiMonitor.WPS_OVERLAP_EVENT:
- case CMD_SET_COUNTRY_CODE:
- case CMD_SET_FREQUENCY_BAND:
- case CMD_START_PACKET_FILTERING:
- case CMD_STOP_PACKET_FILTERING:
- case CMD_START_SCAN:
- case CMD_DISCONNECT:
- case CMD_REASSOCIATE:
- case CMD_RECONNECT:
- deferMessage(message);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class DriverStartedState extends State {
- @Override
- public void enter() {
- mIsRunning = true;
- mInDelayedStop = false;
- mDelayedStopCounter++;
- updateBatteryWorkSource(null);
- /**
- * Enable bluetooth coexistence scan mode when bluetooth connection is active.
- * When this mode is on, some of the low-level scan parameters used by the
- * driver are changed to reduce interference with bluetooth
- */
- mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive);
- /* set country code */
- setCountryCode();
- /* set frequency band of operation */
- setFrequencyBand();
- /* initialize network state */
- setNetworkDetailedState(DetailedState.DISCONNECTED);
-
- /* Remove any filtering on Multicast v6 at start */
- mWifiNative.stopFilteringMulticastV6Packets();
-
- /* Reset Multicast v4 filtering state */
- if (mFilteringMulticastV4Packets.get()) {
- mWifiNative.startFilteringMulticastV4Packets();
- } else {
- mWifiNative.stopFilteringMulticastV4Packets();
- }
-
- mDhcpActive = false;
-
- startBatchedScan();
-
- if (mOperationalMode != CONNECT_MODE) {
- mWifiNative.disconnect();
- mWifiConfigStore.disableAllNetworks();
- if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) {
- setWifiState(WIFI_STATE_DISABLED);
- }
- transitionTo(mScanModeState);
- } else {
- /* Driver stop may have disabled networks, enable right after start */
- mWifiConfigStore.enableAllNetworks();
-
- if (DBG) log("Attempting to reconnect to wifi network ..");
- mWifiNative.reconnect();
-
- // Status pulls in the current supplicant state and network connection state
- // events over the monitor connection. This helps framework sync up with
- // current supplicant state
- mWifiNative.status();
- transitionTo(mDisconnectedState);
- }
-
- // We may have missed screen update at boot
- if (mScreenBroadcastReceived.get() == false) {
- PowerManager powerManager = (PowerManager)mContext.getSystemService(
- Context.POWER_SERVICE);
- handleScreenStateChanged(powerManager.isScreenOn());
- } else {
- // Set the right suspend mode settings
- mWifiNative.setSuspendOptimizations(mSuspendOptNeedsDisabled == 0
- && mUserWantsSuspendOpt.get());
- }
- mWifiNative.setPowerSave(true);
-
- if (mP2pSupported) {
- if (mOperationalMode == CONNECT_MODE) {
- mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P);
- } else {
- // P2P statemachine starts in disabled state, and is not enabled until
- // CMD_ENABLE_P2P is sent from here; so, nothing needs to be done to
- // keep it disabled.
- }
- }
-
- final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_ENABLED);
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- @Override
- public boolean processMessage(Message message) {
- switch(message.what) {
- case CMD_START_SCAN:
- noteScanStart(message.arg1, (WorkSource) message.obj);
- startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP);
- break;
- case CMD_SET_BATCHED_SCAN:
- if (recordBatchedScanSettings(message.arg1, message.arg2,
- (Bundle)message.obj)) {
- startBatchedScan();
- }
- break;
- case CMD_SET_COUNTRY_CODE:
- String country = (String) message.obj;
- if (DBG) log("set country code " + country);
- if (country != null) {
- country = country.toUpperCase(Locale.ROOT);
- if (mLastSetCountryCode == null
- || country.equals(mLastSetCountryCode) == false) {
- if (mWifiNative.setCountryCode(country)) {
- mLastSetCountryCode = country;
- } else {
- loge("Failed to set country code " + country);
- }
- }
- }
- break;
- case CMD_SET_FREQUENCY_BAND:
- int band = message.arg1;
- if (DBG) log("set frequency band " + band);
- if (mWifiNative.setBand(band)) {
- mFrequencyBand.set(band);
- // flush old data - like scan results
- mWifiNative.bssFlush();
- //Fetch the latest scan results when frequency band is set
- startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP);
- } else {
- loge("Failed to set frequency band " + band);
- }
- break;
- case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE:
- mBluetoothConnectionActive = (message.arg1 !=
- BluetoothAdapter.STATE_DISCONNECTED);
- mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive);
- break;
- case CMD_STOP_DRIVER:
- int mode = message.arg1;
-
- /* Already doing a delayed stop */
- if (mInDelayedStop) {
- if (DBG) log("Already in delayed stop");
- break;
- }
- /* disconnect right now, but leave the driver running for a bit */
- mWifiConfigStore.disableAllNetworks();
-
- mInDelayedStop = true;
- mDelayedStopCounter++;
- if (DBG) log("Delayed stop message " + mDelayedStopCounter);
-
- /* send regular delayed shut down */
- Intent driverStopIntent = new Intent(ACTION_DELAYED_DRIVER_STOP, null);
- driverStopIntent.putExtra(DELAYED_STOP_COUNTER, mDelayedStopCounter);
- mDriverStopIntent = PendingIntent.getBroadcast(mContext,
- DRIVER_STOP_REQUEST, driverStopIntent,
- PendingIntent.FLAG_UPDATE_CURRENT);
-
- mAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
- + mDriverStopDelayMs, mDriverStopIntent);
- break;
- case CMD_START_DRIVER:
- if (mInDelayedStop) {
- mInDelayedStop = false;
- mDelayedStopCounter++;
- mAlarmManager.cancel(mDriverStopIntent);
- if (DBG) log("Delayed stop ignored due to start");
- if (mOperationalMode == CONNECT_MODE) {
- mWifiConfigStore.enableAllNetworks();
- }
- }
- break;
- case CMD_DELAYED_STOP_DRIVER:
- if (DBG) log("delayed stop " + message.arg1 + " " + mDelayedStopCounter);
- if (message.arg1 != mDelayedStopCounter) break;
- if (getCurrentState() != mDisconnectedState) {
- mWifiNative.disconnect();
- handleNetworkDisconnect();
- }
- mWakeLock.acquire();
- mWifiNative.stopDriver();
- mWakeLock.release();
- if (mP2pSupported) {
- transitionTo(mWaitForP2pDisableState);
- } else {
- transitionTo(mDriverStoppingState);
- }
- break;
- case CMD_START_PACKET_FILTERING:
- if (message.arg1 == MULTICAST_V6) {
- mWifiNative.startFilteringMulticastV6Packets();
- } else if (message.arg1 == MULTICAST_V4) {
- mWifiNative.startFilteringMulticastV4Packets();
- } else {
- loge("Illegal arugments to CMD_START_PACKET_FILTERING");
- }
- break;
- case CMD_STOP_PACKET_FILTERING:
- if (message.arg1 == MULTICAST_V6) {
- mWifiNative.stopFilteringMulticastV6Packets();
- } else if (message.arg1 == MULTICAST_V4) {
- mWifiNative.stopFilteringMulticastV4Packets();
- } else {
- loge("Illegal arugments to CMD_STOP_PACKET_FILTERING");
- }
- break;
- case CMD_SET_SUSPEND_OPT_ENABLED:
- if (message.arg1 == 1) {
- setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true);
- mSuspendWakeLock.release();
- } else {
- setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false);
- }
- break;
- case CMD_SET_HIGH_PERF_MODE:
- if (message.arg1 == 1) {
- setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, false);
- } else {
- setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true);
- }
- break;
- case CMD_ENABLE_TDLS:
- if (message.obj != null) {
- String remoteAddress = (String) message.obj;
- boolean enable = (message.arg1 == 1);
- mWifiNative.startTdls(remoteAddress, enable);
- }
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- @Override
- public void exit() {
- mIsRunning = false;
- updateBatteryWorkSource(null);
- mScanResults = new ArrayList<ScanResult>();
-
- stopBatchedScan();
-
- final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED);
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- noteScanEnd(); // wrap up any pending request.
-
- mLastSetCountryCode = null;
- }
- }
-
- class WaitForP2pDisableState extends State {
- private State mTransitionToState;
- @Override
- public void enter() {
- switch (getCurrentMessage().what) {
- case WifiMonitor.SUP_DISCONNECTION_EVENT:
- mTransitionToState = mInitialState;
- break;
- case CMD_DELAYED_STOP_DRIVER:
- mTransitionToState = mDriverStoppingState;
- break;
- case CMD_STOP_SUPPLICANT:
- mTransitionToState = mSupplicantStoppingState;
- break;
- default:
- mTransitionToState = mDriverStoppingState;
- break;
- }
- mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_REQ);
- }
- @Override
- public boolean processMessage(Message message) {
- switch(message.what) {
- case WifiStateMachine.CMD_DISABLE_P2P_RSP:
- transitionTo(mTransitionToState);
- break;
- /* Defer wifi start/shut and driver commands */
- case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
- case CMD_START_SUPPLICANT:
- case CMD_STOP_SUPPLICANT:
- case CMD_START_AP:
- case CMD_STOP_AP:
- case CMD_START_DRIVER:
- case CMD_STOP_DRIVER:
- case CMD_SET_OPERATIONAL_MODE:
- case CMD_SET_COUNTRY_CODE:
- case CMD_SET_FREQUENCY_BAND:
- case CMD_START_PACKET_FILTERING:
- case CMD_STOP_PACKET_FILTERING:
- case CMD_START_SCAN:
- case CMD_DISCONNECT:
- case CMD_REASSOCIATE:
- case CMD_RECONNECT:
- deferMessage(message);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class DriverStoppingState extends State {
- @Override
- public boolean processMessage(Message message) {
- switch(message.what) {
- case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
- SupplicantState state = handleSupplicantStateChange(message);
- if (state == SupplicantState.INTERFACE_DISABLED) {
- transitionTo(mDriverStoppedState);
- }
- break;
- /* Queue driver commands */
- case CMD_START_DRIVER:
- case CMD_STOP_DRIVER:
- case CMD_SET_COUNTRY_CODE:
- case CMD_SET_FREQUENCY_BAND:
- case CMD_START_PACKET_FILTERING:
- case CMD_STOP_PACKET_FILTERING:
- case CMD_START_SCAN:
- case CMD_DISCONNECT:
- case CMD_REASSOCIATE:
- case CMD_RECONNECT:
- deferMessage(message);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class DriverStoppedState extends State {
- @Override
- public boolean processMessage(Message message) {
- switch (message.what) {
- case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
- StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
- SupplicantState state = stateChangeResult.state;
- // A WEXT bug means that we can be back to driver started state
- // unexpectedly
- if (SupplicantState.isDriverActive(state)) {
- transitionTo(mDriverStartedState);
- }
- break;
- case CMD_START_DRIVER:
- mWakeLock.acquire();
- mWifiNative.startDriver();
- mWakeLock.release();
- transitionTo(mDriverStartingState);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class ScanModeState extends State {
- private int mLastOperationMode;
- @Override
- public void enter() {
- mLastOperationMode = mOperationalMode;
- }
- @Override
- public boolean processMessage(Message message) {
- switch(message.what) {
- case CMD_SET_OPERATIONAL_MODE:
- if (message.arg1 == CONNECT_MODE) {
-
- if (mLastOperationMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) {
- setWifiState(WIFI_STATE_ENABLED);
- // Load and re-enable networks when going back to enabled state
- // This is essential for networks to show up after restore
- mWifiConfigStore.loadAndEnableAllNetworks();
- mWifiP2pChannel.sendMessage(CMD_ENABLE_P2P);
- } else {
- mWifiConfigStore.enableAllNetworks();
- }
-
- mWifiNative.reconnect();
-
- mOperationalMode = CONNECT_MODE;
- transitionTo(mDisconnectedState);
- } else {
- // Nothing to do
- return HANDLED;
- }
- break;
- // Handle scan. All the connection related commands are
- // handled only in ConnectModeState
- case CMD_START_SCAN:
- noteScanStart(message.arg1, (WorkSource) message.obj);
- startScanNative(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class ConnectModeState extends State {
- @Override
- public boolean processMessage(Message message) {
- WifiConfiguration config;
- boolean ok;
- switch(message.what) {
- case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
- mSupplicantStateTracker.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT);
- break;
- case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
- mSupplicantStateTracker.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT);
- break;
- case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
- SupplicantState state = handleSupplicantStateChange(message);
- // A driver/firmware hang can now put the interface in a down state.
- // We detect the interface going down and recover from it
- if (!SupplicantState.isDriverActive(state)) {
- if (mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) {
- handleNetworkDisconnect();
- }
- log("Detected an interface down, restart driver");
- transitionTo(mDriverStoppedState);
- sendMessage(CMD_START_DRIVER);
- break;
- }
-
- // Supplicant can fail to report a NETWORK_DISCONNECTION_EVENT
- // when authentication times out after a successful connection,
- // we can figure this from the supplicant state. If supplicant
- // state is DISCONNECTED, but the mNetworkInfo says we are not
- // disconnected, we need to handle a disconnection
- if (state == SupplicantState.DISCONNECTED &&
- mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) {
- if (DBG) log("Missed CTRL-EVENT-DISCONNECTED, disconnect");
- handleNetworkDisconnect();
- transitionTo(mDisconnectedState);
- }
- break;
- case WifiP2pService.DISCONNECT_WIFI_REQUEST:
- if (message.arg1 == 1) {
- mWifiNative.disconnect();
- mTemporarilyDisconnectWifi = true;
- } else {
- mWifiNative.reconnect();
- mTemporarilyDisconnectWifi = false;
- }
- break;
- case CMD_ADD_OR_UPDATE_NETWORK:
- config = (WifiConfiguration) message.obj;
- replyToMessage(message, CMD_ADD_OR_UPDATE_NETWORK,
- mWifiConfigStore.addOrUpdateNetwork(config));
- break;
- case CMD_REMOVE_NETWORK:
- ok = mWifiConfigStore.removeNetwork(message.arg1);
- replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
- break;
- case CMD_ENABLE_NETWORK:
- ok = mWifiConfigStore.enableNetwork(message.arg1, message.arg2 == 1);
- replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
- break;
- case CMD_ENABLE_ALL_NETWORKS:
- long time = android.os.SystemClock.elapsedRealtime();
- if (time - mLastEnableAllNetworksTime > MIN_INTERVAL_ENABLE_ALL_NETWORKS_MS) {
- mWifiConfigStore.enableAllNetworks();
- mLastEnableAllNetworksTime = time;
- }
- break;
- case WifiManager.DISABLE_NETWORK:
- if (mWifiConfigStore.disableNetwork(message.arg1,
- WifiConfiguration.DISABLED_UNKNOWN_REASON) == true) {
- replyToMessage(message, WifiManager.DISABLE_NETWORK_SUCCEEDED);
- } else {
- replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED,
- WifiManager.ERROR);
- }
- break;
- case CMD_BLACKLIST_NETWORK:
- mWifiNative.addToBlacklist((String)message.obj);
- break;
- case CMD_CLEAR_BLACKLIST:
- mWifiNative.clearBlacklist();
- break;
- case CMD_SAVE_CONFIG:
- ok = mWifiConfigStore.saveConfig();
- replyToMessage(message, CMD_SAVE_CONFIG, ok ? SUCCESS : FAILURE);
-
- // Inform the backup manager about a data change
- IBackupManager ibm = IBackupManager.Stub.asInterface(
- ServiceManager.getService(Context.BACKUP_SERVICE));
- if (ibm != null) {
- try {
- ibm.dataChanged("com.android.providers.settings");
- } catch (Exception e) {
- // Try again later
- }
- }
- break;
- case CMD_GET_CONFIGURED_NETWORKS:
- replyToMessage(message, message.what,
- mWifiConfigStore.getConfiguredNetworks());
- break;
- /* Do a redundant disconnect without transition */
- case CMD_DISCONNECT:
- mWifiNative.disconnect();
- break;
- case CMD_RECONNECT:
- mWifiNative.reconnect();
- break;
- case CMD_REASSOCIATE:
- mWifiNative.reassociate();
- break;
- case CMD_RELOAD_TLS_AND_RECONNECT:
- if (mWifiConfigStore.needsUnlockedKeyStore()) {
- logd("Reconnecting to give a chance to un-connected TLS networks");
- mWifiNative.disconnect();
- mWifiNative.reconnect();
- }
- break;
- case WifiManager.CONNECT_NETWORK:
- /* The connect message can contain a network id passed as arg1 on message or
- * or a config passed as obj on message.
- * For a new network, a config is passed to create and connect.
- * For an existing network, a network id is passed
- */
- int netId = message.arg1;
- config = (WifiConfiguration) message.obj;
-
- /* Save the network config */
- if (config != null) {
- NetworkUpdateResult result = mWifiConfigStore.saveNetwork(config);
- netId = result.getNetworkId();
- }
-
- if (mWifiConfigStore.selectNetwork(netId) &&
- mWifiNative.reconnect()) {
- /* The state tracker handles enabling networks upon completion/failure */
- mSupplicantStateTracker.sendMessage(WifiManager.CONNECT_NETWORK);
- replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED);
- /* Expect a disconnection from the old connection */
- transitionTo(mDisconnectingState);
- } else {
- loge("Failed to connect config: " + config + " netId: " + netId);
- replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED,
- WifiManager.ERROR);
- break;
- }
- break;
- case WifiManager.SAVE_NETWORK:
- config = (WifiConfiguration) message.obj;
- NetworkUpdateResult result = mWifiConfigStore.saveNetwork(config);
- if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) {
- replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED);
- } else {
- loge("Failed to save network");
- replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED,
- WifiManager.ERROR);
- }
- break;
- case WifiManager.FORGET_NETWORK:
- if (mWifiConfigStore.forgetNetwork(message.arg1)) {
- replyToMessage(message, WifiManager.FORGET_NETWORK_SUCCEEDED);
- } else {
- loge("Failed to forget network");
- replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED,
- WifiManager.ERROR);
- }
- break;
- case WifiManager.START_WPS:
- WpsInfo wpsInfo = (WpsInfo) message.obj;
- WpsResult wpsResult;
- switch (wpsInfo.setup) {
- case WpsInfo.PBC:
- wpsResult = mWifiConfigStore.startWpsPbc(wpsInfo);
- break;
- case WpsInfo.KEYPAD:
- wpsResult = mWifiConfigStore.startWpsWithPinFromAccessPoint(wpsInfo);
- break;
- case WpsInfo.DISPLAY:
- wpsResult = mWifiConfigStore.startWpsWithPinFromDevice(wpsInfo);
- break;
- default:
- wpsResult = new WpsResult(Status.FAILURE);
- loge("Invalid setup for WPS");
- break;
- }
- if (wpsResult.status == Status.SUCCESS) {
- replyToMessage(message, WifiManager.START_WPS_SUCCEEDED, wpsResult);
- transitionTo(mWpsRunningState);
- } else {
- loge("Failed to start WPS with config " + wpsInfo.toString());
- replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.ERROR);
- }
- break;
- case WifiMonitor.NETWORK_CONNECTION_EVENT:
- if (DBG) log("Network connection established");
- mLastNetworkId = message.arg1;
- mLastBssid = (String) message.obj;
-
- mWifiInfo.setBSSID(mLastBssid);
- mWifiInfo.setNetworkId(mLastNetworkId);
- /* send event to CM & network change broadcast */
- setNetworkDetailedState(DetailedState.OBTAINING_IPADDR);
- sendNetworkStateChangeBroadcast(mLastBssid);
- transitionTo(mObtainingIpState);
- break;
- case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
- if (DBG) log("Network connection lost");
- handleNetworkDisconnect();
- transitionTo(mDisconnectedState);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class L2ConnectedState extends State {
- @Override
- public void enter() {
- mRssiPollToken++;
- if (mEnableRssiPolling) {
- sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0);
- }
- }
-
- @Override
- public void exit() {
- handleNetworkDisconnect();
- }
-
- @Override
- public boolean processMessage(Message message) {
- switch (message.what) {
- case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
- handlePreDhcpSetup();
- break;
- case DhcpStateMachine.CMD_POST_DHCP_ACTION:
- handlePostDhcpSetup();
- if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS) {
- if (DBG) log("DHCP successful");
- handleSuccessfulIpConfiguration((DhcpResults) message.obj);
- transitionTo(mVerifyingLinkState);
- } else if (message.arg1 == DhcpStateMachine.DHCP_FAILURE) {
- if (DBG) log("DHCP failed");
- handleFailedIpConfiguration();
- transitionTo(mDisconnectingState);
- }
- break;
- case CMD_DISCONNECT:
- mWifiNative.disconnect();
- transitionTo(mDisconnectingState);
- break;
- case WifiP2pService.DISCONNECT_WIFI_REQUEST:
- if (message.arg1 == 1) {
- mWifiNative.disconnect();
- mTemporarilyDisconnectWifi = true;
- transitionTo(mDisconnectingState);
- }
- break;
- case CMD_SET_OPERATIONAL_MODE:
- if (message.arg1 != CONNECT_MODE) {
- sendMessage(CMD_DISCONNECT);
- deferMessage(message);
- }
- break;
- case CMD_START_SCAN:
- /* Do not attempt to connect when we are already connected */
- noteScanStart(message.arg1, (WorkSource) message.obj);
- startScanNative(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP);
- break;
- /* Ignore connection to same network */
- case WifiManager.CONNECT_NETWORK:
- int netId = message.arg1;
- if (mWifiInfo.getNetworkId() == netId) {
- break;
- }
- return NOT_HANDLED;
- case WifiManager.SAVE_NETWORK:
- WifiConfiguration config = (WifiConfiguration) message.obj;
- NetworkUpdateResult result = mWifiConfigStore.saveNetwork(config);
- if (mWifiInfo.getNetworkId() == result.getNetworkId()) {
- if (result.hasIpChanged()) {
- log("Reconfiguring IP on connection");
- transitionTo(mObtainingIpState);
- }
- if (result.hasProxyChanged()) {
- log("Reconfiguring proxy on connection");
- updateLinkProperties();
- }
- }
-
- if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) {
- replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED);
- } else {
- loge("Failed to save network");
- replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED,
- WifiManager.ERROR);
- }
- break;
- /* Ignore */
- case WifiMonitor.NETWORK_CONNECTION_EVENT:
- break;
- case CMD_RSSI_POLL:
- if (message.arg1 == mRssiPollToken) {
- // Get Info and continue polling
- fetchRssiAndLinkSpeedNative();
- sendMessageDelayed(obtainMessage(CMD_RSSI_POLL,
- mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS);
- } else {
- // Polling has completed
- }
- break;
- case CMD_ENABLE_RSSI_POLL:
- mEnableRssiPolling = (message.arg1 == 1);
- mRssiPollToken++;
- if (mEnableRssiPolling) {
- // first poll
- fetchRssiAndLinkSpeedNative();
- sendMessageDelayed(obtainMessage(CMD_RSSI_POLL,
- mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS);
- }
- break;
- case WifiManager.RSSI_PKTCNT_FETCH:
- RssiPacketCountInfo info = new RssiPacketCountInfo();
- fetchRssiAndLinkSpeedNative();
- info.rssi = mWifiInfo.getRssi();
- fetchPktcntNative(info);
- replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED, info);
- break;
- default:
- return NOT_HANDLED;
- }
-
- return HANDLED;
- }
- }
-
- class ObtainingIpState extends State {
- @Override
- public void enter() {
- if (!mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
- // TODO: If we're switching between static IP configuration and DHCP, remove the
- // static configuration first.
- startDhcp();
- } else {
- // stop any running dhcp before assigning static IP
- stopDhcp();
- DhcpResults dhcpResults = new DhcpResults(
- mWifiConfigStore.getLinkProperties(mLastNetworkId));
- InterfaceConfiguration ifcg = new InterfaceConfiguration();
- Iterator<LinkAddress> addrs =
- dhcpResults.linkProperties.getLinkAddresses().iterator();
- if (!addrs.hasNext()) {
- loge("Static IP lacks address");
- sendMessage(CMD_STATIC_IP_FAILURE);
- } else {
- ifcg.setLinkAddress(addrs.next());
- ifcg.setInterfaceUp();
- try {
- mNwService.setInterfaceConfig(mInterfaceName, ifcg);
- if (DBG) log("Static IP configuration succeeded");
- sendMessage(CMD_STATIC_IP_SUCCESS, dhcpResults);
- } catch (RemoteException re) {
- loge("Static IP configuration failed: " + re);
- sendMessage(CMD_STATIC_IP_FAILURE);
- } catch (IllegalStateException e) {
- loge("Static IP configuration failed: " + e);
- sendMessage(CMD_STATIC_IP_FAILURE);
- }
- }
- }
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) log(getName() + message.toString() + "\n");
- switch(message.what) {
- case CMD_STATIC_IP_SUCCESS:
- handleSuccessfulIpConfiguration((DhcpResults) message.obj);
- transitionTo(mVerifyingLinkState);
- break;
- case CMD_STATIC_IP_FAILURE:
- handleFailedIpConfiguration();
- transitionTo(mDisconnectingState);
- break;
- case WifiManager.SAVE_NETWORK:
- deferMessage(message);
- break;
- /* Defer any power mode changes since we must keep active power mode at DHCP */
- case CMD_SET_HIGH_PERF_MODE:
- deferMessage(message);
- break;
- /* Defer scan request since we should not switch to other channels at DHCP */
- case CMD_START_SCAN:
- deferMessage(message);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class VerifyingLinkState extends State {
- @Override
- public void enter() {
- log(getName() + " enter");
- setNetworkDetailedState(DetailedState.VERIFYING_POOR_LINK);
- mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.VERIFYING_POOR_LINK);
- sendNetworkStateChangeBroadcast(mLastBssid);
- }
- @Override
- public boolean processMessage(Message message) {
- switch (message.what) {
- case WifiWatchdogStateMachine.POOR_LINK_DETECTED:
- //stay here
- log(getName() + " POOR_LINK_DETECTED: no transition");
- break;
- case WifiWatchdogStateMachine.GOOD_LINK_DETECTED:
- log(getName() + " GOOD_LINK_DETECTED: transition to captive portal check");
- // Send out a broadcast with the CAPTIVE_PORTAL_CHECK to preserve
- // existing behaviour. The captive portal check really happens after we
- // transition into DetailedState.CONNECTED.
- setNetworkDetailedState(DetailedState.CAPTIVE_PORTAL_CHECK);
- mWifiConfigStore.updateStatus(mLastNetworkId,
- DetailedState.CAPTIVE_PORTAL_CHECK);
- sendNetworkStateChangeBroadcast(mLastBssid);
-
- // NOTE: This might look like an odd place to enable IPV6 but this is in
- // response to transitioning into GOOD_LINK_DETECTED. Similarly, we disable
- // ipv6 when we transition into POOR_LINK_DETECTED in mConnectedState.
- try {
- mNwService.enableIpv6(mInterfaceName);
- } catch (RemoteException re) {
- loge("Failed to enable IPv6: " + re);
- } catch (IllegalStateException e) {
- loge("Failed to enable IPv6: " + e);
- }
-
- log(getName() + " GOOD_LINK_DETECTED: transition to CONNECTED");
- setNetworkDetailedState(DetailedState.CONNECTED);
- mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.CONNECTED);
- sendNetworkStateChangeBroadcast(mLastBssid);
- transitionTo(mConnectedState);
-
- break;
- default:
- if (DBG) log(getName() + " what=" + message.what + " NOT_HANDLED");
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class ConnectedState extends State {
- @Override
- public boolean processMessage(Message message) {
- switch (message.what) {
- case WifiWatchdogStateMachine.POOR_LINK_DETECTED:
- if (DBG) log("Watchdog reports poor link");
- try {
- mNwService.disableIpv6(mInterfaceName);
- } catch (RemoteException re) {
- loge("Failed to disable IPv6: " + re);
- } catch (IllegalStateException e) {
- loge("Failed to disable IPv6: " + e);
- }
- /* Report a disconnect */
- setNetworkDetailedState(DetailedState.DISCONNECTED);
- mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.DISCONNECTED);
- sendNetworkStateChangeBroadcast(mLastBssid);
-
- transitionTo(mVerifyingLinkState);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
-
- @Override
- public void exit() {
- /* Request a CS wakelock during transition to mobile */
- checkAndSetConnectivityInstance();
- mCm.requestNetworkTransitionWakelock(getName());
- }
- }
-
- class DisconnectingState extends State {
- @Override
- public boolean processMessage(Message message) {
- switch (message.what) {
- case CMD_SET_OPERATIONAL_MODE:
- if (message.arg1 != CONNECT_MODE) {
- deferMessage(message);
- }
- break;
- case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
- /* If we get a SUPPLICANT_STATE_CHANGE_EVENT before NETWORK_DISCONNECTION_EVENT
- * we have missed the network disconnection, transition to mDisconnectedState
- * and handle the rest of the events there
- */
- deferMessage(message);
- handleNetworkDisconnect();
- transitionTo(mDisconnectedState);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class DisconnectedState extends State {
- private boolean mAlarmEnabled = false;
- /* This is set from the overlay config file or from a secure setting.
- * A value of 0 disables scanning in the framework.
- */
- private long mFrameworkScanIntervalMs;
-
- private void setScanAlarm(boolean enabled) {
- if (enabled == mAlarmEnabled) return;
- if (enabled) {
- if (mFrameworkScanIntervalMs > 0) {
- mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
- System.currentTimeMillis() + mFrameworkScanIntervalMs,
- mFrameworkScanIntervalMs,
- mScanIntent);
- mAlarmEnabled = true;
- }
- } else {
- mAlarmManager.cancel(mScanIntent);
- mAlarmEnabled = false;
- }
- }
-
- @Override
- public void enter() {
- // We dont scan frequently if this is a temporary disconnect
- // due to p2p
- if (mTemporarilyDisconnectWifi) {
- mWifiP2pChannel.sendMessage(WifiP2pService.DISCONNECT_WIFI_RESPONSE);
- return;
- }
-
- mFrameworkScanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),
- Settings.Global.WIFI_FRAMEWORK_SCAN_INTERVAL_MS,
- mDefaultFrameworkScanIntervalMs);
- /*
- * We initiate background scanning if it is enabled, otherwise we
- * initiate an infrequent scan that wakes up the device to ensure
- * a user connects to an access point on the move
- */
- if (mEnableBackgroundScan) {
- /* If a regular scan result is pending, do not initiate background
- * scan until the scan results are returned. This is needed because
- * initiating a background scan will cancel the regular scan and
- * scan results will not be returned until background scanning is
- * cleared
- */
- if (!mScanResultIsPending) {
- mWifiNative.enableBackgroundScan(true);
- }
- } else {
- setScanAlarm(true);
- }
-
- /**
- * If we have no networks saved, the supplicant stops doing the periodic scan.
- * The scans are useful to notify the user of the presence of an open network.
- * Note that these are not wake up scans.
- */
- if (!mP2pConnected.get() && mWifiConfigStore.getConfiguredNetworks().size() == 0) {
- sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
- ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
- }
- }
- @Override
- public boolean processMessage(Message message) {
- boolean ret = HANDLED;
- switch (message.what) {
- case CMD_NO_NETWORKS_PERIODIC_SCAN:
- if (mP2pConnected.get()) break;
- if (message.arg1 == mPeriodicScanToken &&
- mWifiConfigStore.getConfiguredNetworks().size() == 0) {
- sendMessage(CMD_START_SCAN, UNKNOWN_SCAN_SOURCE, 0, (WorkSource) null);
- sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
- ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
- }
- break;
- case WifiManager.FORGET_NETWORK:
- case CMD_REMOVE_NETWORK:
- // Set up a delayed message here. After the forget/remove is handled
- // the handled delayed message will determine if there is a need to
- // scan and continue
- sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
- ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
- ret = NOT_HANDLED;
- break;
- case CMD_SET_OPERATIONAL_MODE:
- if (message.arg1 != CONNECT_MODE) {
- mOperationalMode = message.arg1;
-
- mWifiConfigStore.disableAllNetworks();
- if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) {
- mWifiP2pChannel.sendMessage(CMD_DISABLE_P2P_REQ);
- setWifiState(WIFI_STATE_DISABLED);
- }
-
- transitionTo(mScanModeState);
- }
- break;
- case CMD_ENABLE_BACKGROUND_SCAN:
- mEnableBackgroundScan = (message.arg1 == 1);
- if (mEnableBackgroundScan) {
- mWifiNative.enableBackgroundScan(true);
- setScanAlarm(false);
- } else {
- mWifiNative.enableBackgroundScan(false);
- setScanAlarm(true);
- }
- break;
- /* Ignore network disconnect */
- case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
- break;
- case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
- StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
- setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state));
- /* ConnectModeState does the rest of the handling */
- ret = NOT_HANDLED;
- break;
- case CMD_START_SCAN:
- /* Disable background scan temporarily during a regular scan */
- if (mEnableBackgroundScan) {
- mWifiNative.enableBackgroundScan(false);
- }
- /* Handled in parent state */
- ret = NOT_HANDLED;
- break;
- case WifiMonitor.SCAN_RESULTS_EVENT:
- /* Re-enable background scan when a pending scan result is received */
- if (mEnableBackgroundScan && mScanResultIsPending) {
- mWifiNative.enableBackgroundScan(true);
- }
- /* Handled in parent state */
- ret = NOT_HANDLED;
- break;
- case WifiP2pService.P2P_CONNECTION_CHANGED:
- NetworkInfo info = (NetworkInfo) message.obj;
- mP2pConnected.set(info.isConnected());
- if (mP2pConnected.get()) {
- int defaultInterval = mContext.getResources().getInteger(
- R.integer.config_wifi_scan_interval_p2p_connected);
- long scanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),
- Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS,
- defaultInterval);
- mWifiNative.setScanInterval((int) scanIntervalMs/1000);
- } else if (mWifiConfigStore.getConfiguredNetworks().size() == 0) {
- if (DBG) log("Turn on scanning after p2p disconnected");
- sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
- ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
- }
- case CMD_RECONNECT:
- case CMD_REASSOCIATE:
- if (mTemporarilyDisconnectWifi) {
- // Drop a third party reconnect/reassociate if STA is
- // temporarily disconnected for p2p
- break;
- } else {
- // ConnectModeState handles it
- ret = NOT_HANDLED;
- }
- break;
- default:
- ret = NOT_HANDLED;
- }
- return ret;
- }
-
- @Override
- public void exit() {
- /* No need for a background scan upon exit from a disconnected state */
- if (mEnableBackgroundScan) {
- mWifiNative.enableBackgroundScan(false);
- }
- setScanAlarm(false);
- }
- }
-
- class WpsRunningState extends State {
- //Tracks the source to provide a reply
- private Message mSourceMessage;
- @Override
- public void enter() {
- mSourceMessage = Message.obtain(getCurrentMessage());
- }
- @Override
- public boolean processMessage(Message message) {
- switch (message.what) {
- case WifiMonitor.WPS_SUCCESS_EVENT:
- // Ignore intermediate success, wait for full connection
- break;
- case WifiMonitor.NETWORK_CONNECTION_EVENT:
- replyToMessage(mSourceMessage, WifiManager.WPS_COMPLETED);
- mSourceMessage.recycle();
- mSourceMessage = null;
- deferMessage(message);
- transitionTo(mDisconnectedState);
- break;
- case WifiMonitor.WPS_OVERLAP_EVENT:
- replyToMessage(mSourceMessage, WifiManager.WPS_FAILED,
- WifiManager.WPS_OVERLAP_ERROR);
- mSourceMessage.recycle();
- mSourceMessage = null;
- transitionTo(mDisconnectedState);
- break;
- case WifiMonitor.WPS_FAIL_EVENT:
- //arg1 has the reason for the failure
- replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, message.arg1);
- mSourceMessage.recycle();
- mSourceMessage = null;
- transitionTo(mDisconnectedState);
- break;
- case WifiMonitor.WPS_TIMEOUT_EVENT:
- replyToMessage(mSourceMessage, WifiManager.WPS_FAILED,
- WifiManager.WPS_TIMED_OUT);
- mSourceMessage.recycle();
- mSourceMessage = null;
- transitionTo(mDisconnectedState);
- break;
- case WifiManager.START_WPS:
- replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.IN_PROGRESS);
- break;
- case WifiManager.CANCEL_WPS:
- if (mWifiNative.cancelWps()) {
- replyToMessage(message, WifiManager.CANCEL_WPS_SUCCEDED);
- } else {
- replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, WifiManager.ERROR);
- }
- transitionTo(mDisconnectedState);
- break;
- /* Defer all commands that can cause connections to a different network
- * or put the state machine out of connect mode
- */
- case CMD_STOP_DRIVER:
- case CMD_SET_OPERATIONAL_MODE:
- case WifiManager.CONNECT_NETWORK:
- case CMD_ENABLE_NETWORK:
- case CMD_RECONNECT:
- case CMD_REASSOCIATE:
- deferMessage(message);
- break;
- case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
- if (DBG) log("Network connection lost");
- handleNetworkDisconnect();
- break;
- case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
- if (DBG) log("Ignore Assoc reject event during WPS Connection");
- break;
- case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
- // Disregard auth failure events during WPS connection. The
- // EAP sequence is retried several times, and there might be
- // failures (especially for wps pin). We will get a WPS_XXX
- // event at the end of the sequence anyway.
- if (DBG) log("Ignore auth failure during WPS connection");
- break;
- case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
- //Throw away supplicant state changes when WPS is running.
- //We will start getting supplicant state changes once we get
- //a WPS success or failure
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
-
- @Override
- public void exit() {
- mWifiConfigStore.enableAllNetworks();
- mWifiConfigStore.loadConfiguredNetworks();
- }
- }
-
- class SoftApStartingState extends State {
- @Override
- public void enter() {
- final Message message = getCurrentMessage();
- if (message.what == CMD_START_AP) {
- final WifiConfiguration config = (WifiConfiguration) message.obj;
-
- if (config == null) {
- mWifiApConfigChannel.sendMessage(CMD_REQUEST_AP_CONFIG);
- } else {
- mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);
- startSoftApWithConfig(config);
- }
- } else {
- throw new RuntimeException("Illegal transition to SoftApStartingState: " + message);
- }
- }
- @Override
- public boolean processMessage(Message message) {
- switch(message.what) {
- case CMD_START_SUPPLICANT:
- case CMD_STOP_SUPPLICANT:
- case CMD_START_AP:
- case CMD_STOP_AP:
- case CMD_START_DRIVER:
- case CMD_STOP_DRIVER:
- case CMD_SET_OPERATIONAL_MODE:
- case CMD_SET_COUNTRY_CODE:
- case CMD_SET_FREQUENCY_BAND:
- case CMD_START_PACKET_FILTERING:
- case CMD_STOP_PACKET_FILTERING:
- case CMD_TETHER_STATE_CHANGE:
- deferMessage(message);
- break;
- case WifiStateMachine.CMD_RESPONSE_AP_CONFIG:
- WifiConfiguration config = (WifiConfiguration) message.obj;
- if (config != null) {
- startSoftApWithConfig(config);
- } else {
- loge("Softap config is null!");
- sendMessage(CMD_START_AP_FAILURE);
- }
- break;
- case CMD_START_AP_SUCCESS:
- setWifiApState(WIFI_AP_STATE_ENABLED);
- transitionTo(mSoftApStartedState);
- break;
- case CMD_START_AP_FAILURE:
- setWifiApState(WIFI_AP_STATE_FAILED);
- transitionTo(mInitialState);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class SoftApStartedState extends State {
- @Override
- public boolean processMessage(Message message) {
- switch(message.what) {
- case CMD_STOP_AP:
- if (DBG) log("Stopping Soft AP");
- /* We have not tethered at this point, so we just shutdown soft Ap */
- try {
- mNwService.stopAccessPoint(mInterfaceName);
- } catch(Exception e) {
- loge("Exception in stopAccessPoint()");
- }
- setWifiApState(WIFI_AP_STATE_DISABLED);
- transitionTo(mInitialState);
- break;
- case CMD_START_AP:
- // Ignore a start on a running access point
- break;
- /* Fail client mode operation when soft AP is enabled */
- case CMD_START_SUPPLICANT:
- loge("Cannot start supplicant with a running soft AP");
- setWifiState(WIFI_STATE_UNKNOWN);
- break;
- case CMD_TETHER_STATE_CHANGE:
- TetherStateChange stateChange = (TetherStateChange) message.obj;
- if (startTethering(stateChange.available)) {
- transitionTo(mTetheringState);
- }
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class TetheringState extends State {
- @Override
- public void enter() {
- /* Send ourselves a delayed message to shut down if tethering fails to notify */
- sendMessageDelayed(obtainMessage(CMD_TETHER_NOTIFICATION_TIMED_OUT,
- ++mTetherToken, 0), TETHER_NOTIFICATION_TIME_OUT_MSECS);
- }
- @Override
- public boolean processMessage(Message message) {
- switch(message.what) {
- case CMD_TETHER_STATE_CHANGE:
- TetherStateChange stateChange = (TetherStateChange) message.obj;
- if (isWifiTethered(stateChange.active)) {
- transitionTo(mTetheredState);
- }
- return HANDLED;
- case CMD_TETHER_NOTIFICATION_TIMED_OUT:
- if (message.arg1 == mTetherToken) {
- loge("Failed to get tether update, shutdown soft access point");
- transitionTo(mSoftApStartedState);
- // Needs to be first thing handled
- sendMessageAtFrontOfQueue(CMD_STOP_AP);
- }
- break;
- case CMD_START_SUPPLICANT:
- case CMD_STOP_SUPPLICANT:
- case CMD_START_AP:
- case CMD_STOP_AP:
- case CMD_START_DRIVER:
- case CMD_STOP_DRIVER:
- case CMD_SET_OPERATIONAL_MODE:
- case CMD_SET_COUNTRY_CODE:
- case CMD_SET_FREQUENCY_BAND:
- case CMD_START_PACKET_FILTERING:
- case CMD_STOP_PACKET_FILTERING:
- deferMessage(message);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class TetheredState extends State {
- @Override
- public boolean processMessage(Message message) {
- switch(message.what) {
- case CMD_TETHER_STATE_CHANGE:
- TetherStateChange stateChange = (TetherStateChange) message.obj;
- if (!isWifiTethered(stateChange.active)) {
- loge("Tethering reports wifi as untethered!, shut down soft Ap");
- setHostApRunning(null, false);
- setHostApRunning(null, true);
- }
- return HANDLED;
- case CMD_STOP_AP:
- if (DBG) log("Untethering before stopping AP");
- setWifiApState(WIFI_AP_STATE_DISABLING);
- stopTethering();
- transitionTo(mUntetheringState);
- // More work to do after untethering
- deferMessage(message);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class UntetheringState extends State {
- @Override
- public void enter() {
- /* Send ourselves a delayed message to shut down if tethering fails to notify */
- sendMessageDelayed(obtainMessage(CMD_TETHER_NOTIFICATION_TIMED_OUT,
- ++mTetherToken, 0), TETHER_NOTIFICATION_TIME_OUT_MSECS);
-
- }
- @Override
- public boolean processMessage(Message message) {
- switch(message.what) {
- case CMD_TETHER_STATE_CHANGE:
- TetherStateChange stateChange = (TetherStateChange) message.obj;
-
- /* Wait till wifi is untethered */
- if (isWifiTethered(stateChange.active)) break;
-
- transitionTo(mSoftApStartedState);
- break;
- case CMD_TETHER_NOTIFICATION_TIMED_OUT:
- if (message.arg1 == mTetherToken) {
- loge("Failed to get tether update, force stop access point");
- transitionTo(mSoftApStartedState);
- }
- break;
- case CMD_START_SUPPLICANT:
- case CMD_STOP_SUPPLICANT:
- case CMD_START_AP:
- case CMD_STOP_AP:
- case CMD_START_DRIVER:
- case CMD_STOP_DRIVER:
- case CMD_SET_OPERATIONAL_MODE:
- case CMD_SET_COUNTRY_CODE:
- case CMD_SET_FREQUENCY_BAND:
- case CMD_START_PACKET_FILTERING:
- case CMD_STOP_PACKET_FILTERING:
- deferMessage(message);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- //State machine initiated requests can have replyTo set to null indicating
- //there are no recepients, we ignore those reply actions
- private void replyToMessage(Message msg, int what) {
- if (msg.replyTo == null) return;
- Message dstMsg = obtainMessageWithArg2(msg);
- dstMsg.what = what;
- mReplyChannel.replyToMessage(msg, dstMsg);
- }
-
- private void replyToMessage(Message msg, int what, int arg1) {
- if (msg.replyTo == null) return;
- Message dstMsg = obtainMessageWithArg2(msg);
- dstMsg.what = what;
- dstMsg.arg1 = arg1;
- mReplyChannel.replyToMessage(msg, dstMsg);
- }
-
- private void replyToMessage(Message msg, int what, Object obj) {
- if (msg.replyTo == null) return;
- Message dstMsg = obtainMessageWithArg2(msg);
- dstMsg.what = what;
- dstMsg.obj = obj;
- mReplyChannel.replyToMessage(msg, dstMsg);
- }
-
- /**
- * arg2 on the source message has a unique id that needs to be retained in replies
- * to match the request
-
- * see WifiManager for details
- */
- private Message obtainMessageWithArg2(Message srcMsg) {
- Message msg = Message.obtain();
- msg.arg2 = srcMsg.arg2;
- return msg;
- }
-}
diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
deleted file mode 100644
index c2823e8..0000000
--- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
+++ /dev/null
@@ -1,1209 +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.wifi;
-
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.database.ContentObserver;
-import android.net.ConnectivityManager;
-import android.net.LinkProperties;
-import android.net.NetworkInfo;
-import android.net.wifi.RssiPacketCountInfo;
-import android.os.Message;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.util.LruCache;
-
-import com.android.internal.util.AsyncChannel;
-import com.android.internal.util.Protocol;
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.text.DecimalFormat;
-
-/**
- * WifiWatchdogStateMachine monitors the connection to a WiFi network. When WiFi
- * connects at L2 layer, the beacons from access point reach the device and it
- * can maintain a connection, but the application connectivity can be flaky (due
- * to bigger packet size exchange).
- * <p>
- * We now monitor the quality of the last hop on WiFi using packet loss ratio as
- * an indicator to decide if the link is good enough to switch to Wi-Fi as the
- * uplink.
- * <p>
- * When WiFi is connected, the WiFi watchdog keeps sampling the RSSI and the
- * instant packet loss, and record it as per-AP loss-to-rssi statistics. When
- * the instant packet loss is higher than a threshold, the WiFi watchdog sends a
- * poor link notification to avoid WiFi connection temporarily.
- * <p>
- * While WiFi is being avoided, the WiFi watchdog keep watching the RSSI to
- * bring the WiFi connection back. Once the RSSI is high enough to achieve a
- * lower packet loss, a good link detection is sent such that the WiFi
- * connection become available again.
- * <p>
- * BSSID roaming has been taken into account. When user is moving across
- * multiple APs, the WiFi watchdog will detect that and keep watching the
- * currently connected AP.
- * <p>
- * Power impact should be minimal since much of the measurement relies on
- * passive statistics already being tracked at the driver and the polling is
- * done when screen is turned on and the RSSI is in a certain range.
- *
- * @hide
- */
-public class WifiWatchdogStateMachine extends StateMachine {
-
- private static final boolean DBG = false;
-
- private static final int BASE = Protocol.BASE_WIFI_WATCHDOG;
-
- /* Internal events */
- private static final int EVENT_WATCHDOG_TOGGLED = BASE + 1;
- private static final int EVENT_NETWORK_STATE_CHANGE = BASE + 2;
- private static final int EVENT_RSSI_CHANGE = BASE + 3;
- private static final int EVENT_SUPPLICANT_STATE_CHANGE = BASE + 4;
- private static final int EVENT_WIFI_RADIO_STATE_CHANGE = BASE + 5;
- private static final int EVENT_WATCHDOG_SETTINGS_CHANGE = BASE + 6;
- private static final int EVENT_BSSID_CHANGE = BASE + 7;
- private static final int EVENT_SCREEN_ON = BASE + 8;
- private static final int EVENT_SCREEN_OFF = BASE + 9;
-
- /* Internal messages */
- private static final int CMD_RSSI_FETCH = BASE + 11;
-
- /* Notifications from/to WifiStateMachine */
- static final int POOR_LINK_DETECTED = BASE + 21;
- static final int GOOD_LINK_DETECTED = BASE + 22;
-
- public static final boolean DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED = false;
-
- /*
- * RSSI levels as used by notification icon
- * Level 4 -55 <= RSSI
- * Level 3 -66 <= RSSI < -55
- * Level 2 -77 <= RSSI < -67
- * Level 1 -88 <= RSSI < -78
- * Level 0 RSSI < -88
- */
-
- /**
- * WiFi link statistics is monitored and recorded actively below this threshold.
- * <p>
- * Larger threshold is more adaptive but increases sampling cost.
- */
- private static final int LINK_MONITOR_LEVEL_THRESHOLD = WifiManager.RSSI_LEVELS - 1;
-
- /**
- * Remember packet loss statistics of how many BSSIDs.
- * <p>
- * Larger size is usually better but requires more space.
- */
- private static final int BSSID_STAT_CACHE_SIZE = 20;
-
- /**
- * RSSI range of a BSSID statistics.
- * Within the range, (RSSI -> packet loss %) mappings are stored.
- * <p>
- * Larger range is usually better but requires more space.
- */
- private static final int BSSID_STAT_RANGE_LOW_DBM = -105;
-
- /**
- * See {@link #BSSID_STAT_RANGE_LOW_DBM}.
- */
- private static final int BSSID_STAT_RANGE_HIGH_DBM = -45;
-
- /**
- * How many consecutive empty data point to trigger a empty-cache detection.
- * In this case, a preset/default loss value (function on RSSI) is used.
- * <p>
- * In normal uses, some RSSI values may never be seen due to channel randomness.
- * However, the size of such empty RSSI chunk in normal use is generally 1~2.
- */
- private static final int BSSID_STAT_EMPTY_COUNT = 3;
-
- /**
- * Sample interval for packet loss statistics, in msec.
- * <p>
- * Smaller interval is more accurate but increases sampling cost (battery consumption).
- */
- private static final long LINK_SAMPLING_INTERVAL_MS = 1 * 1000;
-
- /**
- * Coefficients (alpha) for moving average for packet loss tracking.
- * Must be within (0.0, 1.0).
- * <p>
- * Equivalent number of samples: N = 2 / alpha - 1 .
- * We want the historic loss to base on more data points to be statistically reliable.
- * We want the current instant loss to base on less data points to be responsive.
- */
- private static final double EXP_COEFFICIENT_RECORD = 0.1;
-
- /**
- * See {@link #EXP_COEFFICIENT_RECORD}.
- */
- private static final double EXP_COEFFICIENT_MONITOR = 0.5;
-
- /**
- * Thresholds for sending good/poor link notifications, in packet loss %.
- * Good threshold must be smaller than poor threshold.
- * Use smaller poor threshold to avoid WiFi more aggressively.
- * Use smaller good threshold to bring back WiFi more conservatively.
- * <p>
- * When approaching the boundary, loss ratio jumps significantly within a few dBs.
- * 50% loss threshold is a good balance between accuracy and reponsiveness.
- * <=10% good threshold is a safe value to avoid jumping back to WiFi too easily.
- */
- private static final double POOR_LINK_LOSS_THRESHOLD = 0.5;
-
- /**
- * See {@link #POOR_LINK_LOSS_THRESHOLD}.
- */
- private static final double GOOD_LINK_LOSS_THRESHOLD = 0.1;
-
- /**
- * Number of samples to confirm before sending a poor link notification.
- * Response time = confirm_count * sample_interval .
- * <p>
- * A smaller threshold improves response speed but may suffer from randomness.
- * According to experiments, 3~5 are good values to achieve a balance.
- * These parameters should be tuned along with {@link #LINK_SAMPLING_INTERVAL_MS}.
- */
- private static final int POOR_LINK_SAMPLE_COUNT = 3;
-
- /**
- * Minimum volume (converted from pkt/sec) to detect a poor link, to avoid randomness.
- * <p>
- * According to experiments, 1pkt/sec is too sensitive but 3pkt/sec is slightly unresponsive.
- */
- private static final double POOR_LINK_MIN_VOLUME = 2.0 * LINK_SAMPLING_INTERVAL_MS / 1000.0;
-
- /**
- * When a poor link is detected, we scan over this range (based on current
- * poor link RSSI) for a target RSSI that satisfies a target packet loss.
- * Refer to {@link #GOOD_LINK_TARGET}.
- * <p>
- * We want range_min not too small to avoid jumping back to WiFi too easily.
- */
- private static final int GOOD_LINK_RSSI_RANGE_MIN = 3;
-
- /**
- * See {@link #GOOD_LINK_RSSI_RANGE_MIN}.
- */
- private static final int GOOD_LINK_RSSI_RANGE_MAX = 20;
-
- /**
- * Adaptive good link target to avoid flapping.
- * When a poor link is detected, a good link target is calculated as follows:
- * <p>
- * targetRSSI = min { rssi | loss(rssi) < GOOD_LINK_LOSS_THRESHOLD } + rssi_adj[i],
- * where rssi is within the above GOOD_LINK_RSSI_RANGE.
- * targetCount = sample_count[i] .
- * <p>
- * While WiFi is being avoided, we keep monitoring its signal strength.
- * Good link notification is sent when we see current RSSI >= targetRSSI
- * for targetCount consecutive times.
- * <p>
- * Index i is incremented each time after a poor link detection.
- * Index i is decreased to at most k if the last poor link was at lease reduce_time[k] ago.
- * <p>
- * Intuitively, larger index i makes it more difficult to get back to WiFi, avoiding flapping.
- * In experiments, (+9 dB / 30 counts) makes it quite difficult to achieve.
- * Avoid using it unless flapping is really bad (say, last poor link is < 1 min ago).
- */
- private static final GoodLinkTarget[] GOOD_LINK_TARGET = {
- /* rssi_adj, sample_count, reduce_time */
- new GoodLinkTarget( 0, 3, 30 * 60000 ),
- new GoodLinkTarget( 3, 5, 5 * 60000 ),
- new GoodLinkTarget( 6, 10, 1 * 60000 ),
- new GoodLinkTarget( 9, 30, 0 * 60000 ),
- };
-
- /**
- * The max time to avoid a BSSID, to prevent avoiding forever.
- * If current RSSI is at least min_rssi[i], the max avoidance time is at most max_time[i]
- * <p>
- * It is unusual to experience high packet loss at high RSSI. Something unusual must be
- * happening (e.g. strong interference). For higher signal strengths, we set the avoidance
- * time to be low to allow for quick turn around from temporary interference.
- * <p>
- * See {@link BssidStatistics#poorLinkDetected}.
- */
- private static final MaxAvoidTime[] MAX_AVOID_TIME = {
- /* max_time, min_rssi */
- new MaxAvoidTime( 30 * 60000, -200 ),
- new MaxAvoidTime( 5 * 60000, -70 ),
- new MaxAvoidTime( 0 * 60000, -55 ),
- };
-
- /* Framework related */
- private Context mContext;
- private ContentResolver mContentResolver;
- private WifiManager mWifiManager;
- private IntentFilter mIntentFilter;
- private BroadcastReceiver mBroadcastReceiver;
- private AsyncChannel mWsmChannel = new AsyncChannel();
- private WifiInfo mWifiInfo;
- private LinkProperties mLinkProperties;
-
- /* System settingss related */
- private static boolean sWifiOnly = false;
- private boolean mPoorNetworkDetectionEnabled;
-
- /* Poor link detection related */
- private LruCache<String, BssidStatistics> mBssidCache =
- new LruCache<String, BssidStatistics>(BSSID_STAT_CACHE_SIZE);
- private int mRssiFetchToken = 0;
- private int mCurrentSignalLevel;
- private BssidStatistics mCurrentBssid;
- private VolumeWeightedEMA mCurrentLoss;
- private boolean mIsScreenOn = true;
- private static double sPresetLoss[];
-
- /* WiFi watchdog state machine related */
- private DefaultState mDefaultState = new DefaultState();
- private WatchdogDisabledState mWatchdogDisabledState = new WatchdogDisabledState();
- private WatchdogEnabledState mWatchdogEnabledState = new WatchdogEnabledState();
- private NotConnectedState mNotConnectedState = new NotConnectedState();
- private VerifyingLinkState mVerifyingLinkState = new VerifyingLinkState();
- private ConnectedState mConnectedState = new ConnectedState();
- private OnlineWatchState mOnlineWatchState = new OnlineWatchState();
- private LinkMonitoringState mLinkMonitoringState = new LinkMonitoringState();
- private OnlineState mOnlineState = new OnlineState();
-
- /**
- * STATE MAP
- * Default
- * / \
- * Disabled Enabled
- * / \ \
- * NotConnected Verifying Connected
- * /---------\
- * (all other states)
- */
- private WifiWatchdogStateMachine(Context context) {
- super("WifiWatchdogStateMachine");
- mContext = context;
- mContentResolver = context.getContentResolver();
- mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
- mWsmChannel.connectSync(mContext, getHandler(),
- mWifiManager.getWifiStateMachineMessenger());
-
- setupNetworkReceiver();
-
- // the content observer to listen needs a handler
- registerForSettingsChanges();
- registerForWatchdogToggle();
- addState(mDefaultState);
- addState(mWatchdogDisabledState, mDefaultState);
- addState(mWatchdogEnabledState, mDefaultState);
- addState(mNotConnectedState, mWatchdogEnabledState);
- addState(mVerifyingLinkState, mWatchdogEnabledState);
- addState(mConnectedState, mWatchdogEnabledState);
- addState(mOnlineWatchState, mConnectedState);
- addState(mLinkMonitoringState, mConnectedState);
- addState(mOnlineState, mConnectedState);
-
- if (isWatchdogEnabled()) {
- setInitialState(mNotConnectedState);
- } else {
- setInitialState(mWatchdogDisabledState);
- }
- setLogRecSize(25);
- setLogOnlyTransitions(true);
- updateSettings();
- }
-
- public static WifiWatchdogStateMachine makeWifiWatchdogStateMachine(Context context) {
- ContentResolver contentResolver = context.getContentResolver();
-
- ConnectivityManager cm = (ConnectivityManager) context.getSystemService(
- Context.CONNECTIVITY_SERVICE);
- sWifiOnly = (cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false);
-
- // Watchdog is always enabled. Poor network detection can be seperately turned on/off
- // TODO: Remove this setting & clean up state machine since we always have
- // watchdog in an enabled state
- putSettingsGlobalBoolean(contentResolver, Settings.Global.WIFI_WATCHDOG_ON, true);
-
- WifiWatchdogStateMachine wwsm = new WifiWatchdogStateMachine(context);
- wwsm.start();
- return wwsm;
- }
-
- private void setupNetworkReceiver() {
- mBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
- obtainMessage(EVENT_RSSI_CHANGE,
- intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200), 0).sendToTarget();
- } else if (action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)) {
- sendMessage(EVENT_SUPPLICANT_STATE_CHANGE, intent);
- } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
- sendMessage(EVENT_NETWORK_STATE_CHANGE, intent);
- } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
- sendMessage(EVENT_SCREEN_ON);
- } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
- sendMessage(EVENT_SCREEN_OFF);
- } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
- sendMessage(EVENT_WIFI_RADIO_STATE_CHANGE,intent.getIntExtra(
- WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN));
- }
- }
- };
-
- mIntentFilter = new IntentFilter();
- mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
- mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
- mIntentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
- mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
- mIntentFilter.addAction(Intent.ACTION_SCREEN_ON);
- mIntentFilter.addAction(Intent.ACTION_SCREEN_OFF);
- mContext.registerReceiver(mBroadcastReceiver, mIntentFilter);
- }
-
- /**
- * Observes the watchdog on/off setting, and takes action when changed.
- */
- private void registerForWatchdogToggle() {
- ContentObserver contentObserver = new ContentObserver(this.getHandler()) {
- @Override
- public void onChange(boolean selfChange) {
- sendMessage(EVENT_WATCHDOG_TOGGLED);
- }
- };
-
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.WIFI_WATCHDOG_ON),
- false, contentObserver);
- }
-
- /**
- * Observes watchdogs secure setting changes.
- */
- private void registerForSettingsChanges() {
- ContentObserver contentObserver = new ContentObserver(this.getHandler()) {
- @Override
- public void onChange(boolean selfChange) {
- sendMessage(EVENT_WATCHDOG_SETTINGS_CHANGE);
- }
- };
-
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED),
- false, contentObserver);
- }
-
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- super.dump(fd, pw, args);
- pw.println("mWifiInfo: [" + mWifiInfo + "]");
- pw.println("mLinkProperties: [" + mLinkProperties + "]");
- pw.println("mCurrentSignalLevel: [" + mCurrentSignalLevel + "]");
- pw.println("mPoorNetworkDetectionEnabled: [" + mPoorNetworkDetectionEnabled + "]");
- }
-
- private boolean isWatchdogEnabled() {
- boolean ret = getSettingsGlobalBoolean(
- mContentResolver, Settings.Global.WIFI_WATCHDOG_ON, true);
- if (DBG) logd("Watchdog enabled " + ret);
- return ret;
- }
-
- private void updateSettings() {
- if (DBG) logd("Updating secure settings");
-
- // disable poor network avoidance
- if (sWifiOnly) {
- logd("Disabling poor network avoidance for wi-fi only device");
- mPoorNetworkDetectionEnabled = false;
- } else {
- mPoorNetworkDetectionEnabled = getSettingsGlobalBoolean(mContentResolver,
- Settings.Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED,
- DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED);
- }
- }
-
- /**
- * Default state, guard for unhandled messages.
- */
- class DefaultState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- }
-
- @Override
- public boolean processMessage(Message msg) {
- switch (msg.what) {
- case EVENT_WATCHDOG_SETTINGS_CHANGE:
- updateSettings();
- if (DBG) logd("Updating wifi-watchdog secure settings");
- break;
- case EVENT_RSSI_CHANGE:
- mCurrentSignalLevel = calculateSignalLevel(msg.arg1);
- break;
- case EVENT_WIFI_RADIO_STATE_CHANGE:
- case EVENT_NETWORK_STATE_CHANGE:
- case EVENT_SUPPLICANT_STATE_CHANGE:
- case EVENT_BSSID_CHANGE:
- case CMD_RSSI_FETCH:
- case WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED:
- case WifiManager.RSSI_PKTCNT_FETCH_FAILED:
- // ignore
- break;
- case EVENT_SCREEN_ON:
- mIsScreenOn = true;
- break;
- case EVENT_SCREEN_OFF:
- mIsScreenOn = false;
- break;
- default:
- loge("Unhandled message " + msg + " in state " + getCurrentState().getName());
- break;
- }
- return HANDLED;
- }
- }
-
- /**
- * WiFi watchdog is disabled by the setting.
- */
- class WatchdogDisabledState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- }
-
- @Override
- public boolean processMessage(Message msg) {
- switch (msg.what) {
- case EVENT_WATCHDOG_TOGGLED:
- if (isWatchdogEnabled())
- transitionTo(mNotConnectedState);
- return HANDLED;
- case EVENT_NETWORK_STATE_CHANGE:
- Intent intent = (Intent) msg.obj;
- NetworkInfo networkInfo = (NetworkInfo)
- intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
-
- switch (networkInfo.getDetailedState()) {
- case VERIFYING_POOR_LINK:
- if (DBG) logd("Watchdog disabled, verify link");
- sendLinkStatusNotification(true);
- break;
- default:
- break;
- }
- break;
- }
- return NOT_HANDLED;
- }
- }
-
- /**
- * WiFi watchdog is enabled by the setting.
- */
- class WatchdogEnabledState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- }
-
- @Override
- public boolean processMessage(Message msg) {
- Intent intent;
- switch (msg.what) {
- case EVENT_WATCHDOG_TOGGLED:
- if (!isWatchdogEnabled())
- transitionTo(mWatchdogDisabledState);
- break;
-
- case EVENT_NETWORK_STATE_CHANGE:
- intent = (Intent) msg.obj;
- NetworkInfo networkInfo =
- (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
- if (DBG) logd("Network state change " + networkInfo.getDetailedState());
-
- mWifiInfo = (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
- updateCurrentBssid(mWifiInfo != null ? mWifiInfo.getBSSID() : null);
-
- switch (networkInfo.getDetailedState()) {
- case VERIFYING_POOR_LINK:
- mLinkProperties = (LinkProperties) intent.getParcelableExtra(
- WifiManager.EXTRA_LINK_PROPERTIES);
- if (mPoorNetworkDetectionEnabled) {
- if (mWifiInfo == null || mCurrentBssid == null) {
- loge("Ignore, wifiinfo " + mWifiInfo +" bssid " + mCurrentBssid);
- sendLinkStatusNotification(true);
- } else {
- transitionTo(mVerifyingLinkState);
- }
- } else {
- sendLinkStatusNotification(true);
- }
- break;
- case CONNECTED:
- transitionTo(mOnlineWatchState);
- break;
- default:
- transitionTo(mNotConnectedState);
- break;
- }
- break;
-
- case EVENT_SUPPLICANT_STATE_CHANGE:
- intent = (Intent) msg.obj;
- SupplicantState supplicantState = (SupplicantState) intent.getParcelableExtra(
- WifiManager.EXTRA_NEW_STATE);
- if (supplicantState == SupplicantState.COMPLETED) {
- mWifiInfo = mWifiManager.getConnectionInfo();
- updateCurrentBssid(mWifiInfo.getBSSID());
- }
- break;
-
- case EVENT_WIFI_RADIO_STATE_CHANGE:
- if (msg.arg1 == WifiManager.WIFI_STATE_DISABLING) {
- transitionTo(mNotConnectedState);
- }
- break;
-
- default:
- return NOT_HANDLED;
- }
-
- return HANDLED;
- }
- }
-
- /**
- * WiFi is disconnected.
- */
- class NotConnectedState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- }
- }
-
- /**
- * WiFi is connected, but waiting for good link detection message.
- */
- class VerifyingLinkState extends State {
-
- private int mSampleCount;
-
- @Override
- public void enter() {
- if (DBG) logd(getName());
- mSampleCount = 0;
- mCurrentBssid.newLinkDetected();
- sendMessage(obtainMessage(CMD_RSSI_FETCH, ++mRssiFetchToken, 0));
- }
-
- @Override
- public boolean processMessage(Message msg) {
- switch (msg.what) {
- case EVENT_WATCHDOG_SETTINGS_CHANGE:
- updateSettings();
- if (!mPoorNetworkDetectionEnabled) {
- sendLinkStatusNotification(true);
- }
- break;
-
- case EVENT_BSSID_CHANGE:
- transitionTo(mVerifyingLinkState);
- break;
-
- case CMD_RSSI_FETCH:
- if (msg.arg1 == mRssiFetchToken) {
- mWsmChannel.sendMessage(WifiManager.RSSI_PKTCNT_FETCH);
- sendMessageDelayed(obtainMessage(CMD_RSSI_FETCH, ++mRssiFetchToken, 0),
- LINK_SAMPLING_INTERVAL_MS);
- }
- break;
-
- case WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED:
- RssiPacketCountInfo info = (RssiPacketCountInfo) msg.obj;
- int rssi = info.rssi;
- if (DBG) logd("Fetch RSSI succeed, rssi=" + rssi);
-
- long time = mCurrentBssid.mBssidAvoidTimeMax - SystemClock.elapsedRealtime();
- if (time <= 0) {
- // max avoidance time is met
- if (DBG) logd("Max avoid time elapsed");
- sendLinkStatusNotification(true);
- } else {
- if (rssi >= mCurrentBssid.mGoodLinkTargetRssi) {
- if (++mSampleCount >= mCurrentBssid.mGoodLinkTargetCount) {
- // link is good again
- if (DBG) logd("Good link detected, rssi=" + rssi);
- mCurrentBssid.mBssidAvoidTimeMax = 0;
- sendLinkStatusNotification(true);
- }
- } else {
- mSampleCount = 0;
- if (DBG) logd("Link is still poor, time left=" + time);
- }
- }
- break;
-
- case WifiManager.RSSI_PKTCNT_FETCH_FAILED:
- if (DBG) logd("RSSI_FETCH_FAILED");
- break;
-
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- /**
- * WiFi is connected and link is verified.
- */
- class ConnectedState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- }
-
- @Override
- public boolean processMessage(Message msg) {
- switch (msg.what) {
- case EVENT_WATCHDOG_SETTINGS_CHANGE:
- updateSettings();
- if (mPoorNetworkDetectionEnabled) {
- transitionTo(mOnlineWatchState);
- } else {
- transitionTo(mOnlineState);
- }
- return HANDLED;
- }
- return NOT_HANDLED;
- }
- }
-
- /**
- * RSSI is high enough and don't need link monitoring.
- */
- class OnlineWatchState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- if (mPoorNetworkDetectionEnabled) {
- // treat entry as an rssi change
- handleRssiChange();
- } else {
- transitionTo(mOnlineState);
- }
- }
-
- private void handleRssiChange() {
- if (mCurrentSignalLevel <= LINK_MONITOR_LEVEL_THRESHOLD && mCurrentBssid != null) {
- transitionTo(mLinkMonitoringState);
- } else {
- // stay here
- }
- }
-
- @Override
- public boolean processMessage(Message msg) {
- switch (msg.what) {
- case EVENT_RSSI_CHANGE:
- mCurrentSignalLevel = calculateSignalLevel(msg.arg1);
- handleRssiChange();
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- /**
- * Keep sampling the link and monitor any poor link situation.
- */
- class LinkMonitoringState extends State {
-
- private int mSampleCount;
-
- private int mLastRssi;
- private int mLastTxGood;
- private int mLastTxBad;
-
- @Override
- public void enter() {
- if (DBG) logd(getName());
- mSampleCount = 0;
- mCurrentLoss = new VolumeWeightedEMA(EXP_COEFFICIENT_MONITOR);
- sendMessage(obtainMessage(CMD_RSSI_FETCH, ++mRssiFetchToken, 0));
- }
-
- @Override
- public boolean processMessage(Message msg) {
- switch (msg.what) {
- case EVENT_RSSI_CHANGE:
- mCurrentSignalLevel = calculateSignalLevel(msg.arg1);
- if (mCurrentSignalLevel <= LINK_MONITOR_LEVEL_THRESHOLD) {
- // stay here;
- } else {
- // we don't need frequent RSSI monitoring any more
- transitionTo(mOnlineWatchState);
- }
- break;
-
- case EVENT_BSSID_CHANGE:
- transitionTo(mLinkMonitoringState);
- break;
-
- case CMD_RSSI_FETCH:
- if (!mIsScreenOn) {
- transitionTo(mOnlineState);
- } else if (msg.arg1 == mRssiFetchToken) {
- mWsmChannel.sendMessage(WifiManager.RSSI_PKTCNT_FETCH);
- sendMessageDelayed(obtainMessage(CMD_RSSI_FETCH, ++mRssiFetchToken, 0),
- LINK_SAMPLING_INTERVAL_MS);
- }
- break;
-
- case WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED:
- RssiPacketCountInfo info = (RssiPacketCountInfo) msg.obj;
- int rssi = info.rssi;
- int mrssi = (mLastRssi + rssi) / 2;
- int txbad = info.txbad;
- int txgood = info.txgood;
- if (DBG) logd("Fetch RSSI succeed, rssi=" + rssi + " mrssi=" + mrssi + " txbad="
- + txbad + " txgood=" + txgood);
-
- // skip the first data point as we want incremental values
- long now = SystemClock.elapsedRealtime();
- if (now - mCurrentBssid.mLastTimeSample < LINK_SAMPLING_INTERVAL_MS * 2) {
-
- // update packet loss statistics
- int dbad = txbad - mLastTxBad;
- int dgood = txgood - mLastTxGood;
- int dtotal = dbad + dgood;
-
- if (dtotal > 0) {
- // calculate packet loss in the last sampling interval
- double loss = ((double) dbad) / ((double) dtotal);
-
- mCurrentLoss.update(loss, dtotal);
-
- if (DBG) {
- DecimalFormat df = new DecimalFormat("#.##");
- logd("Incremental loss=" + dbad + "/" + dtotal + " Current loss="
- + df.format(mCurrentLoss.mValue * 100) + "% volume="
- + df.format(mCurrentLoss.mVolume));
- }
-
- mCurrentBssid.updateLoss(mrssi, loss, dtotal);
-
- // check for high packet loss and send poor link notification
- if (mCurrentLoss.mValue > POOR_LINK_LOSS_THRESHOLD
- && mCurrentLoss.mVolume > POOR_LINK_MIN_VOLUME) {
- if (++mSampleCount >= POOR_LINK_SAMPLE_COUNT)
- if (mCurrentBssid.poorLinkDetected(rssi)) {
- sendLinkStatusNotification(false);
- ++mRssiFetchToken;
- }
- } else {
- mSampleCount = 0;
- }
- }
- }
-
- mCurrentBssid.mLastTimeSample = now;
- mLastTxBad = txbad;
- mLastTxGood = txgood;
- mLastRssi = rssi;
- break;
-
- case WifiManager.RSSI_PKTCNT_FETCH_FAILED:
- // can happen if we are waiting to get a disconnect notification
- if (DBG) logd("RSSI_FETCH_FAILED");
- break;
-
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- /**
- * Child state of ConnectedState indicating that we are online and there is nothing to do.
- */
- class OnlineState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- }
-
- @Override
- public boolean processMessage(Message msg) {
- switch (msg.what) {
- case EVENT_SCREEN_ON:
- mIsScreenOn = true;
- if (mPoorNetworkDetectionEnabled)
- transitionTo(mOnlineWatchState);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- private void updateCurrentBssid(String bssid) {
- if (DBG) logd("Update current BSSID to " + (bssid != null ? bssid : "null"));
-
- // if currently not connected, then set current BSSID to null
- if (bssid == null) {
- if (mCurrentBssid == null) return;
- mCurrentBssid = null;
- if (DBG) logd("BSSID changed");
- sendMessage(EVENT_BSSID_CHANGE);
- return;
- }
-
- // if it is already the current BSSID, then done
- if (mCurrentBssid != null && bssid.equals(mCurrentBssid.mBssid)) return;
-
- // search for the new BSSID in the cache, add to cache if not found
- mCurrentBssid = mBssidCache.get(bssid);
- if (mCurrentBssid == null) {
- mCurrentBssid = new BssidStatistics(bssid);
- mBssidCache.put(bssid, mCurrentBssid);
- }
-
- // send BSSID change notification
- if (DBG) logd("BSSID changed");
- sendMessage(EVENT_BSSID_CHANGE);
- }
-
- private int calculateSignalLevel(int rssi) {
- int signalLevel = WifiManager.calculateSignalLevel(rssi, WifiManager.RSSI_LEVELS);
- if (DBG)
- logd("RSSI current: " + mCurrentSignalLevel + " new: " + rssi + ", " + signalLevel);
- return signalLevel;
- }
-
- private void sendLinkStatusNotification(boolean isGood) {
- if (DBG) logd("########################################");
- if (isGood) {
- mWsmChannel.sendMessage(GOOD_LINK_DETECTED);
- if (mCurrentBssid != null) {
- mCurrentBssid.mLastTimeGood = SystemClock.elapsedRealtime();
- }
- if (DBG) logd("Good link notification is sent");
- } else {
- mWsmChannel.sendMessage(POOR_LINK_DETECTED);
- if (mCurrentBssid != null) {
- mCurrentBssid.mLastTimePoor = SystemClock.elapsedRealtime();
- }
- logd("Poor link notification is sent");
- }
- }
-
- /**
- * Convenience function for retrieving a single secure settings value as a
- * boolean. Note that internally setting values are always stored as
- * strings; this function converts the string to a boolean for you. The
- * default value will be returned if the setting is not defined or not a
- * valid boolean.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to retrieve.
- * @param def Value to return if the setting is not defined.
- * @return The setting's current value, or 'def' if it is not defined or not
- * a valid boolean.
- */
- private static boolean getSettingsGlobalBoolean(ContentResolver cr, String name, boolean def) {
- return Settings.Global.getInt(cr, name, def ? 1 : 0) == 1;
- }
-
- /**
- * Convenience function for updating a single settings value as an integer.
- * This will either create a new entry in the table if the given name does
- * not exist, or modify the value of the existing row with that name. Note
- * that internally setting values are always stored as strings, so this
- * function converts the given value to a string before storing it.
- *
- * @param cr The ContentResolver to access.
- * @param name The name of the setting to modify.
- * @param value The new value for the setting.
- * @return true if the value was set, false on database errors
- */
- private static boolean putSettingsGlobalBoolean(ContentResolver cr, String name, boolean value) {
- return Settings.Global.putInt(cr, name, value ? 1 : 0);
- }
-
- /**
- * Bundle of good link count parameters
- */
- private static class GoodLinkTarget {
- public final int RSSI_ADJ_DBM;
- public final int SAMPLE_COUNT;
- public final int REDUCE_TIME_MS;
- public GoodLinkTarget(int adj, int count, int time) {
- RSSI_ADJ_DBM = adj;
- SAMPLE_COUNT = count;
- REDUCE_TIME_MS = time;
- }
- }
-
- /**
- * Bundle of max avoidance time parameters
- */
- private static class MaxAvoidTime {
- public final int TIME_MS;
- public final int MIN_RSSI_DBM;
- public MaxAvoidTime(int time, int rssi) {
- TIME_MS = time;
- MIN_RSSI_DBM = rssi;
- }
- }
-
- /**
- * Volume-weighted Exponential Moving Average (V-EMA)
- * - volume-weighted: each update has its own weight (number of packets)
- * - exponential: O(1) time and O(1) space for both update and query
- * - moving average: reflect most recent results and expire old ones
- */
- private class VolumeWeightedEMA {
- private double mValue;
- private double mVolume;
- private double mProduct;
- private final double mAlpha;
-
- public VolumeWeightedEMA(double coefficient) {
- mValue = 0.0;
- mVolume = 0.0;
- mProduct = 0.0;
- mAlpha = coefficient;
- }
-
- public void update(double newValue, int newVolume) {
- if (newVolume <= 0) return;
- // core update formulas
- double newProduct = newValue * newVolume;
- mProduct = mAlpha * newProduct + (1 - mAlpha) * mProduct;
- mVolume = mAlpha * newVolume + (1 - mAlpha) * mVolume;
- mValue = mProduct / mVolume;
- }
- }
-
- /**
- * Record (RSSI -> pakce loss %) mappings of one BSSID
- */
- private class BssidStatistics {
-
- /* MAC address of this BSSID */
- private final String mBssid;
-
- /* RSSI -> packet loss % mappings */
- private VolumeWeightedEMA[] mEntries;
- private int mRssiBase;
- private int mEntriesSize;
-
- /* Target to send good link notification, set when poor link is detected */
- private int mGoodLinkTargetRssi;
- private int mGoodLinkTargetCount;
-
- /* Index of GOOD_LINK_TARGET array */
- private int mGoodLinkTargetIndex;
-
- /* Timestamps of some last events */
- private long mLastTimeSample;
- private long mLastTimeGood;
- private long mLastTimePoor;
-
- /* Max time to avoid this BSSID */
- private long mBssidAvoidTimeMax;
-
- /**
- * Constructor
- *
- * @param bssid is the address of this BSSID
- */
- public BssidStatistics(String bssid) {
- this.mBssid = bssid;
- mRssiBase = BSSID_STAT_RANGE_LOW_DBM;
- mEntriesSize = BSSID_STAT_RANGE_HIGH_DBM - BSSID_STAT_RANGE_LOW_DBM + 1;
- mEntries = new VolumeWeightedEMA[mEntriesSize];
- for (int i = 0; i < mEntriesSize; i++)
- mEntries[i] = new VolumeWeightedEMA(EXP_COEFFICIENT_RECORD);
- }
-
- /**
- * Update this BSSID cache
- *
- * @param rssi is the RSSI
- * @param value is the new instant loss value at this RSSI
- * @param volume is the volume for this single update
- */
- public void updateLoss(int rssi, double value, int volume) {
- if (volume <= 0) return;
- int index = rssi - mRssiBase;
- if (index < 0 || index >= mEntriesSize) return;
- mEntries[index].update(value, volume);
- if (DBG) {
- DecimalFormat df = new DecimalFormat("#.##");
- logd("Cache updated: loss[" + rssi + "]=" + df.format(mEntries[index].mValue * 100)
- + "% volume=" + df.format(mEntries[index].mVolume));
- }
- }
-
- /**
- * Get preset loss if the cache has insufficient data, observed from experiments.
- *
- * @param rssi is the input RSSI
- * @return preset loss of the given RSSI
- */
- public double presetLoss(int rssi) {
- if (rssi <= -90) return 1.0;
- if (rssi > 0) return 0.0;
-
- if (sPresetLoss == null) {
- // pre-calculate all preset losses only once, then reuse them
- final int size = 90;
- sPresetLoss = new double[size];
- for (int i = 0; i < size; i++) sPresetLoss[i] = 1.0 / Math.pow(90 - i, 1.5);
- }
- return sPresetLoss[-rssi];
- }
-
- /**
- * A poor link is detected, calculate a target RSSI to bring WiFi back.
- *
- * @param rssi is the current RSSI
- * @return true iff the current BSSID should be avoided
- */
- public boolean poorLinkDetected(int rssi) {
- if (DBG) logd("Poor link detected, rssi=" + rssi);
-
- long now = SystemClock.elapsedRealtime();
- long lastGood = now - mLastTimeGood;
- long lastPoor = now - mLastTimePoor;
-
- // reduce the difficulty of good link target if last avoidance was long time ago
- while (mGoodLinkTargetIndex > 0
- && lastPoor >= GOOD_LINK_TARGET[mGoodLinkTargetIndex - 1].REDUCE_TIME_MS)
- mGoodLinkTargetIndex--;
- mGoodLinkTargetCount = GOOD_LINK_TARGET[mGoodLinkTargetIndex].SAMPLE_COUNT;
-
- // scan for a target RSSI at which the link is good
- int from = rssi + GOOD_LINK_RSSI_RANGE_MIN;
- int to = rssi + GOOD_LINK_RSSI_RANGE_MAX;
- mGoodLinkTargetRssi = findRssiTarget(from, to, GOOD_LINK_LOSS_THRESHOLD);
- mGoodLinkTargetRssi += GOOD_LINK_TARGET[mGoodLinkTargetIndex].RSSI_ADJ_DBM;
- if (mGoodLinkTargetIndex < GOOD_LINK_TARGET.length - 1) mGoodLinkTargetIndex++;
-
- // calculate max avoidance time to prevent avoiding forever
- int p = 0, pmax = MAX_AVOID_TIME.length - 1;
- while (p < pmax && rssi >= MAX_AVOID_TIME[p + 1].MIN_RSSI_DBM) p++;
- long avoidMax = MAX_AVOID_TIME[p].TIME_MS;
-
- // don't avoid if max avoidance time is 0 (RSSI is super high)
- if (avoidMax <= 0) return false;
-
- // set max avoidance time, send poor link notification
- mBssidAvoidTimeMax = now + avoidMax;
-
- if (DBG) logd("goodRssi=" + mGoodLinkTargetRssi + " goodCount=" + mGoodLinkTargetCount
- + " lastGood=" + lastGood + " lastPoor=" + lastPoor + " avoidMax=" + avoidMax);
-
- return true;
- }
-
- /**
- * A new BSSID is connected, recalculate target RSSI threshold
- */
- public void newLinkDetected() {
- // if this BSSID is currently being avoided, the reuse those values
- if (mBssidAvoidTimeMax > 0) {
- if (DBG) logd("Previous avoidance still in effect, rssi=" + mGoodLinkTargetRssi
- + " count=" + mGoodLinkTargetCount);
- return;
- }
-
- // calculate a new RSSI threshold for new link verifying
- int from = BSSID_STAT_RANGE_LOW_DBM;
- int to = BSSID_STAT_RANGE_HIGH_DBM;
- mGoodLinkTargetRssi = findRssiTarget(from, to, GOOD_LINK_LOSS_THRESHOLD);
- mGoodLinkTargetCount = 1;
- mBssidAvoidTimeMax = SystemClock.elapsedRealtime() + MAX_AVOID_TIME[0].TIME_MS;
- if (DBG) logd("New link verifying target set, rssi=" + mGoodLinkTargetRssi + " count="
- + mGoodLinkTargetCount);
- }
-
- /**
- * Return the first RSSI within the range where loss[rssi] < threshold
- *
- * @param from start scanning from this RSSI
- * @param to stop scanning at this RSSI
- * @param threshold target threshold for scanning
- * @return target RSSI
- */
- public int findRssiTarget(int from, int to, double threshold) {
- from -= mRssiBase;
- to -= mRssiBase;
- int emptyCount = 0;
- int d = from < to ? 1 : -1;
- for (int i = from; i != to; i += d)
- // don't use a data point if it volume is too small (statistically unreliable)
- if (i >= 0 && i < mEntriesSize && mEntries[i].mVolume > 1.0) {
- emptyCount = 0;
- if (mEntries[i].mValue < threshold) {
- // scan target found
- int rssi = mRssiBase + i;
- if (DBG) {
- DecimalFormat df = new DecimalFormat("#.##");
- logd("Scan target found: rssi=" + rssi + " threshold="
- + df.format(threshold * 100) + "% value="
- + df.format(mEntries[i].mValue * 100) + "% volume="
- + df.format(mEntries[i].mVolume));
- }
- return rssi;
- }
- } else if (++emptyCount >= BSSID_STAT_EMPTY_COUNT) {
- // cache has insufficient data around this RSSI, use preset loss instead
- int rssi = mRssiBase + i;
- double lossPreset = presetLoss(rssi);
- if (lossPreset < threshold) {
- if (DBG) {
- DecimalFormat df = new DecimalFormat("#.##");
- logd("Scan target found: rssi=" + rssi + " threshold="
- + df.format(threshold * 100) + "% value="
- + df.format(lossPreset * 100) + "% volume=preset");
- }
- return rssi;
- }
- }
-
- return mRssiBase + to;
- }
- }
-}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
index 482d9cb..b019fd7 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -60,7 +60,8 @@ public class WifiP2pConfig implements Parcelable {
wps.setup = WpsInfo.PBC;
}
- void invalidate() {
+ /** @hide */
+ public void invalidate() {
deviceAddress = "";
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
index 398d987..a0cb035 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
@@ -274,7 +274,7 @@ public class WifiP2pDevice implements Parcelable {
}
/** Updates details obtained from supplicant @hide */
- void updateSupplicantDetails(WifiP2pDevice device) {
+ public void updateSupplicantDetails(WifiP2pDevice device) {
if (device == null) {
throw new IllegalArgumentException("device is null");
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
index fbcf09b..3d0bb3d 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
@@ -89,7 +89,7 @@ public class WifiP2pDeviceList implements Parcelable {
}
/** Only updates details fetched from the supplicant @hide */
- void updateSupplicantDetails(WifiP2pDevice device) {
+ public void updateSupplicantDetails(WifiP2pDevice device) {
validateDevice(device);
WifiP2pDevice d = mDevices.get(device.deviceAddress);
if (d != null) {
@@ -107,7 +107,7 @@ public class WifiP2pDeviceList implements Parcelable {
}
/** @hide */
- void updateGroupCapability(String deviceAddress, int groupCapab) {
+ public void updateGroupCapability(String deviceAddress, int groupCapab) {
validateDeviceAddress(deviceAddress);
WifiP2pDevice d = mDevices.get(deviceAddress);
if (d != null) {
@@ -116,7 +116,7 @@ public class WifiP2pDeviceList implements Parcelable {
}
/** @hide */
- void updateStatus(String deviceAddress, int status) {
+ public void updateStatus(String deviceAddress, int status) {
validateDeviceAddress(deviceAddress);
WifiP2pDevice d = mDevices.get(deviceAddress);
if (d != null) {
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
index 98f0972..64bb00b 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
@@ -42,11 +42,13 @@ public class WifiP2pGroupList implements Parcelable {
public void onDeleteGroup(int netId);
}
- WifiP2pGroupList() {
+ /** @hide */
+ public WifiP2pGroupList() {
this(null, null);
}
- WifiP2pGroupList(WifiP2pGroupList source, GroupDeleteListener listener) {
+ /** @hide */
+ public WifiP2pGroupList(WifiP2pGroupList source, GroupDeleteListener listener) {
mListener = listener;
mGroups = new LruCache<Integer, WifiP2pGroup>(CREDENTIAL_MAX_NUM) {
@Override
@@ -78,8 +80,9 @@ public class WifiP2pGroupList implements Parcelable {
* Add the specified group to this group list.
*
* @param group
+ * @hide
*/
- void add(WifiP2pGroup group) {
+ public void add(WifiP2pGroup group) {
mGroups.put(group.getNetworkId(), group);
}
@@ -87,8 +90,9 @@ public class WifiP2pGroupList implements Parcelable {
* Remove the group with the specified network id from this group list.
*
* @param netId
+ * @hide
*/
- void remove(int netId) {
+ public void remove(int netId) {
mGroups.remove(netId);
}
@@ -103,8 +107,9 @@ public class WifiP2pGroupList implements Parcelable {
/**
* Clear the group.
+ * @hide
*/
- boolean clear() {
+ public boolean clear() {
if (mGroups.size() == 0) return false;
isClearCalled = true;
mGroups.evictAll();
@@ -120,8 +125,9 @@ public class WifiP2pGroupList implements Parcelable {
*
* @param deviceAddress p2p device address.
* @return the network id. if not found, return -1.
+ * @hide
*/
- int getNetworkId(String deviceAddress) {
+ public int getNetworkId(String deviceAddress) {
if (deviceAddress == null) return -1;
final Collection<WifiP2pGroup> groups = mGroups.snapshot().values();
@@ -142,8 +148,9 @@ public class WifiP2pGroupList implements Parcelable {
* @param deviceAddress p2p device address.
* @param ssid ssid.
* @return the network id. if not found, return -1.
+ * @hide
*/
- int getNetworkId(String deviceAddress, String ssid) {
+ public int getNetworkId(String deviceAddress, String ssid) {
if (deviceAddress == null || ssid == null) {
return -1;
}
@@ -166,8 +173,9 @@ public class WifiP2pGroupList implements Parcelable {
*
* @param netId network id.
* @return the address. if not found, return null.
+ * @hide
*/
- String getOwnerAddr(int netId) {
+ public String getOwnerAddr(int netId) {
WifiP2pGroup grp = mGroups.get(netId);
if (grp != null) {
return grp.getOwner().deviceAddress;
@@ -182,8 +190,9 @@ public class WifiP2pGroupList implements Parcelable {
*
* @param netId network id.
* @return true if the specified network id is present in this group list.
+ * @hide
*/
- boolean contains(int netId) {
+ public boolean contains(int netId) {
final Collection<WifiP2pGroup> groups = mGroups.snapshot().values();
for (WifiP2pGroup grp: groups) {
if (netId == grp.getNetworkId()) {
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
deleted file mode 100644
index 7803f7d..0000000
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ /dev/null
@@ -1,2949 +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.wifi.p2p;
-
-import android.app.AlertDialog;
-import android.app.Notification;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.net.ConnectivityManager;
-import android.net.DhcpResults;
-import android.net.DhcpStateMachine;
-import android.net.InterfaceConfiguration;
-import android.net.LinkAddress;
-import android.net.NetworkInfo;
-import android.net.NetworkUtils;
-import android.net.wifi.WifiMonitor;
-import android.net.wifi.WifiNative;
-import android.net.wifi.WifiStateMachine;
-import android.net.wifi.WpsInfo;
-import android.net.wifi.p2p.WifiP2pGroupList.GroupDeleteListener;
-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.Bundle;
-import android.os.IBinder;
-import android.os.INetworkManagementService;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.EditText;
-import android.widget.TextView;
-
-import com.android.internal.R;
-import com.android.internal.util.AsyncChannel;
-import com.android.internal.util.Protocol;
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-
-
-/**
- * WifiP2pService includes a state machine to perform Wi-Fi p2p operations. Applications
- * communicate with this service to issue device discovery and connectivity requests
- * through the WifiP2pManager interface. The state machine communicates with the wifi
- * driver through wpa_supplicant and handles the event responses through WifiMonitor.
- *
- * Note that the term Wifi when used without a p2p suffix refers to the client mode
- * of Wifi operation
- * @hide
- */
-public class WifiP2pService extends IWifiP2pManager.Stub {
- private static final String TAG = "WifiP2pService";
- private static final boolean DBG = false;
- private static final String NETWORKTYPE = "WIFI_P2P";
-
- private Context mContext;
- private String mInterface;
- private Notification mNotification;
-
- INetworkManagementService mNwService;
- private DhcpStateMachine mDhcpStateMachine;
-
- private P2pStateMachine mP2pStateMachine;
- private AsyncChannel mReplyChannel = new AsyncChannel();
- private AsyncChannel mWifiChannel;
-
- private static final Boolean JOIN_GROUP = true;
- private static final Boolean FORM_GROUP = false;
-
- private static final Boolean RELOAD = true;
- private static final Boolean NO_RELOAD = false;
-
- /* Two minutes comes from the wpa_supplicant setting */
- private static final int GROUP_CREATING_WAIT_TIME_MS = 120 * 1000;
- private static int mGroupCreatingTimeoutIndex = 0;
-
- private static final int DISABLE_P2P_WAIT_TIME_MS = 5 * 1000;
- private static int mDisableP2pTimeoutIndex = 0;
-
- /* Set a two minute discover timeout to avoid STA scans from being blocked */
- private static final int DISCOVER_TIMEOUT_S = 120;
-
- /* Idle time after a peer is gone when the group is torn down */
- private static final int GROUP_IDLE_TIME_S = 10;
-
- private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE;
-
- /* Delayed message to timeout group creation */
- public static final int GROUP_CREATING_TIMED_OUT = BASE + 1;
-
- /* User accepted a peer request */
- private static final int PEER_CONNECTION_USER_ACCEPT = BASE + 2;
- /* User rejected a peer request */
- private static final int PEER_CONNECTION_USER_REJECT = BASE + 3;
- /* User wants to disconnect wifi in favour of p2p */
- private static final int DROP_WIFI_USER_ACCEPT = BASE + 4;
- /* User wants to keep his wifi connection and drop p2p */
- private static final int DROP_WIFI_USER_REJECT = BASE + 5;
- /* Delayed message to timeout p2p disable */
- public static final int DISABLE_P2P_TIMED_OUT = BASE + 6;
-
-
- /* Commands to the WifiStateMachine */
- public static final int P2P_CONNECTION_CHANGED = BASE + 11;
-
- /* These commands are used to temporarily disconnect wifi when we detect
- * a frequency conflict which would make it impossible to have with p2p
- * and wifi active at the same time.
- *
- * If the user chooses to disable wifi temporarily, we keep wifi disconnected
- * until the p2p connection is done and terminated at which point we will
- * bring back wifi up
- *
- * DISCONNECT_WIFI_REQUEST
- * msg.arg1 = 1 enables temporary disconnect and 0 disables it.
- */
- public static final int DISCONNECT_WIFI_REQUEST = BASE + 12;
- public static final int DISCONNECT_WIFI_RESPONSE = BASE + 13;
-
- public static final int SET_MIRACAST_MODE = BASE + 14;
-
- // During dhcp (and perhaps other times) we can't afford to drop packets
- // but Discovery will switch our channel enough we will.
- // msg.arg1 = ENABLED for blocking, DISABLED for resumed.
- // msg.arg2 = msg to send when blocked
- // msg.obj = StateMachine to send to when blocked
- public static final int BLOCK_DISCOVERY = BASE + 15;
-
- // set country code
- public static final int SET_COUNTRY_CODE = BASE + 16;
-
- public static final int ENABLED = 1;
- public static final int DISABLED = 0;
-
- private final boolean mP2pSupported;
-
- private WifiP2pDevice mThisDevice = new WifiP2pDevice();
-
- /* When a group has been explicitly created by an app, we persist the group
- * even after all clients have been disconnected until an explicit remove
- * is invoked */
- private boolean mAutonomousGroup;
-
- /* Invitation to join an existing p2p group */
- private boolean mJoinExistingGroup;
-
- /* Track whether we are in p2p discovery. This is used to avoid sending duplicate
- * broadcasts
- */
- private boolean mDiscoveryStarted;
- /* Track whether servcice/peer discovery is blocked in favor of other wifi actions
- * (notably dhcp)
- */
- private boolean mDiscoveryBlocked;
-
- // Supplicant doesn't like setting the same country code multiple times (it may drop
- // current connected network), so we save the country code here to avoid redundency
- private String mLastSetCountryCode;
-
- /*
- * remember if we were in a scan when it had to be stopped
- */
- private boolean mDiscoveryPostponed = false;
-
- private NetworkInfo mNetworkInfo;
-
- private boolean mTempoarilyDisconnectedWifi = false;
-
- /* The transaction Id of service discovery request */
- private byte mServiceTransactionId = 0;
-
- /* Service discovery request ID of wpa_supplicant.
- * null means it's not set yet. */
- private String mServiceDiscReqId;
-
- /* clients(application) information list. */
- private HashMap<Messenger, ClientInfo> mClientInfoList = new HashMap<Messenger, ClientInfo>();
-
- /* Is chosen as a unique range to avoid conflict with
- the range defined in Tethering.java */
- private static final String[] DHCP_RANGE = {"192.168.49.2", "192.168.49.254"};
- private static final String SERVER_ADDRESS = "192.168.49.1";
-
- /**
- * Error code definition.
- * see the Table.8 in the WiFi Direct specification for the detail.
- */
- public static enum P2pStatus {
- /* Success. */
- SUCCESS,
-
- /* The target device is currently unavailable. */
- INFORMATION_IS_CURRENTLY_UNAVAILABLE,
-
- /* Protocol error. */
- INCOMPATIBLE_PARAMETERS,
-
- /* The target device reached the limit of the number of the connectable device.
- * For example, device limit or group limit is set. */
- LIMIT_REACHED,
-
- /* Protocol error. */
- INVALID_PARAMETER,
-
- /* Unable to accommodate request. */
- UNABLE_TO_ACCOMMODATE_REQUEST,
-
- /* Previous protocol error, or disruptive behavior. */
- PREVIOUS_PROTOCOL_ERROR,
-
- /* There is no common channels the both devices can use. */
- NO_COMMON_CHANNEL,
-
- /* Unknown p2p group. For example, Device A tries to invoke the previous persistent group,
- * but device B has removed the specified credential already. */
- UNKNOWN_P2P_GROUP,
-
- /* Both p2p devices indicated an intent of 15 in group owner negotiation. */
- BOTH_GO_INTENT_15,
-
- /* Incompatible provisioning method. */
- INCOMPATIBLE_PROVISIONING_METHOD,
-
- /* Rejected by user */
- REJECTED_BY_USER,
-
- /* Unknown error */
- UNKNOWN;
-
- public static P2pStatus valueOf(int error) {
- switch(error) {
- case 0 :
- return SUCCESS;
- case 1:
- return INFORMATION_IS_CURRENTLY_UNAVAILABLE;
- case 2:
- return INCOMPATIBLE_PARAMETERS;
- case 3:
- return LIMIT_REACHED;
- case 4:
- return INVALID_PARAMETER;
- case 5:
- return UNABLE_TO_ACCOMMODATE_REQUEST;
- case 6:
- return PREVIOUS_PROTOCOL_ERROR;
- case 7:
- return NO_COMMON_CHANNEL;
- case 8:
- return UNKNOWN_P2P_GROUP;
- case 9:
- return BOTH_GO_INTENT_15;
- case 10:
- return INCOMPATIBLE_PROVISIONING_METHOD;
- case 11:
- return REJECTED_BY_USER;
- default:
- return UNKNOWN;
- }
- }
- }
-
- public WifiP2pService(Context context) {
- mContext = context;
-
- //STOPSHIP: get this from native side
- mInterface = "p2p0";
- mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORKTYPE, "");
-
- mP2pSupported = mContext.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_WIFI_DIRECT);
-
- mThisDevice.primaryDeviceType = mContext.getResources().getString(
- com.android.internal.R.string.config_wifi_p2p_device_type);
-
- mP2pStateMachine = new P2pStateMachine(TAG, mP2pSupported);
- mP2pStateMachine.start();
- }
-
- public void connectivityServiceReady() {
- IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
- mNwService = INetworkManagementService.Stub.asInterface(b);
- }
-
- private void enforceAccessPermission() {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE,
- "WifiP2pService");
- }
-
- private void enforceChangePermission() {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE,
- "WifiP2pService");
- }
-
- private void enforceConnectivityInternalPermission() {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.CONNECTIVITY_INTERNAL,
- "WifiP2pService");
- }
-
- /**
- * Get a reference to handler. This is used by a client to establish
- * an AsyncChannel communication with WifiP2pService
- */
- public Messenger getMessenger() {
- enforceAccessPermission();
- enforceChangePermission();
- return new Messenger(mP2pStateMachine.getHandler());
- }
-
- /** This is used to provide information to drivers to optimize performance depending
- * on the current mode of operation.
- * 0 - disabled
- * 1 - source operation
- * 2 - sink operation
- *
- * As an example, the driver could reduce the channel dwell time during scanning
- * when acting as a source or sink to minimize impact on miracast.
- */
- public void setMiracastMode(int mode) {
- enforceConnectivityInternalPermission();
- mP2pStateMachine.sendMessage(SET_MIRACAST_MODE, mode);
- }
-
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump WifiP2pService from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
- mP2pStateMachine.dump(fd, pw, args);
- pw.println("mAutonomousGroup " + mAutonomousGroup);
- pw.println("mJoinExistingGroup " + mJoinExistingGroup);
- pw.println("mDiscoveryStarted " + mDiscoveryStarted);
- pw.println("mNetworkInfo " + mNetworkInfo);
- pw.println("mTempoarilyDisconnectedWifi " + mTempoarilyDisconnectedWifi);
- pw.println("mServiceDiscReqId " + mServiceDiscReqId);
- pw.println();
- }
-
-
- /**
- * Handles interaction with WifiStateMachine
- */
- private class P2pStateMachine extends StateMachine {
-
- private DefaultState mDefaultState = new DefaultState();
- private P2pNotSupportedState mP2pNotSupportedState = new P2pNotSupportedState();
- private P2pDisablingState mP2pDisablingState = new P2pDisablingState();
- private P2pDisabledState mP2pDisabledState = new P2pDisabledState();
- private P2pEnablingState mP2pEnablingState = new P2pEnablingState();
- private P2pEnabledState mP2pEnabledState = new P2pEnabledState();
- // Inactive is when p2p is enabled with no connectivity
- private InactiveState mInactiveState = new InactiveState();
- private GroupCreatingState mGroupCreatingState = new GroupCreatingState();
- private UserAuthorizingInviteRequestState mUserAuthorizingInviteRequestState
- = new UserAuthorizingInviteRequestState();
- private UserAuthorizingNegotiationRequestState mUserAuthorizingNegotiationRequestState
- = new UserAuthorizingNegotiationRequestState();
- private ProvisionDiscoveryState mProvisionDiscoveryState = new ProvisionDiscoveryState();
- private GroupNegotiationState mGroupNegotiationState = new GroupNegotiationState();
- private FrequencyConflictState mFrequencyConflictState =new FrequencyConflictState();
-
- private GroupCreatedState mGroupCreatedState = new GroupCreatedState();
- private UserAuthorizingJoinState mUserAuthorizingJoinState = new UserAuthorizingJoinState();
- private OngoingGroupRemovalState mOngoingGroupRemovalState = new OngoingGroupRemovalState();
-
- private WifiNative mWifiNative = new WifiNative(mInterface);
- private WifiMonitor mWifiMonitor = new WifiMonitor(this, mWifiNative);
-
- private final WifiP2pDeviceList mPeers = new WifiP2pDeviceList();
- /* During a connection, supplicant can tell us that a device was lost. From a supplicant's
- * perspective, the discovery stops during connection and it purges device since it does
- * not get latest updates about the device without being in discovery state.
- *
- * From the framework perspective, the device is still there since we are connecting or
- * connected to it. so we keep these devices in a separate list, so that they are removed
- * when connection is cancelled or lost
- */
- private final WifiP2pDeviceList mPeersLostDuringConnection = new WifiP2pDeviceList();
- private final WifiP2pGroupList mGroups = new WifiP2pGroupList(null,
- new GroupDeleteListener() {
- @Override
- public void onDeleteGroup(int netId) {
- if (DBG) logd("called onDeleteGroup() netId=" + netId);
- mWifiNative.removeNetwork(netId);
- mWifiNative.saveConfig();
- sendP2pPersistentGroupsChangedBroadcast();
- }
- });
- private final WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo();
- private WifiP2pGroup mGroup;
-
- // Saved WifiP2pConfig for an ongoing peer connection. This will never be null.
- // The deviceAddress will be an empty string when the device is inactive
- // or if it is connected without any ongoing join request
- private WifiP2pConfig mSavedPeerConfig = new WifiP2pConfig();
-
- // Saved WifiP2pGroup from invitation request
- private WifiP2pGroup mSavedP2pGroup;
-
- P2pStateMachine(String name, boolean p2pSupported) {
- super(name);
-
- addState(mDefaultState);
- addState(mP2pNotSupportedState, mDefaultState);
- addState(mP2pDisablingState, mDefaultState);
- addState(mP2pDisabledState, mDefaultState);
- addState(mP2pEnablingState, mDefaultState);
- addState(mP2pEnabledState, mDefaultState);
- addState(mInactiveState, mP2pEnabledState);
- addState(mGroupCreatingState, mP2pEnabledState);
- addState(mUserAuthorizingInviteRequestState, mGroupCreatingState);
- addState(mUserAuthorizingNegotiationRequestState, mGroupCreatingState);
- addState(mProvisionDiscoveryState, mGroupCreatingState);
- addState(mGroupNegotiationState, mGroupCreatingState);
- addState(mFrequencyConflictState, mGroupCreatingState);
- addState(mGroupCreatedState, mP2pEnabledState);
- addState(mUserAuthorizingJoinState, mGroupCreatedState);
- addState(mOngoingGroupRemovalState, mGroupCreatedState);
-
- if (p2pSupported) {
- setInitialState(mP2pDisabledState);
- } else {
- setInitialState(mP2pNotSupportedState);
- }
- setLogRecSize(50);
- setLogOnlyTransitions(true);
- }
-
- class DefaultState extends State {
- @Override
- public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
- switch (message.what) {
- case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
- if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
- if (DBG) logd("Full connection with WifiStateMachine established");
- mWifiChannel = (AsyncChannel) message.obj;
- } else {
- loge("Full connection failure, error = " + message.arg1);
- mWifiChannel = null;
- }
- break;
-
- case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
- if (message.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
- loge("Send failed, client connection lost");
- } else {
- loge("Client connection lost with reason: " + message.arg1);
- }
- mWifiChannel = null;
- break;
-
- case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
- AsyncChannel ac = new AsyncChannel();
- ac.connect(mContext, getHandler(), message.replyTo);
- break;
- case BLOCK_DISCOVERY:
- mDiscoveryBlocked = (message.arg1 == ENABLED ? true : false);
- // always reset this - we went to a state that doesn't support discovery so
- // it would have stopped regardless
- mDiscoveryPostponed = false;
- if (mDiscoveryBlocked) {
- try {
- StateMachine m = (StateMachine)message.obj;
- m.sendMessage(message.arg2);
- } catch (Exception e) {
- loge("unable to send BLOCK_DISCOVERY response: " + e);
- }
- }
- break;
- case WifiP2pManager.DISCOVER_PEERS:
- replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.STOP_DISCOVERY:
- replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.DISCOVER_SERVICES:
- replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.CONNECT:
- replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.CANCEL_CONNECT:
- replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.CREATE_GROUP:
- replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.REMOVE_GROUP:
- replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.ADD_LOCAL_SERVICE:
- replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.REMOVE_LOCAL_SERVICE:
- replyToMessage(message, WifiP2pManager.REMOVE_LOCAL_SERVICE_FAILED,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.CLEAR_LOCAL_SERVICES:
- replyToMessage(message, WifiP2pManager.CLEAR_LOCAL_SERVICES_FAILED,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.ADD_SERVICE_REQUEST:
- replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_FAILED,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.REMOVE_SERVICE_REQUEST:
- replyToMessage(message,
- WifiP2pManager.REMOVE_SERVICE_REQUEST_FAILED,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.CLEAR_SERVICE_REQUESTS:
- replyToMessage(message,
- WifiP2pManager.CLEAR_SERVICE_REQUESTS_FAILED,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.SET_DEVICE_NAME:
- replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_FAILED,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.DELETE_PERSISTENT_GROUP:
- replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.SET_WFD_INFO:
- replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.REQUEST_PEERS:
- replyToMessage(message, WifiP2pManager.RESPONSE_PEERS,
- new WifiP2pDeviceList(mPeers));
- break;
- case WifiP2pManager.REQUEST_CONNECTION_INFO:
- replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO,
- new WifiP2pInfo(mWifiP2pInfo));
- break;
- case WifiP2pManager.REQUEST_GROUP_INFO:
- replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO,
- mGroup != null ? new WifiP2pGroup(mGroup) : null);
- break;
- case WifiP2pManager.REQUEST_PERSISTENT_GROUP_INFO:
- replyToMessage(message, WifiP2pManager.RESPONSE_PERSISTENT_GROUP_INFO,
- new WifiP2pGroupList(mGroups, null));
- break;
- case WifiP2pManager.START_WPS:
- replyToMessage(message, WifiP2pManager.START_WPS_FAILED,
- WifiP2pManager.BUSY);
- break;
- // Ignore
- case WifiMonitor.P2P_INVITATION_RESULT_EVENT:
- case WifiMonitor.SCAN_RESULTS_EVENT:
- case WifiMonitor.SUP_CONNECTION_EVENT:
- case WifiMonitor.SUP_DISCONNECTION_EVENT:
- case WifiMonitor.NETWORK_CONNECTION_EVENT:
- case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
- case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
- case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
- case WifiMonitor.WPS_SUCCESS_EVENT:
- case WifiMonitor.WPS_FAIL_EVENT:
- case WifiMonitor.WPS_OVERLAP_EVENT:
- case WifiMonitor.WPS_TIMEOUT_EVENT:
- case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
- case WifiMonitor.P2P_DEVICE_FOUND_EVENT:
- case WifiMonitor.P2P_DEVICE_LOST_EVENT:
- case WifiMonitor.P2P_FIND_STOPPED_EVENT:
- case WifiMonitor.P2P_SERV_DISC_RESP_EVENT:
- case PEER_CONNECTION_USER_ACCEPT:
- case PEER_CONNECTION_USER_REJECT:
- case DISCONNECT_WIFI_RESPONSE:
- case DROP_WIFI_USER_ACCEPT:
- case DROP_WIFI_USER_REJECT:
- case GROUP_CREATING_TIMED_OUT:
- case DISABLE_P2P_TIMED_OUT:
- case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
- case DhcpStateMachine.CMD_POST_DHCP_ACTION:
- case DhcpStateMachine.CMD_ON_QUIT:
- case WifiMonitor.P2P_PROV_DISC_FAILURE_EVENT:
- case SET_MIRACAST_MODE:
- case WifiP2pManager.START_LISTEN:
- case WifiP2pManager.STOP_LISTEN:
- case WifiP2pManager.SET_CHANNEL:
- case SET_COUNTRY_CODE:
- break;
- case WifiStateMachine.CMD_ENABLE_P2P:
- // Enable is lazy and has no response
- break;
- case WifiStateMachine.CMD_DISABLE_P2P_REQ:
- // If we end up handling in default, p2p is not enabled
- mWifiChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_RSP);
- break;
- /* unexpected group created, remove */
- case WifiMonitor.P2P_GROUP_STARTED_EVENT:
- mGroup = (WifiP2pGroup) message.obj;
- loge("Unexpected group creation, remove " + mGroup);
- mWifiNative.p2pGroupRemove(mGroup.getInterface());
- break;
- // A group formation failure is always followed by
- // a group removed event. Flushing things at group formation
- // failure causes supplicant issues. Ignore right now.
- case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
- break;
- default:
- loge("Unhandled message " + message);
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class P2pNotSupportedState extends State {
- @Override
- public boolean processMessage(Message message) {
- switch (message.what) {
- case WifiP2pManager.DISCOVER_PEERS:
- replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.STOP_DISCOVERY:
- replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.DISCOVER_SERVICES:
- replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.CONNECT:
- replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.CANCEL_CONNECT:
- replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.CREATE_GROUP:
- replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.REMOVE_GROUP:
- replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.ADD_LOCAL_SERVICE:
- replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.REMOVE_LOCAL_SERVICE:
- replyToMessage(message, WifiP2pManager.REMOVE_LOCAL_SERVICE_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.CLEAR_LOCAL_SERVICES:
- replyToMessage(message, WifiP2pManager.CLEAR_LOCAL_SERVICES_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.ADD_SERVICE_REQUEST:
- replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.REMOVE_SERVICE_REQUEST:
- replyToMessage(message,
- WifiP2pManager.REMOVE_SERVICE_REQUEST_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.CLEAR_SERVICE_REQUESTS:
- replyToMessage(message,
- WifiP2pManager.CLEAR_SERVICE_REQUESTS_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.SET_DEVICE_NAME:
- replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.DELETE_PERSISTENT_GROUP:
- replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.SET_WFD_INFO:
- replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.START_WPS:
- replyToMessage(message, WifiP2pManager.START_WPS_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.START_LISTEN:
- replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
- case WifiP2pManager.STOP_LISTEN:
- replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED,
- WifiP2pManager.P2P_UNSUPPORTED);
- break;
-
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class P2pDisablingState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- sendMessageDelayed(obtainMessage(DISABLE_P2P_TIMED_OUT,
- ++mDisableP2pTimeoutIndex, 0), DISABLE_P2P_WAIT_TIME_MS);
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
- switch (message.what) {
- case WifiMonitor.SUP_DISCONNECTION_EVENT:
- if (DBG) logd("p2p socket connection lost");
- transitionTo(mP2pDisabledState);
- break;
- case WifiStateMachine.CMD_ENABLE_P2P:
- case WifiStateMachine.CMD_DISABLE_P2P_REQ:
- deferMessage(message);
- break;
- case DISABLE_P2P_TIMED_OUT:
- if (mGroupCreatingTimeoutIndex == message.arg1) {
- loge("P2p disable timed out");
- transitionTo(mP2pDisabledState);
- }
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
-
- @Override
- public void exit() {
- mWifiChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_RSP);
- }
- }
-
- class P2pDisabledState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
- switch (message.what) {
- case WifiStateMachine.CMD_ENABLE_P2P:
- try {
- mNwService.setInterfaceUp(mInterface);
- } catch (RemoteException re) {
- loge("Unable to change interface settings: " + re);
- } catch (IllegalStateException ie) {
- loge("Unable to change interface settings: " + ie);
- }
- mWifiMonitor.startMonitoring();
- transitionTo(mP2pEnablingState);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class P2pEnablingState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
- switch (message.what) {
- case WifiMonitor.SUP_CONNECTION_EVENT:
- if (DBG) logd("P2p socket connection successful");
- transitionTo(mInactiveState);
- break;
- case WifiMonitor.SUP_DISCONNECTION_EVENT:
- loge("P2p socket connection failed");
- transitionTo(mP2pDisabledState);
- break;
- case WifiStateMachine.CMD_ENABLE_P2P:
- case WifiStateMachine.CMD_DISABLE_P2P_REQ:
- deferMessage(message);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class P2pEnabledState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- sendP2pStateChangedBroadcast(true);
- mNetworkInfo.setIsAvailable(true);
- sendP2pConnectionChangedBroadcast();
- initializeP2pSettings();
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
- switch (message.what) {
- case WifiMonitor.SUP_DISCONNECTION_EVENT:
- loge("Unexpected loss of p2p socket connection");
- transitionTo(mP2pDisabledState);
- break;
- case WifiStateMachine.CMD_ENABLE_P2P:
- //Nothing to do
- break;
- case WifiStateMachine.CMD_DISABLE_P2P_REQ:
- if (mPeers.clear()) {
- sendPeersChangedBroadcast();
- }
- if (mGroups.clear()) sendP2pPersistentGroupsChangedBroadcast();
-
- mWifiMonitor.stopMonitoring();
- transitionTo(mP2pDisablingState);
- break;
- case WifiP2pManager.SET_DEVICE_NAME:
- {
- WifiP2pDevice d = (WifiP2pDevice) message.obj;
- if (d != null && setAndPersistDeviceName(d.deviceName)) {
- if (DBG) logd("set device name " + d.deviceName);
- replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_SUCCEEDED);
- } else {
- replyToMessage(message, WifiP2pManager.SET_DEVICE_NAME_FAILED,
- WifiP2pManager.ERROR);
- }
- break;
- }
- case WifiP2pManager.SET_WFD_INFO:
- {
- WifiP2pWfdInfo d = (WifiP2pWfdInfo) message.obj;
- if (d != null && setWfdInfo(d)) {
- replyToMessage(message, WifiP2pManager.SET_WFD_INFO_SUCCEEDED);
- } else {
- replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED,
- WifiP2pManager.ERROR);
- }
- break;
- }
- case BLOCK_DISCOVERY:
- boolean blocked = (message.arg1 == ENABLED ? true : false);
- if (mDiscoveryBlocked == blocked) break;
- mDiscoveryBlocked = blocked;
- if (blocked && mDiscoveryStarted) {
- mWifiNative.p2pStopFind();
- mDiscoveryPostponed = true;
- }
- if (!blocked && mDiscoveryPostponed) {
- mDiscoveryPostponed = false;
- mWifiNative.p2pFind(DISCOVER_TIMEOUT_S);
- }
- if (blocked) {
- try {
- StateMachine m = (StateMachine)message.obj;
- m.sendMessage(message.arg2);
- } catch (Exception e) {
- loge("unable to send BLOCK_DISCOVERY response: " + e);
- }
- }
- break;
- case WifiP2pManager.DISCOVER_PEERS:
- if (mDiscoveryBlocked) {
- replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
- WifiP2pManager.BUSY);
- break;
- }
- // do not send service discovery request while normal find operation.
- clearSupplicantServiceRequest();
- if (mWifiNative.p2pFind(DISCOVER_TIMEOUT_S)) {
- replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED);
- sendP2pDiscoveryChangedBroadcast(true);
- } else {
- replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
- WifiP2pManager.ERROR);
- }
- break;
- case WifiMonitor.P2P_FIND_STOPPED_EVENT:
- sendP2pDiscoveryChangedBroadcast(false);
- break;
- case WifiP2pManager.STOP_DISCOVERY:
- if (mWifiNative.p2pStopFind()) {
- replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_SUCCEEDED);
- } else {
- replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED,
- WifiP2pManager.ERROR);
- }
- break;
- case WifiP2pManager.DISCOVER_SERVICES:
- if (mDiscoveryBlocked) {
- replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED,
- WifiP2pManager.BUSY);
- break;
- }
- if (DBG) logd(getName() + " discover services");
- if (!updateSupplicantServiceRequest()) {
- replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED,
- WifiP2pManager.NO_SERVICE_REQUESTS);
- break;
- }
- if (mWifiNative.p2pFind(DISCOVER_TIMEOUT_S)) {
- replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_SUCCEEDED);
- } else {
- replyToMessage(message, WifiP2pManager.DISCOVER_SERVICES_FAILED,
- WifiP2pManager.ERROR);
- }
- break;
- case WifiMonitor.P2P_DEVICE_FOUND_EVENT:
- WifiP2pDevice device = (WifiP2pDevice) message.obj;
- if (mThisDevice.deviceAddress.equals(device.deviceAddress)) break;
- mPeers.updateSupplicantDetails(device);
- sendPeersChangedBroadcast();
- break;
- case WifiMonitor.P2P_DEVICE_LOST_EVENT:
- device = (WifiP2pDevice) message.obj;
- // Gets current details for the one removed
- device = mPeers.remove(device.deviceAddress);
- if (device != null) {
- sendPeersChangedBroadcast();
- }
- break;
- case WifiP2pManager.ADD_LOCAL_SERVICE:
- if (DBG) logd(getName() + " add service");
- WifiP2pServiceInfo servInfo = (WifiP2pServiceInfo)message.obj;
- if (addLocalService(message.replyTo, servInfo)) {
- replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_SUCCEEDED);
- } else {
- replyToMessage(message, WifiP2pManager.ADD_LOCAL_SERVICE_FAILED);
- }
- break;
- case WifiP2pManager.REMOVE_LOCAL_SERVICE:
- if (DBG) logd(getName() + " remove service");
- servInfo = (WifiP2pServiceInfo)message.obj;
- removeLocalService(message.replyTo, servInfo);
- replyToMessage(message, WifiP2pManager.REMOVE_LOCAL_SERVICE_SUCCEEDED);
- break;
- case WifiP2pManager.CLEAR_LOCAL_SERVICES:
- if (DBG) logd(getName() + " clear service");
- clearLocalServices(message.replyTo);
- replyToMessage(message, WifiP2pManager.CLEAR_LOCAL_SERVICES_SUCCEEDED);
- break;
- case WifiP2pManager.ADD_SERVICE_REQUEST:
- if (DBG) logd(getName() + " add service request");
- if (!addServiceRequest(message.replyTo, (WifiP2pServiceRequest)message.obj)) {
- replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_FAILED);
- break;
- }
- replyToMessage(message, WifiP2pManager.ADD_SERVICE_REQUEST_SUCCEEDED);
- break;
- case WifiP2pManager.REMOVE_SERVICE_REQUEST:
- if (DBG) logd(getName() + " remove service request");
- removeServiceRequest(message.replyTo, (WifiP2pServiceRequest)message.obj);
- replyToMessage(message, WifiP2pManager.REMOVE_SERVICE_REQUEST_SUCCEEDED);
- break;
- case WifiP2pManager.CLEAR_SERVICE_REQUESTS:
- if (DBG) logd(getName() + " clear service request");
- clearServiceRequests(message.replyTo);
- replyToMessage(message, WifiP2pManager.CLEAR_SERVICE_REQUESTS_SUCCEEDED);
- break;
- case WifiMonitor.P2P_SERV_DISC_RESP_EVENT:
- if (DBG) logd(getName() + " receive service response");
- List<WifiP2pServiceResponse> sdRespList =
- (List<WifiP2pServiceResponse>) message.obj;
- for (WifiP2pServiceResponse resp : sdRespList) {
- WifiP2pDevice dev =
- mPeers.get(resp.getSrcDevice().deviceAddress);
- resp.setSrcDevice(dev);
- sendServiceResponse(resp);
- }
- break;
- case WifiP2pManager.DELETE_PERSISTENT_GROUP:
- if (DBG) logd(getName() + " delete persistent group");
- mGroups.remove(message.arg1);
- replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP_SUCCEEDED);
- break;
- case SET_MIRACAST_MODE:
- mWifiNative.setMiracastMode(message.arg1);
- break;
- case WifiP2pManager.START_LISTEN:
- if (DBG) logd(getName() + " start listen mode");
- mWifiNative.p2pFlush();
- if (mWifiNative.p2pExtListen(true, 500, 500)) {
- replyToMessage(message, WifiP2pManager.START_LISTEN_SUCCEEDED);
- } else {
- replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED);
- }
- break;
- case WifiP2pManager.STOP_LISTEN:
- if (DBG) logd(getName() + " stop listen mode");
- if (mWifiNative.p2pExtListen(false, 0, 0)) {
- replyToMessage(message, WifiP2pManager.STOP_LISTEN_SUCCEEDED);
- } else {
- replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED);
- }
- mWifiNative.p2pFlush();
- break;
- case WifiP2pManager.SET_CHANNEL:
- Bundle p2pChannels = (Bundle) message.obj;
- int lc = p2pChannels.getInt("lc", 0);
- int oc = p2pChannels.getInt("oc", 0);
- if (DBG) logd(getName() + " set listen and operating channel");
- if (mWifiNative.p2pSetChannel(lc, oc)) {
- replyToMessage(message, WifiP2pManager.SET_CHANNEL_SUCCEEDED);
- } else {
- replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED);
- }
- break;
- case SET_COUNTRY_CODE:
- String countryCode = (String) message.obj;
- countryCode = countryCode.toUpperCase(Locale.ROOT);
- if (mLastSetCountryCode == null ||
- countryCode.equals(mLastSetCountryCode) == false) {
- if (mWifiNative.setCountryCode(countryCode)) {
- mLastSetCountryCode = countryCode;
- }
- }
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
-
- @Override
- public void exit() {
- sendP2pDiscoveryChangedBroadcast(false);
- sendP2pStateChangedBroadcast(false);
- mNetworkInfo.setIsAvailable(false);
-
- mLastSetCountryCode = null;
- }
- }
-
- class InactiveState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- mSavedPeerConfig.invalidate();
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
- switch (message.what) {
- case WifiP2pManager.CONNECT:
- if (DBG) logd(getName() + " sending connect");
- WifiP2pConfig config = (WifiP2pConfig) message.obj;
- if (isConfigInvalid(config)) {
- loge("Dropping connect requeset " + config);
- replyToMessage(message, WifiP2pManager.CONNECT_FAILED);
- break;
- }
-
- mAutonomousGroup = false;
- mWifiNative.p2pStopFind();
- if (reinvokePersistentGroup(config)) {
- transitionTo(mGroupNegotiationState);
- } else {
- transitionTo(mProvisionDiscoveryState);
- }
- mSavedPeerConfig = config;
- mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);
- sendPeersChangedBroadcast();
- replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
- break;
- case WifiP2pManager.STOP_DISCOVERY:
- if (mWifiNative.p2pStopFind()) {
- // When discovery stops in inactive state, flush to clear
- // state peer data
- mWifiNative.p2pFlush();
- mServiceDiscReqId = null;
- replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_SUCCEEDED);
- } else {
- replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED,
- WifiP2pManager.ERROR);
- }
- break;
- case WifiMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT:
- config = (WifiP2pConfig) message.obj;
- if (isConfigInvalid(config)) {
- loge("Dropping GO neg request " + config);
- break;
- }
- mSavedPeerConfig = config;
- mAutonomousGroup = false;
- mJoinExistingGroup = false;
- transitionTo(mUserAuthorizingNegotiationRequestState);
- break;
- case WifiMonitor.P2P_INVITATION_RECEIVED_EVENT:
- WifiP2pGroup group = (WifiP2pGroup) message.obj;
- WifiP2pDevice owner = group.getOwner();
-
- if (owner == null) {
- loge("Ignored invitation from null owner");
- break;
- }
-
- config = new WifiP2pConfig();
- config.deviceAddress = group.getOwner().deviceAddress;
-
- if (isConfigInvalid(config)) {
- loge("Dropping invitation request " + config);
- break;
- }
- mSavedPeerConfig = config;
-
- //Check if we have the owner in peer list and use appropriate
- //wps method. Default is to use PBC.
- if ((owner = mPeers.get(owner.deviceAddress)) != null) {
- if (owner.wpsPbcSupported()) {
- mSavedPeerConfig.wps.setup = WpsInfo.PBC;
- } else if (owner.wpsKeypadSupported()) {
- mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD;
- } else if (owner.wpsDisplaySupported()) {
- mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY;
- }
- }
-
- mAutonomousGroup = false;
- mJoinExistingGroup = 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 WifiP2pManager.CREATE_GROUP:
- mAutonomousGroup = true;
- int netId = message.arg1;
- boolean ret = false;
- if (netId == WifiP2pGroup.PERSISTENT_NET_ID) {
- // check if the go persistent group is present.
- netId = mGroups.getNetworkId(mThisDevice.deviceAddress);
- if (netId != -1) {
- ret = mWifiNative.p2pGroupAdd(netId);
- } else {
- ret = mWifiNative.p2pGroupAdd(true);
- }
- } else {
- ret = mWifiNative.p2pGroupAdd(false);
- }
-
- if (ret) {
- replyToMessage(message, WifiP2pManager.CREATE_GROUP_SUCCEEDED);
- transitionTo(mGroupNegotiationState);
- } else {
- replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
- WifiP2pManager.ERROR);
- // remain at this state.
- }
- break;
- case WifiMonitor.P2P_GROUP_STARTED_EVENT:
- mGroup = (WifiP2pGroup) message.obj;
- if (DBG) logd(getName() + " group started");
-
- // We hit this scenario when a persistent group is reinvoked
- if (mGroup.getNetworkId() == WifiP2pGroup.PERSISTENT_NET_ID) {
- mAutonomousGroup = false;
- deferMessage(message);
- transitionTo(mGroupNegotiationState);
- } else {
- loge("Unexpected group creation, remove " + mGroup);
- mWifiNative.p2pGroupRemove(mGroup.getInterface());
- }
- break;
- case WifiP2pManager.START_LISTEN:
- if (DBG) logd(getName() + " start listen mode");
- mWifiNative.p2pFlush();
- if (mWifiNative.p2pExtListen(true, 500, 500)) {
- replyToMessage(message, WifiP2pManager.START_LISTEN_SUCCEEDED);
- } else {
- replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED);
- }
- break;
- case WifiP2pManager.STOP_LISTEN:
- if (DBG) logd(getName() + " stop listen mode");
- if (mWifiNative.p2pExtListen(false, 0, 0)) {
- replyToMessage(message, WifiP2pManager.STOP_LISTEN_SUCCEEDED);
- } else {
- replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED);
- }
- mWifiNative.p2pFlush();
- break;
- case WifiP2pManager.SET_CHANNEL:
- Bundle p2pChannels = (Bundle) message.obj;
- int lc = p2pChannels.getInt("lc", 0);
- int oc = p2pChannels.getInt("oc", 0);
- if (DBG) logd(getName() + " set listen and operating channel");
- if (mWifiNative.p2pSetChannel(lc, oc)) {
- replyToMessage(message, WifiP2pManager.SET_CHANNEL_SUCCEEDED);
- } else {
- replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED);
- }
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class GroupCreatingState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- sendMessageDelayed(obtainMessage(GROUP_CREATING_TIMED_OUT,
- ++mGroupCreatingTimeoutIndex, 0), GROUP_CREATING_WAIT_TIME_MS);
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
- boolean ret = HANDLED;
- switch (message.what) {
- case GROUP_CREATING_TIMED_OUT:
- if (mGroupCreatingTimeoutIndex == message.arg1) {
- if (DBG) logd("Group negotiation timed out");
- handleGroupCreationFailure();
- transitionTo(mInactiveState);
- }
- break;
- case WifiMonitor.P2P_DEVICE_LOST_EVENT:
- WifiP2pDevice device = (WifiP2pDevice) message.obj;
- if (!mSavedPeerConfig.deviceAddress.equals(device.deviceAddress)) {
- if (DBG) {
- logd("mSavedPeerConfig " + mSavedPeerConfig.deviceAddress +
- "device " + device.deviceAddress);
- }
- // Do the regular device lost handling
- ret = NOT_HANDLED;
- break;
- }
- // Do nothing
- if (DBG) logd("Add device to lost list " + device);
- mPeersLostDuringConnection.updateSupplicantDetails(device);
- break;
- case WifiP2pManager.DISCOVER_PEERS:
- /* Discovery will break negotiation */
- replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
- WifiP2pManager.BUSY);
- break;
- case WifiP2pManager.CANCEL_CONNECT:
- //Do a supplicant p2p_cancel which only cancels an ongoing
- //group negotiation. This will fail for a pending provision
- //discovery or for a pending user action, but at the framework
- //level, we always treat cancel as succeeded and enter
- //an inactive state
- mWifiNative.p2pCancelConnect();
- handleGroupCreationFailure();
- transitionTo(mInactiveState);
- replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_SUCCEEDED);
- break;
- default:
- ret = NOT_HANDLED;
- }
- return ret;
- }
- }
-
- class UserAuthorizingNegotiationRequestState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- notifyInvitationReceived();
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
- boolean ret = HANDLED;
- switch (message.what) {
- case PEER_CONNECTION_USER_ACCEPT:
- mWifiNative.p2pStopFind();
- p2pConnectWithPinDisplay(mSavedPeerConfig);
- mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);
- sendPeersChangedBroadcast();
- transitionTo(mGroupNegotiationState);
- break;
- case PEER_CONNECTION_USER_REJECT:
- if (DBG) logd("User rejected negotiation " + mSavedPeerConfig);
- transitionTo(mInactiveState);
- break;
- default:
- return NOT_HANDLED;
- }
- return ret;
- }
-
- @Override
- public void exit() {
- //TODO: dismiss dialog if not already done
- }
- }
-
- class UserAuthorizingInviteRequestState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- notifyInvitationReceived();
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
- boolean ret = HANDLED;
- switch (message.what) {
- case PEER_CONNECTION_USER_ACCEPT:
- mWifiNative.p2pStopFind();
- if (!reinvokePersistentGroup(mSavedPeerConfig)) {
- // Do negotiation when persistence fails
- p2pConnectWithPinDisplay(mSavedPeerConfig);
- }
- mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);
- sendPeersChangedBroadcast();
- transitionTo(mGroupNegotiationState);
- break;
- case PEER_CONNECTION_USER_REJECT:
- if (DBG) logd("User rejected invitation " + mSavedPeerConfig);
- transitionTo(mInactiveState);
- break;
- default:
- return NOT_HANDLED;
- }
- return ret;
- }
-
- @Override
- public void exit() {
- //TODO: dismiss dialog if not already done
- }
- }
-
-
-
- class ProvisionDiscoveryState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- mWifiNative.p2pProvisionDiscovery(mSavedPeerConfig);
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
- WifiP2pProvDiscEvent provDisc;
- WifiP2pDevice device;
- switch (message.what) {
- case WifiMonitor.P2P_PROV_DISC_PBC_RSP_EVENT:
- provDisc = (WifiP2pProvDiscEvent) message.obj;
- device = provDisc.device;
- if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) break;
-
- if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) {
- if (DBG) logd("Found a match " + mSavedPeerConfig);
- p2pConnectWithPinDisplay(mSavedPeerConfig);
- transitionTo(mGroupNegotiationState);
- }
- break;
- case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
- provDisc = (WifiP2pProvDiscEvent) message.obj;
- device = provDisc.device;
- if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) break;
-
- if (mSavedPeerConfig.wps.setup == WpsInfo.KEYPAD) {
- if (DBG) logd("Found a match " + mSavedPeerConfig);
- /* we already have the pin */
- if (!TextUtils.isEmpty(mSavedPeerConfig.wps.pin)) {
- p2pConnectWithPinDisplay(mSavedPeerConfig);
- transitionTo(mGroupNegotiationState);
- } else {
- mJoinExistingGroup = false;
- transitionTo(mUserAuthorizingNegotiationRequestState);
- }
- }
- break;
- case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
- provDisc = (WifiP2pProvDiscEvent) message.obj;
- device = provDisc.device;
- if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) break;
-
- if (mSavedPeerConfig.wps.setup == WpsInfo.DISPLAY) {
- if (DBG) logd("Found a match " + mSavedPeerConfig);
- mSavedPeerConfig.wps.pin = provDisc.pin;
- p2pConnectWithPinDisplay(mSavedPeerConfig);
- notifyInvitationSent(provDisc.pin, device.deviceAddress);
- transitionTo(mGroupNegotiationState);
- }
- break;
- case WifiMonitor.P2P_PROV_DISC_FAILURE_EVENT:
- loge("provision discovery failed");
- handleGroupCreationFailure();
- transitionTo(mInactiveState);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class GroupNegotiationState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
- switch (message.what) {
- // We ignore these right now, since we get a GROUP_STARTED notification
- // afterwards
- case WifiMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT:
- case WifiMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT:
- if (DBG) logd(getName() + " go success");
- break;
- case WifiMonitor.P2P_GROUP_STARTED_EVENT:
- mGroup = (WifiP2pGroup) message.obj;
- if (DBG) logd(getName() + " group started");
-
- if (mGroup.getNetworkId() == WifiP2pGroup.PERSISTENT_NET_ID) {
- /*
- * update cache information and set network id to mGroup.
- */
- updatePersistentNetworks(NO_RELOAD);
- String devAddr = mGroup.getOwner().deviceAddress;
- mGroup.setNetworkId(mGroups.getNetworkId(devAddr,
- mGroup.getNetworkName()));
- }
-
- if (mGroup.isGroupOwner()) {
- /* Setting an idle time out on GO causes issues with certain scenarios
- * on clients where it can be off-channel for longer and with the power
- * save modes used.
- *
- * TODO: Verify multi-channel scenarios and supplicant behavior are
- * better before adding a time out in future
- */
- //Set group idle timeout of 10 sec, to avoid GO beaconing incase of any
- //failure during 4-way Handshake.
- if (!mAutonomousGroup) {
- mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S);
- }
- startDhcpServer(mGroup.getInterface());
- } else {
- mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S);
- mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(mContext,
- P2pStateMachine.this, mGroup.getInterface());
- // TODO: We should use DHCP state machine PRE message like WifiStateMachine
- mWifiNative.setP2pPowerSave(mGroup.getInterface(), false);
- mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
- WifiP2pDevice groupOwner = mGroup.getOwner();
- WifiP2pDevice peer = mPeers.get(groupOwner.deviceAddress);
- if (peer != null) {
- // update group owner details with peer details found at discovery
- groupOwner.updateSupplicantDetails(peer);
- mPeers.updateStatus(groupOwner.deviceAddress, WifiP2pDevice.CONNECTED);
- sendPeersChangedBroadcast();
- } else {
- // A supplicant bug can lead to reporting an invalid
- // group owner address (all zeroes) at times. Avoid a
- // crash, but continue group creation since it is not
- // essential.
- logw("Unknown group owner " + groupOwner);
- }
- }
- transitionTo(mGroupCreatedState);
- break;
- case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT:
- P2pStatus status = (P2pStatus) message.obj;
- if (status == P2pStatus.NO_COMMON_CHANNEL) {
- transitionTo(mFrequencyConflictState);
- break;
- }
- /* continue with group removal handling */
- case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
- if (DBG) logd(getName() + " go failure");
- handleGroupCreationFailure();
- transitionTo(mInactiveState);
- break;
- // A group formation failure is always followed by
- // a group removed event. Flushing things at group formation
- // failure causes supplicant issues. Ignore right now.
- case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
- status = (P2pStatus) message.obj;
- if (status == P2pStatus.NO_COMMON_CHANNEL) {
- transitionTo(mFrequencyConflictState);
- break;
- }
- break;
- case WifiMonitor.P2P_INVITATION_RESULT_EVENT:
- status = (P2pStatus)message.obj;
- if (status == P2pStatus.SUCCESS) {
- // invocation was succeeded.
- // wait P2P_GROUP_STARTED_EVENT.
- break;
- }
- loge("Invitation result " + status);
- if (status == P2pStatus.UNKNOWN_P2P_GROUP) {
- // target device has already removed the credential.
- // So, remove this credential accordingly.
- int netId = mSavedPeerConfig.netId;
- if (netId >= 0) {
- if (DBG) logd("Remove unknown client from the list");
- removeClientFromList(netId, mSavedPeerConfig.deviceAddress, true);
- }
-
- // Reinvocation has failed, try group negotiation
- mSavedPeerConfig.netId = WifiP2pGroup.PERSISTENT_NET_ID;
- p2pConnectWithPinDisplay(mSavedPeerConfig);
- } else if (status == P2pStatus.INFORMATION_IS_CURRENTLY_UNAVAILABLE) {
-
- // Devices setting persistent_reconnect to 0 in wpa_supplicant
- // always defer the invocation request and return
- // "information is currently unable" error.
- // So, try another way to connect for interoperability.
- mSavedPeerConfig.netId = WifiP2pGroup.PERSISTENT_NET_ID;
- p2pConnectWithPinDisplay(mSavedPeerConfig);
- } else if (status == P2pStatus.NO_COMMON_CHANNEL) {
- transitionTo(mFrequencyConflictState);
- } else {
- handleGroupCreationFailure();
- transitionTo(mInactiveState);
- }
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- class FrequencyConflictState extends State {
- private AlertDialog mFrequencyConflictDialog;
- @Override
- public void enter() {
- if (DBG) logd(getName());
- notifyFrequencyConflict();
- }
-
- private void notifyFrequencyConflict() {
- logd("Notify frequency conflict");
- Resources r = Resources.getSystem();
-
- AlertDialog dialog = new AlertDialog.Builder(mContext)
- .setMessage(r.getString(R.string.wifi_p2p_frequency_conflict_message,
- getDeviceName(mSavedPeerConfig.deviceAddress)))
- .setPositiveButton(r.getString(R.string.dlg_ok), new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- sendMessage(DROP_WIFI_USER_ACCEPT);
- }
- })
- .setNegativeButton(r.getString(R.string.decline), new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- sendMessage(DROP_WIFI_USER_REJECT);
- }
- })
- .setOnCancelListener(new DialogInterface.OnCancelListener() {
- @Override
- public void onCancel(DialogInterface arg0) {
- sendMessage(DROP_WIFI_USER_REJECT);
- }
- })
- .create();
-
- dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
- dialog.show();
- mFrequencyConflictDialog = dialog;
- }
-
- @Override
- public boolean processMessage(Message message) {
- 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!");
- break;
- case WifiMonitor.P2P_GROUP_STARTED_EVENT:
- loge(getName() + "group started after freq conflict, handle anyway");
- deferMessage(message);
- transitionTo(mGroupNegotiationState);
- break;
- case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT:
- case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
- case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
- // Ignore failures since we retry again
- break;
- case DROP_WIFI_USER_REJECT:
- // User rejected dropping wifi in favour of p2p
- handleGroupCreationFailure();
- transitionTo(mInactiveState);
- break;
- case DROP_WIFI_USER_ACCEPT:
- // User accepted dropping wifi in favour of p2p
- mWifiChannel.sendMessage(WifiP2pService.DISCONNECT_WIFI_REQUEST, 1);
- mTempoarilyDisconnectedWifi = true;
- break;
- case DISCONNECT_WIFI_RESPONSE:
- // Got a response from wifistatemachine, retry p2p
- if (DBG) logd(getName() + "Wifi disconnected, retry p2p");
- transitionTo(mInactiveState);
- sendMessage(WifiP2pManager.CONNECT, mSavedPeerConfig);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
-
- public void exit() {
- if (mFrequencyConflictDialog != null) mFrequencyConflictDialog.dismiss();
- }
- }
-
- class GroupCreatedState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- // Once connected, peer config details are invalid
- mSavedPeerConfig.invalidate();
- mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
-
- updateThisDevice(WifiP2pDevice.CONNECTED);
-
- //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();
- }
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
- switch (message.what) {
- case WifiMonitor.AP_STA_CONNECTED_EVENT:
- WifiP2pDevice device = (WifiP2pDevice) message.obj;
- String deviceAddress = device.deviceAddress;
- // Clear timeout that was set when group was started.
- mWifiNative.setP2pGroupIdle(mGroup.getInterface(), 0);
- if (deviceAddress != null) {
- if (mPeers.get(deviceAddress) != null) {
- mGroup.addClient(mPeers.get(deviceAddress));
- } else {
- mGroup.addClient(deviceAddress);
- }
- mPeers.updateStatus(deviceAddress, WifiP2pDevice.CONNECTED);
- if (DBG) logd(getName() + " ap sta connected");
- sendPeersChangedBroadcast();
- } else {
- loge("Connect on null device address, ignore");
- }
- sendP2pConnectionChangedBroadcast();
- break;
- case WifiMonitor.AP_STA_DISCONNECTED_EVENT:
- device = (WifiP2pDevice) message.obj;
- deviceAddress = device.deviceAddress;
- if (deviceAddress != null) {
- mPeers.updateStatus(deviceAddress, WifiP2pDevice.AVAILABLE);
- if (mGroup.removeClient(deviceAddress)) {
- if (DBG) logd("Removed client " + deviceAddress);
- if (!mAutonomousGroup && mGroup.isClientListEmpty()) {
- logd("Client list empty, remove non-persistent p2p group");
- mWifiNative.p2pGroupRemove(mGroup.getInterface());
- // We end up sending connection changed broadcast
- // when this happens at exit()
- } else {
- // Notify when a client disconnects from group
- sendP2pConnectionChangedBroadcast();
- }
- } else {
- if (DBG) logd("Failed to remove client " + deviceAddress);
- for (WifiP2pDevice c : mGroup.getClientList()) {
- if (DBG) logd("client " + c.deviceAddress);
- }
- }
- sendPeersChangedBroadcast();
- if (DBG) logd(getName() + " ap sta disconnected");
- } else {
- loge("Disconnect on unknown device: " + device);
- }
- break;
- case DhcpStateMachine.CMD_POST_DHCP_ACTION:
- DhcpResults dhcpResults = (DhcpResults) message.obj;
- if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS &&
- dhcpResults != null) {
- if (DBG) logd("DhcpResults: " + dhcpResults);
- setWifiP2pInfoOnGroupFormation(dhcpResults.serverAddress);
- sendP2pConnectionChangedBroadcast();
- //Turn on power save on client
- mWifiNative.setP2pPowerSave(mGroup.getInterface(), true);
- } else {
- loge("DHCP failed");
- mWifiNative.p2pGroupRemove(mGroup.getInterface());
- }
- break;
- case WifiP2pManager.REMOVE_GROUP:
- if (DBG) logd(getName() + " remove group");
- if (mWifiNative.p2pGroupRemove(mGroup.getInterface())) {
- transitionTo(mOngoingGroupRemovalState);
- replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED);
- } else {
- handleGroupRemoved();
- transitionTo(mInactiveState);
- replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
- WifiP2pManager.ERROR);
- }
- break;
- /* We do not listen to NETWORK_DISCONNECTION_EVENT for group removal
- * handling since supplicant actually tries to reconnect after a temporary
- * disconnect until group idle time out. Eventually, a group removal event
- * will come when group has been removed.
- *
- * When there are connectivity issues during temporary disconnect, the application
- * will also just remove the group.
- *
- * Treating network disconnection as group removal causes race conditions since
- * supplicant would still maintain the group at that stage.
- */
- case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
- if (DBG) logd(getName() + " group removed");
- handleGroupRemoved();
- transitionTo(mInactiveState);
- break;
- case WifiMonitor.P2P_DEVICE_LOST_EVENT:
- device = (WifiP2pDevice) message.obj;
- //Device loss for a connected device indicates it is not in discovery any more
- if (mGroup.contains(device)) {
- if (DBG) logd("Add device to lost list " + device);
- mPeersLostDuringConnection.updateSupplicantDetails(device);
- return HANDLED;
- }
- // Do the regular device lost handling
- return NOT_HANDLED;
- case WifiStateMachine.CMD_DISABLE_P2P_REQ:
- sendMessage(WifiP2pManager.REMOVE_GROUP);
- deferMessage(message);
- break;
- // This allows any client to join the GO during the
- // WPS window
- case WifiP2pManager.START_WPS:
- WpsInfo wps = (WpsInfo) message.obj;
- if (wps == null) {
- replyToMessage(message, WifiP2pManager.START_WPS_FAILED);
- break;
- }
- boolean ret = true;
- if (wps.setup == WpsInfo.PBC) {
- ret = mWifiNative.startWpsPbc(mGroup.getInterface(), null);
- } else {
- if (wps.pin == null) {
- String pin = mWifiNative.startWpsPinDisplay(mGroup.getInterface());
- try {
- Integer.parseInt(pin);
- notifyInvitationSent(pin, "any");
- } catch (NumberFormatException ignore) {
- ret = false;
- }
- } else {
- ret = mWifiNative.startWpsPinKeypad(mGroup.getInterface(),
- wps.pin);
- }
- }
- replyToMessage(message, ret ? WifiP2pManager.START_WPS_SUCCEEDED :
- WifiP2pManager.START_WPS_FAILED);
- break;
- case WifiP2pManager.CONNECT:
- WifiP2pConfig config = (WifiP2pConfig) message.obj;
- if (isConfigInvalid(config)) {
- loge("Dropping connect requeset " + config);
- replyToMessage(message, WifiP2pManager.CONNECT_FAILED);
- break;
- }
- logd("Inviting device : " + config.deviceAddress);
- mSavedPeerConfig = config;
- if (mWifiNative.p2pInvite(mGroup, config.deviceAddress)) {
- mPeers.updateStatus(config.deviceAddress, WifiP2pDevice.INVITED);
- sendPeersChangedBroadcast();
- replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
- } else {
- replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
- WifiP2pManager.ERROR);
- }
- // TODO: figure out updating the status to declined when invitation is rejected
- break;
- case WifiMonitor.P2P_INVITATION_RESULT_EVENT:
- P2pStatus status = (P2pStatus)message.obj;
- if (status == P2pStatus.SUCCESS) {
- // invocation was succeeded.
- break;
- }
- loge("Invitation result " + status);
- if (status == P2pStatus.UNKNOWN_P2P_GROUP) {
- // target device has already removed the credential.
- // So, remove this credential accordingly.
- int netId = mGroup.getNetworkId();
- if (netId >= 0) {
- if (DBG) logd("Remove unknown client from the list");
- if (!removeClientFromList(netId,
- mSavedPeerConfig.deviceAddress, false)) {
- // not found the client on the list
- loge("Already removed the client, ignore");
- break;
- }
- // try invitation.
- sendMessage(WifiP2pManager.CONNECT, mSavedPeerConfig);
- }
- }
- 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:
- WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj;
- mSavedPeerConfig = new WifiP2pConfig();
- mSavedPeerConfig.deviceAddress = provDisc.device.deviceAddress;
- if (message.what == WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT) {
- mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD;
- } else if (message.what == WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT) {
- mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY;
- mSavedPeerConfig.wps.pin = provDisc.pin;
- } else {
- mSavedPeerConfig.wps.setup = WpsInfo.PBC;
- }
- transitionTo(mUserAuthorizingJoinState);
- break;
- case WifiMonitor.P2P_GROUP_STARTED_EVENT:
- loge("Duplicate group creation event notice, ignore");
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
-
- public void exit() {
- updateThisDevice(WifiP2pDevice.AVAILABLE);
- resetWifiP2pInfo();
- mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
- sendP2pConnectionChangedBroadcast();
- }
- }
-
- class UserAuthorizingJoinState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- notifyInvitationReceived();
- }
-
- @Override
- public boolean processMessage(Message message) {
- 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:
- case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT:
- //Ignore more client requests
- break;
- case PEER_CONNECTION_USER_ACCEPT:
- //Stop discovery to avoid failure due to channel switch
- mWifiNative.p2pStopFind();
- if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) {
- mWifiNative.startWpsPbc(mGroup.getInterface(), null);
- } else {
- mWifiNative.startWpsPinKeypad(mGroup.getInterface(),
- mSavedPeerConfig.wps.pin);
- }
- transitionTo(mGroupCreatedState);
- break;
- case PEER_CONNECTION_USER_REJECT:
- if (DBG) logd("User rejected incoming request");
- transitionTo(mGroupCreatedState);
- break;
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
-
- @Override
- public void exit() {
- //TODO: dismiss dialog if not already done
- }
- }
-
- class OngoingGroupRemovalState extends State {
- @Override
- public void enter() {
- if (DBG) logd(getName());
- }
-
- @Override
- public boolean processMessage(Message message) {
- if (DBG) logd(getName() + message.toString());
- switch (message.what) {
- // Group removal ongoing. Multiple calls
- // end up removing persisted network. Do nothing.
- case WifiP2pManager.REMOVE_GROUP:
- replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED);
- break;
- // Parent state will transition out of this state
- // when removal is complete
- default:
- return NOT_HANDLED;
- }
- return HANDLED;
- }
- }
-
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- super.dump(fd, pw, args);
- pw.println("mWifiP2pInfo " + mWifiP2pInfo);
- pw.println("mGroup " + mGroup);
- pw.println("mSavedPeerConfig " + mSavedPeerConfig);
- pw.println("mSavedP2pGroup " + mSavedP2pGroup);
- pw.println();
- }
-
- private void sendP2pStateChangedBroadcast(boolean enabled) {
- final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- if (enabled) {
- intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE,
- WifiP2pManager.WIFI_P2P_STATE_ENABLED);
- } else {
- intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE,
- WifiP2pManager.WIFI_P2P_STATE_DISABLED);
- }
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- private void sendP2pDiscoveryChangedBroadcast(boolean started) {
- if (mDiscoveryStarted == started) return;
- mDiscoveryStarted = started;
-
- if (DBG) logd("discovery change broadcast " + started);
-
- final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE, started ?
- WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED :
- WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED);
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- private void sendThisDeviceChangedBroadcast() {
- final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE, new WifiP2pDevice(mThisDevice));
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- private void sendPeersChangedBroadcast() {
- final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
- intent.putExtra(WifiP2pManager.EXTRA_P2P_DEVICE_LIST, new WifiP2pDeviceList(mPeers));
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- private void sendP2pConnectionChangedBroadcast() {
- if (DBG) logd("sending p2p connection changed broadcast");
- Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
- | Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo));
- intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo));
- intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP, new WifiP2pGroup(mGroup));
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- mWifiChannel.sendMessage(WifiP2pService.P2P_CONNECTION_CHANGED,
- new NetworkInfo(mNetworkInfo));
- }
-
- private void sendP2pPersistentGroupsChangedBroadcast() {
- if (DBG) logd("sending p2p persistent groups changed broadcast");
- Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- private void startDhcpServer(String intf) {
- InterfaceConfiguration ifcg = null;
- try {
- ifcg = mNwService.getInterfaceConfig(intf);
- ifcg.setLinkAddress(new LinkAddress(NetworkUtils.numericToInetAddress(
- SERVER_ADDRESS), 24));
- ifcg.setInterfaceUp();
- mNwService.setInterfaceConfig(intf, ifcg);
- /* This starts the dnsmasq server */
- mNwService.startTethering(DHCP_RANGE);
- } catch (Exception e) {
- loge("Error configuring interface " + intf + ", :" + e);
- return;
- }
-
- logd("Started Dhcp server on " + intf);
- }
-
- private void stopDhcpServer(String intf) {
- try {
- mNwService.stopTethering();
- } catch (Exception e) {
- loge("Error stopping Dhcp server" + e);
- return;
- }
-
- logd("Stopped Dhcp server");
- }
-
- private void notifyP2pEnableFailure() {
- Resources r = Resources.getSystem();
- AlertDialog dialog = new AlertDialog.Builder(mContext)
- .setTitle(r.getString(R.string.wifi_p2p_dialog_title))
- .setMessage(r.getString(R.string.wifi_p2p_failed_message))
- .setPositiveButton(r.getString(R.string.ok), null)
- .create();
- dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
- dialog.show();
- }
-
- private void addRowToDialog(ViewGroup group, int stringId, String value) {
- Resources r = Resources.getSystem();
- View row = LayoutInflater.from(mContext).inflate(R.layout.wifi_p2p_dialog_row,
- group, false);
- ((TextView) row.findViewById(R.id.name)).setText(r.getString(stringId));
- ((TextView) row.findViewById(R.id.value)).setText(value);
- group.addView(row);
- }
-
- private void notifyInvitationSent(String pin, String peerAddress) {
- Resources r = Resources.getSystem();
-
- 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.ok), null)
- .create();
- dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
- dialog.show();
- }
-
- private void notifyInvitationReceived() {
- Resources r = Resources.getSystem();
- final WpsInfo wps = mSavedPeerConfig.wps;
- 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_from_message, getDeviceName(
- mSavedPeerConfig.deviceAddress));
-
- final EditText pin = (EditText) textEntryView.findViewById(R.id.wifi_p2p_wps_pin);
-
- AlertDialog dialog = new AlertDialog.Builder(mContext)
- .setTitle(r.getString(R.string.wifi_p2p_invitation_to_connect_title))
- .setView(textEntryView)
- .setPositiveButton(r.getString(R.string.accept), new OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- if (wps.setup == WpsInfo.KEYPAD) {
- mSavedPeerConfig.wps.pin = pin.getText().toString();
- }
- if (DBG) logd(getName() + " accept invitation " + mSavedPeerConfig);
- sendMessage(PEER_CONNECTION_USER_ACCEPT);
- }
- })
- .setNegativeButton(r.getString(R.string.decline), new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (DBG) logd(getName() + " ignore connect");
- sendMessage(PEER_CONNECTION_USER_REJECT);
- }
- })
- .setOnCancelListener(new DialogInterface.OnCancelListener() {
- @Override
- public void onCancel(DialogInterface arg0) {
- if (DBG) logd(getName() + " ignore connect");
- sendMessage(PEER_CONNECTION_USER_REJECT);
- }
- })
- .create();
-
- //make the enter pin area or the display pin area visible
- switch (wps.setup) {
- case WpsInfo.KEYPAD:
- if (DBG) logd("Enter pin section visible");
- textEntryView.findViewById(R.id.enter_pin_section).setVisibility(View.VISIBLE);
- break;
- case WpsInfo.DISPLAY:
- if (DBG) logd("Shown pin section visible");
- addRowToDialog(group, R.string.wifi_p2p_show_pin_message, wps.pin);
- break;
- default:
- break;
- }
-
- if ((r.getConfiguration().uiMode & Configuration.UI_MODE_TYPE_APPLIANCE) ==
- Configuration.UI_MODE_TYPE_APPLIANCE) {
- // For appliance devices, add a key listener which accepts.
- dialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
-
- @Override
- public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
- // TODO: make the actual key come from a config value.
- if (keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
- sendMessage(PEER_CONNECTION_USER_ACCEPT);
- dialog.dismiss();
- return true;
- }
- return false;
- }
- });
- // TODO: add timeout for this dialog.
- // TODO: update UI in appliance mode to tell user what to do.
- }
-
- dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
- dialog.show();
- }
-
- /**
- * Synchronize the persistent group list between
- * wpa_supplicant and mGroups.
- */
- private void updatePersistentNetworks(boolean reload) {
- String listStr = mWifiNative.listNetworks();
- if (listStr == null) return;
-
- boolean isSaveRequired = false;
- String[] lines = listStr.split("\n");
- if (lines == null) return;
-
- if (reload) mGroups.clear();
-
- // Skip the first line, which is a header
- for (int i = 1; i < lines.length; i++) {
- String[] result = lines[i].split("\t");
- if (result == null || result.length < 4) {
- continue;
- }
- // network-id | ssid | bssid | flags
- int netId = -1;
- String ssid = result[1];
- String bssid = result[2];
- String flags = result[3];
- try {
- netId = Integer.parseInt(result[0]);
- } catch(NumberFormatException e) {
- e.printStackTrace();
- continue;
- }
-
- if (flags.indexOf("[CURRENT]") != -1) {
- continue;
- }
- if (flags.indexOf("[P2P-PERSISTENT]") == -1) {
- /*
- * The unused profile is sometimes remained when the p2p group formation is failed.
- * So, we clean up the p2p group here.
- */
- if (DBG) logd("clean up the unused persistent group. netId=" + netId);
- mWifiNative.removeNetwork(netId);
- isSaveRequired = true;
- continue;
- }
-
- if (mGroups.contains(netId)) {
- continue;
- }
-
- WifiP2pGroup group = new WifiP2pGroup();
- group.setNetworkId(netId);
- group.setNetworkName(ssid);
- String mode = mWifiNative.getNetworkVariable(netId, "mode");
- if (mode != null && mode.equals("3")) {
- group.setIsGroupOwner(true);
- }
- if (bssid.equalsIgnoreCase(mThisDevice.deviceAddress)) {
- group.setOwner(mThisDevice);
- } else {
- WifiP2pDevice device = new WifiP2pDevice();
- device.deviceAddress = bssid;
- group.setOwner(device);
- }
- mGroups.add(group);
- isSaveRequired = true;
- }
-
- if (reload || isSaveRequired) {
- mWifiNative.saveConfig();
- sendP2pPersistentGroupsChangedBroadcast();
- }
- }
-
- /**
- * A config is valid if it has a peer address that has already been
- * discovered
- * @return true if it is invalid, false otherwise
- */
- private boolean isConfigInvalid(WifiP2pConfig config) {
- if (config == null) return true;
- if (TextUtils.isEmpty(config.deviceAddress)) return true;
- if (mPeers.get(config.deviceAddress) == null) return true;
- return false;
- }
-
- /* TODO: The supplicant does not provide group capability changes as an event.
- * Having it pushed as an event would avoid polling for this information right
- * before a connection
- */
- private WifiP2pDevice fetchCurrentDeviceDetails(WifiP2pConfig config) {
- /* Fetch & update group capability from supplicant on the device */
- int gc = mWifiNative.getGroupCapability(config.deviceAddress);
- mPeers.updateGroupCapability(config.deviceAddress, gc);
- return mPeers.get(config.deviceAddress);
- }
-
- /**
- * Start a p2p group negotiation and display pin if necessary
- * @param config for the peer
- */
- private void p2pConnectWithPinDisplay(WifiP2pConfig config) {
- WifiP2pDevice dev = fetchCurrentDeviceDetails(config);
-
- String pin = mWifiNative.p2pConnect(config, dev.isGroupOwner());
- try {
- Integer.parseInt(pin);
- notifyInvitationSent(pin, config.deviceAddress);
- } catch (NumberFormatException ignore) {
- // do nothing if p2pConnect did not return a pin
- }
- }
-
- /**
- * Reinvoke a persistent group.
- *
- * @param config for the peer
- * @return true on success, false on failure
- */
- private boolean reinvokePersistentGroup(WifiP2pConfig config) {
- WifiP2pDevice dev = fetchCurrentDeviceDetails(config);
-
- boolean join = dev.isGroupOwner();
- String ssid = mWifiNative.p2pGetSsid(dev.deviceAddress);
- if (DBG) logd("target ssid is " + ssid + " join:" + join);
-
- if (join && dev.isGroupLimit()) {
- if (DBG) logd("target device reaches group limit.");
-
- // if the target group has reached the limit,
- // try group formation.
- join = false;
- } else if (join) {
- int netId = mGroups.getNetworkId(dev.deviceAddress, ssid);
- if (netId >= 0) {
- // Skip WPS and start 4way handshake immediately.
- if (!mWifiNative.p2pGroupAdd(netId)) {
- return false;
- }
- return true;
- }
- }
-
- if (!join && dev.isDeviceLimit()) {
- loge("target device reaches the device limit.");
- return false;
- }
-
- if (!join && dev.isInvitationCapable()) {
- int netId = WifiP2pGroup.PERSISTENT_NET_ID;
- if (config.netId >= 0) {
- if (config.deviceAddress.equals(mGroups.getOwnerAddr(config.netId))) {
- netId = config.netId;
- }
- } else {
- netId = mGroups.getNetworkId(dev.deviceAddress);
- }
- if (netId < 0) {
- netId = getNetworkIdFromClientList(dev.deviceAddress);
- }
- if (DBG) logd("netId related with " + dev.deviceAddress + " = " + netId);
- if (netId >= 0) {
- // Invoke the persistent group.
- if (mWifiNative.p2pReinvoke(netId, dev.deviceAddress)) {
- // Save network id. It'll be used when an invitation result event is received.
- config.netId = netId;
- return true;
- } else {
- loge("p2pReinvoke() failed, update networks");
- updatePersistentNetworks(RELOAD);
- return false;
- }
- }
- }
-
- return false;
- }
-
- /**
- * Return the network id of the group owner profile which has the p2p client with
- * the specified device address in it's client list.
- * If more than one persistent group of the same address is present in its client
- * lists, return the first one.
- *
- * @param deviceAddress p2p device address.
- * @return the network id. if not found, return -1.
- */
- private int getNetworkIdFromClientList(String deviceAddress) {
- if (deviceAddress == null) return -1;
-
- Collection<WifiP2pGroup> groups = mGroups.getGroupList();
- for (WifiP2pGroup group : groups) {
- int netId = group.getNetworkId();
- String[] p2pClientList = getClientList(netId);
- if (p2pClientList == null) continue;
- for (String client : p2pClientList) {
- if (deviceAddress.equalsIgnoreCase(client)) {
- return netId;
- }
- }
- }
- return -1;
- }
-
- /**
- * Return p2p client list associated with the specified network id.
- * @param netId network id.
- * @return p2p client list. if not found, return null.
- */
- private String[] getClientList(int netId) {
- String p2pClients = mWifiNative.getNetworkVariable(netId, "p2p_client_list");
- if (p2pClients == null) {
- return null;
- }
- return p2pClients.split(" ");
- }
-
- /**
- * Remove the specified p2p client from the specified profile.
- * @param netId network id of the profile.
- * @param addr p2p client address to be removed.
- * @param isRemovable if true, remove the specified profile if its client list becomes empty.
- * @return whether removing the specified p2p client is successful or not.
- */
- private boolean removeClientFromList(int netId, String addr, boolean isRemovable) {
- StringBuilder modifiedClientList = new StringBuilder();
- String[] currentClientList = getClientList(netId);
- boolean isClientRemoved = false;
- if (currentClientList != null) {
- for (String client : currentClientList) {
- if (!client.equalsIgnoreCase(addr)) {
- modifiedClientList.append(" ");
- modifiedClientList.append(client);
- } else {
- isClientRemoved = true;
- }
- }
- }
- if (modifiedClientList.length() == 0 && isRemovable) {
- // the client list is empty. so remove it.
- if (DBG) logd("Remove unknown network");
- mGroups.remove(netId);
- return true;
- }
-
- if (!isClientRemoved) {
- // specified p2p client is not found. already removed.
- return false;
- }
-
- if (DBG) logd("Modified client list: " + modifiedClientList);
- if (modifiedClientList.length() == 0) {
- modifiedClientList.append("\"\"");
- }
- mWifiNative.setNetworkVariable(netId,
- "p2p_client_list", modifiedClientList.toString());
- mWifiNative.saveConfig();
- return true;
- }
-
- private void setWifiP2pInfoOnGroupFormation(InetAddress serverInetAddress) {
- mWifiP2pInfo.groupFormed = true;
- mWifiP2pInfo.isGroupOwner = mGroup.isGroupOwner();
- mWifiP2pInfo.groupOwnerAddress = serverInetAddress;
- }
-
- private void resetWifiP2pInfo() {
- mWifiP2pInfo.groupFormed = false;
- mWifiP2pInfo.isGroupOwner = false;
- mWifiP2pInfo.groupOwnerAddress = null;
- }
-
- private String getDeviceName(String deviceAddress) {
- WifiP2pDevice d = mPeers.get(deviceAddress);
- if (d != null) {
- return d.deviceName;
- }
- //Treat the address as name if there is no match
- return deviceAddress;
- }
-
- private String getPersistedDeviceName() {
- String deviceName = Settings.Global.getString(mContext.getContentResolver(),
- Settings.Global.WIFI_P2P_DEVICE_NAME);
- if (deviceName == null) {
- /* 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(),
- Settings.Secure.ANDROID_ID);
- return "Android_" + id.substring(0,4);
- }
- return deviceName;
- }
-
- private boolean setAndPersistDeviceName(String devName) {
- if (devName == null) return false;
-
- if (!mWifiNative.setDeviceName(devName)) {
- loge("Failed to set device name " + devName);
- return false;
- }
-
- mThisDevice.deviceName = devName;
- mWifiNative.setP2pSsidPostfix("-" + mThisDevice.deviceName);
-
- Settings.Global.putString(mContext.getContentResolver(),
- Settings.Global.WIFI_P2P_DEVICE_NAME, devName);
- sendThisDeviceChangedBroadcast();
- return true;
- }
-
- private boolean setWfdInfo(WifiP2pWfdInfo wfdInfo) {
- boolean success;
-
- if (!wfdInfo.isWfdEnabled()) {
- success = mWifiNative.setWfdEnable(false);
- } else {
- success =
- mWifiNative.setWfdEnable(true)
- && mWifiNative.setWfdDeviceInfo(wfdInfo.getDeviceInfoHex());
- }
-
- if (!success) {
- loge("Failed to set wfd properties");
- return false;
- }
-
- mThisDevice.wfdInfo = wfdInfo;
- sendThisDeviceChangedBroadcast();
- return true;
- }
-
- private void initializeP2pSettings() {
- mWifiNative.setPersistentReconnect(true);
- mThisDevice.deviceName = getPersistedDeviceName();
- mWifiNative.setDeviceName(mThisDevice.deviceName);
- // DIRECT-XY-DEVICENAME (XY is randomly generated)
- mWifiNative.setP2pSsidPostfix("-" + mThisDevice.deviceName);
- mWifiNative.setDeviceType(mThisDevice.primaryDeviceType);
- // Supplicant defaults to using virtual display with display
- // which refers to a remote display. Use physical_display
- mWifiNative.setConfigMethods("virtual_push_button physical_display keypad");
- // STA has higher priority over P2P
- mWifiNative.setConcurrencyPriority("sta");
-
- mThisDevice.deviceAddress = mWifiNative.p2pGetDeviceAddress();
- updateThisDevice(WifiP2pDevice.AVAILABLE);
- if (DBG) logd("DeviceAddress: " + mThisDevice.deviceAddress);
-
- mClientInfoList.clear();
- mWifiNative.p2pFlush();
- mWifiNative.p2pServiceFlush();
- mServiceTransactionId = 0;
- mServiceDiscReqId = null;
-
- String countryCode = Settings.Global.getString(mContext.getContentResolver(),
- Settings.Global.WIFI_COUNTRY_CODE);
- if (countryCode != null && !countryCode.isEmpty()) {
- mP2pStateMachine.sendMessage(SET_COUNTRY_CODE, countryCode);
- }
-
- updatePersistentNetworks(RELOAD);
- }
-
- private void updateThisDevice(int status) {
- mThisDevice.status = status;
- sendThisDeviceChangedBroadcast();
- }
-
- private void handleGroupCreationFailure() {
- resetWifiP2pInfo();
- mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.FAILED, null, null);
- sendP2pConnectionChangedBroadcast();
-
- // Remove only the peer we failed to connect to so that other devices discovered
- // that have not timed out still remain in list for connection
- boolean peersChanged = mPeers.remove(mPeersLostDuringConnection);
- if (mPeers.remove(mSavedPeerConfig.deviceAddress) != null) {
- peersChanged = true;
- }
- if (peersChanged) {
- sendPeersChangedBroadcast();
- }
-
- mPeersLostDuringConnection.clear();
- mServiceDiscReqId = null;
- sendMessage(WifiP2pManager.DISCOVER_PEERS);
- }
-
- private void handleGroupRemoved() {
- if (mGroup.isGroupOwner()) {
- stopDhcpServer(mGroup.getInterface());
- } else {
- if (DBG) logd("stop DHCP client");
- mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
- mDhcpStateMachine.doQuit();
- mDhcpStateMachine = null;
- }
-
- try {
- mNwService.clearInterfaceAddresses(mGroup.getInterface());
- } catch (Exception e) {
- loge("Failed to clear addresses " + e);
- }
- NetworkUtils.resetConnections(mGroup.getInterface(), NetworkUtils.RESET_ALL_ADDRESSES);
-
- // Clear any timeout that was set. This is essential for devices
- // that reuse the main p2p interface for a created group.
- mWifiNative.setP2pGroupIdle(mGroup.getInterface(), 0);
-
- boolean peersChanged = false;
- // Remove only peers part of the group, so that other devices discovered
- // that have not timed out still remain in list for connection
- for (WifiP2pDevice d : mGroup.getClientList()) {
- if (mPeers.remove(d)) peersChanged = true;
- }
- if (mPeers.remove(mGroup.getOwner())) peersChanged = true;
- if (mPeers.remove(mPeersLostDuringConnection)) peersChanged = true;
- if (peersChanged) {
- sendPeersChangedBroadcast();
- }
-
- mGroup = null;
- mPeersLostDuringConnection.clear();
- mServiceDiscReqId = null;
-
- if (mTempoarilyDisconnectedWifi) {
- mWifiChannel.sendMessage(WifiP2pService.DISCONNECT_WIFI_REQUEST, 0);
- mTempoarilyDisconnectedWifi = false;
- }
- }
-
- //State machine initiated requests can have replyTo set to null indicating
- //there are no recipients, we ignore those reply actions
- private void replyToMessage(Message msg, int what) {
- if (msg.replyTo == null) return;
- Message dstMsg = obtainMessage(msg);
- dstMsg.what = what;
- mReplyChannel.replyToMessage(msg, dstMsg);
- }
-
- private void replyToMessage(Message msg, int what, int arg1) {
- if (msg.replyTo == null) return;
- Message dstMsg = obtainMessage(msg);
- dstMsg.what = what;
- dstMsg.arg1 = arg1;
- mReplyChannel.replyToMessage(msg, dstMsg);
- }
-
- private void replyToMessage(Message msg, int what, Object obj) {
- if (msg.replyTo == null) return;
- Message dstMsg = obtainMessage(msg);
- dstMsg.what = what;
- dstMsg.obj = obj;
- mReplyChannel.replyToMessage(msg, dstMsg);
- }
-
- /* arg2 on the source message has a hash code that needs to be retained in replies
- * see WifiP2pManager for details */
- private Message obtainMessage(Message srcMsg) {
- Message msg = Message.obtain();
- msg.arg2 = srcMsg.arg2;
- return msg;
- }
-
- @Override
- protected void logd(String s) {
- Slog.d(TAG, s);
- }
-
- @Override
- protected void loge(String s) {
- Slog.e(TAG, s);
- }
-
- /**
- * Update service discovery request to wpa_supplicant.
- */
- private boolean updateSupplicantServiceRequest() {
- clearSupplicantServiceRequest();
-
- StringBuffer sb = new StringBuffer();
- for (ClientInfo c: mClientInfoList.values()) {
- int key;
- WifiP2pServiceRequest req;
- for (int i=0; i < c.mReqList.size(); i++) {
- req = c.mReqList.valueAt(i);
- if (req != null) {
- sb.append(req.getSupplicantQuery());
- }
- }
- }
-
- if (sb.length() == 0) {
- return false;
- }
-
- mServiceDiscReqId = mWifiNative.p2pServDiscReq("00:00:00:00:00:00", sb.toString());
- if (mServiceDiscReqId == null) {
- return false;
- }
- return true;
- }
-
- /**
- * Clear service discovery request in wpa_supplicant
- */
- private void clearSupplicantServiceRequest() {
- if (mServiceDiscReqId == null) return;
-
- mWifiNative.p2pServDiscCancelReq(mServiceDiscReqId);
- mServiceDiscReqId = null;
- }
-
- /* TODO: We could track individual service adds separately and avoid
- * having to do update all service requests on every new request
- */
- private boolean addServiceRequest(Messenger m, WifiP2pServiceRequest req) {
- clearClientDeadChannels();
- ClientInfo clientInfo = getClientInfo(m, true);
- if (clientInfo == null) {
- return false;
- }
-
- ++mServiceTransactionId;
- //The Wi-Fi p2p spec says transaction id should be non-zero
- if (mServiceTransactionId == 0) ++mServiceTransactionId;
- req.setTransactionId(mServiceTransactionId);
- clientInfo.mReqList.put(mServiceTransactionId, req);
-
- if (mServiceDiscReqId == null) {
- return true;
- }
-
- return updateSupplicantServiceRequest();
- }
-
- private void removeServiceRequest(Messenger m, WifiP2pServiceRequest req) {
- ClientInfo clientInfo = getClientInfo(m, false);
- if (clientInfo == null) {
- return;
- }
-
- //Application does not have transaction id information
- //go through stored requests to remove
- boolean removed = false;
- for (int i=0; i<clientInfo.mReqList.size(); i++) {
- if (req.equals(clientInfo.mReqList.valueAt(i))) {
- removed = true;
- clientInfo.mReqList.removeAt(i);
- break;
- }
- }
-
- if (!removed) return;
-
- if (clientInfo.mReqList.size() == 0 && clientInfo.mServList.size() == 0) {
- if (DBG) logd("remove client information from framework");
- mClientInfoList.remove(clientInfo.mMessenger);
- }
-
- if (mServiceDiscReqId == null) {
- return;
- }
-
- updateSupplicantServiceRequest();
- }
-
- private void clearServiceRequests(Messenger m) {
-
- ClientInfo clientInfo = getClientInfo(m, false);
- if (clientInfo == null) {
- return;
- }
-
- if (clientInfo.mReqList.size() == 0) {
- return;
- }
-
- clientInfo.mReqList.clear();
-
- if (clientInfo.mServList.size() == 0) {
- if (DBG) logd("remove channel information from framework");
- mClientInfoList.remove(clientInfo.mMessenger);
- }
-
- if (mServiceDiscReqId == null) {
- return;
- }
-
- updateSupplicantServiceRequest();
- }
-
- private boolean addLocalService(Messenger m, WifiP2pServiceInfo servInfo) {
- clearClientDeadChannels();
- ClientInfo clientInfo = getClientInfo(m, true);
- if (clientInfo == null) {
- return false;
- }
-
- if (!clientInfo.mServList.add(servInfo)) {
- return false;
- }
-
- if (!mWifiNative.p2pServiceAdd(servInfo)) {
- clientInfo.mServList.remove(servInfo);
- return false;
- }
-
- return true;
- }
-
- private void removeLocalService(Messenger m, WifiP2pServiceInfo servInfo) {
- ClientInfo clientInfo = getClientInfo(m, false);
- if (clientInfo == null) {
- return;
- }
-
- mWifiNative.p2pServiceDel(servInfo);
-
- clientInfo.mServList.remove(servInfo);
- if (clientInfo.mReqList.size() == 0 && clientInfo.mServList.size() == 0) {
- if (DBG) logd("remove client information from framework");
- mClientInfoList.remove(clientInfo.mMessenger);
- }
- }
-
- private void clearLocalServices(Messenger m) {
- ClientInfo clientInfo = getClientInfo(m, false);
- if (clientInfo == null) {
- return;
- }
-
- for (WifiP2pServiceInfo servInfo: clientInfo.mServList) {
- mWifiNative.p2pServiceDel(servInfo);
- }
-
- clientInfo.mServList.clear();
- if (clientInfo.mReqList.size() == 0) {
- if (DBG) logd("remove client information from framework");
- mClientInfoList.remove(clientInfo.mMessenger);
- }
- }
-
- private void clearClientInfo(Messenger m) {
- clearLocalServices(m);
- clearServiceRequests(m);
- }
-
- /**
- * Send the service response to the WifiP2pManager.Channel.
- *
- * @param resp
- */
- private void sendServiceResponse(WifiP2pServiceResponse resp) {
- for (ClientInfo c : mClientInfoList.values()) {
- WifiP2pServiceRequest req = c.mReqList.get(resp.getTransactionId());
- if (req != null) {
- Message msg = Message.obtain();
- msg.what = WifiP2pManager.RESPONSE_SERVICE;
- msg.arg1 = 0;
- msg.arg2 = 0;
- msg.obj = resp;
- try {
- c.mMessenger.send(msg);
- } catch (RemoteException e) {
- if (DBG) logd("detect dead channel");
- clearClientInfo(c.mMessenger);
- return;
- }
- }
- }
- }
-
- /**
- * We dont get notifications of clients that have gone away.
- * We detect this actively when services are added and throw
- * them away.
- *
- * TODO: This can be done better with full async channels.
- */
- private void clearClientDeadChannels() {
- ArrayList<Messenger> deadClients = new ArrayList<Messenger>();
-
- for (ClientInfo c : mClientInfoList.values()) {
- Message msg = Message.obtain();
- msg.what = WifiP2pManager.PING;
- msg.arg1 = 0;
- msg.arg2 = 0;
- msg.obj = null;
- try {
- c.mMessenger.send(msg);
- } catch (RemoteException e) {
- if (DBG) logd("detect dead channel");
- deadClients.add(c.mMessenger);
- }
- }
-
- for (Messenger m : deadClients) {
- clearClientInfo(m);
- }
- }
-
- /**
- * Return the specified ClientInfo.
- * @param m Messenger
- * @param createIfNotExist if true and the specified channel info does not exist,
- * create new client info.
- * @return the specified ClientInfo.
- */
- private ClientInfo getClientInfo(Messenger m, boolean createIfNotExist) {
- ClientInfo clientInfo = mClientInfoList.get(m);
-
- if (clientInfo == null && createIfNotExist) {
- if (DBG) logd("add a new client");
- clientInfo = new ClientInfo(m);
- mClientInfoList.put(m, clientInfo);
- }
-
- return clientInfo;
- }
-
- }
-
- /**
- * Information about a particular client and we track the service discovery requests
- * and the local services registered by the client.
- */
- private class ClientInfo {
-
- /*
- * A reference to WifiP2pManager.Channel handler.
- * The response of this request is notified to WifiP2pManager.Channel handler
- */
- private Messenger mMessenger;
-
- /*
- * A service discovery request list.
- */
- private SparseArray<WifiP2pServiceRequest> mReqList;
-
- /*
- * A local service information list.
- */
- private List<WifiP2pServiceInfo> mServList;
-
- private ClientInfo(Messenger m) {
- mMessenger = m;
- mReqList = new SparseArray();
- mServList = new ArrayList<WifiP2pServiceInfo>();
- }
- }
-}