Softap热点原理分析

本文分析了Android 4.1.2中开启Softap热点的流程,从Settings应用的开关操作,经过WifiManager和WifiStateMachine,深入到状态机的工作机制,特别是CMD_LOAD_DRIVER和CMD_START_AP消息的处理。讲解了配置文件的处理以及固件重载和netd Socket在开启AP过程中的作用。
摘要由CSDN通过智能技术生成

Android4.1.2


设置中开关:

packages/apps/Settings/src/com/android/settings/TetherSettings.java

|----private void startTethering()

|     |----mWifiApEnabler.setSoftapEnabled(true);


packages/apps/Settings/src/com/android/settings/wifi/WifiApEnabler.java

|----public void setSoftapEnabled(boolean enable)

|     |----mWifiManager.setWifiApEnabled(null, enable)


框架:

frameworks/base/wifi/java/android/net/wifi/WifiManager.java

|----public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled)

|     |----mService.setWifiApEnabled(wifiConfig, enabled);


IWifiManager.aidl

|----void setWifiApEnabled(in WifiConfiguration wifiConfig, boolean enable);


frameworks/base/services/java/com/android/server/WifiService.java

|----public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled)

|     |----mWifiStateMachine.setWifiApEnabled(wifiConfig, enabled);


frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java

|----public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enable)

|     |----sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_AP_STATE_ENABLING, 0));

|     |----sendMessage(obtainMessage(CMD_START_AP, wifiConfig));


斗胆分析一下状态机的运作

WifiStateMachine 继承于StateMachine, 而在WifiStateMachine中未有对sendMessage方法的复写,所以实现是使用父类的实现:

    /**  
     * Enqueue a message to this state machine.
     */
    public final void sendMessage(int what) {
        // mSmHandler can be null if the state machine has quit.
        if (mSmHandler == null) return;

        mSmHandler.sendMessage(obtainMessage(what));
    }    

    /**  
     * Enqueue a message to this state machine.
     */
    public final void sendMessage(int what, Object obj) {
        // mSmHandler can be null if the state machine has quit.
        if (mSmHandler == null) return;

        mSmHandler.sendMessage(obtainMessage(what,obj));
    }    

    /**  
     * Enqueue a message to this state machine.
     */
    public final void sendMessage(Message msg) {
        // mSmHandler can be null if the state machine has quit.
        if (mSmHandler == null) return;

        mSmHandler.sendMessage(msg);
    }

可见,mSmHandler的定义是类SmHandler, 继承于Handler, SmHandler对handleMessage进行了复写,所以对于消息的接收处理应该是在SmHandler的handleMessage中:

        /**
         * Handle messages sent to the state machine by calling
         * the current state's processMessage. It also handles
         * the enter/exit calls and placing any deferred messages
         * back onto the queue when transitioning to a new state.
         */
        @Override
        public final void handleMessage(Message msg) {
            if (mDbg) Log.d(TAG, "handleMessage: E msg.what=" + msg.what);

            /** Save the current message */
            mMsg = msg;

            if (mIsConstructionCompleted) {    //正常的操作
                /** Normal path */
                processMsg(msg);
            } else if (!mIsConstructionCompleted &&
                    (mMsg.what == SM_INIT_CMD) && (mMsg.obj == mSmHandlerObj)) {    //初始化操作
                /** Initial one time path. */
                mIsConstructionCompleted = true;
                invokeEnterMethods(0);
            } else {
                throw new RuntimeException("StateMachine.handleMessage: " +
                            "The start method not called, received msg: " + msg);
            }
            performTransitions();    //应用改变

            if (mDbg) Log.d(TAG, "handleMessage: X");
        }

processMsg(msg):

        /**  
         * Process the message. If the current state doesn't handle
         * it, call the states parent and so on. If it is never handled then
         * call the state machines unhandledMessage method.
         */
        private final void processMsg(Message msg) {
            StateInfo curStateInfo = mStateStack[mStateStackTopIndex];    //获取当前状态
            if (mDbg) {
                Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
            }    
            while (!curStateInfo.state.processMessage(msg)) {    //判断该消息是否处理
                /**  
                 * Not processed
                 */
                curStateInfo = curStateInfo.parentStateInfo;
                if (curStateInfo == null) {
                    /**  
                     * No parents left so it's not handled
                     */
                    mSm.unhandledMessage(msg);
                    if (isQuit(msg)) {
                        transitionTo(mQuittingState);    //设置状态
                    }    
                    break;
                }    
                if (mDbg) {
                    Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
                }    
            }   
在WifiStateMachine中有很多状态,截取几个来看:

    /* Loading the driver */
    private State mDriverUnloadedState = new DriverUnloadedState();
    /* Driver load/unload failed */
    private State mDriverFailedState = new DriverFailedState();
    /* Driver loading */
    private State mDriverLoadingState = new DriverLoadingState();
    /* Driver loaded */
    private State mDriverLoadedState = new DriverLoadedState();
以上4个都是关于Wifi驱动加载与卸载的相关状态,每一个都有复写自己的processMessage方法,比如DriverUnloadedState():

        @Override
        public boolean processMessage(Message message) {
            if (DBG) log(getName() + message.toString() + "\n");
            switch (message.what) {
                case CMD_LOAD_DRIVER:
                    transitionTo(mDriverLoadingState);
                    break;
                default:
                    return NOT_HANDLED;
            }
            return HANDLED;
        }

这说明,在状态是“Wifi驱动已经成功卸载”时,系统只响应(handle)CMD_LOAD_DRIVER的消息,也就是驱动加载命令,其他一概不管。很符合逻辑吧。

假设,在打开Wifi热点的时候,驱动就是卸载的(默认状态),那么sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_AP_STATE_ENABLING, 0));过后会来到这里,也就会将新的状态mDriverLoadingState加入状态栈。随后返回HANDLED,另一种NOT_HANDLED就不做讨论了。那么现在的流程变成了processMsg(msg) --> transitionTo(mDriverLoadingState) --> performTransitions(),所以在分析performTransitions()之前要先看看transitionTo(实现在父类StateMachine中):

        /** @see StateMachine#transitionTo(IState) */
        private final void transitionTo(IState destState) {
            mDestState = (State) destState;
            if (mDbg) Log.d(TAG, "transitionTo: destState=" + mDestState.getName());
        }

由于State是IState的子类,所以这样的参数传递进去没有问题,mDestState目标状态变成了mDriverLoadingState,然后是performTransitions()(还是在父类StateMachine中):

        /**
         * Do any transiti
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值