Android4.0 无线网络代码分析

Android网络分析之WIFI 模块  

张国良 2012-9-17

序:

Android 是一种基于 Linux® V2.6/3.0 内核的综合操作环境。从开发人员角度看,ANDROID是一个大型应用程序,将各种开源项目的应用组织在一起,整合成了一个有综合功能的系统。

系统启动:

上电启动,Fastboot会加载kernel到内存,并跳转到kernel运行,调用脚本init.rc,创建系统运行的各种环境变量,接着创建各种文件系统,挂载点,挂载。启动守护进程Daemons 等,然后启动第一个虚拟机Zygote

启动代码详见:init.rc

vim device/hisilicon/godbox/etc/init.rc

service zygote /system/bin/app_process-Xzygote /system/bin --zygote --start-system-server

    class main

    socket zygote stream 666

    onrestart write/sys/android_power/request_state wake

    onrestart write/sys/power/state on

    onrestart restart media

    onrestart restart camera

    onrestart restart netd

app_process:app_main函数初始化虚拟机

app_main.cpp(frameworks\base\cmds\app_process)  5394     2012-8-26

if (zygote) {

       runtime.start("com.android.internal.os.ZygoteInit",

               startSystemServer ? "start-system-server" :"");

    }

调用ZygoteInit.java(frameworks\base\core\java\com\android\internal\os)      27111   2012-8-26

。。。 

          if (argv[1].equals("start-system-server")) {

               startSystemServer();

           }

第一步: 初始化

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

具体启动流程如下:

SystemServer.java (frameworks\base\services\java\com\android\server)

class ServerThread extends Thread {

    private static final String TAG= "SystemServer";

....

 

           try{

               Slog.i(TAG, "Wi-Fi P2pService");

               wifiP2p = new WifiP2pService(context);

               ServiceManager.addService(Context.WIFI_P2P_SERVICE, wifiP2p);

            }catch (Throwable e) {

               reportWtf("starting Wi-Fi P2pService", e);

            }

创建WifiService

           try{

               Slog.i(TAG, "Wi-Fi Service");

               wifi = new WifiService(context);

               ServiceManager.addService(Context.WIFI_SERVICE, wifi);

            }catch (Throwable e) {

               reportWtf("starting Wi-Fi Service", e);

            }

 

            try{

               Slog.i(TAG, "Ethernet Service");

               ethernet = new EthernetService(context);

               ServiceManager.addService(Context.ETHERNET_SERVICE, ethernet);

            }catch (Throwable e) {

               reportWtf("starting ETHERNET Service", e);

            }

       Slog.i(TAG, "11111");

 

       try {

               Slog.i(TAG, "Pppoe Service aaa");

               pppoe = new PppoeService(context);

               ServiceManager.addService(Context.PPPOE_SERVICE, pppoe);

            }catch (Throwable e) {

               reportWtf("starting ETHERNET Service", e);

            }

启动连接管理服务:

            try{

               Slog.i(TAG, "Connectivity Service");

               connectivity = new ConnectivityService(

                       context, networkManagement,networkStats, networkPolicy);

               ServiceManager.addService(Context.CONNECTIVITY_SERVICE,connectivity);

               networkStats.bindConnectivityManager(connectivity);

               networkPolicy.bindConnectivityManager(connectivity);

               ethernet.checkAndStartEthernet();

               wifi.checkAndStartWifi();

               wifiP2p.connectivityServiceReady();

            }catch (Throwable e) {

               reportWtf("starting Connectivity Service", e);

            }

 

.....

======= WifiService ===================================

在:WifiService 实例化的过程中,其构造函数 WifiService 中启动 WifiStateMachine 

    WifiService(Context context){

        mContext =context;

 

        mInterfaceName=  SystemProperties.get("wifi.interface", "wlan0");

 

       mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName);

       mWifiStateMachine.enableRssiPolling(true);

        mBatteryStats= BatteryStatsService.getService();

......

 

在类WifiStateMachine的构造函数WifiStateMachine 中开启WifiMonitor实例

 public WifiStateMachine(Contextcontext, String wlanInterface) {

        super(TAG);

 mWifiMonitor = new WifiMonitor(this);

。。。。

}

BTW:当用户使能wifi,wifi sta的驱动加载时class DriverLoadedState ,会启动

。。。。。

                    if(WifiNative.startSupplicant()) {

                       if (DBG) log("Supplicant startsuccessful and starting Monitoring");

                       mWifiMonitor.startMonitoring();

                       transitionTo(mSupplicantStartingState);

                   } else {

                       loge("Failed to startsupplicant!");

                      sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0));

                   }

                   break;

startMonitoring:作用监控wpa_supplicant的消息并实时作出处理。

Listens for events from the wpa_supplicantserver, and passes them on to the {@link StateMachine} for handling. Runs inits own thread.专门负责接收来自wpa_supplicant的事件,并将这些消息进行分类再交予StateMachine处理。

