Android wifi-framework StateMachine和AsyncChannel 学习

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/myvest/article/details/75522891

android中,wifi的核心是WPAS(wpa_supplicant),它管理和控制Android平台中的Wi-Fi功能。在整个wifi模块中,其更像是一个一个服务端,实现了连接,认证等工作流程。
而客户端有wpa_cli,和wpa_supplicant之间的通信依靠wpa ctrl接口来实现,而在wifi的framework层,其实主要工作就是向下实现wpa_cli的功能和wpa_supplicant通信,向上实现WiFiManager的简易接口供上层app调用。

wifi的framework分析起来相对于wpa_supplicant比较简单,先记录这几天看代码的一些点(阅读《深入理解Android:WiFi模块 NFC和GPS卷 - 邓凡平》和android4.2代码的一些笔记)。

首先必须了解两个类:StateMachine和AsyncChannel

1、StateMachine

在wifi模块framework层的东西中,有很多地方都是用了状态机的机制:WifiStateMachine,SupplicantStateTracker,DhcpStateMachine,WifiWatchdogStateMachine等。了解状态机的运行方式,是了解wifi模块在framework层运作的基础。

StateMachine是具有层级关系的状态机类,记录几个重要的点:
(1)addState函数可以增加一个状态,同时,该函数可以指定父子层级关系。
setInitialState函数指定初始状态。调用start函数时,状态机开始运行。
(2)从一个状态跳转到另一个状态时调用transitionTo函数。进入另一个状态时会先调用到状态的enter函数,退出时调用exit函数,同时得考虑他们的层级关系,而不是直接跳转。以WifiWatchdogStateMachine的状态机map为例,从Disabled 状态转到Verifying ,会先调用Disabled的exit,再依次调用Enabled和Verifying的enter。
下面是WifiWatchdogStateMachine的状态机map:

/**
 * STATE MAP
 *          Default
 *         /       \
 * Disabled      Enabled
 *             /     \     \
 * NotConnected  Verifying  Connected
 *                         /---------\
 *                       (all other states)
 */

(3)消息会在当前的状态中处理,对应的函数为processMessage。如果当前状态不能处理,会返回NOT_HANDLED。转到父状态处理,如果父状态依旧处理不了,则依次上去,如果都不能处理,最后unhandledMessage函数会被调用。
已经处理则返回HANDLED,如果一个消息想保留到下个状态再处理,可以调用deferMessage函数。
(4)由于StateMachine内部是围绕一个Handler来工作的, 所以外界只能调用StateMachine的obtainMessage函数以获取一个Message。发想送消息给StateMachine,调用sendMessage函数,StateMachine中的Handler会处理它。

2、AsyncChannel

这个类在wifi模块中也是被大量使用,是了解wifi的framework避不开的类。该类用于在两个handler之间传递消息。
有两种工作模式:一种是单通道模式,只有客户端连接了AsyncChannel,能向客户端发送请求,服务端只要回应即可。另一种是双通道模式,客户端服务端都连接AsyncChannel,双方均可以向对方发送请求。

单通道使用步骤:
(1)客户端拿到自己的handler;
(2)拿到服务端的Messenger(使用服务端handler构建),或者是服务端的handler;
(3)创建AsyncChannel对象,调用其connect函数,请求连接客户端自己的handler和服务端的Messenger;
(4)连接成功后,服务端会回应CMD_CHANNEL_HALF_CONNECTED消息。

双通道使用步骤:
其实双通道是在单通道的基础上完成的,
(1)客户端在接收到CMD_CHANNEL_HALF_CONNECTED消息后,
发送sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
(2)服务端在handler中会受到该消息,接着服务端也创建AsyncChannel对象,调用其connect函数connect(mContext, this, msg.replyTo)。
(3)另外还有一种比较方便的方法创建双通道,即调用该函数即可:
public int fullyConnectSync(Context srcContext, Handler srcHandler, Handler dstHandler)
需要传入客户端的context,客户端的handler和服务端的handler。返回值STATUS_SUCCESSFUL即代表建立成功。

一些例子:
(1)在wifi的framework层,WifiManager和WifiService之间建立起了双通道:
WifiManager作为客户端:
申请单通道连接:

private void init() {
        synchronized (sThreadRefLock) {
            if (++sThreadRefCount == 1) {
                Messenger messenger = getWifiServiceMessenger();
                if (messenger == null) {
                    sAsyncChannel = null;
                    return;
                }

                sHandlerThread = new HandlerThread("WifiManager");
                sAsyncChannel = new AsyncChannel();
                sConnected = new CountDownLatch(1);

                sHandlerThread.start();
                Handler handler = new ServiceHandler(sHandlerThread.getLooper());
                sAsyncChannel.connect(mContext, handler, messenger);
            ......
            }
        }
    }

在单通道连接基础上,请求双通道连接
sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION):

private static class ServiceHandler extends Handler {
        ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message message) {
            Object listener = removeListener(message.arg2);
            switch (message.what) {
                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
                    if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
                        sAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
                    } else {
            ......

WifiService作为服务端,在接收到CMD_CHANNEL_FULL_CONNECTION消息后,请求connect:

private class ClientHandler extends Handler {

        ClientHandler(android.os.Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
                        if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
                        // We track the clients by the Messenger
                        // since it is expected to be always available
                        mTrafficPoller.addClient(msg.replyTo);
                    } else {
                        Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
                    }
                    break;
                }
......
                case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
                    AsyncChannel ac = new AsyncChannel();
                    ac.connect(mContext, this, msg.replyTo);
                    break;
                }

(2)WifiService和WifiStateMachine之间连接方式为单通道,WifiStateMachine作为服务端,WifiService作为客户端,连接后,使用sendMessageSynchronously来进行请求,而WifiStateMachine会使用replyToMessage来进行回复(WifiStateMachine会用到mReplyChannel这个对象):

private class WifiStateMachineHandler extends Handler {
        private AsyncChannel mWsmChannel;

        WifiStateMachineHandler(android.os.Looper looper) {
            super(looper);
            mWsmChannel = new AsyncChannel();
            mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler());
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
                        mWifiStateMachineChannel = mWsmChannel;
                    } else {
                        Slog.e(TAG, "WifiStateMachine connection failure, error=" + msg.arg1);
                        mWifiStateMachineChannel = null;
                    }
                    break;
                }

猜你喜欢

转载自blog.csdn.net/myvest/article/details/75522891