Skip to content

Commit 7b6d238

Browse files
isheriffAndroid (Google) Code Review
authored andcommitted
Merge "Fix tethering interaction from wifi" into ics-mr1
2 parents e95f498 + c74694d commit 7b6d238

File tree

1 file changed

+191
-15
lines changed

1 file changed

+191
-15
lines changed

wifi/java/android/net/wifi/WifiStateMachine.java

Lines changed: 191 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ public class WifiStateMachine extends StateMachine {
123123
private final LruCache<String, ScanResult> mScanResultCache;
124124

125125
private String mInterfaceName;
126+
/* Tethering interface could be seperate from wlan interface */
127+
private String mTetherInterfaceName;
126128

127129
private int mLastSignalLevel = -1;
128130
private String mLastBssid;
@@ -156,6 +158,14 @@ public class WifiStateMachine extends StateMachine {
156158
/* Tracks sequence number on stop failure message */
157159
private int mSupplicantStopFailureToken = 0;
158160

161+
/**
162+
* Tether state change notification time out
163+
*/
164+
private static final int TETHER_NOTIFICATION_TIME_OUT_MSECS = 5000;
165+
166+
/* Tracks sequence number on a tether notification time out */
167+
private int mTetherToken = 0;
168+
159169
private LinkProperties mLinkProperties;
160170

161171
// Wakelock held during wifi start/stop and driver load/unload
@@ -240,10 +250,12 @@ public class WifiStateMachine extends StateMachine {
240250
static final int CMD_REQUEST_AP_CONFIG = BASE + 27;
241251
/* Response to access point configuration request */
242252
static final int CMD_RESPONSE_AP_CONFIG = BASE + 28;
243-
/* Set configuration on tether interface */
244-
static final int CMD_TETHER_INTERFACE = BASE + 29;
253+
/* Invoked when getting a tether state change notification */
254+
static final int CMD_TETHER_STATE_CHANGE = BASE + 29;
255+
/* A delayed message sent to indicate tether state change failed to arrive */
256+
static final int CMD_TETHER_NOTIFICATION_TIMED_OUT = BASE + 30;
245257

246-
static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 30;
258+
static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 31;
247259

248260
/* Supplicant commands */
249261
/* Is supplicant alive ? */
@@ -455,12 +467,25 @@ public class WifiStateMachine extends StateMachine {
455467
private State mSoftApStartingState = new SoftApStartingState();
456468
/* Soft ap is running */
457469
private State mSoftApStartedState = new SoftApStartedState();
470+
/* Soft ap is running and we are waiting for tether notification */
471+
private State mTetheringState = new TetheringState();
458472
/* Soft ap is running and we are tethered through connectivity service */
459473
private State mTetheredState = new TetheredState();
474+
/* Waiting for untether confirmation to stop soft Ap */
475+
private State mSoftApStoppingState = new SoftApStoppingState();
460476

461477
/* Wait till p2p is disabled */
462478
private State mWaitForP2pDisableState = new WaitForP2pDisableState();
463479

480+
private class TetherStateChange {
481+
ArrayList<String> available;
482+
ArrayList<String> active;
483+
TetherStateChange(ArrayList<String> av, ArrayList<String> ac) {
484+
available = av;
485+
active = ac;
486+
}
487+
}
488+
464489

465490
/**
466491
* One of {@link WifiManager#WIFI_STATE_DISABLED},
@@ -562,7 +587,9 @@ public WifiStateMachine(Context context, String wlanInterface) {
562587
public void onReceive(Context context, Intent intent) {
563588
ArrayList<String> available = intent.getStringArrayListExtra(
564589
ConnectivityManager.EXTRA_AVAILABLE_TETHER);
565-
sendMessage(CMD_TETHER_INTERFACE, available);
590+
ArrayList<String> active = intent.getStringArrayListExtra(
591+
ConnectivityManager.EXTRA_ACTIVE_TETHER);
592+
sendMessage(CMD_TETHER_STATE_CHANGE, new TetherStateChange(available, active));
566593
}
567594
},new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
568595

@@ -603,7 +630,9 @@ public void onReceive(Context context, Intent intent) {
603630
addState(mSupplicantStoppingState, mDefaultState);
604631
addState(mSoftApStartingState, mDefaultState);
605632
addState(mSoftApStartedState, mDefaultState);
633+
addState(mTetheringState, mSoftApStartedState);
606634
addState(mTetheredState, mSoftApStartedState);
635+
addState(mSoftApStoppingState, mDefaultState);
607636
addState(mWaitForP2pDisableState, mDefaultState);
608637

609638
setInitialState(mInitialState);
@@ -1139,6 +1168,7 @@ private boolean startTethering(ArrayList<String> available) {
11391168
loge("Error tethering on " + intf);
11401169
return false;
11411170
}
1171+
mTetherInterfaceName = intf;
11421172
return true;
11431173
}
11441174
}
@@ -1165,11 +1195,27 @@ private void stopTethering() {
11651195
loge("Error resetting interface " + mInterfaceName + ", :" + e);
11661196
}
11671197

1168-
if (mCm.untether(mInterfaceName) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
1198+
if (mCm.untether(mTetherInterfaceName) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
11691199
loge("Untether initiate failed!");
11701200
}
11711201
}
11721202

1203+
private boolean isWifiTethered(ArrayList<String> active) {
1204+
1205+
checkAndSetConnectivityInstance();
1206+
1207+
String[] wifiRegexs = mCm.getTetherableWifiRegexs();
1208+
for (String intf : active) {
1209+
for (String regex : wifiRegexs) {
1210+
if (intf.matches(regex)) {
1211+
return true;
1212+
}
1213+
}
1214+
}
1215+
// We found no interfaces that are tethered
1216+
return false;
1217+
}
1218+
11731219
/**
11741220
* Set the country code from the system setting value, if any.
11751221
*/
@@ -1800,7 +1846,8 @@ public boolean processMessage(Message message) {
18001846
case CMD_START_AP_SUCCESS:
18011847
case CMD_START_AP_FAILURE:
18021848
case CMD_STOP_AP:
1803-
case CMD_TETHER_INTERFACE:
1849+
case CMD_TETHER_STATE_CHANGE:
1850+
case CMD_TETHER_NOTIFICATION_TIMED_OUT:
18041851
case CMD_START_SCAN:
18051852
case CMD_DISCONNECT:
18061853
case CMD_RECONNECT:
@@ -3284,7 +3331,7 @@ public boolean processMessage(Message message) {
32843331
case CMD_SET_FREQUENCY_BAND:
32853332
case CMD_START_PACKET_FILTERING:
32863333
case CMD_STOP_PACKET_FILTERING:
3287-
case CMD_TETHER_INTERFACE:
3334+
case CMD_TETHER_STATE_CHANGE:
32883335
case WifiP2pService.P2P_ENABLE_PENDING:
32893336
deferMessage(message);
32903337
break;
@@ -3326,7 +3373,8 @@ public boolean processMessage(Message message) {
33263373
case CMD_STOP_AP:
33273374
if (DBG) log("Stopping Soft AP");
33283375
setWifiApState(WIFI_AP_STATE_DISABLING);
3329-
stopTethering();
3376+
3377+
/* We have not tethered at this point, so we just shutdown soft Ap */
33303378
try {
33313379
mNwService.stopAccessPoint(mInterfaceName);
33323380
} catch(Exception e) {
@@ -3342,10 +3390,10 @@ public boolean processMessage(Message message) {
33423390
loge("Cannot start supplicant with a running soft AP");
33433391
setWifiState(WIFI_STATE_UNKNOWN);
33443392
break;
3345-
case CMD_TETHER_INTERFACE:
3346-
ArrayList<String> available = (ArrayList<String>) message.obj;
3347-
if (startTethering(available)) {
3348-
transitionTo(mTetheredState);
3393+
case CMD_TETHER_STATE_CHANGE:
3394+
TetherStateChange stateChange = (TetherStateChange) message.obj;
3395+
if (startTethering(stateChange.available)) {
3396+
transitionTo(mTetheringState);
33493397
}
33503398
break;
33513399
case WifiP2pService.P2P_ENABLE_PENDING:
@@ -3405,6 +3453,58 @@ public boolean processMessage(Message message) {
34053453
}
34063454
}
34073455

3456+
class TetheringState extends State {
3457+
@Override
3458+
public void enter() {
3459+
if (DBG) log(getName() + "\n");
3460+
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
3461+
3462+
/* Send ourselves a delayed message to shut down if tethering fails to notify */
3463+
sendMessageDelayed(obtainMessage(CMD_TETHER_NOTIFICATION_TIMED_OUT,
3464+
++mTetherToken, 0), TETHER_NOTIFICATION_TIME_OUT_MSECS);
3465+
}
3466+
@Override
3467+
public boolean processMessage(Message message) {
3468+
if (DBG) log(getName() + message.toString() + "\n");
3469+
switch(message.what) {
3470+
case CMD_TETHER_STATE_CHANGE:
3471+
TetherStateChange stateChange = (TetherStateChange) message.obj;
3472+
if (isWifiTethered(stateChange.active)) {
3473+
transitionTo(mTetheredState);
3474+
}
3475+
return HANDLED;
3476+
case CMD_TETHER_NOTIFICATION_TIMED_OUT:
3477+
if (message.arg1 == mTetherToken) {
3478+
loge("Failed to get tether update, shutdown soft access point");
3479+
setWifiApEnabled(null, false);
3480+
}
3481+
break;
3482+
case CMD_LOAD_DRIVER:
3483+
case CMD_UNLOAD_DRIVER:
3484+
case CMD_START_SUPPLICANT:
3485+
case CMD_STOP_SUPPLICANT:
3486+
case CMD_START_AP:
3487+
case CMD_STOP_AP:
3488+
case CMD_START_DRIVER:
3489+
case CMD_STOP_DRIVER:
3490+
case CMD_SET_SCAN_MODE:
3491+
case CMD_SET_SCAN_TYPE:
3492+
case CMD_SET_HIGH_PERF_MODE:
3493+
case CMD_SET_COUNTRY_CODE:
3494+
case CMD_SET_FREQUENCY_BAND:
3495+
case CMD_START_PACKET_FILTERING:
3496+
case CMD_STOP_PACKET_FILTERING:
3497+
case WifiP2pService.P2P_ENABLE_PENDING:
3498+
deferMessage(message);
3499+
break;
3500+
default:
3501+
return NOT_HANDLED;
3502+
}
3503+
EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
3504+
return HANDLED;
3505+
}
3506+
}
3507+
34083508
class TetheredState extends State {
34093509
@Override
34103510
public void enter() {
@@ -3415,13 +3515,89 @@ public void enter() {
34153515
public boolean processMessage(Message message) {
34163516
if (DBG) log(getName() + message.toString() + "\n");
34173517
switch(message.what) {
3418-
case CMD_TETHER_INTERFACE:
3419-
// Ignore any duplicate interface available notifications
3420-
// when in tethered state
3518+
case CMD_TETHER_STATE_CHANGE:
3519+
TetherStateChange stateChange = (TetherStateChange) message.obj;
3520+
if (!isWifiTethered(stateChange.active)) {
3521+
loge("Tethering reports wifi as untethered!, shut down soft Ap");
3522+
setWifiApEnabled(null, false);
3523+
}
34213524
return HANDLED;
3525+
case CMD_STOP_AP:
3526+
if (DBG) log("Untethering before stopping AP");
3527+
setWifiApState(WIFI_AP_STATE_DISABLING);
3528+
stopTethering();
3529+
transitionTo(mSoftApStoppingState);
3530+
break;
34223531
default:
34233532
return NOT_HANDLED;
34243533
}
3534+
EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
3535+
return HANDLED;
3536+
}
3537+
}
3538+
3539+
class SoftApStoppingState extends State {
3540+
@Override
3541+
public void enter() {
3542+
if (DBG) log(getName() + "\n");
3543+
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
3544+
3545+
/* Send ourselves a delayed message to shut down if tethering fails to notify */
3546+
sendMessageDelayed(obtainMessage(CMD_TETHER_NOTIFICATION_TIMED_OUT,
3547+
++mTetherToken, 0), TETHER_NOTIFICATION_TIME_OUT_MSECS);
3548+
3549+
}
3550+
@Override
3551+
public boolean processMessage(Message message) {
3552+
if (DBG) log(getName() + message.toString() + "\n");
3553+
switch(message.what) {
3554+
case CMD_TETHER_STATE_CHANGE:
3555+
TetherStateChange stateChange = (TetherStateChange) message.obj;
3556+
3557+
/* Wait till wifi is untethered */
3558+
if (isWifiTethered(stateChange.active)) break;
3559+
3560+
try {
3561+
mNwService.stopAccessPoint(mInterfaceName);
3562+
} catch(Exception e) {
3563+
loge("Exception in stopAccessPoint()");
3564+
}
3565+
transitionTo(mDriverLoadedState);
3566+
break;
3567+
case CMD_TETHER_NOTIFICATION_TIMED_OUT:
3568+
if (message.arg1 == mTetherToken) {
3569+
loge("Failed to get tether update, force stop access point");
3570+
try {
3571+
mNwService.stopAccessPoint(mInterfaceName);
3572+
} catch(Exception e) {
3573+
loge("Exception in stopAccessPoint()");
3574+
}
3575+
transitionTo(mDriverLoadedState);
3576+
}
3577+
break;
3578+
case CMD_LOAD_DRIVER:
3579+
case CMD_UNLOAD_DRIVER:
3580+
case CMD_START_SUPPLICANT:
3581+
case CMD_STOP_SUPPLICANT:
3582+
case CMD_START_AP:
3583+
case CMD_STOP_AP:
3584+
case CMD_START_DRIVER:
3585+
case CMD_STOP_DRIVER:
3586+
case CMD_SET_SCAN_MODE:
3587+
case CMD_SET_SCAN_TYPE:
3588+
case CMD_SET_HIGH_PERF_MODE:
3589+
case CMD_SET_COUNTRY_CODE:
3590+
case CMD_SET_FREQUENCY_BAND:
3591+
case CMD_START_PACKET_FILTERING:
3592+
case CMD_STOP_PACKET_FILTERING:
3593+
case WifiP2pService.P2P_ENABLE_PENDING:
3594+
deferMessage(message);
3595+
break;
3596+
default:
3597+
return NOT_HANDLED;
3598+
}
3599+
EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
3600+
return HANDLED;
34253601
}
34263602
}
34273603

0 commit comments

Comments
 (0)