在WifiStateMachine里面的内部类DriverLoadedState中启动wpa_supplicant之后调用了WifiMonitor的startMonitor()方法。该方法开启了一个新的线程MonitorThread,接受来自wpa_supplicant的事件。

========= ConnectivityService======================

ConnectivityService 的作用:创建一系列的Tracker,监控各种网络接口的变化

 

 

ConnectivityService.java(frameworks\base\services\java\com\android\server)     

    

   privateConnectivityService(Context context) {

        if (DBG)Slog.v(TAG, "ConnectivityService starting up");

。。。。

    /*

         * Createthe network state trackers for Wi-Fi and mobile

         * data.Maybe this could be done with a factory class,

         * butit's not clear that it's worth it, given that

         * thenumber of different network types is not going

         * tochange very often.

         */

        for (int netType: mPriorityList) {

           switch (mNetConfigs[netType].radio) {

           case ConnectivityManager.TYPE_WIFI:

               mNetTrackers[netType] = new WifiStateTracker(netType,

                       mNetConfigs[netType].name);

               mNetTrackers[netType].startMonitoring(context, mHandler);

              break;

           case ConnectivityManager.TYPE_MOBILE:

               mNetTrackers[netType] = new MobileDataStateTracker(netType,

                       mNetConfigs[netType].name);

               mNetTrackers[netType].startMonitoring(context, mHandler);

               break;

           case ConnectivityManager.TYPE_DUMMY:

               mNetTrackers[netType] = new DummyDataStateTracker(netType,

                       mNetConfigs[netType].name);

               mNetTrackers[netType].startMonitoring(context, mHandler);

               break;

           case ConnectivityManager.TYPE_BLUETOOTH:

               mNetTrackers[netType] = BluetoothTetheringDataTracker.getInstance();

               mNetTrackers[netType].startMonitoring(context, mHandler);

               break;

           case ConnectivityManager.TYPE_WIMAX:

               mNetTrackers[netType] = makeWimaxStateTracker();

               if (mNetTrackers[netType]!= null) {

                   mNetTrackers[netType].startMonitoring(context,mHandler);

               }

               break;

           case ConnectivityManager.TYPE_ETHERNET:

               mNetTrackers[netType] = EthernetDataTracker.getInstance();

               mNetTrackers[netType].startMonitoring(context, mHandler);

               break;

          case ConnectivityManager.TYPE_PPPOE:

              loge("caoqf,come into TYPE_PPPOE!!!!!!!!!!!!!!!");

              mNetTrackers[netType]= PppoeStateTracker.getInstance();

              mNetTrackers[netType].startMonitoring(context,mHandler);

           default:

               loge("Trying to create a DataStateTracker for an unknownradio type " +

                       mNetConfigs[netType].radio);

               continue;

           }

           mCurrentLinkProperties[netType] = null;

           if (mNetTrackers[netType] != null && mNetConfigs[netType].isDefault()){

               mNetTrackers[netType].reconnect();

           }

        }

。。。

 

WifiStateTracker.java(frameworks\base\wifi\java\android\net\wifi)      97552   2012-7-3

WifiStateTracker :主要提供给WifiMonitor模块使用

其注册广播,用来监控NETWORK_STATE_CHANGED_ACTION

    /**

     * Begin monitoringwifi connectivity

     */

    public voidstartMonitoring(Context context, Handler target) {

        mCsHandler =target;

        mContext =context;

 

        mWifiManager =(WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);

        IntentFilterfilter = new IntentFilter();

       filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);

       filter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);

       filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);

 

       mWifiStateReceiver = new WifiStateReceiver();

        mContext.registerReceiver(mWifiStateReceiver,filter);

    }

 

总结:android4.0后期的wifi管理越来越偏重到WifiService 

WifiService 负责启动关闭wpa_supplicant、启动关闭WifiMonitor 监视线程

和把命令下发给wpa_supplicant,而WifiMonitor 则负责从wpa_supplicant 接收事件通知。

 

第二步:连接 AP

1.使能wifi

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

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

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

 

 public void onActivityCreated创建实例

{

.....

  mWifiEnabler = new WifiEnabler(activity, actionBarSwitch);

 

}

WifiEnabler的构造函数,获得mWifiManager,并添加广播包 捕获

    public WifiEnabler(Contextcontext, Switch switch_) {

        mContext =context;

        mSwitch =switch_;

 

        mWifiManager =(WifiManager) context.getSystemService(Context.WIFI_SERVICE);

        mIntentFilter= new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);

        // The ordermatters! We really should not depend on this. :(

       mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);

       mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);

    }

 

WifiEnabler 调用WifiManager 的接口函数,通过AIDL,实际调用的是WifiService 的setWifiEnabled

setWifiEnabled 函数。

 

