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 transitions         */        private void performTransitions() {            /**             * If transitionTo has been called, exit and then enter             * the appropriate states. We loop on this to allow             * enter and exit methods to use transitionTo.             */            State destState = null;            while (mDestState != null) {  //即transitionTo设置的新状态 mDriverLoadingState                if (mDbg) Log.d(TAG, "handleMessage: new destination call exit");                /**                 * Save mDestState locally and set to null                 * to know if enter/exit use transitionTo.                 */                destState = mDestState;                mDestState = null;                /**                 * Determine the states to exit and enter and return the                 * common ancestor state of the enter/exit states. Then                 * invoke the exit methods then the enter methods.                 */                StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);  //将状态装入临时队列                invokeExitMethods(commonStateInfo);    //将该状态之前的所有状态全部退出                int stateStackEnteringIndex = moveTempStateStackToStateStack();    //把临时队列合并至标准队列,并且返回界限值stateStaclEnteringIndex                invokeEnterMethods(stateStackEnteringIndex);    //遍历执行自界限值到队列顶部的所有状态的enter方法,如下图所示:/*    |-------------|High|   stack_x   |  mStateStackTopIndex    |-------------|    |   .....     |    |-------------|    |   stack_y   |  stateStackEnteringIndex  以上都是从Temp临时队列合并来的    |-------------|    |   .....     |    |-------------|Low |   stack_1   |    |-------------|*//** * Since we have transitioned to a new state we need to have * any deferred messages moved to the front of the message queue * so they will be processed before any other messages in the * message queue. */ moveDeferredMessageAtFrontOfQueue(); //将所有延迟消息再次发送到队列顶部,随后清除延迟消息队列。 } /** * After processing all transitions check and * see if the last transition was to quit or halt. */            if (destState != null) {    //以下检查状态是否是需求退出或挂起的,是则进行相应处理                if (destState == mQuittingState) {                    cleanupAfterQuitting();                } else if (destState == mHaltingState) {                    /**                     * Call halting() if we've transitioned to the halting                     * state. All subsequent messages will be processed in                     * in the halting state which invokes haltedProcessMessage(msg);                     */                    mSm.halting();                }            }        }

看了好多子函数,有点晕晕的。看得出来这个performTransitions()是对所有状态进行处理的关键节点,可能同一时间会受到很多Message,而这些Message所携带的不同状态会被加入到一个临时队列中,然后会将标准队列顶端到此状态之前的所有状态都退出(也就是触发exit()),并设置为非活跃,然后剔除。之后会将临时队列合并入标准队列,取得一个界限值,从界限值到队列顶端依次激活(触发enter())。其实在sendMessage的同时,还有一种消息处理方式就是deferMessage,是对消息的延迟发送,最终会将消息加入到一个延迟消息队列mDeferredMessages中,每次的performTransitions()都会对延迟消息队列进行重新发送并且清空它的队列。最后,还会检测一下是否有特殊的状态需要处理,如退出和挂起。


回到正题

WifiStateMachine.java

应该关注一下mDriverLoadingState了,前边看到这是一个DriverLoadingState(),enter()的主要内容是一个工作线程:

            new Thread(new Runnable() {                public void run() {                    mWakeLock.acquire();    //整个过程需要wakelock保护                    //enabling state                    switch(message.arg1) {                        case WIFI_STATE_ENABLING:    //打开WIFI                            setWifiState(WIFI_STATE_ENABLING);                            break;                        case WIFI_AP_STATE_ENABLING:    //打开WIFI AP                            setWifiApState(WIFI_AP_STATE_ENABLING);                            break;                    }                    if(mWifiNative.loadDriver()) {    //加载Wifi驱动,WifiNative.java --> core/jni/android_net_wifi_Wifi.cpp --> hardware/libhardware_legacy/wifi.c 就是insmod xxx.ko,也许带参数blablabla                        if (DBG) log("Driver load successful");                        sendMessage(CMD_LOAD_DRIVER_SUCCESS);                    } else {                        loge("Failed to load driver!");                        switch(message.arg1) {                            case WIFI_STATE_ENABLING:                                setWifiState(WIFI_STATE_UNKNOWN);                                break;                            case WIFI_AP_STATE_ENABLING:                                setWifiApState(WIFI_AP_STATE_FAILED);                                break;                        }                        sendMessage(CMD_LOAD_DRIVER_FAILURE);                    }                    mWakeLock.release();                }            }).start();        }

而这里可以快速的复习一下前边的流程,加载成功后会sendMessage(CMD_LOAD_DRIVER_SUCCESS),失败了就会发送CMD_LOAD_DRIVER_FAILURE。当前的状态就是mDriverLoadingState,所以是DriverLoadingState的processMessage来处理这两个消息了:

        @Override        public boolean processMessage(Message message) {            if (DBG) log(getName() + message.toString() + "\n");            switch (message.what) {                case CMD_LOAD_DRIVER_SUCCESS:                    transitionTo(mDriverLoadedState);                    break;                case CMD_LOAD_DRIVER_FAILURE:                    transitionTo(mDriverFailedState);                    break;                case CMD_LOAD_DRIVER:                case CMD_UNLOAD_DRIVER:                case CMD_START_SUPPLICANT:                case CMD_STOP_SUPPLICANT:                case CMD_START_AP:                case CMD_STOP_AP:                case CMD_START_DRIVER:                case CMD_STOP_DRIVER:                case CMD_SET_SCAN_MODE:                case CMD_SET_SCAN_TYPE:                case CMD_SET_COUNTRY_CODE:                case CMD_SET_FREQUENCY_BAND:                case CMD_START_PACKET_FILTERING:                case CMD_STOP_PACKET_FILTERING:                    deferMessage(message);                    break;                default:                    return NOT_HANDLED;            }            return HANDLED;        }    }

由此可见,加载成功后状态就变为mDriverLoadedState,失败了状态就是mDriverFailedState。回到DriverLoadingState的enter,setWifiApState:

    private void setWifiApState(int wifiApState) {        final int previousWifiApState = mWifiApState.get();        try {            if (wifiApState == WIFI_AP_STATE_ENABLED) {    //WIFI AP已经打开,则电池状态开始记录Wifi相关                mBatteryStats.noteWifiOn();            } else if (wifiApState == WIFI_AP_STATE_DISABLED) {    //WIFI AP已经关闭,则电池状态对WIFI的记录关闭                mBatteryStats.noteWifiOff();            }        } catch (RemoteException e) {            loge("Failed to note battery stats in wifi");        }        // Update state        mWifiApState.set(wifiApState);    //设置WIFI AP的状态,原子状态        if (DBG) log("setWifiApState: " + syncGetWifiApStateByName());        //将状态消息发送至WifiManager进行进一步处理。终于脱离了状态机,回到WifiManager了。        final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);        intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, wifiApState);        intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, previousWifiApState);        mContext.sendStickyBroadcast(intent);    }

PS:通过sendBroadcast中发出的intent在Reciever注册后才能正确收到,未注册的时候不能被接收,即使后面再次注册上也无法接受到。而sendStickyBroadcast发出的Intent当Reciever注册后就能收到Intent,即使注册发生在广播之后。也就是说sendStickyBroadcast安全性更高,能够保证广播不会丢失,而sendBroadcast有一定危险。

好的,分析了这么久,只是有一条sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_AP_STATE_ENABLING, 0)),发送出状态广播给别人获取,在系统中一个很好的例子是桌面电源控件对这个状态进行接收,可以直观的理解为当ing的状态时某按钮是不可用的。

然后才是真正的开启动作:

sendMessage(obtainMessage(CMD_START_AP, wifiConfig));

假设加载成功,当前状态变成了mDriverLoadedState,那么去DriverLoadedState的processMessage寻找这个Message的处理方法:

    case CMD_START_AP:        transitionTo(mSoftApStartingState);        break;

新的状态,mSoftApStartingState:

    /* Soft ap is starting up */    private State mSoftApStartingState = new SoftApStartingState();

        @Override        public void enter() {            if (DBG) log(getName() + "\n");            EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());            final Message message = getCurrentMessage();            if (message.what == CMD_START_AP) {    //如果进入这个状态而不是打开AP,那么就直接抛出runtime异常,一般来说就是重启了。又一次验证了:不以结婚为目的的谈恋爱都是耍流氓。                final WifiConfiguration config = (WifiConfiguration) message.obj;                if (config == null) {                    mWifiApConfigChannel.sendMessage(CMD_REQUEST_AP_CONFIG);                } else {                    mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);                    startSoftApWithConfig(config);                }            } else {                throw new RuntimeException("Illegal transition to SoftApStartingState: " + message);            }        }

OK, config为NULL,又是一个Message:

mWifiApConfigChannel.sendMessage(CMD_REQUEST_AP_CONFIG);

在WifiStateMachine构造的时候对mWifiApConfigChannel设置了handler:

mWifiApConfigChannel.connectSync(mContext, getHandler(), wifiApConfigStore.getMessenger());

WifiApConfigStore.java

CMD_REQUEST_AP_CONFIG的消息处理是在WifiApConfigStore中处理的:

    class DefaultState extends State {        public boolean processMessage(Message message) {            switch (message.what) {                case WifiStateMachine.CMD_SET_AP_CONFIG:                case WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED:                    Log.e(TAG, "Unexpected message: " + message);                    break;                case WifiStateMachine.CMD_REQUEST_AP_CONFIG:                    mReplyChannel.replyToMessage(message,                            WifiStateMachine.CMD_RESPONSE_AP_CONFIG, mWifiApConfig);                    break;                default:                    Log.e(TAG, "Failed to handle " + message);                    break;            }               return HANDLED;        }       }  

当前WIFI状态机状态为SoftApStartingState,所以回复消息在这里处理:

        @Override           public boolean processMessage(Message message) {            if (DBG) log(getName() + message.toString() + "\n");            switch(message.what) {                case CMD_LOAD_DRIVER:                case CMD_UNLOAD_DRIVER:                case CMD_START_SUPPLICANT:                case CMD_STOP_SUPPLICANT:                case CMD_START_AP:                 case CMD_STOP_AP:                case CMD_START_DRIVER:                case CMD_STOP_DRIVER:                case CMD_SET_SCAN_MODE:                case CMD_SET_SCAN_TYPE:                case CMD_SET_COUNTRY_CODE:                case CMD_SET_FREQUENCY_BAND:                case CMD_START_PACKET_FILTERING:                case CMD_STOP_PACKET_FILTERING:                case CMD_TETHER_STATE_CHANGE:                    deferMessage(message);                    break;                case WifiStateMachine.CMD_RESPONSE_AP_CONFIG:                    WifiConfiguration config = (WifiConfiguration) message.obj;    //设置文件就是WifiApConfigStore中的mWifiApConfig                    if (config != null) {                        startSoftApWithConfig(config);    //如果配置文件存在就继续开启AP                    } else {                        loge("Softap config is null!");    //如果配置文件为空则开启失败,发送个消息CMD_START_AP_FAILURE,还是在本状态中处理                        sendMessage(CMD_START_AP_FAILURE);                    }                    break;                case CMD_START_AP_SUCCESS:                    setWifiApState(WIFI_AP_STATE_ENABLED);                    transitionTo(mSoftApStartedState);                    break;                case CMD_START_AP_FAILURE:                    // initiate driver unload                    sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));  //卸载驱动,并更改状态为AP开启失败                    break;                default:                    return NOT_HANDLED;            }               return HANDLED;        }


配置文件

这里的配置文件是通过WifiManager的setWifiApConfiguration接口生成的:

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

    /**       * Sets the Wi-Fi AP Configuration.     * @return {@code true} if the operation succeeded, {@code false} otherwise     *     * @hide Dont open yet     */    public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {        try {            mService.setWifiApConfiguration(wifiConfig);            return true;        } catch (RemoteException e) {             return false;        }        } 

mService为IWifiManager,该接口定义如下:

void setWifiApConfiguration(in WifiConfiguration wifiConfig);

而实现为WifiService

public class WifiService extends IWifiManager.Stub

    /**       * see {@link WifiManager#setWifiApConfiguration(WifiConfiguration)}     * @param wifiConfig WifiConfiguration details for soft access point     */    public void setWifiApConfiguration(WifiConfiguration wifiConfig) {        enforceChangePermission();        if (wifiConfig == null)            return;        mWifiStateMachine.setWifiApConfiguration(wifiConfig);    } 

真是的实现有抛给了WifiStateMachine:

    public void setWifiApConfiguration(WifiConfiguration config) {        mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);    } 

消息交给WifiApConfigStore处理,而
    WifiApConfigStore(Context context, Handler target) {        super(TAG, target.getLooper());        mContext = context;        addState(mDefaultState);            addState(mInactiveState, mDefaultState);            addState(mActiveState, mDefaultState);        setInitialState(mInactiveState);    }

WifiApConfigStore在构造的时候分mDefaultState分配了两个子状态mInactiveState, mActiveState, 初始化状态为mInactiveState。

    class InactiveState extends State {        public boolean processMessage(Message message) {            switch (message.what) {                case WifiStateMachine.CMD_SET_AP_CONFIG:                    mWifiApConfig = (WifiConfiguration) message.obj;                    transitionTo(mActiveState);    //触发ActiveState.enter()                    break;                default:                    return NOT_HANDLED;            }               return HANDLED;        }    }

    class ActiveState extends State {        public void enter() {            new Thread(new Runnable() {                public void run() {                    writeApConfiguration(mWifiApConfig);                    sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED);                }            }).start();        }

writeApConfiguration实现:
    private void writeApConfiguration(final WifiConfiguration config) {        DataOutputStream out = null;        try {            out = new DataOutputStream(new BufferedOutputStream(                        new FileOutputStream(AP_CONFIG_FILE)));            out.writeInt(AP_CONFIG_FILE_VERSION);            out.writeUTF(config.SSID);            int authType = config.getAuthType();            out.writeInt(authType);            if(authType != KeyMgmt.NONE) {                out.writeUTF(config.preSharedKey);            }        } catch (IOException e) {            Log.e(TAG, "Error writing hotspot configuration" + e);        } finally {            if (out != null) {                try {                    out.close();                } catch (IOException e) {}            }        }    }

默认文件路径即为/misc/wifi/softap.conf,写好配置文件后发送WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED,自己发自己收了:

        public boolean processMessage(Message message) {            switch (message.what) {                //TODO: have feedback to the user when we do this                //to indicate the write is currently in progress                case WifiStateMachine.CMD_SET_AP_CONFIG:                    deferMessage(message);                    break;                case WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED:    //修改完后切换状态到InactiveState                    transitionTo(mInactiveState);                    break;                default:                    return NOT_HANDLED;            }            return HANDLED;        }

这样配置文件就配置完了,结果是保存在mWifiConfig中的。


带着配置文件开启AP

frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java      startSoftApWithConfig
    /* Current design is to not set the config on a running hostapd but instead     * stop and start tethering when user changes config on a running access point     *     * TODO: Add control channel setup through hostapd that allows changing config     * on a running daemon     */    private void startSoftApWithConfig(final WifiConfiguration config) {        // start hostapd on a seperate thread        new Thread(new Runnable() {            public void run() {                try {                    mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);                } catch (Exception e) {                    loge("Exception in softap start " + e);                    try {                        mNwService.stopAccessPoint(mInterfaceName);                        mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);                    } catch (Exception e1) {                        loge("Exception in softap re-start " + e1);                        sendMessage(CMD_START_AP_FAILURE);                        return;                    }                }                if (DBG) log("Soft AP start successful");                sendMessage(CMD_START_AP_SUCCESS);            }        }).start();    }

逻辑就是尝试开启,如果发生错误就尝试重启,如果再错误就承认失败,发送失败状态,如果没错误就发送成功的消息。关键在mNwService的startAccessPoint方法中。 config, mInterfaceName, SOFTAP_IFACE
这三个参数:config为传递下来的配置文件,SOFTAP_IFACE为字符串wl0.1,mInterfaceName为WifiStateMachine构造时传递下来的参数,而这个构造动作由WifiService构造的时候发起:
    WifiService(Context context) {        mContext = context;        mInterfaceName =  SystemProperties.get("wifi.interface", "wlan0");        mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName);        mWifiStateMachine.enableRssiPolling(true);...}

可见,这个mInterfaceName由prop wifi.interface控制,如我们经常能在build.prop中看到wifi.interface=eth0/wlan0等,如果没有会默认给wlan0。 接下来看startAccessPoint的实现(frameworks/base/services/java/com/android/server/NetworkManagementService.java):
    @Override    public void startAccessPoint(            WifiConfiguration wifiConfig, String wlanIface, String softapIface) {        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);        try {            Resources resources = mContext.getResources();            if (resources.getBoolean(com.android.internal.R.bool.config_wifiApFirmwareReload))                wifiFirmwareReload(wlanIface, "AP");            if (resources.getBoolean(com.android.internal.R.bool.config_wifiApStartInterface))                mConnector.execute("softap", "start", wlanIface);            if (wifiConfig == null) {                mConnector.execute("softap", "set", wlanIface, softapIface);            } else {                mConnector.execute("softap", "set", wlanIface, softapIface, wifiConfig.SSID,                        getSecurityType(wifiConfig), wifiConfig.preSharedKey);            }                mConnector.execute("softap", "startap");        } catch (NativeDaemonConnectorException e) {             throw e.rethrowAsParcelableException();        }        }

config_wifiApFirmwareReload、config_wifiApStartInterface都是可以用户自定义的xml配置接口,默认在frameworks/base/core/res/res/values/config.xml中,默认如:
        true        false

想关联的几个函数有:
    private static String getSecurityType(WifiConfiguration wifiConfig) {    //获取网络安全类型        switch (wifiConfig.getAuthType()) {            case KeyMgmt.WPA_PSK:                return "wpa-psk";            case KeyMgmt.WPA2_PSK:                return "wpa2-psk";            default:                return "open";        }        }        /* @param mode can be "AP", "STA" or "P2P" */    @Override    public void wifiFirmwareReload(String wlanIface, String mode) {    //根据不同模式装在不同的固件(如果有需要的话)        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);        try {            mConnector.execute("softap", "fwreload", wlanIface, mode);        } catch (NativeDaemonConnectorException e) {             throw e.rethrowAsParcelableException();        }        } 

通过以上不难看出,最终都是通过mConnector.execute来执行命令。
    /**     * Constructs a new NetworkManagementService instance     *     * @param context  Binder context for this service     */    private NetworkManagementService(Context context) {        mContext = context;        if ("simulator".equals(SystemProperties.get("ro.product.device"))) {            return;        }        mConnector = new NativeDaemonConnector(                new NetdCallbackReceiver(), "netd", 10, NETD_TAG, 160);        mThread = new Thread(mConnector, NETD_TAG);        // Add ourself to the Watchdog monitors.        Watchdog.getInstance().addMonitor(this);    }

mConnector是在构造时生成的NativeDaemonConnector对象,查看一下NativeDaemonConnector的构造过程(frameworks/base/services/java/com/android/server/NativeDaemonConnector.java):
    NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket,            int responseQueueSize, String logTag, int maxLogSize) {        mCallbacks = callbacks;        mSocket = socket;        mResponseQueue = new ResponseQueue(responseQueueSize);        mSequenceNumber = new AtomicInteger(0);        TAG = logTag != null ? logTag : "NativeDaemonConnector";        mLocalLog = new LocalLog(maxLogSize);    }  

1.分别在handleMessage和listenToSocket的时候调用回调对象的onEvent和onDaemonConnected方法。而监听socket的服务被创建后就已经开出一个线程始终监听了。在这里为new NetdCallbackReceiver(); 2.mSocket也就是在NetworkManagementService中始终监听的那个local socket。在这里为netd(/dev/socket/netd); 3.mResponseQueue是新建了一个命令队列ResponseQueue,传递金的参数responseQueuesize就是这个队列的容量上限。这个子类算上构造在内总共4个方法:
    a.构造     b.添加命令     c.移除命令     d.打印队列信息 4.mSequeueceNumber作为指令执行计数器,是个原子量, 防止线程操作混乱; 5.日志标签 6.日志容量 构造完成后,会new出一个线程,这个线程的工作就是调用listenToSocket。最后会使用看门狗来保护这个服务。
回到主线,默认情况下,并有有效的配置文件,打开WIFI AP需要执行两条命令:
mConnector.execute("softap", "fwreload", wlanIface, mode);mConnector.execute("softap", "set", wlanIface, softapIface, wifiConfig.SSID,                        getSecurityType(wifiConfig), wifiConfig.preSharedKey);

逐个分析一下:

固件重载

wlanIface就是prop指定的wifi.interface,默认为wlan0,mode为"AP",共计四个参数。 这两条命令都会最终执行到这里:
    public NativeDaemonEvent[] execute(int timeout, String cmd, Object... args)            throws NativeDaemonConnectorException {        final ArrayList events = Lists.newArrayList();        final int sequenceNumber = mSequenceNumber.incrementAndGet();    //命令计数器加一并返回        final StringBuilder cmdBuilder =                new StringBuilder(Integer.toString(sequenceNumber)).append(' ');        final long startTime = SystemClock.elapsedRealtime();  //返回的是自从系统启动到当前的时间        makeCommand(cmdBuilder, cmd, args);    //将所有参数整合成一条命令,放置在cmdBuilder中        final String logCmd = cmdBuilder.toString(); /* includes cmdNum, cmd, args */        log("SND -> {" + logCmd + "}");        cmdBuilder.append('\0');    //给字符串来个尾巴,然后化作真正的字符串sentCmd        final String sentCmd = cmdBuilder.toString(); /* logCmd + \0 */        synchronized (mDaemonLock) {            if (mOutputStream == null) {    //mOutputStraem是netd的输出通道                throw new NativeDaemonConnectorException("missing output stream");            } else {                try {                    mOutputStream.write(sentCmd.getBytes(Charsets.UTF_8));    //将命令发送出去  netd socket                } catch (IOException e) {                    throw new NativeDaemonConnectorException("problem sending command", e);                }            }        }        NativeDaemonEvent event = null;        do {            event = mResponseQueue.remove(sequenceNumber, timeout, sentCmd);  //从命令队列中删除已经发送出去的命令            if (event == null) {                loge("timed-out waiting for response to " + logCmd);                throw new NativeDaemonFailureException(logCmd, event);            }            log("RMV <- {" + event + "}");            events.add(event);        } while (event.isClassContinue());        final long endTime = SystemClock.elapsedRealtime();        if (endTime - startTime > WARN_EXECUTE_DELAY_MS) {            loge("NDC Command {" + logCmd + "} took too long (" + (endTime - startTime) + "ms)");        }        if (event.isClassClientError()) {            throw new NativeDaemonArgumentException(logCmd, event);        }        if (event.isClassServerError()) {            throw new NativeDaemonFailureException(logCmd, event);        }        return events.toArray(new NativeDaemonEvent[events.size()]);    }

现在看来,所有命令都是通过netd socket发送出去。但是这个socket是谁来接收呢?

netd Socket

system/netd [to be continued...]

更多相关文章

  1. android 监听 USB 拔插广播消息
  2. android edittxet 设置可点击不可编辑状态
  3. Android获取、设置Wifi状态
  4. Android 标题栏、状态栏隐藏
  5. Android软键盘之代码改变软键盘状态
  6. Android TabLayout设置选中状态标题字体大小,粗细
  7. android 获取联系人和短消息信息

随机推荐

  1. Android(安卓)Things创客DIY第一课-用And
  2. 如何在Android中启动JAVA程序
  3. Android界面编程——Android布局组件(二)
  4. Android(安卓)Studio系列教程三--快捷键
  5. android矢量图vector的简单介绍
  6. 前端和Android(安卓)/ IOS 对接问题
  7. Android内核开发:开发板选购
  8. Java后端学Android(1)-Hello World
  9. android:layout_gravity 和 android:grav
  10. Android坐标系、视图坐标系与触控事件(Mot