关闭热点时序图如下:
WifiTetherFragment是实现开关热点的Fragment,调用TetherManager::stopTethering()去关闭WiFi共享
/*** com.android.car.settings.wifi.WifiTetherFragment.stopTethering ***/
private void stopTethering() {
mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
}
TetheringManager内部通过ITetheringConnector实现具体功能,类似于WifiManager
/*** android.net.TetheringManager.stopTethering ***/
public void stopTethering(@TetheringType final int type) {
final String callerPkg = mContext.getOpPackageName();
Log.i(TAG, "stopTethering caller:" + callerPkg);
getConnector(c -> c.stopTethering(type, callerPkg, new IIntResultListener.Stub() {
@Override
public void onResult(int resultCode) {
// TODO: provide an API to obtain result
// This has never been possible as stopTethering has always been void and never
// taken a callback object. The only indication that callers have is if the call
// results in a TETHER_STATE_CHANGE broadcast.
}
}));
}
传入的Tethering type是ConnectivityManager.TETHERING_WIFI,直接看TetheringService
stopTethering之前需要check是否支持操作热点,不支持直接返回
/*** com.android.networkstack.tethering.TetheringService.TetheringConnector.stopTethering ***/
public void stopTethering(int type, String callerPkg, IIntResultListener listener) {
if (checkAndNotifyCommonError(callerPkg, listener)) return;
try {
mTethering.stopTethering(type);
listener.onResult(TETHER_ERROR_NO_ERROR);
} catch (RemoteException e) { }
}
在enableTetheringInternal之前需要检查没有其他打开热点的请求
/*** com.android.networkstack.tethering.Tethering.stopTethering ***/
void stopTethering(int type) {
mHandler.post(() -> {
mActiveTetheringRequests.remove(type);
enableTetheringInternal(type, false /* disabled */, null);
mEntitlementMgr.stopProvisioningIfNeeded(type);
});
}
打开对应请求的功能,这里对应的应该是TETHERING_WIFI
/*** com.android.networkstack.tethering.Tethering.enableTetheringInternal ***/
private void enableTetheringInternal(int type, boolean enable, final IIntResultListener listener) {
int result = TETHER_ERROR_NO_ERROR;
switch (type) {
case TETHERING_WIFI:
result = setWifiTethering(enable);
break;
...
}
...
}
关闭传入的enable为false,因此获取WifiManager对象后操作stopSoftAp
/*** com.android.networkstack.tethering.Tethering.setWifiTethering ***/
private int setWifiTethering(final boolean enable) {
...
if ((enable && mgr.startTetheredHotspot(null /* use existing softap config */))
|| (!enable && mgr.stopSoftAp())) {
mWifiTetherRequested = enable;
return TETHER_ERROR_NO_ERROR;
}
...
}
/*** android.net.wifi.WifiManager.stopSoftAp ***/
public boolean stopSoftAp() {
try {
return mService.stopSoftAp();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
调用内部接口stopSoftApInternal
/*** com.android.server.wifi.WifiServiceImpl.stopSoftAp ***/
public boolean stopSoftAp() {
// NETWORK_STACK is a signature only permission.
enforceNetworkStackPermission();
// only permitted callers are allowed to this point - they must have gone through
// connectivity service since this method is protected with the NETWORK_STACK PERMISSION
mLog.info("stopSoftAp uid=%").c(Binder.getCallingUid()).flush();
stopSoftApInternal(WifiManager.IFACE_IP_MODE_TETHERED);
return true;
}
/*** com.android.server.wifi.WifiServiceImpl.stopSoftApInternal ***/
private void stopSoftApInternal(int mode) {
mLog.trace("stopSoftApInternal uid=% mode=%").c(Binder.getCallingUid()).c(mode).flush();
mSoftApExtendingWifi = false;
mActiveModeWarden.stopSoftAp(mode);
}
通过WifiController状态机,发送热点状态消息
/*** com.android.server.wifi.ActiveModeWarden.stopSoftAp ***/
public void stopSoftAp(int mode) {
mWifiController.sendMessage(WifiController.CMD_SET_AP, arg1:0, mode);
}
状态机之前应该是EnabledState状态,因此处理此消息流程如下,msg.arg1=WifiController.CMD_SET_AP!=1??调用了stopSoftApModeManagers
/*** com.android.server.wifi.ActiveModeWarden.WifiController.EnabledState.processMessageFiltered ***/
case CMD_SET_AP:
// note: CMD_SET_AP is handled/dropped in ECM mode - will not start here
// If request is to start dual sap, turn off sta.
if (msg.arg1 == 1 && mWifiApConfigStore.getDualSapStatus()) {
stopAllClientModeManagers();
}
if (msg.arg1 == 1) {
startSoftApModeManager((SoftApModeConfiguration) msg.obj);
} else {
stopSoftApModeManagers(msg.arg2);
}
break;
由step8可知,ipMode=IFACE_IP_MODE_TETHERED,因而getRoleForSoftApIpMode返回ActiveModeManager.ROLE_SOFTAP_TETHERED
getRole的值为ROLE_SOFTAP_TETHERED(我猜测哈哈哈懒得去看了),所以执行softApManager.stop
/*** com.android.server.wifi.ActiveModeWarden.stopSoftApModeManagers ***/
private void stopSoftApModeManagers(int ipMode) {
Log.d(TAG, "Shutting down all softap mode managers in mode " + ipMode);
for (ActiveModeManager manager : mActiveModeManagers) {
if (!(manager instanceof SoftApManager)) continue;
SoftApManager softApManager = (SoftApManager) manager;
if (ipMode == WifiManager.IFACE_IP_MODE_UNSPECIFIED
|| getRoleForSoftApIpMode(ipMode) == softApManager.getRole()) {
softApManager.stop();
}
}
}
/*** com.android.server.wifi.ActiveModeWarden.getRoleForSoftApIpMode ***/
private @ActiveModeManager.Role int getRoleForSoftApIpMode(int ipMode) {
return ipMode == IFACE_IP_MODE_TETHERED
? ActiveModeManager.ROLE_SOFTAP_TETHERED : ActiveModeManager.ROLE_SOFTAP_LOCAL_ONLY;
}
调用到SoftApManager.stop,状态机发送SoftApStateMachine.CMD_STOP消息
/*** com.android.server.wifi.SoftApManager.stop ***/
public void stop() {
Log.d(TAG, " currentstate: " + getCurrentStateName());
mTargetRole = ROLE_UNSPECIFIED;
mStateMachine.sendMessage(SoftApStateMachine.CMD_STOP);
}
成功开启热点之后SoftApStateMachine状态机状态为StartedState,因此在StartedState中处理此消息
开启之后mIfaceIsUp肯定为true的,于是广播ap状态由WifiManager.WIFI_AP_STATE_ENABLED变更为WifiManager.WIFI_AP_STATE_DISABLING
状态机切换到IdleState
/*** com.android.server.wifi.SoftApManager.SoftApStateMachine.StartedState.processMessage ***/
case CMD_STOP:
if (mIfaceIsUp) {
updateApState(WifiManager.WIFI_AP_STATE_DISABLING,
WifiManager.WIFI_AP_STATE_ENABLED, 0);
} else {
updateApState(WifiManager.WIFI_AP_STATE_DISABLING,
WifiManager.WIFI_AP_STATE_ENABLING, 0);
}
transitionTo(mIdleState);
break;
状态机切换,调用StartedState.exit,首先调用内部封装的stopSoftAp,还有一些注销回调操作省略了,然后通知APP状态变更为WifiManager.WIFI_AP_STATE_DISABLED,复位一些变量
/*** com.android.server.wifi.SoftApManager.SoftApStateMachine.StartedState.exit ***/
public void exit() {
if (!mIfaceIsDestroyed) {
stopSoftAp();
}
...
// Need this here since we are exiting |Started| state and won't handle any
// future CMD_INTERFACE_STATUS_CHANGED events after this point
mWifiMetrics.addSoftApUpChangedEvent(false, mApConfig.getTargetMode(),
mDefaultShutDownTimeoutMills);
updateApState(WifiManager.WIFI_AP_STATE_DISABLED,
WifiManager.WIFI_AP_STATE_DISABLING, 0);
...
}
这个方法会调用到Native接口去把之前创建的iface都关闭
/*** com.android.server.wifi.SoftApManager.stopSoftAp ***/
private void stopSoftAp() {
disconnectAllClients();
if (mWifiApConfigStore.getDualSapStatus() && !mDualSapIfacesDestroyed) {
mDualSapIfacesDestroyed = true;
mWifiNative.teardownInterface(mdualApInterfaces[0]);
mWifiNative.teardownInterface(mdualApInterfaces[1]);
}
mWifiDiagnostics.stopLogging(mApInterfaceName);
mWifiNative.teardownInterface(mApInterfaceName);
Log.d(TAG, "Soft AP is stopped");
}
于是SoftApStateMachine切换到IdleState状态,最后进入到IdleState.enter,重置成员变量
/*** com.android.server.wifi.SoftApManager.SoftApStateMachine.IdleState.enter ***/
public void enter() {
mApInterfaceName = null;
mDataInterfaceName = null;
mIfaceIsUp = false;
mIfaceIsDestroyed = false;
}
欢迎大家指正,一起学习共同进步~