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沉浸式状态栏
  2. android 监听 USB 拔插广播消息
  3. Android之高仿手机QQ图案解锁
  4. Android(安卓)标题栏、状态栏隐藏
  5. Android获取、设置Wifi状态
  6. android edittxet 设置可点击不可编辑状态
  7. 【Android】Android(安卓)SurfaceFlinger之BufferQueue
  8. Android录制或播放语音消息时关闭其他媒体播放
  9. Android软键盘不能正确显示

随机推荐

  1. 今天给大家分享一下Android中的资源与国
  2. Android(安卓)最火的快速开发框架XUtils
  3. Android学习路线
  4. 做好准备,让你的短信应用迎接Android(安卓
  5. Android生成APK文件
  6. Android官方开发指南翻译(1)-什么是Andro
  7. Android(安卓)HAL 开发 (1)
  8. 在android的webview中实现websocket
  9. android demo之ApiDemos下的text
  10. android打包apk流程