WifiManager.java(frameworks\base\wifi\java\android\net\wifi)      45025   2012-5-10

 

    /**

     * Enable or disableWi-Fi.

     * @param enabled{@code true} to enable, {@code false} to disable.

     * @return {@code true}if the operation succeeds (or if the existing state

     *        is the same as the requested state).

     */

    public booleansetWifiEnabled(boolean enabled) {

        try {

           return mService.setWifiEnabled(enabled);

        } catch(RemoteException e) {

           return false;

        }

    }

WifiService.java (frameworks\base\services\java\com\android\server) 88448   2012-6-3

   

WifiService 接着向自身发送一条MESSAGE_ENABLE_WIFI 消息,在处理该消息的代码中做真正的使能工作:

   

  /**

     * see {@linkandroid.net.wifi.WifiManager#setWifiEnabled(boolean)}

     * @param enable {@codetrue} to enable, {@code false} to disable.

     * @return {@code true}if the enable/disable operation was

     *        started or is already in the queue.

     */

    public synchronized booleansetWifiEnabled(boolean enable) {

       enforceChangePermission();

        if (DBG) {

           Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n");

        }

 

        if (enable) {

           reportStartWorkSource();

        }

        mWifiStateMachine.setWifiEnabled(enable);

/* 检查,加载wifi驱动 */

        /*

         * Callermight not have WRITE_SECURE_SETTINGS,

         * onlyCHANGE_WIFI_STATE is enforced

         */

 

        /* Avoidsoverriding of airplane state when wifi is already in the expected state */

        if (enable !=mWifiEnabled) {

           long ident = Binder.clearCallingIdentity();

           persistWifiState(enable);

           Binder.restoreCallingIdentity(ident);

        }

 

        if (enable) {

           if (!mIsReceiverRegistered) {

               registerForBroadcasts();

               mIsReceiverRegistered = true;

           }

        } else if(mIsReceiverRegistered) {

           mContext.unregisterReceiver(mReceiver);

           mIsReceiverRegistered = false;

        }

 

        return true;

    }

 

 

使能wifi完成的功能:

首先装载WIFI 内核模块(该模块的位置硬编码为"/system/lib/modules/wlan.ko" ),

 然后启动wpa_supplicant ( 配置文件硬编码为"/data/misc/wifi/wpa_supplicant.conf"),

再通过WifiStateTracker 来启动WifiMonitor 中的监视线程。

以上功能有本文件中的私有函数privateboolean setWifiEnabledBlocking完成

代码:

       setWifiEnabledState(enable ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING, uid);

 

        if (enable) {

           if (!mWifiStateTracker.loadDriver()) {   //首先装载WIFI 内核模块

               Slog.e(TAG, "Failed to load Wi-Fi driver.");

               setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);

               return false;

           }

           if (!mWifiStateTracker.startSupplicant()) {

               mWifiStateTracker.unloadDriver();

               Slog.e(TAG, "Failed to start supplicant daemon.");

               setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);

               return false;

           }

 

           registerForBroadcasts();

           mWifiStateTracker.startEventLoop(); //来启动WifiMonitor 中的监视线程

 

        } else {

 

           //停止wifi

           。。。。

      }

当使能成功后,会广播发送WIFI_STATE_CHANGED_ACTION这个Intent 通知外界WIFI

已经成功使能了。WifiEnabler 创建的时候就会向Android 注册接收

WIFI_STATE_CHANGED_ACTION,因此它会收到该Intent,从而开始扫描。

 

2. 查找AP

 

  扫描的入口函数是WifiService 的startScan,它其实也就是往wpa_supplicant 发送SCAN 命令。

 

过程:

WifiService 调用native函数android_net_wifi_Wifi.cpp

android_net_wifi_Wifi.cpp(frameworks\base\core\jni) 23061   2012-5-10

static jbooleanandroid_net_wifi_scanCommand(JNIEnv* env, jobject clazz, jboolean forceActive)

{

    jboolean result;

 

    // Ignore any error from settingthe scan mode.

    // The scan will still work.

    if (forceActive &&!sScanModeActive)

       doSetScanMode(true);

    result =doBooleanCommand("SCAN", "OK"); //往wpa_supplicant 发送SCAN 命令

    if (forceActive &&!sScanModeActive)

        doSetScanMode(sScanModeActive);

    return result;

}

 

调用HAL层的接口与WPA进程通信,wifi的HAL层代码

wifi.c (hardware\libhardware_legacy\wifi)   20969   2012-5-10

 

3. 配置 AP 参数

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

 

4. 连接

当用户在 AcessPointDialog 中选择好加密方式和输入密钥之后,再点击连接按钮,Android

就会去连接这个AP

WifiLayer 会先检测这个AP 是不是之前被配置过,这个是通过向wpa_supplicant 发送

LIST_NETWORK 命令并且比较返回值来实现的。

 

5. 配置 IP 地址

当 wpa_supplicant 成功连接上AP 之后,它会向控制通道发送事件通知连接上AP 了,从而

wifi_wait_for_event 函数会接收到该事件,由此WifiMonitor 中的MonitorThread。

 


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值