您的位置:首页 > 移动开发 > Android开发

android中wifi原理及流程分析

2012-03-26 11:39 363 查看
在网上找的一篇好文章,分析的很详细,自己再加了些东西,图片有点大,不能完全显示,点击图像拖动鼠标直接查看图像。

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地址的配置

流程如图:



到此结束
 
From : http://blog.csdn.net/lbmygf/article/details/6599511
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息