美文网首页
android中wifi原理及流程分析

android中wifi原理及流程分析

作者: lisx_ | 来源:发表于2020-06-01 20:04 被阅读0次

    wifi相关的文件位置:

    WIFI Settings应用程序位于

       packages/apps/Settings/src/com/android/settings/wifi/
    

    JAVA部分:

        frameworks/base/services/java/com/android/server/
    
        frameworks/base/wifi/java/android/net/wifi/
    

    JNI部分:

       frameworks/base/core/jni/android_net_wifi_Wifi.cpp
    

    wifi管理库。

        hardware/libhardware_legary/wifi/
    

    wifi用户空间的程序和库:

        external/wpa_supplicant/
    
       生成库libwpaclient.so和守护进程wpa_supplicant。
    

    调用流程:

    wifi模块的初始化:

    (frameworks/base/services/java/com/android/server/SystemServer.Java)

    在 SystemServer 启动的时候,会生成一个ConnectivityService 的实例,

    classServerThread extends Thread {

    。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
    try {

                Slog.i(TAG,"Connectivity Service");
    
                connectivity= **ConnectivityService.getInstance(context);**
    
               ServiceManager.addService(Context.CONNECTIVITY_SERVICE,connectivity);
    
            } catch(Throwable e) {
    
                Slog.e(TAG,"Failure starting Connectivity Service", e);
    
            }
    

    。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

    }

    其中 ,ConnectivityService.getInstance(context); 对应于(frameworks/base/services/java/com/android/server/ ConnectivityService.JavaConnectivityService.Java。

    下面看下ConnectivityService.Java中的

    public static ConnectivityServicegetInstance(Context context) {

       return** ConnectivityThread.getServiceInstance**(context);
    

    }函数, 继续往下看:

           public static ConnectivityService getServiceInstance(Context context) {
    
               ConnectivityThread thread = **newConnectivityThread**(context);
    
                thread.start();
    
               synchronized (thread) {
    
                   while (sServiceInstance == null) {
    
                        try {
    
                            // Wait until sServiceInstance has beeninitialized.
    
                            thread.wait();
    
                        } catch (InterruptedExceptionignore) {
    
                            Slog.e(TAG,
    
                                "UnexpectedInterruptedException while waiting"+
    
                                " forConnectivityService thread");
    
                        }
    
                   }
    
               }
    
                return sServiceInstance;
    
            }
    
        }
    
    继续往下跟:
    
    private static class **ConnectivityThread **extends Thread {
    
           private Context mContext;
    
           private ConnectivityThread(Context context) {
    
               super("ConnectivityThread");
    
               mContext = context;
    
            }
    
           @Override
    
       **     public void run() {**
    
               Looper.prepare();
    
               synchronized (this) {
    
                   sServiceInstance = **newConnectivityService**(mContext);
    
                   notifyAll();
    
               }
    
                Looper.loop();
    
            }
    
           public static ConnectivityService getServiceInstance(Context context) {
    
               ConnectivityThread thread = new ConnectivityThread(context);
    
               thread.start();
    
               synchronized (thread) {
    
                    while (sServiceInstance == null) {
    
                        try {
    
                            // Wait untilsServiceInstance has been initialized.
    
                            thread.wait();
    
                        } catch(InterruptedException ignore) {
    
                            Slog.e(TAG,
    
                                "UnexpectedInterruptedException while waiting"+
    
                                " forConnectivityService thread");
    
                        }
    
                   }
    
               }
    
               return sServiceInstance;
    
            }
    
        }
    
    继续**newConnectivityService**(mContext)
    
    private ConnectivityService(Context context) {
    
    。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
    
        for(int netType : mPriorityList) {
    
               switch (mNetAttributes[netType].mRadio) {
    
               case ConnectivityManager.TYPE_WIFI:
    
                   Slog.v(TAG, "Starting Wifi Service.");
    
                  ** WifiStateTracker wst = newWifiStateTracker(context, mHandler);**
    
                   WifiService wifiService = **newWifiService(context, wst);**
    
                   **ServiceManager.addService(Context.WIFI_SERVICE,wifiService);**
    
                   **wifiService.startWifi();//启动wifiservice**
    
                   mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
    
                   **wst.startMonitoring();//启动Monitoring**
    
                   break;   。。。。。
    
              }//endfor
    
    。。。。。。。。。。。。。。。。。。。。。。。。。。
    
    }
    

    到这里模块初始化的工作完成,具体流程图如下:

    image.png

    WifiStateTracker 会创建 WifiMonitor 接收来自底层的事件, WifiService 和 WifiMonitor 是整个模块的核心。WifiService 负责启动关闭 wpa_supplicant、启动关闭 WifiMonitor 监视线程和把命令下发给 wpa_supplicant,而 WifiMonitor 则负责从 wpa_supplicant 接收事件通知。

    也就是说WifiService负责wifi整个流程的控制,而WifiMonitor负责监视底层的事件。

    此时WifiService starting up withWi-Fi disabled,

    Wifi模块的启动(Enable):

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

    WirelessSettings 在初始化的时候配置了由WifiEnabler 来处理Wifi 按钮,

        protected void onCreate(BundlesavedInstanceState) {
    
            super.onCreate(savedInstanceState);
    
            mWifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
    
            if (getIntent().getBooleanExtra("only_access_points",false)) {
    
               addPreferencesFromResource(R.xml.wifi_access_points);
    
            } else {
    
               addPreferencesFromResource(R.xml.wifi_settings);
    
                **mWifiEnabler = new WifiEnabler(this,**
    
    **                    (CheckBoxPreference)findPreference("enable_wifi"));**
    
                mNotifyOpenNetworks =
    
                        (CheckBoxPreference)findPreference("notify_open_networks");
    
               mNotifyOpenNetworks.setChecked(Secure.getInt(getContentResolver(),
    
                        Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,0) == 1);
    
            }
    
            mAccessPoints = (ProgressCategory)findPreference("access_points");
    
           mAccessPoints.setOrderingAsAdded(false);
    
            mAddNetwork =findPreference("add_network");
    
            registerForContextMenu(getListView());
    
        }
    
    然后调用:**(**packages/apps/Settings/src/com/android/settings/wifi/ **WifiEnabler.java)**
    
    publicclass WifiEnabler implements Preference.OnPreferenceChangeListener {
    
    。。。。。。。。。。。。。。。。。。。。。。
    
      public boolean onPreferenceChange(Preferencepreference, Object value) {
    
    。。。。。。。。。。。。。。。。。。。。。。。。。。。
    
            if (mWifiManager.**setWifiEnabled(enable)**){
    
                mCheckBox.setEnabled(false);
    
            } else {
    
               mCheckBox.setSummary(R.string.wifi_error);
    
            }
    
    。。。。。。。。。。。。。。。。。。。。。。
    
            }
    
    。。。。。。。。。。。。。。。。。。。。。
    
    }
    
    调用:
    
    **(**packages/apps/Settings/src/com/android/settings/wifi/ **WifiManager.java)**
    
       public boolean setWifiEnabled(booleanenabled) {
    
            try {
    
                returnmService.**setWifiEnabled**(enabled);
    
            } catch(RemoteException e) {
    
                returnfalse;
    
            }
    
        }
    
      当用户按下 Wifi 按钮后,  Android 会调用 WifiEnabler 的onPreferenceChange,  再由 WifiEnabler调用 WifiManager 的 **setWifiEnabled** 接口函数,通过 AIDL,实际调用的是 WifiService 的**setWifiEnabled** 函数,WifiService 接着向自身发送一条 MESSAGE_ENABLE_WIFI 消息,在处理该消息的代码中做真正的使能工作:首先装载 WIFI 内核模块(该模块的位置硬编码为"/system/lib/modules/wlan.ko" ), 然 后 启 动 wpa_supplicant ( 配 置 文 件 硬 编 码 为"/data/misc/wifi/wpa_supplicant.conf")再通过 WifiStateTracker 来启动 WifiMonitor 中的监视线程。
    

    WifiService(WifiService.java) 收到MESSAGE_ENABLE_WIFI 消息后的操作如下:

    AIDL:

    Android Interface Definition Language,即Android接口描述语言。Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。

    为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(InterfaceDefinition Language,IDL)来公开服务的接口。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务。

    接下来继续道wifiService.Java

    (frameworks/base/services/java/com/android/server/ **wifiService.Java**)
    
        public boolean **setWifiEnabled(**boolean enable) {
    
            enforceChangePermission();
    
            if (mWifiHandler == null) return false;
    
            synchronized (mWifiHandler) {
    
                // caller may not have WAKE_LOCKpermission - it's not required here
    
                long ident =Binder.clearCallingIdentity();
    
                sWakeLock.acquire();
    
               Binder.restoreCallingIdentity(ident);
    
                mLastEnableUid =Binder.getCallingUid();
    
                // set a flag if the user isenabling Wifi while in airplane mode
    
                mAirplaneModeOverwridden = (enable&& isAirplaneModeOn() && isAirplaneToggleable());
    
                **sendEnableMessage(enable, true,Binder.getCallingUid());**  //  **here send a mesage to himself**
    
            }
    
            return true;
    
        }
    
    继续往下:
    
        private void **sendEnableMessage**(boolean enable,boolean persist, int uid) {
    
            Message msg= Message.obtain(mWifiHandler,
    
                                         (enable ?MESSAGE_ENABLE_WIFI : MESSAGE_DISABLE_WIFI),
    
                                         (persist ? 1 : 0), uid);
    
           ** msg.sendToTarget();**
    
        }
    
    WifiHandler会收到消息:
    
    private class **WifiHandler**extends Handler {
    
    。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
    
    public voidhandleMessage(Message msg) {
    
                switch (msg.what) {
    
                    case MESSAGE_ENABLE_WIFI:
    
                        **setWifiEnabledBlocking(true, msg.arg1 == 1,msg.arg2);**
    
                        if (mWifiWatchdogService ==null) {
    
                            mWifiWatchdogService = newWifiWatchdogService(mContext, mWifiStateTracker);
    
                        }
    
                        sWakeLock.release();
    
                        break;
    
    。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
    
                      }
    
    。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
    
    }
    
    privateboolean **setWifiEnabledBlocking**(booleanenable, boolean persist, int uid) {
    
    。。。。。。。。。。。。
    
    **  setWifiEnabledState(enable ?WIFI_STATE_ENABLING : WIFI_STATE_DISABLING, uid);**
    
    ** if (enable) {**
    
                if (!mWifiStateTracker.**loadDriver()**){
    
                    Slog.e(TAG, "Failed toload Wi-Fi driver.");
    
                   setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
    
                    return false;
    
                }
    
                if (!mWifiStateTracker.**startSupplicant()**){
    
                   mWifiStateTracker.unloadDriver();
    
                    Slog.e(TAG, "Failed tostart supplicant daemon.");
    
                   setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
    
                    return false;
    
                }
    
                registerForBroadcasts();
    
                mWifiStateTracker.**startEventLoop()**;
    
    **        } else {**
    
               mContext.unregisterReceiver(mReceiver);
    
               // Remove notification (it willno-op if it isn't visible)
    
                mWifiStateTracker.**setNotificationVisible**(false,0, false, 0);
    
                booleanfailedToStopSupplicantOrUnloadDriver = false;
    
                if (!mWifiStateTracker.**stopSupplicant()**){
    
                    Slog.e(TAG, "Failed tostop supplicant daemon.");
    
                    setWifiEnabledState(WIFI_STATE_UNKNOWN,uid);
    
                   failedToStopSupplicantOrUnloadDriver = true;
    
                }
    
                /**
    
                 * Reset connections and disableinterface
    
                 * before we unload the driver
    
                 */
    
                mWifiStateTracker.**resetConnections(true)**;
    
                if (!mWifiStateTracker.**unloadDriver()**){
    
                    Slog.e(TAG, "Failed tounload Wi-Fi driver.");
    
                    if(!failedToStopSupplicantOrUnloadDriver) {
    
                        setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
    
                       failedToStopSupplicantOrUnloadDriver = true;
    
                    }
    
                }
    
                if(failedToStopSupplicantOrUnloadDriver) {
    
                    return false;
    
    **            }**
    
            }
    
    。。。。。。。。。。。。。。。。。。。。。。
    
    }
    

    具体流程如下流程图所示:

    image.png image.png

    扫描查找热点(AP)

    上一节中讲到Wifi模块开启后会对外发送WIFI_STATE_CHANGED_ACTION。WifiLayer中注册了Action的Receiver。
    当WifiLayer收到此Action后开始scan的流程,具体如下:

    image.png

    当wpa_supplicant 处理完SCAN 命令后,它会向控制通道发送事件通知扫描完成,从wifi_wait_for_event函数会接收到该事件,由此WifiMonitor 中的MonitorThread会被执行来出来这个事件:

    image.png

    配置 AP 参数
    当用户在WifiSettings 界面上选择了一个AP 后,会显示配置AP 参数的一个对话框:

    image.png

    Wifi连接

    具体流程参见以下流程图:

    image.png

    IP地址的配置
    流程如图:

    image.png

    到此结束。

    相关文章

      网友评论

          本文标题:android中wifi原理及流程分析

          本文链接:https://www.haomeiwen.com/subject/vzzszhtx.html