【Android 11 framework学习之热点 关闭】

关闭热点时序图如下:
disable ap

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;
}

欢迎大家指正,一起学习共同进步~

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值