Wifi服务框架介绍(原)

来源:互联网 发布:作息时间表 知乎 编辑:程序博客网 时间:2024/04/28 03:11
        本文简要介绍WIFI服务的主要框架以及运作机制

        WIFI框架主要涉及到以下几个对象:WifiService、WifiManager、WifiServiceImpl、WifiStateMachine等。下面来介绍这四个对象的内在联系。


一、WIFI服务的初始化


        WIFI服务的初始化分为两个部分,WifiService的初始化和WifiManager的初始化,下面分别介绍。


1.1、WifiService的初始化流程


        WifiService的初始化流程是在SystemService中被启动的:
        @SystemServer.java        private static final String WIFI_SERVICE_CLASS = "com.android.server.wifi.WifiService";        private void startOtherServices() {            mSystemServiceManager.startService(WIFI_SERVICE_CLASS);        }
        在这里通过SystemServiceManager将WIFI的主服务(WifiService)启动,然后来看该Service的启动过程:
        @WifiService.java        public final class WifiService extends SystemService {            private static final String TAG = "WifiService";            final WifiServiceImpl mImpl;            public WifiService(Context context) {                super(context);                //创建WifiServiceImpl对象                mImpl = new WifiServiceImpl(context);            }            @Override            public void onStart() {                //将WifiServiceImpl注册到ServiceManager                publishBinderService(Context.WIFI_SERVICE, mImpl);            }            @Override            public void onBootPhase(int phase) {                if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {                    mImpl.checkAndStartWifi();                }            }        }
        以上是WifiService的全部内容,其实该Service只完成了两个任务:
        1、在初始化时,也就是构造方法中,创建WifiServiceImpl对象。
        2、在onStart时,将WifiServiceImpl对象注册到ServiceManager中。

        这里创建的WifiServiceImpl是整个WIFI服务的管理者,他负责将客户端对WIFI的请求分类,然后派发给不同的处理中心。
        下面先来看WifiServiceImpl的属性:
        public final class WifiServiceImpl extends IWifiManager.Stub {}
        这说明该类是一个服务的实现类。
        然后来看该对象的初始化过程,也就是构造方法:
        @WifiServiceImpl.java        public WifiServiceImpl(Context context) {            mContext = context;            mInterfaceName =  SystemProperties.get("wifi.interface", "wlan0");            mTrafficPoller = new WifiTrafficPoller(mContext, mInterfaceName);            //创建wifi状态机            mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName, mTrafficPoller);            mWifiStateMachine.enableRssiPolling(true);            //初始化各种管理者            mBatteryStats = BatteryStatsService.getService();            mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);            mNotificationController = new WifiNotificationController(mContext, mWifiStateMachine);            mSettingsStore = new WifiSettingsStore(mContext);            HandlerThread wifiThread = new HandlerThread("WifiService");            wifiThread.start();            mClientHandler = new ClientHandler(wifiThread.getLooper());            mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());            mWifiController = new WifiController(mContext, this, wifiThread.getLooper());            mBatchedScanSupported = mContext.getResources().getBoolean( R.bool.config_wifi_batched_scan_supported);        }
        在这里初始化各种与WIFI管理有关的辅助类,其中包含最重要的一个就是WIFI的状态机WifiStateMachine,他是整个WIFI机制的核心。下面来看该状态机的初始化流程:
        @WifiStateMachine.java        public WifiStateMachine(Context context, String wlanInterface, WifiTrafficPoller trafficPoller){            super("WifiStateMachine");            mContext = context;            mInterfaceName = wlanInterface;            //创建NetworkInfo对象            mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");            mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService( BatteryStats.SERVICE_NAME));            //创建各种辅助类            IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);            mNwService = INetworkManagementService.Stub.asInterface(b);            mP2pSupported = mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_WIFI_DIRECT);            mWifiNative = new WifiNative(mInterfaceName);            mWifiConfigStore = new WifiConfigStore(context, mWifiNative);            mWifiAutoJoinController = new WifiAutoJoinController(context, this, mWifiConfigStore, mWifiConnectionStatistics, mWifiNative);            mWifiMonitor = new WifiMonitor(this, mWifiNative);            mWifiInfo = new WifiInfo();            ......            //初始化状态机            addState(mDefaultState);            addState(mInitialState, mDefaultState);            addState(mSupplicantStartingState, mDefaultState);            addState(mSupplicantStartedState, mDefaultState);            addState(mDriverStartingState, mSupplicantStartedState);            addState(mDriverStartedState, mSupplicantStartedState);            addState(mScanModeState, mDriverStartedState);            addState(mConnectModeState, mDriverStartedState);            addState(mL2ConnectedState, mConnectModeState);            addState(mObtainingIpState, mL2ConnectedState);            addState(mVerifyingLinkState, mL2ConnectedState);            addState(mConnectedState, mL2ConnectedState);            addState(mRoamingState, mL2ConnectedState);            addState(mDisconnectingState, mConnectModeState);            addState(mDisconnectedState, mConnectModeState);            addState(mWpsRunningState, mConnectModeState);            addState(mWaitForP2pDisableState, mSupplicantStartedState);            addState(mDriverStoppingState, mSupplicantStartedState);            addState(mDriverStoppedState, mSupplicantStartedState);            addState(mSupplicantStoppingState, mDefaultState);            addState(mSoftApStartingState, mDefaultState);            addState(mSoftApStartedState, mDefaultState);            addState(mTetheringState, mSoftApStartedState);            addState(mTetheredState, mSoftApStartedState);            addState(mUntetheringState, mSoftApStartedState);            //设置状态机初始模式            setInitialState(mInitialState);            //启动状态机            start();            ......        }
        我们看到,在WifiStateMachine的初始化过程中创建了大量的辅助类,其中就包括NetworkInfo,他的作用就是标记当前网络的各项属性,比如当前网络的类型、是否可用、是否处于漫游等,然后还创建了许多WIFI的状态机,标识当前WIFI所处的状态,最后将状态机初始状态设置为mInitialState,并将状态机start。
        以上就是WifiService的全部初始化过程,其主要过程分为以下四个部分:
        1、在SystemServer中启动WifiService;
        2、在WifiService启动过程中创建并初始化WifiServiceImpl;
        3、在WifiServiceImpl初始化过程中创建并初始化WifiStateMachine对象;

        4、在WifiStateMachine初始化过程中创建各种状态机并启动他们;


1.2、WifiManager的初始化流程


        WIFI框架还有另外一个初始化流程实在ContextImpl中进行的。
        当系统初始化时,会在Context对象的实现类ContextImpl中注册一些常用的服务,这样就可以在应用内部通过Context对象的getSystemService()方法来获取相应的服务。而WIFI在ContextImpl中注册了WifiManager用于向一般应用提供WIFI的服务:
        @ContextImpl.java        registerService(WIFI_SERVICE, new ServiceFetcher() {            public Object createService(ContextImpl ctx) {                IBinder b = ServiceManager.getService(WIFI_SERVICE);                IWifiManager service = IWifiManager.Stub.asInterface(b);                return new WifiManager(ctx.getOuterContext(), service);            }});
        从这里可以知道两个信息:
        1、应用可以通过Context对象的getSystemService(Context.WIFI_SERVICE)的方法获取到一个WifiManager的对象用于控制WIFI;
        2、WifiManager的创建需要使用ServiceManager的WIFI_SERVICE服务,而这个WIFI_SERVICE就是在WifiService中注册的WifiServiceImpl对象;

        下面来看WifiManager的创建过程:
        @WifiManager.java        public WifiManager(Context context, IWifiManager service) {            mContext = context;            //这里的mService就是创建WifiManager时传递进来的WifiServiceImpl对象            mService = service;            init();        }        private void init() {            synchronized (sThreadRefLock) {                if (++sThreadRefCount == 1) {                    //获取WifiServiceImpl中的Messenger对象                    Messenger messenger = getWifiServiceMessenger();                    if (messenger == null) {                        sAsyncChannel = null;                        return;                    }                    //创建AsyncChannel通道                    sHandlerThread = new HandlerThread("WifiManager");                    sAsyncChannel = new AsyncChannel();                    sConnected = new CountDownLatch(1);                    sHandlerThread.start();                    Handler handler = new ServiceHandler(sHandlerThread.getLooper());                    //与WifiServiceImpl申请建立单向AsyncChannel                    sAsyncChannel.connect(mContext, handler, messenger);                    try {                        sConnected.await();                    } catch (InterruptedException e) {                        Log.e(TAG, "interrupted wait at init");                    }                }            }        }
        从上面WifiManager的初始化过程中我们看到,其初始化的过程中完成了以下两个任务:
        1、用WifiServiceImpl初始化mService对象;
        2、向WifiServiceImpl申请单向的AsyncChannel(想要连接AsyncChannel请点击这里);

        至此,WIFI框架就完成了所有需要初始化的动作,我们用一张流程图来标识该过程:



二、WIFI服务的运作机制


        由于应用操作WIFI是通过WifiManager进行的,那么我们可以从WifiManager开始来查找消息在WIFI内部的传递机制。
        以下是WifiManager提供的几个比较重要的对外接口:
        //获取所有网络连接        public List<WifiConfiguration> getConfiguredNetworks() {}        //添加网络连接        public int addNetwork(WifiConfiguration config) {}        //更新网络连接        public int updateNetwork(WifiConfiguration config) {}        //是否支持5Ghz        public boolean is5GHzBandSupported() {}        //是否支持WIFI热点        public boolean isPortableHotspotSupported() {}        //打开关闭WIFI        public boolean setWifiEnabled(boolean enabled) {}        //连接某个WIFI        public void connect(int networkId, ActionListener listener) {}        //断开当前连接        public boolean disconnect() {}        //添加黑名单        public boolean addToBlacklist(String bssid) {}        //清除黑名单        public boolean clearBlacklist() {}
        我们挑选两个比较典型的方法进行跟踪,分别是:控制WIFI开关的setWifiEnabled()和连接某个WIFI的connect()方法。

        为什么要挑选这两个方法呢?是因为这两个方法分别使用两种方式与WifiService进行通讯


2.1、setWifiEnabled方式


        在该方式中,WifiManager通过直接调用的方式与WifiServiceImpl进行通讯。
        @WifiManager.java        public boolean setWifiEnabled(boolean enabled) {            try {                //直接调用mService的setWifiEnabled方法                return mService.setWifiEnabled(enabled);            } catch (RemoteException e) {                return false;            }        }


2.2、connect方式


        与setWifiEnabled不同,在该方式中,WifiManager利用与WifiServiceImpl之间的AsyncChannel来交换信息
        @WifiManager.java        public void connect(int networkId, ActionListener listener) {            if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");            validateChannel();            //通过AsyncChannel与WifiServiceImpl传递信息            sAsyncChannel.sendMessage(CONNECT_NETWORK, networkId, putListener(listener));        }


2.3、WifiManager小结


        在上面两节中分别介绍了两种WifiManager与WifiServiceImpl通讯的方式,其实不仅是以上两个方法,WifiManager中所有的对外公开的public方法,最终都是通过这两种方式与WifiServiceImpl进行沟通

        我们可以这样理解WifiManager:他是WIFI模块向外部应用透漏出来的接口,其他所有应用都可以通过WifiManager操作WIFI各项功能,但是WifiManager本身并不具备处理请求的能力,而是把所有请求转发给WifiServiceImpl对象,而发送请求的方式就是直接调用或者通过AsyncChannel。


2.4、WifiServiceImpl中对请求的处理


        无论采用何种沟通方式,WifiManager最终都会把应用的请求转交给WifiServiceImpl来处理。那么接下来的流程是怎样的呢?WifiServiceImpl将会如何处理WifiManager转发过来的请求呢?
        我们继续跟踪上面两个方法的调用流程来查看WifiServiceImpl的处理过程。
        先来看setWifiEnabled()方法,该方法是直接由WifiManager调用到WifiServiceImpl中的,其实现如下:
        @WifiServiceImpl.java        public synchronized boolean setWifiEnabled(boolean enable) {            //权限检查            enforceChangePermission();            //权限检查            long ident = Binder.clearCallingIdentity();            try {                if (! mSettingsStore.handleWifiToggled(enable)) {                    return true;                }            } finally {                Binder.restoreCallingIdentity(ident);            }            //向WifiController发送请求            mWifiController.sendMessage(CMD_WIFI_TOGGLED);            return true;        }
        在这里我们看到,WifiServiceImpl将请求转交给WifiController来处理。
        下面来看WifiManager中connect()方法的处理,当初WifiManager收到该请求后,通过AsyncChannel的方式向WifiServiceImpl发送CONNECT_NETWORK的请求,那么WifiServiceImpl的接下来就需要在自己的Messenger中处理,而这个Messenger是从getWifiServiceMessenger()中传递给WifiManager的,我们来看是哪个Messenger来处理该请求:
        @WifiServiceImpl.java        public Messenger getWifiServiceMessenger() {            //权限检查            enforceAccessPermission();            enforceChangePermission();            //这里的Messenger的Handler是mClientHandler            return new Messenger(mClientHandler);        }
        从这里看到,WifiManager拿到的Messenger中的Handler其实就是mClientHandler,他是在WifiServiceImpl初始化时被创建的:
        @WifiServiceImpl.java        public WifiServiceImpl(Context context) {            ......            HandlerThread wifiThread = new HandlerThread("WifiService");            wifiThread.start();            mClientHandler = new ClientHandler(wifiThread.getLooper());        }
        也就是说WifiManager通过AsyncChannel发送的消息都会在ClientHandler中接收到:
        private class ClientHandler extends Handler {            ClientHandler(android.os.Looper looper) {                super(looper);            }            @Override            public void handleMessage(Message msg) {                switch (msg.what) {                    case WifiManager.CONNECT_NETWORK:                    case WifiManager.SAVE_NETWORK: {                       WifiConfiguration config = (WifiConfiguration) msg.obj;                       int networkId = msg.arg1;                       if (msg.what == WifiManager.SAVE_NETWORK) {                       }                       if (msg.what == WifiManager.CONNECT_NETWORK) {                           if (config != null) {                               //配置config                               if (config.networkId == WifiConfiguration.INVALID_NETWORK_ID) {                                   config.creatorUid = Binder.getCallingUid();                               } else {                                   config.lastUpdateUid = Binder.getCallingUid();                               }                           }                       }                       if (config != null && config.isValid()) {                           //将请求发送给WifiStateMachine                           mWifiStateMachine.sendMessage(Message.obtain(msg));                       } else if (config == null && networkId != WifiConfiguration.INVALID_NETWORK_ID) {                           mWifiStateMachine.sendMessage(Message.obtain(msg));                       } else {                           if (msg.what == WifiManager.CONNECT_NETWORK) {                               replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED, WifiManager.INVALID_ARGS);                           } else {                               replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED, WifiManager.INVALID_ARGS);                           }                       }                       break;                   }                }            }        }
        从上面这个处理来看,WifiServiceImpl将请求转交给WifiStateMachine来处理。
        其实WifiServiceImpl对请求的处理与WifiManager类似,他本身并不具备处理事物的能力,只是将请求分类后交由不同的处理者去处理
        以上就是整个WIFI框架的初始化以及内部消息处理机制,下面用一张图来标识WIFI内部的消息流:
        
2 0