精华内容
下载资源
问答
  • Esp8266_Wifi原理

    2018-12-11 18:09:57
    Esp8266_Wifi原理图----ESP8266模块的原理图,很有参考的价值!!!
  • android中wifi原理详解 转

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

    也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                   

    二:Wifi模块的初始化::

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


    try {
    Log.i(TAG, "Starting Connectivity Service.");
    ServiceManager.addService(Context.CONNECTIVITY_SERVICE, new
    ConnectivityService(context));
    } catch (Throwable e) {
    Log.e(TAG, "Failure starting Connectivity Service", e);
    }


    ConnectivityService 的构造函数会创建WifiService,

    if (DBG) Log.v(TAG, "Starting Wifi Service.");
    mWifiStateTracker = new WifiStateTracker(context, handler);
    WifiService wifiService = new WifiService(context, mWifiStateTracker);
    ServiceManager.addService(Context.WIFI_SERVICE, wifiService);


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

    具体流程图如下:

     

     

     

     

    第三部分:Wifi模块的启动(使能)

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

    private void initToggles() {
    mWifiEnabler = new WifiEnabler(this,
                                     (WifiManager) getSystemService(WIFI_SERVICE),
                                     (CheckBoxPreference) findPreference(KEY_TOGGLE_WIFI));


    当用户按下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 中的监视
    线程。

    private boolean setWifiEnabledBlocking(boolean enable) {
        final int eventualWifiState = enable ?WIFI_STATE_ENABLED :WIFI_STATE_DISABLED;
        updateWifiState(enable ? WIFI_STATE_ENABLING :WIFI_STATE_DISABLING);
        if (enable) {
                if(!WifiNative.loadDriver()) {
                     Log.e(TAG, "Failed to load Wi-Fi driver.");
                     updateWifiState(WIFI_STATE_UNKNOWN);
                     return false;
                }
        if (!WifiNative.startSupplicant()) {
               WifiNative.unloadDriver();
               Log.e(TAG,"Failed to start supplicant daemon.");
               updateWifiState(WIFI_STATE_UNKNOWN);
               return false;
         }
         mWifiStateTracker.startEventLoop();
    }
         // Success!
         persistWifiEnabled(enable);
         updateWifiState(eventualWifiState);
         return true;
    }


    当使能成功后,会广播发送WIFI_STATE_CHANGED_ACTION 这个Intent通知外界WIFI
    已经成功使能了。WifiEnabler 创建的时候就会向Android注册接收
    WIFI_STATE_CHANGED_ACTION,因此它会收到该Intent,从而开始扫描。

    private void handleWifiStateChanged(int wifiState) {
    if (wifiState == WIFI_STATE_ENABLED) {
    loadConfiguredAccessPoints();
    attemptScan();
    }

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

    第四部分:查找热点(AP)

    上一节(第三部分:Wifi开启)中讲到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地址的配置

    流程如图:

     

     

               

    给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

    这里写图片描述
    展开全文
  • wifi原理

    2013-12-05 13:59:11
    wifi模块电路原理图,用于智能家居系统的开发
  • RP5小车MCU与WiFi原理图.pdf
  • android中wifi原理及流程分析 很经典

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

    也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                   

    wifi相关的文件位置:

    WIFISettings应用程序位于

          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 的实例,

    classServerThreadextends 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中的  

     publicstatic ConnectivityServicegetInstance(Context context) {

           return ConnectivityThread.getServiceInstance(context);

       }函数,继续往下看:

           publicstatic ConnectivityService getServiceInstance(Context context) {

               ConnectivityThreadthread = 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;

           }

       }

    继续往下跟:

    privatestatic class ConnectivityThread extends Thread {

           privateContext mContext;

     

           privateConnectivityThread(Context context) {

               super("ConnectivityThread");

               mContext= context;

           }

           @Override

            publicvoid run() {

               Looper.prepare();

               synchronized(this) {

                   sServiceInstance= newConnectivityService(mContext);

                   notifyAll();

               }

               Looper.loop();

           }

           publicstatic ConnectivityService getServiceInstance(Context context) {

               ConnectivityThreadthread = 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");

                       }

                   }

               }

               returnsServiceInstance;

           }

       }

    继续newConnectivityService(mContext)

    privateConnectivityService(Context context) {

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

       for(int netType : mPriorityList) {

               switch(mNetAttributes[netType].mRadio) {

               caseConnectivityManager.TYPE_WIFI:

                   Slog.v(TAG,"Starting Wifi Service.");

                   WifiStateTracker wst =newWifiStateTracker(context, mHandler);

                   WifiServicewifiService = 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

    publicclassWifiEnabler 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,实际调用的是 WifiServicesetWifiEnabled 函数,WifiService接着向自身发送一条MESSAGE_ENABLE_WIFI消息,在处理该消息的代码中做真正的使能工作:首先装载 WIFI内核模块(该模块的位置硬编码为"/system/lib/modules/wlan.ko"),wpa_supplicant ("/data/misc/wifi/wpa_supplicant.conf")再通过 WifiStateTracker 来启动WifiMonitor中的监视线程。

    WifiServiceWifiService.java收到MESSAGE_ENABLE_WIFI消息后的操作如下:

    AIDL:

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

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

    接下来继续道wifiService.Java

    frameworks/base/services/java/com/android/server/ wifiService.Java

       public boolean setWifiEnabled(booleanenable) {

           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());  //  heresend a mesage to himself

           }

           return true;

       }

    继续往下:

       private void sendEnableMessage(booleanenable,boolean persist, int uid) {

           Message msg= Message.obtain(mWifiHandler,

                                        (enable ?MESSAGE_ENABLE_WIFI : MESSAGE_DISABLE_WIFI),

                                        (persist ? 1 : 0), uid);

           msg.sendToTarget();

       }

    WifiHandler会收到消息:

    privateclass WifiHandlerextendsHandler {

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

    publicvoidhandleMessage(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_ACTIONWifiLayer中注册了ActionReceiver
    WifiLayer收到此Action后开始scan的流程,具体如下

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

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

    Wifi连接

    具体流程参见以下流程图

     

     

    IP地址的配置
    流程如图

    到此结束

               

    给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

    这里写图片描述
    展开全文
  • s3c2416_GPS_GSM_WiFi 原理
  • android中wifi原理及流程分析(很经典)

    From: http://blog.csdn.net/eager7/article/details/8177677


    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地址的配置
    流程如图:


    到此结束。


    展开全文
  • SD-TF-WIFI 原理

    2013-10-14 15:18:41
    wifi模块原理图,经过实际应用测试,稳定可靠
  • idea6410WIFI原理

    2012-09-12 20:42:36
    表述了idea6410 无线网卡的工作原理
  • 安卓WIFI原理浅析

    千次阅读 2015-05-06 16:30:51
    最近,在好几个安卓手机群里面都看到有朋友寻求WIFI密码破解工具,在网上经过一番搜索后发现居然没有这样的软件,这让我感到很奇怪,难道这样的功能实现起来很难?思索再三,决定探个究竟。 首先看SDK中查看WIFI...

    最近,在好几个安卓手机群里面都看到有朋友寻求WIFI密码破解工具,在网上经过一番搜索后发现居然没有这样的软件,这让我感到很奇怪,难道这样的功能实现起来很难?思索再三,决定探个究竟。

    首先看SDK中查看WIFI操作的相关类。WIFI的支持是在android.net.wifi包中提供的。里面有WifiManager、WifiInfo、WifiConfiguration与ScanResult等几个常用到的类,WIFI的管理通过WifiManager暴露出来的方法来操作,仔细一看还真让人郁闷,这个类没有提供连接WIFI的方法,倒是有disconnect()方法来断开连接,不过有个reconnect()方法倒是值得注意,只是该方法SDK中却没有详细的介绍。在谷歌中搜索安卓连接WIFI的代码又测试失败,心里顿时凉了一截!看来要想完成这个功能还得下一番功夫。

    转念一想,安卓会不会把这样的接口隐藏了,通过AIDL的方式就可以访问呢?为了验证我的想法,开始在安卓源代码的“frameworks”目录中搜索以aidl结尾的文件,最终锁定“IWifiManager.aidl”文件,用Editplus打开它,发现IWifiManager接口里面也没有提供连接WIFI的方法。这条线索也断了!

    看来只能从手机WIFI的连接过程着手了。掏出手机,进入“设置”->“无线和网络设置”->“WLAN设置”里面打开“WLAN”,这时手机会自动搜索附近的WIFI热点,点击任一个加密的热点会弹出密码输入框,如图1所示:

    安卓WIFI密码破解工具编写初探

    输入任意长度大于或等于8位的密码后点击连接按钮,此时手机就会去连接该热点,如果验证失败就会提示“密码错误,请重新输入正确的密码并且再试一次”,如图2所示:

    安卓WIFI密码破解工具编写初探

    如果此时更换密码后再试一次仍然失败的话,手机就不会再访问该热点并将该WLAN网络设为禁用。既然在手机设置里可以连接WIFI,那么说明设置里面就有连接WIFI的代码存在。

    手机设置这一块是做为安卓手机的一个软件包提供的,它的代码位于安卓源码的“packages\apps\Settings”目录中,为了弄清楚操作流程,我决定到源码中查看相关代码。首先根据文件名判断打开“packages\apps\Settings\src\com\android\settings\wifi\WifiSettings.java”文件,可以看到WifiSettings类继承自SettingsPreferenceFragment,SettingsPreferenceFragment类使用一系列的PreferenceScreen作为显示的列表项,现在很多软件都用它来作为自身的设置页面,不仅布局更简单,而且也很方便。

    找到WifiSettings的构造函数代码如下:

    public WifiSettings() {

    mFilter = new IntentFilter();

    mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);

    mFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);

    mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);

    mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);

    mFilter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);

    mFilter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);

    mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);

    mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);

    mFilter.addAction(WifiManager.ERROR_ACTION);

     

    mReceiver = new BroadcastReceiver() {

    @Override

    public void onReceive(Context context, Intent intent) {

    handleEvent(context, intent);

    }

    };

    mScanner = new Scanner();

    }

    这段代码注册了一个广播接收者,接收一系列的广播事件,WIFI_STATE_CHANGED_ACTION事件当WIFI功能开启或关闭时会收到,SCAN_RESULTS_AVAILABLE_ACTION事件当手机扫描到有可用的WIFI连接时会收到,SUPPLICANT_STATE_CHANGED_ACTION事件当连接请求状态发生改变时会收到,NETWORK_STATE_CHANGED_ACTION事件当网络状态发生变化时会收到,对于其它的事件我们不用去关心,广播接收者中调用handleEvent()方法对所有的事件进行判断并处理,事件处理代码如下:

    private void handleEvent(Context context, Intent intent) {

    String action = intent.getAction();

    if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {

    updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,

    WifiManager.WIFI_STATE_UNKNOWN));

    } else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action) ||

    WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals(action) ||

    WifiManager.LINK_CONFIGURATION_CHANGED_ACTION.equals(action)) {

    updateAccessPoints();

    } else if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(action)) {

    if (!mConnected.get()) {

    updateConnectionState(WifiInfo.getDetailedStateOf((SupplicantState)

    intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE)));

    }

    if (mInXlSetupWizard) {

    ((WifiSettingsForSetupWizardXL)getActivity()).onSupplicantStateChanged(intent);

    }

    } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {

    NetworkInfo info = (NetworkInfo) intent.getParcelableExtra(

    WifiManager.EXTRA_NETWORK_INFO);

    mConnected.set(info.isConnected());

    changeNextButtonState(info.isConnected());

    updateAccessPoints();

    updateConnectionState(info.getDetailedState());

    }

    .....

    }

    代码中分别调用updateWifiState()、updateConnectionState()、updateAccessPoints()等方法进行更新操作,同样凭感觉查看updateAccessPoints()方法,代码如下:

    private void updateAccessPoints() {

    final int wifiState = mWifiManager.getWifiState();

    switch (wifiState) {

    case WifiManager.WIFI_STATE_ENABLED:

    // AccessPoints are automatically sorted with TreeSet.

    final Collection<AccessPoint> accessPoints = constructAccessPoints();

    getPreferenceScreen().removeAll();

    if (mInXlSetupWizard) {

    ((WifiSettingsForSetupWizardXL)getActivity()).onAccessPointsUpdated(

    getPreferenceScreen(), accessPoints);

    } else {

    for (AccessPoint accessPoint : accessPoints) {

    getPreferenceScreen().addPreference(accessPoint);

    }

    }

    break;

    .....

    }

    成功开启WIFI,即getWifiState()返回为WIFI_STATE_ENABLED时首先会调用constructAccessPoints(),在这个方法中调用mWifiManager.getConfiguredNetworks()与mWifiManager.getScanResults()来分别获取已保存与可用的WIFI热点网络,接着判断mInXlSetupWizard并调用onAccessPointsUpdated()或addPreference(accessPoint),这两者的操作都是往页面添加显示搜索到的WIFI热点网络,区别只是调用者是不是大屏手机或平板电脑(mInXlSetupWizard意思为是否为大屏幕的设置向导,这个结论由长时间分析所得!*_*,XL=XLarge)。AccessPoints 的构造函数有三个,代码如下:

    AccessPoint(Context context, WifiConfiguration config) {

    super(context);

    setWidgetLayoutResource(R.layout.preference_widget_wifi_signal);

    loadConfig(config);

    refresh();

    }

     

    AccessPoint(Context context, ScanResult result) {

    super(context);

    setWidgetLayoutResource(R.layout.preference_widget_wifi_signal);

    loadResult(result);

    refresh();

    }

     

    AccessPoint(Context context, Bundle savedState) {

    super(context);

    setWidgetLayoutResource(R.layout.preference_widget_wifi_signal);

     

    mConfig = savedState.getParcelable(KEY_CONFIG);

    if (mConfig != null) {

    loadConfig(mConfig);

    }

    mScanResult = (ScanResult) savedState.getParcelable(KEY_SCANRESULT);

    if (mScanResult != null) {

    loadResult(mScanResult);

    }

    mInfo = (WifiInfo) savedState.getParcelable(KEY_WIFIINFO);

    if (savedState.containsKey(KEY_DETAILEDSTATE)) {

    mState = DetailedState.valueOf(savedState.getString(KEY_DETAILEDSTATE));

    }

    update(mInfo, mState);

    }

    上面的两个构造函数分别针对调用mWifiManager.getConfiguredNetworks()与mWifiManager.getScanResults()得来的结果调用loadConfig(WifiConfiguration config)与loadResult(ScanResult result),经过这一步后,AccessPoints 的成员变量也初始化完了,然后调用refresh()方法进行刷新显示操作,代码我就不帖了,主要就是设置显示SSID,SSID的加密方式,信号强度等。显示工作做完后,我们的重点应用转向WIFI热点网络点击事件的处理。点击事件的处理同样在WifiSettings.java文件中,代码如下:

    @Override

    public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {

    if (preference instanceof AccessPoint) {

    mSelectedAccessPoint = (AccessPoint) preference;

    /** Bypass dialog for unsecured, unsaved networks */

    if (mSelectedAccessPoint.security == AccessPoint.SECURITY_NONE &&

    mSelectedAccessPoint.networkId == INVALID_NETWORK_ID) {

    mSelectedAccessPoint.generateOpenNetworkConfig();

    mWifiManager.connectNetwork(mSelectedAccessPoint.getConfig());

    } else {

    showConfigUi(mSelectedAccessPoint, false);

    }

    } else {

    return super.onPreferenceTreeClick(screen, preference);

    }

    return true;

    }

    这段代码很简单,如果WIFI没有加密,直接调用mSelectedAccessPoint.generateOpenNetworkConfig()生成一个不加密的WifiConfiguration,代码如下:

    protected void generateOpenNetworkConfig() {

    if (security != SECURITY_NONE)

    throw new IllegalStateException();

    if (mConfig != null)

    return;

    mConfig = new WifiConfiguration();

    mConfig.SSID = AccessPoint.convertToQuotedString(ssid);

    mConfig.allowedKeyManagement.set(KeyMgmt.NONE);

    }

    代码首先new了一个WifiConfiguration赋值给mConfig,然后设置allowedKeyManagement为KeyMgmt.NONE表示不使用加密连接,这个工作做完成后就调用了mWifiManager的connectNetwork()方法进行连接,看这个方法的父亲可以发现是WifiManager,居然是WifiManager,可这个方法却没有导出!!!

    继续分析,如果是加密的WIFI,就调用showConfigUi()方法来显示输入密码框,对于大屏手机,即mInXlSetupWizard为真时,调用了WifiSettingsForSetupWizardXL类的showConfigUi()方法,如果为假就直接调用showDialog(accessPoint, edit)显示对话框,代码如下:

    private void showDialog(AccessPoint accessPoint, boolean edit) {

    if (mDialog != null) {

    removeDialog(WIFI_DIALOG_ID);

    mDialog = null;

    }

    // Save the access point and edit mode

    mDlgAccessPoint = accessPoint;

    mDlgEdit = edit;

    showDialog(WIFI_DIALOG_ID);

    }

     

    @Override

    public Dialog onCreateDialog(int dialogId) {

    AccessPoint ap = mDlgAccessPoint; // For manual launch

    if (ap == null) { // For re-launch from saved state

    if (mAccessPointSavedState != null) {

    ap = new AccessPoint(getActivity(), mAccessPointSavedState);

    // For repeated orientation changes

    mDlgAccessPoint = ap;

    }

    }

    // If it's still null, fine, it's for Add Network

    mSelectedAccessPoint = ap;

    mDialog = new WifiDialog(getActivity(), this, ap, mDlgEdit);

    return mDialog;

    }

    这段代码保存accessPoint后就调用showDialog(WIFI_DIALOG_ID)了,在onCreateDialog()初始化方法中判断mDlgAccessPoint是否为null,如果为null就调用AccessPoint的第三个构造方法从保存的状态中生成一个AccessPoint,最后new WifiDialog(getActivity(), this, ap, mDlgEdit)生成一个WifiDialog,这个WifiDialog继承自AlertDialog,也就是它,最终将对话框展现在我们面前,WifiDialog构造函数的第二个参数为DialogInterface.OnClickListener的监听器,设置为this表示类本身对按钮点击事件进行响应,接下来找找事件响应代码,马上就到关键啰!

    public void onClick(DialogInterface dialogInterface, int button) {

    if (mInXlSetupWizard) {

    if (button == WifiDialog.BUTTON_FORGET && mSelectedAccessPoint != null) {

    forget();

    } else if (button == WifiDialog.BUTTON_SUBMIT) {

    ((WifiSettingsForSetupWizardXL)getActivity()).onConnectButtonPressed();

    }

    } else {

    if (button == WifiDialog.BUTTON_FORGET && mSelectedAccessPoint != null) {

    forget();

    } else if (button == WifiDialog.BUTTON_SUBMIT) {

    submit(mDialog.getController());

    }

    }

    }

    代码判断弹出的对话框是WIFI热点抛弃还是WIFI连接,并做出相应的处理,这里看看submit()方法的代码:

    void submit(WifiConfigController configController) {

    int networkSetup = configController.chosenNetworkSetupMethod();

    switch(networkSetup) {

    case WifiConfigController.WPS_PBC:

    case WifiConfigController.WPS_DISPLAY:

    case WifiConfigController.WPS_KEYPAD:

    mWifiManager.startWps(configController.getWpsConfig());

    break;

    case WifiConfigController.MANUAL:

    final WifiConfiguration config = configController.getConfig();

    if (config == null) {

    if (mSelectedAccessPoint != null

    && !requireKeyStore(mSelectedAccessPoint.getConfig())

    && mSelectedAccessPoint.networkId != INVALID_NETWORK_ID) {

    mWifiManager.connectNetwork(mSelectedAccessPoint.networkId);

    }

    } else if (config.networkId != INVALID_NETWORK_ID) {

    if (mSelectedAccessPoint != null) {

    saveNetwork(config);

    }

    } else {

    if (configController.isEdit() || requireKeyStore(config)) {

    saveNetwork(config);

    } else {

    mWifiManager.connectNetwork(config);

    }

    }

    break;

    }

     

    if (mWifiManager.isWifiEnabled()) {

    mScanner.resume();

    }

    updateAccessPoints();

    }

    关键代码终于找到了,那个叫激动啊T_T!按钮事件首先对WIFI网络加密类型进行判断,是WPS的就调用mWifiManager.startWps(configController.getWpsConfig()),是手动设置就调用被点击AccessPoint 项的getConfig()方法读取WifiConfiguration信息,如果不为null调用connectNetwork(mSelectedAccessPoint.networkId)连接网络,为null说明可能是AccessPoint 调用第二个构造函数使用ScanResult生成的,则调用saveNetwork(config),看看saveNetwork()的代码:

    private void saveNetwork(WifiConfiguration config) {

    if (mInXlSetupWizard) {

    ((WifiSettingsForSetupWizardXL)getActivity()).onSaveNetwork(config);

    } else {

    mWifiManager.saveNetwork(config);

    }

    }

    调用的mWifiManager.saveNetwork(config)方法,这个方法同样在SDK中没有导出,到源码中找找,最终在源代码的“frameworks\base\wifi\java\android\net\wifi\WifiManager.java”文件中找到是通过向自身发送消息的方式调用了WifiStateMachine.java->WifiConfigStore.java->saveNetwork()方法,最终保存WIFI网络后发送了一个已配置网络变更广播,这里由于篇幅就不再展开了。

    分析到这里,大概了解了WIFI连接的整个流程,程序无论是否为加密的WIFI网络,最终调用WifiManager的connectNetwork()方法来连接网络。而这个方法在SDK中却没有导出,我们该如何解决这个问题,一杯茶后,马上回来......

    connectNetwork()方法

    我始终不明白安卓SDK中为什么不开放connectNetwork这个接口,但现在需要用到了,也只能接着往下面分析,WifiManager是Framework层的,接下来的探索移步到安卓源码“frameworks\base\wifi\java\android\net\wifi”目录中去,在WifiManager.java中搜索“connectNetwork”,代码如下:

    /**

    * Connect to a network with the given configuration. The network also

    * gets added to the supplicant configuration.

    *

    * For a new network, this function is used instead of a

    * sequence of addNetwork(), enableNetwork(), saveConfiguration() and

    * reconnect()

    *

    * @param config the set of variables that describe the configuration,

    *           contained in a {@link WifiConfiguration} object.

    * @hide

    */

    public void connectNetwork(WifiConfiguration config) {

    if (config == null) {

    return;

    }

    mAsyncChannel.sendMessage(CMD_CONNECT_NETWORK, config);

    }

    注意看注释部分!“对于一个新的网络,这个函数相当于陆续调用了addNetwork(), enableNetwork(), saveConfiguration() 与 reconnect()”。看到这句话,心里可美了,因为这四个函数在SDK中都有导出,在代码中分别调用它们不就达到调用connectNetwork的目的了么?

    继续分析代码,如果config不为空,connectNetwork就通过mAsyncChannel发送了一条“CMD_CONNECT_NETWORK”的消息,mAsyncChannel的声明如下:

    /* For communication with WifiService */

    private AsyncChannel mAsyncChannel = new AsyncChannel();

    从注释上理解,这个东西是用来与WifiService 通信的。WifiService 属于Framework底层的服务,位于源码“\frameworks\base\services\java\com\android\server”目录,找到代码如下:

    @Override

    public void handleMessage(Message msg) {

    switch (msg.what) {

           ......

    case WifiManager.CMD_CONNECT_NETWORK: {

    if (msg.obj != null) {

    mWifiStateMachine.connectNetwork((WifiConfiguration)msg.obj);

    } else {

    mWifiStateMachine.connectNetwork(msg.arg1);

    }

    break;

    }

           ......

    }

    }

    在handleMessage()方法中有很多消息处理,这里由于篇幅只列出了CMD_CONNECT_NETWORK,可以看出这WifiService 就是个“托”,它只是将“病人”重新转给mWifiStateMachine处理,mWifiStateMachine为WifiStateMachine类,代码和WifiManager在同一目录,找到connectNetwork代码如下:

    public void connectNetwork(int netId) {

    sendMessage(obtainMessage(CMD_CONNECT_NETWORK, netId, 0));

    }

    public void connectNetwork(WifiConfiguration wifiConfig) {

    /* arg1 is used to indicate netId, force a netId value of

    * WifiConfiguration.INVALID_NETWORK_ID when we are passing

    * a configuration since the default value of 0 is a valid netId

    */

    sendMessage(obtainMessage(CMD_CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID,

    0, wifiConfig));

    }

    真有才了!还在发消息,只不过是给自已发,我真怀疑这写WIFI模块的是不是90后,这一层层绕的不头晕?找到处理代码如下:

    @Override

    public boolean processMessage(Message message) {

               ......

    case CMD_CONNECT_NETWORK:

    int netId = message.arg1;

    WifiConfiguration config = (WifiConfiguration) message.obj;

    /* We connect to a specific network by issuing a select

    * to the WifiConfigStore. This enables the network,

    * while disabling all other networks in the supplicant.

    * Disabling a connected network will cause a disconnection

    * from the network. A reconnectCommand() will then initiate

    * a connection to the enabled network.

    */

    if (config != null) {

    netId = WifiConfigStore.selectNetwork(config);

    } else {

    WifiConfigStore.selectNetwork(netId);

    }

     

    /* The state tracker handles enabling networks upon completion/failure */

    mSupplicantStateTracker.sendMessage(CMD_CONNECT_NETWORK);

     

    WifiNative.reconnectCommand();

    mLastExplicitNetworkId = netId;

    mLastNetworkChoiceTime = SystemClock.elapsedRealtime();

    mNextWifiActionExplicit = true;

    if (DBG) log("Setting wifi connect explicit for netid " + netId);

    /* Expect a disconnection from the old connection */

    transitionTo(mDisconnectingState);

    break;

                       ......

    注释中说:通过WifiConfigStore的selectNetwork()方法连接一个特定的网络,当禁用supplicant中其它所有网络时,会连接网络,而禁用一个已经连接的网络,将会引发disconnection操作,reconnectCommand()方法会初始化并连接已启用的网络。

    selectNetwork()过后,mSupplicantStateTracker发送了一条CMD_CONNECT_NETWORK消息,它其实只做了一件事,就是将“mNetworksDisabledDuringConnect ”设为true。最后WifiNative.reconnectCommand()对网络进行重新连接,至此,WIFI的连接过程就完毕了,下面看看selectNetwork()代码:

    static int selectNetwork(WifiConfiguration config) {

    if (config != null) {

    NetworkUpdateResult result = addOrUpdateNetworkNative(config);

    int netId = result.getNetworkId();

    if (netId != INVALID_NETWORK_ID) {

    selectNetwork(netId);

    } else {

    loge("Failed to update network " + config);

    }

    return netId;

    }

    return INVALID_NETWORK_ID;

    }

    static void selectNetwork(int netId) {

    // Reset the priority of each network at start or if it goes too high.

    if (sLastPriority == -1 || sLastPriority > 1000000) {

    synchronized (sConfiguredNetworks) {

    for(WifiConfiguration config : sConfiguredNetworks.values()) {

    if (config.networkId != INVALID_NETWORK_ID) {

    config.priority = 0;

    addOrUpdateNetworkNative(config);

    }

    }

    }

    sLastPriority = 0;

    }

    // Set to the highest priority and save the configuration.

    WifiConfiguration config = new WifiConfiguration();

    config.networkId = netId;

    config.priority = ++sLastPriority;

     

    addOrUpdateNetworkNative(config);

    WifiNative.saveConfigCommand();

    enableNetworkWithoutBroadcast(netId, true);

    }

    代码都在这里了,我再也不帖了,帖了太多了,这段代码流程为addOrUpdateNetworkNative()先保存一个,然后对已保存的网络优先级降下来,这是为了让新网络拥有更高的优先连接权,接着执行saveConfigCommand()将配置信息保存,这里的保存操作在底层是将网络信息保存到了“/data/misc/wifi/wpa_supplicant.conf”文件中,最后enableNetworkWithoutBroadcast(netId, true)启用本网络并禁用其它网络。

    小结一下connectNetwork的执行步骤为“WifiConfigStore.selectNetwork()”->“addOrUpdateNetworkNative()”->“其它网络降级并设置自已最高优先级”->“WifiNative.saveConfigCommand()”->“enableNetworkWithoutBroadcast(netId, true);”->“WifiNative.reconnectCommand()”->“通过广播判断连接成功或失败”。

    既然connectNetwork的执行步骤现在清楚了,那我们自己实现它便可以完成WIFI的手动连接了,

    代码编写

    WIFI密码破解器的编写有三种思路:

    第一种就是上面说的自己动手实现connectNetwork,按照SDK中常规步骤连接WIFI,本文采用此方法。

    第二种就是参看WIFI的连接代码,通过NDK方式自己实现WIFI底层操作的调用,这种方法本文不介绍。

    第三种方法同样通过NDK方式,但优雅些。在上面的分析中,我没有提到安卓WIFI的核心wpa_supplicant,它作为安卓WIFI的一个组件存在,为安卓系统提供了WPA、WPA2等加密网络的连接支持。在手机系统的“/system/bin”目录中,有“wpa_supplicant”与“wpa_cli”两个文件,前者是一个服务,客户端通过它控制手机无线网卡,如发送AP扫描指令、提取扫描结果、关联AP操作等。后者是一个命令行工具,用来与wpa_supplicant通信,在正常启动wpa_supplicant服务后执行下面的指令便可以连接上WIFI网络:

    wpa_cli -iwlan0 add_network                  // 增加一个网络,会返回一个网络号,假设为1

    wpa_cli -iwlan0 set_network 1 ssid '"……"'   //ssid为要连接的网络名

    wpa_cli -iwlan0 set_network 1 psk '"……"'               //psk为连接的密码

    wpa_cli -iwlan0 enable_network 1                            //以下三条与上面connectNetwork分析功能一致

    wpa_cli -iwlan0 select_network 1

    wpa_cli -iwlan0 save_config

    但实际上,通过命令行启动wpa_supplicant却不能成功,因为需要先加载WIFI驱动,然后才能启用wpa_supplicant服务。在手机WLAN设置中启用WIFI后,会调用WifiManager.setWifiEnabled,这个方法会依次调用WifiNative.loadDriver()->WifiNative.startSupplicant()。在加载成功后会设置一个延迟时间,到延迟时间后就会调用WifiNative.stopSupplicant()->WifiNative.unloadDriver()停止wpa_supplicant服务并卸载驱动,这是为了给设备省电,因为WIFI驱动长时间加载可是很耗电的。

    命令行本身无法直接加载驱动,导致了wpa_supplicant无法成功开启,这也是无法通过命令行直接连接WIFI的原因,但并不是没有突破方法!可以写代码并使用NDK方式调用WifiNative.loadDriver(),接着启用wpa_supplicant服务,服务加载成功后执行上面的wpa_cli命令行,就可以轻松连接WIFI了。可以直接写一个原生的bin,实现驱动加载及WIFI连接,然后在安卓代码中直接以创建进程的方式启动或者在shell中执行等方式运行。这些方法都具有可行性,本文不做深入探讨,只采用文中介绍的第一种方法来完成程序的功能。

    目前WIFI加密种类常用的有WEP、WPA、WPA2、EAP等,WifiManager将WEP与EAP做了内部消化,WPA与WPA2则使用wpa_supplicant进行管理,目前,由于WEP的安全性问题,使用的人已经不多了,一般用户采用WPA与WPA2方式接入较多,在今天的程序中,也只处理了这两种加密的情况。

    按照上面的分析思路,代码实现应该很明了了,但实际编码过程中还是存在着诸多问题,首先是停止扫描的问题,在WifiManager中没有提供stopScan()方法,而是在其中通过一个内部继承自Handler的SCanner来管理,目前来说,我没想到解决方案,在开始破解跑WIFI密码的过程中,WIFI扫描线程一直还是开着,我只是通过一个cracking的布尔值判断来阻止界面的更新,这个问题可能在SDK层无法得到解决。第二个问题是一些类的枚举值,如SupplicantState.AUTHENTICATING、KeyMgmt.WPA2_PSK等在SDK中都是没导出的,要想使用就需要自己添加。谈到WPA2_PSK,很有必要讲一下WifiConfiguration类的构造,连接WIFI前需要先构造这个类,然后通过addNetwork()添加网络操作后才能进行下一步的连接,在网上搜索到的连接代码如下:

    ......

    mConfig = new WifiConfiguration();

    mConfig.status = WifiConfiguration.Status.ENABLED;

    mConfig.hiddenSSID = false;

    mConfig.SSID = "\"ssid\"";

    mConfig.preSharedKey = "\"password\"";

    mConfig.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);

    mConfig.allowedKeyManagement.set(KeyMgmt.WPA_PSK);

    mConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);

    mConfig.allowedPairwiseCiphers.set(PairwiseCipher.CCMP);

    mConfig.allowedPairwiseCiphers.set(PairwiseCipher.TKIP);

    mConfig.allowedGroupCiphers.set(GroupCipher.CCMP);

    mConfig.allowedGroupCiphers.set(GroupCipher.TKIP);

    Int netid = wm.addNetwork(mConfig);

    wm.enableNetwork(netid, false);

    ......

    在测试初期我是直接搬这代码来用的,实际上这代码是废的,根本连接不上任何的WIFI,状态代码显示一直停留在关联AP中,而且这样设置WifiConfiguration后在手机设置中也无法开启使用WIFI了,当时我也很纳闷,你都不能用的代码,怎么还在网上好多篇帖子里乱窜?后来跟踪WIFI连接的过程后,整理出的代码如下:

    ......

    if (security == SECURITY_PSK) {

    mConfig = new WifiConfiguration();

    mConfig.SSID = AccessPoint.convertToQuotedString(ssid);

    if (pskType == PskType.WPA) {

    mConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);

    }

    else if (pskType == PskType.WPA2) {

    mConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);

    }

    mConfig.priority = 1;

    mConfig.status = WifiConfiguration.Status.ENABLED;

    mConfig.SSID = "\"ssid\"";

    mConfig.preSharedKey = "\"password\"";

    Int netid = wm.addNetwork(mConfig);

    wm.enableNetwork(netid, false);

    ......

    代码比上面的要简洁些,这不该有的东西啊你坚决不能有!

    启动Eclipse新建一个WIFICracker的工程,OnCreate()方法代码如下:

    public void onCreate(Bundle savedInstanceState) {

    public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    try {

    passwordGetter = new PasswordGetter("/sdcard/password.txt");

    } catch (FileNotFoundException e) {

    showMessageDialog("程序初始化失败", "请将密码字典放到SD卡目录并更名为password.txt", "确定",

    false, new OnClickListener() {

    public void onClick(DialogInterface dialog, int which) {

    WIFICracker.this.finish();

    }

    });

    }

    wm = (WifiManager) getSystemService(WIFI_SERVICE);

    if(!wm.isWifiEnabled())

    wm.setWifiEnabled(true);   //开启WIFI

     

    deleteSavedConfigs();

    cracking = false;

    netid = -1;

     

    wifiReceiver = new WifiReceiver();

    intentFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);

    intentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);

    registerReceiver(wifiReceiver, intentFilter);

     

    wm.startScan(); //开始扫描网络

    }

    deleteSavedConfigs()方法将手机已存的Config中全部删除,原因是因为如果已经保存了正确的WIFI连接密码,程序运行会无法工作,具体代码参看附件。然后构造一个PasswordGetter对象,它用来读取"/sdcard/password.txt"文件每一行作为WIFI的探测密码,类的完整代码如下:

    public class PasswordGetter {

    private String password;

    private File file;

    private FileReader reader;

    private BufferedReader br;

     

    public PasswordGetter(String passwordFile){

    password = null;

    try {

    //File file = new File("/sdcard/password.txt");

    file = new File(passwordFile);

    if (!file.exists())

    throw new FileNotFoundException();

    reader = new FileReader(file);

    br = new BufferedReader(reader);

     

    } catch (FileNotFoundException e) {

    e.printStackTrace();

    }

    }

     

    public void reSet(){

    try {

    br.close();

    reader.close();

    reader = new FileReader(file);

    br = new BufferedReader(reader);

    } catch (IOException e) {

    e.printStackTrace();

    password = null;

    }

    }

     

    public String getPassword(){

    try {

    password = br.readLine();

    } catch (IOException e) {

    e.printStackTrace();

    password = null;

    }

    return password;

    }

     

    public void Clean(){

    try {

    br.close();

    reader.close();

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    }

    这个类很简单,具体代码就不分析了,为了方便配置与加载WifiConfiguration,我将安卓源码中的AccessPoint类进行了部分改装后用到程序中,这样可以节省很多时间。

    程序的核心在于对WIFI状态的控制与连接,前者我使用了广播接收者进行监听,在收到广播后进行相应处理,代码如下:

    class WifiReceiver extends BroadcastReceiver {

    @Override

    public void onReceive(Context context, Intent intent) {

    String action = intent.getAction();

    if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) {

    if (results == null)   //只初始化一次

    results = wm.getScanResults();

    try {

    setTitle("WIFI连接点个数为:"

    + String.valueOf(getPreferenceScreen().getPreferenceCount()));

    } catch (Exception e) {

    e.printStackTrace();

    }

    if( cracking == false) //破解WIFI密码时不更新界面

    update();

    } else if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(action)) {

    WifiInfo info = wm.getConnectionInfo();

    SupplicantState state = info.getSupplicantState();

    String str = null;

    if (state == SupplicantState.ASSOCIATED){

    str = "关联AP完成";

    } else if(state.toString().equals("AUTHENTICATING")){

    str = "正在验证";

    } else if (state == SupplicantState.ASSOCIATING){

    str = "正在关联AP...";

    } else if (state == SupplicantState.COMPLETED){

    if(cracking) {

    cracking = false;

    showMessageDialog("恭喜您,密码跑出来了!", "密码为:"

    + AccessPoint.removeDoubleQuotes(password),

    "确定", false, new OnClickListener(){

    public void onClick(DialogInterface dialog, int which) {

    wm.disconnect();

    enablePreferenceScreens(true);

    }

    });

    cracking = false;

    return;

    } else

    str = "已连接";

    } else if (state == SupplicantState.DISCONNECTED){

    str = "已断开";

    } else if (state == SupplicantState.DORMANT){

    str = "暂停活动";

    } else if (state == SupplicantState.FOUR_WAY_HANDSHAKE){

    str = "四路握手中...";

    } else if (state == SupplicantState.GROUP_HANDSHAKE){

    str = "GROUP_HANDSHAKE";

    } else if (state == SupplicantState.INACTIVE){

    str = "休眠中...";

    if (cracking) connectNetwork(); //连接网络

    } else if (state == SupplicantState.INVALID){

    str = "无效";

    } else if (state == SupplicantState.SCANNING){

    str = "扫描中...";

    } else if (state == SupplicantState.UNINITIALIZED){

    str = "未初始化";

    }

    setTitle(str);

    final int errorCode = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);

    if (errorCode == WifiManager.ERROR_AUTHENTICATING) {

    Log.d(TAG, "WIFI验证失败!");

    setTitle("WIFI验证失败!");

    if( cracking == true)

    connectNetwork();

    }

    }

    }

    }

    这些代码的实现一部分源于查看SDK后的测试,另一部分源于跟踪安卓源码时的摘录。如这段:

    final int errorCode = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);

    if (errorCode == WifiManager.ERROR_AUTHENTICATING) {

    Log.d(TAG, "WIFI验证失败!");

    setTitle("WIFI验证失败!");

    if( cracking == true)

    connectNetwork();

    }

    不查看安卓源码,你根本不会知道怎么检测WifiManager.ERROR_AUTHENTICATING,这让我在写测试代码时也着实苦恼了一段时间。好了,代码就分析到这里,回想一下,网上为什么没有这样的软件也知道原因了,因为SDK中没有提供相应的WIFI连接接口,要想实现就必须要深入研究这块,因此,太多人觉得过于繁琐也就没弄了。

    最后,测试了一下效果,一分钟大概能跑20个密码,上个跑密码截图:

     

    安卓WIFI密码破解工具编写初探

     

    转载:http://www.u9vip.com/743.html点击打开链接
    展开全文
  • 目前,在无线监控、工业控制、视频传输等行业应用中,嵌入式无线系统主要采用以NORDIC解决方案为代表的无操作系统环境,该方案由“CPU+无线数传模块”构成,能够实现短距离低带宽无线通信。
  • WIFI原理总结_cdh

    2011-07-19 11:42:04
    基于linux。android软件平台qualcomm硬件平台中WIFI开发总结。
  • WIFI原理,WIFI6各代介绍 2020-11-23

    千次阅读 2020-11-23 10:38:30
    “Wi-Fi”常被写成“WiFi”或“Wifi”,但是这些写法并没有被Wi-Fi联盟认可。 Wi-Fi产品经由Wi-Fi联盟的一家独立授权测试实验室进行严格测试,产品成功通过测试后,授予制造商或销售商使用Wi-Fi标志、Wi-Fi ...
  • WIFI从界面启动到WPA_SUPPLICANCT 的整体流程。。结合代码比较详细
  • 虽然该博客有点老,但是对于WiFi的学习来讲还是非常值得借鉴的wifi相关的文件位置:WIFI Settings应用程序位于 packages/apps/Settings/src/com/android/settings/wifi/JAVA部分: frameworks/base/services/java/...
  • 最新最全的wifi开发与应用技术 WiFi与IEEE 802.11
  • 自备WiFi模块对目标WiFi进行Deauth攻击,连接了目标WiFi的机器全部断开网络。(图取自网络)2.将自备的WiFi模块的名字改成目标WiFi同名,并上传自备WiFi模块一个Web,WiFi Web即你自己设计一个192.168.1.1登陆界面,...
  • 目前,在无线监控、工业控制、视频传输等行业应用中,嵌入式无线系统主要采用以NORDIC解决方案为代表的无操作系统环境,该方案由“CPU+无线数传模块”构成,能够实现短距离低带宽无线通信。但由于窄带无线通信的技术...
  • 在网上找的一篇好文章,分析的很详细,自己再加了些...wifi相关的文件位置: WIFI Settings应用程序位于 packages/apps/Settings/src/com/android/settings/wifi/ JAVA部分: frameworks/base/services/java...
  • android中wifi原理及流程分析(很经典)

    千次阅读 2018-05-07 21:37:48
    在网上找的一篇好文章,分析的很详细,自己再加了...wifi相关的文件位置:WIFI Settings应用程序位于 packages/apps/Settings/src/com/android/settings/wifi/JAVA部分: frameworks/base/services/java/com/andro...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,595
精华内容 1,038
关键字:

wifi原理