Initial support for concurrency

Use of multiple socket connections over wlan0 and p2p and
p2p state machine is now controlled entirely from wifi state machine

Add discovery stop to allow STA scans to proceed after p2p is used

Change-Id: I790c9112d3f475f638f06fc3ae9e191f6d90ef35
This commit is contained in:
Irfan Sheriff
2012-01-10 15:50:45 -08:00
parent ea77ed02e4
commit 7d6d9c005e
8 changed files with 129 additions and 450 deletions

View File

@@ -116,14 +116,9 @@ static jboolean android_net_wifi_unloadDriver(JNIEnv* env, jobject)
return (jboolean)(::wifi_unload_driver() == 0);
}
static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject)
static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject, jboolean p2pSupported)
{
return (jboolean)(::wifi_start_supplicant() == 0);
}
static jboolean android_net_wifi_startP2pSupplicant(JNIEnv* env, jobject)
{
return (jboolean)(::wifi_start_p2p_supplicant() == 0);
return (jboolean)(::wifi_start_supplicant(p2pSupported) == 0);
}
static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject)
@@ -207,8 +202,7 @@ static JNINativeMethod gWifiMethods[] = {
{ "loadDriver", "()Z", (void *)android_net_wifi_loadDriver },
{ "isDriverLoaded", "()Z", (void *)android_net_wifi_isDriverLoaded },
{ "unloadDriver", "()Z", (void *)android_net_wifi_unloadDriver },
{ "startSupplicant", "()Z", (void *)android_net_wifi_startSupplicant },
{ "startP2pSupplicant", "()Z", (void *)android_net_wifi_startP2pSupplicant },
{ "startSupplicant", "(Z)Z", (void *)android_net_wifi_startSupplicant },
{ "killSupplicant", "()Z", (void *)android_net_wifi_killSupplicant },
{ "connectToSupplicant", "(Ljava/lang/String;)Z",
(void *)android_net_wifi_connectToSupplicant },

View File

@@ -2696,11 +2696,6 @@
<!-- Do not translate. Default access point SSID used for tethering -->
<string name="wifi_tether_configure_ssid_default" translatable="false">AndroidAP</string>
<!-- Wi-Fi p2p dialog title-->
<string name="wifi_p2p_dialog_title">Wi-Fi Direct</string>
<string name="wifi_p2p_turnon_message">Start Wi-Fi Direct. This will turn off Wi-Fi client/hotspot.</string>
<string name="wifi_p2p_failed_message">Couldn\'t start Wi-Fi Direct.</string>
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="wifi_p2p_invitation_sent_title">Invitation sent</string>
@@ -2711,9 +2706,6 @@
<string name="wifi_p2p_enter_pin_message">Type the required PIN: </string>
<string name="wifi_p2p_show_pin_message">PIN: </string>
<string name="wifi_p2p_enabled_notification_title">Wi-Fi Direct is on</string>
<string name="wifi_p2p_enabled_notification_message">Touch for settings</string>
<!-- Name of the dialog that lets the user choose an accented character to insert -->
<string name="select_character">Insert character</string>

View File

@@ -365,17 +365,6 @@ public class WifiMonitor {
} else if (event == DRIVER_STATE) {
handleDriverEvent(eventData);
} else if (event == TERMINATING) {
/**
* If monitor socket is closed, we have already
* stopped the supplicant, simply exit the monitor thread
*/
if (eventData.startsWith(MONITOR_SOCKET_CLOSED_STR)) {
if (false) {
Log.d(TAG, "Monitor socket is closed, exiting thread");
}
break;
}
/**
* Close the supplicant connection if we see
* too many recv errors

View File

@@ -39,6 +39,8 @@ import java.util.List;
*/
public class WifiNative {
private static final boolean DBG = false;
private final String mTAG;
private static final int DEFAULT_GROUP_OWNER_INTENT = 7;
static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED = 0;
@@ -53,9 +55,7 @@ public class WifiNative {
public native static boolean unloadDriver();
public native static boolean startSupplicant();
public native static boolean startP2pSupplicant();
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 */
@@ -79,6 +79,7 @@ public class WifiNative {
public WifiNative(String iface) {
mInterface = iface;
mTAG = "WifiNative-" + iface;
}
public boolean connectToSupplicant() {
@@ -94,14 +95,17 @@ public class WifiNative {
}
private boolean doBooleanCommand(String command) {
if (DBG) Log.d(mTAG, "doBoolean: " + command);
return doBooleanCommand(mInterface, command);
}
private int doIntCommand(String command) {
if (DBG) Log.d(mTAG, "doInt: " + command);
return doIntCommand(mInterface, command);
}
private String doStringCommand(String command) {
if (DBG) Log.d(mTAG, "doString: " + command);
return doStringCommand(mInterface, command);
}
@@ -437,6 +441,10 @@ public class WifiNative {
return doBooleanCommand("P2P_FIND " + timeout);
}
public boolean p2pStopFind() {
return doBooleanCommand("P2P_STOP_FIND");
}
public boolean p2pListen() {
return doBooleanCommand("P2P_LISTEN");
}

View File

@@ -45,6 +45,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.DhcpInfoInternal;
@@ -118,6 +119,8 @@ public class WifiStateMachine extends StateMachine {
private INetworkManagementService mNwService;
private ConnectivityManager mCm;
private final boolean mP2pSupported;
/* Scan results handling */
private List<ScanResult> mScanResults;
private static final Pattern scanResultPattern = Pattern.compile("\t+");
@@ -361,9 +364,9 @@ public class WifiStateMachine extends StateMachine {
/* Reset the WPS state machine */
static final int CMD_RESET_WPS_STATE = BASE + 122;
/* Interaction with WifiP2pService */
public static final int WIFI_ENABLE_PENDING = BASE + 131;
public static final int P2P_ENABLE_PROCEED = BASE + 132;
/* P2p commands */
public static final int CMD_ENABLE_P2P = BASE + 131;
public static final int CMD_DISABLE_P2P = BASE + 132;
private static final int CONNECT_MODE = 1;
private static final int SCAN_ONLY_MODE = 2;
@@ -482,9 +485,6 @@ public class WifiStateMachine extends StateMachine {
/* Waiting for untether confirmation to stop soft Ap */
private State mSoftApStoppingState = new SoftApStoppingState();
/* Wait till p2p is disabled */
private State mWaitForP2pDisableState = new WaitForP2pDisableState();
private class TetherStateChange {
ArrayList<String> available;
ArrayList<String> active;
@@ -556,6 +556,9 @@ public class WifiStateMachine extends StateMachine {
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);
@@ -639,7 +642,6 @@ public class WifiStateMachine extends StateMachine {
addState(mTetheringState, mSoftApStartedState);
addState(mTetheredState, mSoftApStartedState);
addState(mSoftApStoppingState, mDefaultState);
addState(mWaitForP2pDisableState, mDefaultState);
setInitialState(mInitialState);
@@ -1892,11 +1894,6 @@ public class WifiStateMachine extends StateMachine {
mReplyChannel.replyToMessage(message, WifiManager.CMD_WPS_COMPLETED,
new WpsResult(Status.FAILURE));
break;
case WifiP2pService.P2P_ENABLE_PENDING:
// turn off wifi and defer to be handled in DriverUnloadedState
setWifiEnabled(false);
deferMessage(message);
break;
default:
loge("Error! unhandled message" + message);
break;
@@ -2056,7 +2053,7 @@ public class WifiStateMachine extends StateMachine {
loge("Unable to change interface settings: " + ie);
}
if(mWifiNative.startSupplicant()) {
if(mWifiNative.startSupplicant(mP2pSupported)) {
if (DBG) log("Supplicant start successful");
mWifiMonitor.startMonitoring();
transitionTo(mSupplicantStartingState);
@@ -2168,11 +2165,7 @@ public class WifiStateMachine extends StateMachine {
if (DBG) log(getName() + message.toString() + "\n");
switch (message.what) {
case CMD_LOAD_DRIVER:
mWifiP2pChannel.sendMessage(WIFI_ENABLE_PENDING);
transitionTo(mWaitForP2pDisableState);
break;
case WifiP2pService.P2P_ENABLE_PENDING:
mReplyChannel.replyToMessage(message, P2P_ENABLE_PROCEED);
transitionTo(mDriverLoadingState);
break;
default:
return NOT_HANDLED;
@@ -2549,13 +2542,15 @@ public class WifiStateMachine extends StateMachine {
mWifiNative.status();
transitionTo(mDisconnectedState);
}
if (mP2pSupported) mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P);
}
@Override
public boolean processMessage(Message message) {
if (DBG) log(getName() + message.toString() + "\n");
boolean eventLoggingEnabled = true;
switch(message.what) {
case CMD_SET_SCAN_TYPE:
case CMD_SET_SCAN_TYPE:
mSetScanActive = (message.arg1 == SCAN_ACTIVE);
mWifiNative.setScanMode(mSetScanActive);
break;
@@ -2668,6 +2663,8 @@ public class WifiStateMachine extends StateMachine {
mIsRunning = false;
updateBatteryWorkSource(null);
mScanResults = null;
if (mP2pSupported) mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P);
}
}
@@ -3341,7 +3338,6 @@ public class WifiStateMachine extends StateMachine {
case CMD_START_PACKET_FILTERING:
case CMD_STOP_PACKET_FILTERING:
case CMD_TETHER_STATE_CHANGE:
case WifiP2pService.P2P_ENABLE_PENDING:
deferMessage(message);
break;
case WifiStateMachine.CMD_RESPONSE_AP_CONFIG:
@@ -3405,55 +3401,6 @@ public class WifiStateMachine extends StateMachine {
transitionTo(mTetheringState);
}
break;
case WifiP2pService.P2P_ENABLE_PENDING:
// turn of soft Ap and defer to be handled in DriverUnloadedState
setWifiApEnabled(null, false);
deferMessage(message);
break;
default:
return NOT_HANDLED;
}
EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
return HANDLED;
}
}
class WaitForP2pDisableState extends State {
private int mSavedArg;
@Override
public void enter() {
if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
//Preserve the argument arg1 that has information used in DriverLoadingState
mSavedArg = getCurrentMessage().arg1;
}
@Override
public boolean processMessage(Message message) {
if (DBG) log(getName() + message.toString() + "\n");
switch(message.what) {
case WifiP2pService.WIFI_ENABLE_PROCEED:
//restore argument from original message (CMD_LOAD_DRIVER)
message.arg1 = mSavedArg;
transitionTo(mDriverLoadingState);
break;
case CMD_LOAD_DRIVER:
case CMD_UNLOAD_DRIVER:
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_SCAN_MODE:
case CMD_SET_SCAN_TYPE:
case CMD_SET_HIGH_PERF_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;
}
@@ -3503,7 +3450,6 @@ public class WifiStateMachine extends StateMachine {
case CMD_SET_FREQUENCY_BAND:
case CMD_START_PACKET_FILTERING:
case CMD_STOP_PACKET_FILTERING:
case WifiP2pService.P2P_ENABLE_PENDING:
deferMessage(message);
break;
default:
@@ -3599,7 +3545,6 @@ public class WifiStateMachine extends StateMachine {
case CMD_SET_FREQUENCY_BAND:
case CMD_START_PACKET_FILTERING:
case CMD_STOP_PACKET_FILTERING:
case WifiP2pService.P2P_ENABLE_PENDING:
deferMessage(message);
break;
default:

View File

@@ -301,7 +301,8 @@ public class WifiP2pDevice implements Parcelable {
private String trimQuotes(String str) {
str = str.trim();
if (str.startsWith("'") && str.endsWith("'")) {
return str.substring(1, str.length()-1);
if (str.length() <= 2) return "";
else return str.substring(1, str.length()-1);
}
return str;
}

View File

@@ -199,68 +199,61 @@ public class WifiP2pManager {
private static final int BASE = Protocol.BASE_WIFI_P2P_MANAGER;
/** @hide */
public static final int ENABLE_P2P = BASE + 1;
public static final int DISCOVER_PEERS = BASE + 1;
/** @hide */
public static final int ENABLE_P2P_FAILED = BASE + 2;
public static final int DISCOVER_PEERS_FAILED = BASE + 2;
/** @hide */
public static final int ENABLE_P2P_SUCCEEDED = BASE + 3;
public static final int DISCOVER_PEERS_SUCCEEDED = BASE + 3;
/** @hide */
public static final int DISABLE_P2P = BASE + 4;
public static final int STOP_DISCOVERY = BASE + 4;
/** @hide */
public static final int DISABLE_P2P_FAILED = BASE + 5;
public static final int STOP_DISCOVERY_FAILED = BASE + 5;
/** @hide */
public static final int DISABLE_P2P_SUCCEEDED = BASE + 6;
public static final int STOP_DISCOVERY_SUCCEEDED = BASE + 6;
/** @hide */
public static final int DISCOVER_PEERS = BASE + 7;
public static final int CONNECT = BASE + 7;
/** @hide */
public static final int DISCOVER_PEERS_FAILED = BASE + 8;
public static final int CONNECT_FAILED = BASE + 8;
/** @hide */
public static final int DISCOVER_PEERS_SUCCEEDED = BASE + 9;
public static final int CONNECT_SUCCEEDED = BASE + 9;
/** @hide */
public static final int CONNECT = BASE + 10;
public static final int CANCEL_CONNECT = BASE + 10;
/** @hide */
public static final int CONNECT_FAILED = BASE + 11;
public static final int CANCEL_CONNECT_FAILED = BASE + 11;
/** @hide */
public static final int CONNECT_SUCCEEDED = BASE + 12;
public static final int CANCEL_CONNECT_SUCCEEDED = BASE + 12;
/** @hide */
public static final int CANCEL_CONNECT = BASE + 13;
public static final int CREATE_GROUP = BASE + 13;
/** @hide */
public static final int CANCEL_CONNECT_FAILED = BASE + 14;
public static final int CREATE_GROUP_FAILED = BASE + 14;
/** @hide */
public static final int CANCEL_CONNECT_SUCCEEDED = BASE + 15;
public static final int CREATE_GROUP_SUCCEEDED = BASE + 15;
/** @hide */
public static final int CREATE_GROUP = BASE + 16;
public static final int REMOVE_GROUP = BASE + 16;
/** @hide */
public static final int CREATE_GROUP_FAILED = BASE + 17;
public static final int REMOVE_GROUP_FAILED = BASE + 17;
/** @hide */
public static final int CREATE_GROUP_SUCCEEDED = BASE + 18;
public static final int REMOVE_GROUP_SUCCEEDED = BASE + 18;
/** @hide */
public static final int REMOVE_GROUP = BASE + 19;
public static final int REQUEST_PEERS = BASE + 19;
/** @hide */
public static final int REMOVE_GROUP_FAILED = BASE + 20;
/** @hide */
public static final int REMOVE_GROUP_SUCCEEDED = BASE + 21;
public static final int RESPONSE_PEERS = BASE + 20;
/** @hide */
public static final int REQUEST_PEERS = BASE + 22;
public static final int REQUEST_CONNECTION_INFO = BASE + 21;
/** @hide */
public static final int RESPONSE_PEERS = BASE + 23;
public static final int RESPONSE_CONNECTION_INFO = BASE + 22;
/** @hide */
public static final int REQUEST_CONNECTION_INFO = BASE + 24;
public static final int REQUEST_GROUP_INFO = BASE + 23;
/** @hide */
public static final int RESPONSE_CONNECTION_INFO = BASE + 25;
/** @hide */
public static final int REQUEST_GROUP_INFO = BASE + 26;
/** @hide */
public static final int RESPONSE_GROUP_INFO = BASE + 27;
public static final int RESPONSE_GROUP_INFO = BASE + 24;
/**
* Create a new WifiP2pManager instance. Applications use
@@ -376,6 +369,7 @@ public class WifiP2pManager {
break;
/* ActionListeners grouped together */
case WifiP2pManager.DISCOVER_PEERS_FAILED:
case WifiP2pManager.STOP_DISCOVERY_FAILED:
case WifiP2pManager.CONNECT_FAILED:
case WifiP2pManager.CANCEL_CONNECT_FAILED:
case WifiP2pManager.CREATE_GROUP_FAILED:
@@ -386,6 +380,7 @@ public class WifiP2pManager {
break;
/* ActionListeners grouped together */
case WifiP2pManager.DISCOVER_PEERS_SUCCEEDED:
case WifiP2pManager.STOP_DISCOVERY_SUCCEEDED:
case WifiP2pManager.CONNECT_SUCCEEDED:
case WifiP2pManager.CANCEL_CONNECT_SUCCEEDED:
case WifiP2pManager.CREATE_GROUP_SUCCEEDED:
@@ -458,26 +453,6 @@ public class WifiP2pManager {
}
}
/**
* Sends in a request to the system to enable p2p. This will pop up a dialog
* to the user and upon authorization will enable p2p.
* @hide
*/
public void enableP2p(Channel c) {
if (c == null) return;
c.mAsyncChannel.sendMessage(ENABLE_P2P);
}
/**
* Sends in a request to the system to disable p2p. This will pop up a dialog
* to the user and upon authorization will enable p2p.
* @hide
*/
public void disableP2p(Channel c) {
if (c == null) return;
c.mAsyncChannel.sendMessage(DISABLE_P2P);
}
/**
* Initiate peer discovery. A discovery process involves scanning for available Wi-Fi peers
* for the purpose of establishing a connection.
@@ -502,6 +477,16 @@ public class WifiP2pManager {
c.mAsyncChannel.sendMessage(DISCOVER_PEERS, 0, c.putListener(listener));
}
/**
* TODO: Add more documentation before opening up
* Cancel peer discovery
* @hide
*/
public void stopPeerDiscovery(Channel c, ActionListener listener) {
if (c == null) return;
c.mAsyncChannel.sendMessage(STOP_DISCOVERY, 0, c.putListener(listener));
}
/**
* Start a p2p connection to a device with the specified configuration.
*

View File

@@ -49,6 +49,7 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.provider.Settings;
@@ -84,7 +85,7 @@ import java.util.Collection;
*/
public class WifiP2pService extends IWifiP2pManager.Stub {
private static final String TAG = "WifiP2pService";
private static final boolean DBG = true;
private static final boolean DBG = false;
private static final String NETWORKTYPE = "WIFI_P2P";
private Context mContext;
@@ -94,11 +95,6 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
INetworkManagementService mNwService;
private DhcpStateMachine mDhcpStateMachine;
//Tracked to notify the user about wifi client/hotspot being shut down
//during p2p bring up
private int mWifiState = WifiManager.WIFI_STATE_DISABLED;
private int mWifiApState = WifiManager.WIFI_AP_STATE_DISABLED;
private P2pStateMachine mP2pStateMachine;
private AsyncChannel mReplyChannel = new AsyncChannel();
private AsyncChannel mWifiChannel;
@@ -110,6 +106,9 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
private static final int GROUP_CREATING_WAIT_TIME_MS = 120 * 1000;
private static int mGroupCreatingTimeoutIndex = 0;
/* Set a two minute discover timeout to avoid STA scans from being blocked */
private static final int DISCOVER_TIMEOUT_S = 120;
/**
* Delay between restarts upon failure to setup connection with supplicant
*/
@@ -124,28 +123,13 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE;
/* Message sent to WifiStateMachine to indicate p2p enable is pending */
public static final int P2P_ENABLE_PENDING = BASE + 1;
/* Message sent to WifiStateMachine to indicate Wi-Fi client/hotspot operation can proceed */
public static final int WIFI_ENABLE_PROCEED = BASE + 2;
/* Delayed message to timeout group creation */
public static final int GROUP_CREATING_TIMED_OUT = BASE + 3;
/* User accepted to disable Wi-Fi in order to enable p2p */
private static final int WIFI_DISABLE_USER_ACCEPT = BASE + 4;
/* User rejected to disable Wi-Fi in order to enable p2p */
private static final int WIFI_DISABLE_USER_REJECT = BASE + 5;
public static final int GROUP_CREATING_TIMED_OUT = BASE + 1;
/* User accepted a peer request */
private static final int PEER_CONNECTION_USER_ACCEPT = BASE + 6;
private static final int PEER_CONNECTION_USER_ACCEPT = BASE + 2;
/* User rejected a peer request */
private static final int PEER_CONNECTION_USER_REJECT = BASE + 7;
/* Airplane mode changed */
private static final int AIRPLANE_MODE_CHANGED = BASE + 8;
/* Emergency callback mode */
private static final int EMERGENCY_CALLBACK_MODE = BASE + 9;
private static final int PEER_CONNECTION_USER_REJECT = BASE + 3;
private final boolean mP2pSupported;
@@ -166,7 +150,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
public WifiP2pService(Context context) {
mContext = context;
//STOPSHIP: fix this
//STOPSHIP: get this from native side
mInterface = "p2p0";
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORKTYPE, "");
@@ -179,15 +163,6 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
mP2pStateMachine = new P2pStateMachine(TAG, mP2pSupported);
mP2pStateMachine.start();
// broadcasts
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
mContext.registerReceiver(new WifiStateReceiver(), filter);
}
public void connectivityServiceReady() {
@@ -195,26 +170,6 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
mNwService = INetworkManagementService.Stub.asInterface(b);
}
private class WifiStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_DISABLED);
} else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
mWifiApState = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE,
WifiManager.WIFI_AP_STATE_DISABLED);
} else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
mP2pStateMachine.sendMessage(AIRPLANE_MODE_CHANGED);
} else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
if (intent.getBooleanExtra("phoneinECMState", false) == true) {
mP2pStateMachine.sendMessage(EMERGENCY_CALLBACK_MODE);
}
}
}
}
private void enforceAccessPermission() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_WIFI_STATE,
"WifiP2pService");
@@ -264,8 +219,6 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
private P2pNotSupportedState mP2pNotSupportedState = new P2pNotSupportedState();
private P2pDisablingState mP2pDisablingState = new P2pDisablingState();
private P2pDisabledState mP2pDisabledState = new P2pDisabledState();
private WaitForUserActionState mWaitForUserActionState = new WaitForUserActionState();
private WaitForWifiDisableState mWaitForWifiDisableState = new WaitForWifiDisableState();
private P2pEnablingState mP2pEnablingState = new P2pEnablingState();
private P2pEnabledState mP2pEnabledState = new P2pEnabledState();
// Inactive is when p2p is enabled with no connectivity
@@ -299,8 +252,6 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
addState(mP2pNotSupportedState, mDefaultState);
addState(mP2pDisablingState, mDefaultState);
addState(mP2pDisabledState, mDefaultState);
addState(mWaitForUserActionState, mP2pDisabledState);
addState(mWaitForWifiDisableState, mP2pDisabledState);
addState(mP2pEnablingState, mDefaultState);
addState(mP2pEnabledState, mDefaultState);
addState(mInactiveState, mP2pEnabledState);
@@ -346,23 +297,14 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
AsyncChannel ac = new AsyncChannel();
ac.connect(mContext, getHandler(), message.replyTo);
break;
case WifiStateMachine.WIFI_ENABLE_PENDING:
// Disable p2p operation before we can respond
sendMessage(WifiP2pManager.DISABLE_P2P);
deferMessage(message);
break;
case WifiP2pManager.ENABLE_P2P:
replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED,
WifiP2pManager.BUSY);
break;
case WifiP2pManager.DISABLE_P2P:
replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED,
WifiP2pManager.BUSY);
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.CONNECT:
replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
WifiP2pManager.BUSY);
@@ -388,16 +330,14 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
case WifiP2pManager.REQUEST_GROUP_INFO:
replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, mGroup);
break;
case AIRPLANE_MODE_CHANGED:
if (isAirplaneModeOn()) sendMessage(WifiP2pManager.DISABLE_P2P);
break;
case EMERGENCY_CALLBACK_MODE:
sendMessage(WifiP2pManager.DISABLE_P2P);
break;
// Ignore
case WifiMonitor.P2P_INVITATION_RESULT_EVENT:
case WIFI_DISABLE_USER_ACCEPT:
case WIFI_DISABLE_USER_REJECT:
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 PEER_CONNECTION_USER_ACCEPT:
case PEER_CONNECTION_USER_REJECT:
case GROUP_CREATING_TIMED_OUT:
@@ -414,22 +354,14 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
@Override
public boolean processMessage(Message message) {
switch (message.what) {
// Allow Wi-Fi to proceed
case WifiStateMachine.WIFI_ENABLE_PENDING:
replyToMessage(message, WIFI_ENABLE_PROCEED);
break;
case WifiP2pManager.ENABLE_P2P:
replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED,
WifiP2pManager.P2P_UNSUPPORTED);
break;
case WifiP2pManager.DISABLE_P2P:
replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED,
WifiP2pManager.P2P_UNSUPPORTED);
break;
case WifiP2pManager.DISCOVER_PEERS:
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.CONNECT:
replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
WifiP2pManager.P2P_UNSUPPORTED);
@@ -438,7 +370,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED,
WifiP2pManager.P2P_UNSUPPORTED);
break;
case WifiP2pManager.CREATE_GROUP:
case WifiP2pManager.CREATE_GROUP:
replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
WifiP2pManager.P2P_UNSUPPORTED);
break;
@@ -454,27 +386,16 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
}
class P2pDisablingState extends State {
@Override
public void enter() {
if (DBG) logd(getName());
logd("stopping supplicant");
if (!mWifiNative.stopSupplicant()) {
loge("Failed to stop supplicant, issue kill");
mWifiNative.killSupplicant();
}
}
@Override
public boolean processMessage(Message message) {
if (DBG) logd(getName() + message.toString());
switch (message.what) {
case WifiMonitor.SUP_DISCONNECTION_EVENT:
logd("Supplicant connection lost");
mWifiNative.closeSupplicantConnection();
if (DBG) logd("p2p socket connection lost");
transitionTo(mP2pDisabledState);
break;
case WifiP2pManager.ENABLE_P2P:
case WifiP2pManager.DISABLE_P2P:
case WifiStateMachine.CMD_ENABLE_P2P:
case WifiStateMachine.CMD_DISABLE_P2P:
deferMessage(message);
break;
default:
@@ -484,7 +405,6 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
}
}
class P2pDisabledState extends State {
@Override
public void enter() {
@@ -495,118 +415,19 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
public boolean processMessage(Message message) {
if (DBG) logd(getName() + message.toString());
switch (message.what) {
case WifiP2pManager.ENABLE_P2P:
OnClickListener listener = new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
sendMessage(WIFI_DISABLE_USER_ACCEPT);
} else {
sendMessage(WIFI_DISABLE_USER_REJECT);
}
}
};
// Show a user request dialog if we know Wi-Fi client/hotspot is in operation
if (mWifiState != WifiManager.WIFI_STATE_DISABLED ||
mWifiApState != WifiManager.WIFI_AP_STATE_DISABLED) {
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_turnon_message))
.setPositiveButton(r.getString(R.string.ok), listener)
.setNegativeButton(r.getString(R.string.cancel), listener)
.create();
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
dialog.show();
transitionTo(mWaitForUserActionState);
} else {
mWifiChannel.sendMessage(P2P_ENABLE_PENDING);
transitionTo(mWaitForWifiDisableState);
}
replyToMessage(message, WifiP2pManager.ENABLE_P2P_SUCCEEDED);
break;
case WifiP2pManager.DISABLE_P2P:
replyToMessage(message, WifiP2pManager.DISABLE_P2P_SUCCEEDED);
break;
case WifiStateMachine.WIFI_ENABLE_PENDING:
replyToMessage(message, WIFI_ENABLE_PROCEED);
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
}
class WaitForUserActionState 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 WIFI_DISABLE_USER_ACCEPT:
mWifiChannel.sendMessage(P2P_ENABLE_PENDING);
transitionTo(mWaitForWifiDisableState);
break;
case WIFI_DISABLE_USER_REJECT:
logd("User rejected enabling p2p");
sendP2pStateChangedBroadcast(false);
transitionTo(mP2pDisabledState);
break;
case WifiP2pManager.ENABLE_P2P:
case WifiP2pManager.DISABLE_P2P:
deferMessage(message);
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
}
class WaitForWifiDisableState 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.P2P_ENABLE_PROCEED:
case WifiStateMachine.CMD_ENABLE_P2P:
try {
mNwService.wifiFirmwareReload(mInterface, "P2P");
} catch (Exception e) {
loge("Failed to reload p2p firmware " + e);
// continue
}
//A runtime crash can leave the interface up and
//this affects p2p when supplicant starts up.
//Ensure interface is down before a supplicant start.
try {
mNwService.setInterfaceDown(mInterface);
} catch (Exception e) {
if (DBG) Slog.w(TAG, "Unable to bring down wlan interface: " + e);
}
if (mWifiNative.startP2pSupplicant()) {
mWifiMonitor.startMonitoring();
transitionTo(mP2pEnablingState);
} else {
notifyP2pEnableFailure();
transitionTo(mP2pDisabledState);
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;
case WifiP2pManager.ENABLE_P2P:
case WifiP2pManager.DISABLE_P2P:
deferMessage(message);
case WifiStateMachine.CMD_DISABLE_P2P:
//Nothing to do
break;
default:
return NOT_HANDLED;
@@ -626,22 +447,15 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
if (DBG) logd(getName() + message.toString());
switch (message.what) {
case WifiMonitor.SUP_CONNECTION_EVENT:
logd("P2p start successful");
if (DBG) logd("P2p socket connection successful");
transitionTo(mInactiveState);
break;
case WifiMonitor.SUP_DISCONNECTION_EVENT:
if (++mP2pRestartCount <= P2P_RESTART_TRIES) {
loge("Failed to start p2p, retry");
mWifiNative.killSupplicant();
sendMessageDelayed(WifiP2pManager.ENABLE_P2P, P2P_RESTART_INTERVAL_MSECS);
} else {
loge("Failed " + mP2pRestartCount + " times to start p2p, quit ");
mP2pRestartCount = 0;
}
loge("P2p socket connection failed");
transitionTo(mP2pDisabledState);
break;
case WifiP2pManager.ENABLE_P2P:
case WifiP2pManager.DISABLE_P2P:
case WifiStateMachine.CMD_ENABLE_P2P:
case WifiStateMachine.CMD_DISABLE_P2P:
deferMessage(message);
break;
default:
@@ -658,30 +472,36 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
sendP2pStateChangedBroadcast(true);
mNetworkInfo.setIsAvailable(true);
initializeP2pSettings();
showNotification();
}
@Override
public boolean processMessage(Message message) {
if (DBG) logd(getName() + message.toString());
switch (message.what) {
case WifiP2pManager.ENABLE_P2P:
replyToMessage(message, WifiP2pManager.ENABLE_P2P_SUCCEEDED);
case WifiStateMachine.CMD_ENABLE_P2P:
//Nothing to do
break;
case WifiP2pManager.DISABLE_P2P:
case WifiStateMachine.CMD_DISABLE_P2P:
if (mPeers.clear()) sendP2pPeersChangedBroadcast();
replyToMessage(message, WifiP2pManager.DISABLE_P2P_SUCCEEDED);
mWifiNative.closeSupplicantConnection();
transitionTo(mP2pDisablingState);
break;
case WifiP2pManager.DISCOVER_PEERS:
int timeout = message.arg1;
if (mWifiNative.p2pFind(timeout)) {
if (mWifiNative.p2pFind(DISCOVER_TIMEOUT_S)) {
replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED);
} else {
replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
WifiP2pManager.ERROR);
}
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 WifiMonitor.P2P_DEVICE_FOUND_EVENT:
WifiP2pDevice device = (WifiP2pDevice) message.obj;
if (mThisDevice.deviceAddress.equals(device.deviceAddress)) break;
@@ -692,15 +512,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
device = (WifiP2pDevice) message.obj;
if (mPeers.remove(device)) sendP2pPeersChangedBroadcast();
break;
case WifiMonitor.SUP_DISCONNECTION_EVENT: /* Supplicant died */
loge("Connection lost, restart p2p");
mWifiNative.killSupplicant();
mWifiNative.closeSupplicantConnection();
if (mPeers.clear()) sendP2pPeersChangedBroadcast();
transitionTo(mP2pDisabledState);
sendMessageDelayed(WifiP2pManager.ENABLE_P2P, P2P_RESTART_INTERVAL_MSECS);
break;
default:
default:
return NOT_HANDLED;
}
return HANDLED;
@@ -710,7 +522,6 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
public void exit() {
sendP2pStateChangedBroadcast(false);
mNetworkInfo.setIsAvailable(false);
clearNotification();
}
}
@@ -719,7 +530,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
public void enter() {
if (DBG) logd(getName());
//Start listening every time we get inactive
mWifiNative.p2pListen();
//TODO: Fix listen after driver behavior is fixed
//mWifiNative.p2pListen();
}
@Override
@@ -737,6 +549,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
//TODO: if failure, remove config and do a regular p2pConnect()
mWifiNative.p2pReinvoke(netId, mSavedPeerConfig.deviceAddress);
} else {
//Stop discovery before issuing connect
mWifiNative.p2pStopFind();
//If peer is a GO, we do not need to send provisional discovery,
//the supplicant takes care of it.
if (isGroupOwner(mSavedPeerConfig.deviceAddress)) {
@@ -1114,7 +928,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
}
// Do the regular device lost handling
return NOT_HANDLED;
case WifiP2pManager.DISABLE_P2P:
case WifiStateMachine.CMD_DISABLE_P2P:
sendMessage(WifiP2pManager.REMOVE_GROUP);
deferMessage(message);
break;
@@ -1494,54 +1308,5 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
Slog.e(TAG, s);
}
private void showNotification() {
NotificationManager notificationManager =
(NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager == null || mNotification != null) {
return;
}
Intent intent = new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
Resources r = Resources.getSystem();
CharSequence title = r.getText(R.string.wifi_p2p_enabled_notification_title);
CharSequence message = r.getText(R.string.wifi_p2p_enabled_notification_message);
mNotification = new Notification();
mNotification.when = 0;
//TODO: might change to be a seperate icon
mNotification.icon = R.drawable.stat_sys_tether_wifi;
mNotification.defaults &= ~Notification.DEFAULT_SOUND;
mNotification.flags = Notification.FLAG_ONGOING_EVENT;
mNotification.tickerText = title;
mNotification.setLatestEventInfo(mContext, title, message, pi);
notificationManager.notify(mNotification.icon, mNotification);
}
private void clearNotification() {
NotificationManager notificationManager =
(NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null && mNotification != null) {
notificationManager.cancel(mNotification.icon);
mNotification = null;
}
}
private boolean isAirplaneSensitive() {
String airplaneModeRadios = Settings.System.getString(mContext.getContentResolver(),
Settings.System.AIRPLANE_MODE_RADIOS);
return airplaneModeRadios == null
|| airplaneModeRadios.contains(Settings.System.RADIO_WIFI);
}
private boolean isAirplaneModeOn() {
return isAirplaneSensitive() && Settings.System.getInt(mContext.getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, 0) == 1;
}
}
}