@@ -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