• wifi基础知识及原理


    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

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

    }

     

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

     

    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 WifiHandlerextends 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;

                }

            }

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

    }

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

     

     

    扫描查找热点(AP)

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

     

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


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

    Wifi连接

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

     

    IP地址的配置
    流程如图:

    到此结束。

  • 相关阅读:
    通过反射实现IOC功能
    数据访问模式之Repository模式
    .NET自带IOC容器MEF之初体验
    权限管理系统进入关键的开发阶段
    待销售分拣单App数据推送
    做一个自己的权限管理系统
    linux tar 命令 --致力于“一眼看懂,随手就用”的随笔
    python 简单实现文件拷贝
    实验比较python中的range和xrange
    安装 chardet ,出现ImportError: No module named setuptools
  • 原文地址:https://www.cnblogs.com/pyj63/p/8046467.html
Copyright © 2020-2023  润新知