Android 4.0 WIFI初始化与启动流程

这几天闲着没事,我就随便拿起Android源码看看。以下要讲的是在ICS中wifi初始化的一些流程。

涉及的文件有:

SystemServer.java

WifiSettings.java

WifiEnabler.java

WifiManager.java

WifiService.java

WifiStateMachine.java

android_net_wifi_wifi.cpp

wifi.c


首先从SystemServer.java开始,它做了3个动作:

1.添加注册ConnectivityService连接服务,它跟所有手机的无线通信都有联系,包括wifi,蓝牙,2g网络,3g网络等

connectivity = new ConnectivityService(
                       context, networkManagement, networkStats, networkPolicy);
ServiceManager.addService(Context.CONNECTIVITY_SERVICE,connectivity);

2.管理开机wifi开启与否的问题

wifi.checkAndStartWifi();

    public voidcheckAndStartWifi() {
       mAirplaneModeOn.set(isAirplaneModeOn());
       mPersistWifiState.set(getPersistedWifiState());
       boolean wifiEnabled = shouldWifiBeEnabled() ||testAndClearWifiSavedState();
       setWifiEnabled(wifiEnabled);
       mWifiWatchdogStateMachine = WifiWatchdogStateMachine.
              makeWifiWatchdogStateMachine(mContext);

    }


3.添加注册wifi的核心服务wifiservice

 wifi = new WifiService(context);
 ServiceManager.addService(Context.WIFI_SERVICE,wifi);

好了,机器启动的时候动作就这些。要开启wifi,还需要人在设置界面进行开启。·

下面将一步步介绍wifi是怎样开启起来的

进入wifi设置界面,相关文件WifiSettings.java

开启Wifi的组件是一个CompoundButton,跟它关联起来的是一个WifiEnabler.java类,它是在WifiSettings里面初始化的

    public voidonActivityCreated(Bundle savedInstanceState) {
               mWifiEnabler = new WifiEnabler(activity, actionBarSwitch);

    }

当用户点击wifi的开启按钮时候,会触发WifiEnabler里面的onCheckedChanged函数

    public voidonCheckedChanged(CompoundButton buttonView, boolean isChecked){

       if (mWifiManager.setWifiEnabled(isChecked)) {
           mSwitch.setEnabled(false);
        } else {
              Toast.makeText(mContext, R.string.wifi_error,Toast.LENGTH_SHORT).show();
    }

在onCheckedChanged函数里面,调用了WifiManager的setWifiEnabled方法

    publicboolean setWifiEnabled(boolean enabled) {
       try {
           return mService.setWifiEnabled(enabled);
       } catch (RemoteException e) {
           return false;
       }
    }

它返回的是mService.setWifiEnabled(enabled),这里的mService是WifiService的代理,所以它实际调用的是wifiService里面的setWifiEnabled函数

public class WifiService extends IWifiManager.Stub,我们可以看到WifiService继承一个接口IWifiManager.Stub,凡是继承了像这种形式写法的接口服务,都可以进行远程调用,这就是Android内部的aidl通信。接下来进入wifiservice

    publicsynchronized boolean setWifiEnabled(boolean enable) {

       mWifiStateMachine.setWifiEnabled(enable);

    }

可以看到,又进入WifiStateMachine的setWifiEnabled方法,mWifiStateMachine是在Wifiservice的构造函数完成初始化的

   WifiService(Context context) {

       mWifiStateMachine = new WifiStateMachine(mContext,mInterfaceName);

    }

先介绍一下WifiStateMachine这个类,光看名字就知道wifi状态机,它里面记录了wifi的各种状态,driverUnloadedstate、mDriverUnloadingState、mDriverLoadingState、mDriverLoadedState、mSupplicantStartingState,每种状态都有enter()、exit()、processMessage()3个函数,分别处理进入该状态,退出该状态的动作,以及消息处理。在WifiStateMachine构造函数里面,它把所有状态都添加进状态机去,形成一个状态树,并在结尾出启动这个状态机工作。

    publicWifiStateMachine(Context context, String wlanInterface) {

       addState(mDefaultState);
           addState(mInitialState, mDefaultState);
           addState(mDriverUnloadingState, mDefaultState);
           addState(mDriverUnloadedState, mDefaultState);
               addState(mDriverFailedState, mDriverUnloadedState);
           addState(mDriverLoadingState, mDefaultState);
           addState(mDriverLoadedState, mDefaultState);
           addState(mSupplicantStartingState, mDefaultState);
           addState(mSupplicantStartedState, mDefaultState);
               addState(mDriverStartingState, mSupplicantStartedState);
               addState(mDriverStartedState, mSupplicantStartedState);
                   addState(mScanModeState, mDriverStartedState);
                   addState(mConnectModeState, mDriverStartedState);
                       addState(mConnectingState, mConnectModeState);
                       addState(mConnectedState, mConnectModeState);
                       addState(mDisconnectingState, mConnectModeState);
                       addState(mDisconnectedState, mConnectModeState);
                       addState(mWaitForWpsCompletionState, mConnectModeState);
               addState(mDriverStoppingState, mSupplicantStartedState);
               addState(mDriverStoppedState, mSupplicantStartedState);
           addState(mSupplicantStoppingState, mDefaultState);
           addState(mSoftApStartingState, mDefaultState);
           addState(mSoftApStartedState, mDefaultState);
               addState(mTetheringState, mSoftApStartedState);
               addState(mTetheredState, mSoftApStartedState);
           addState(mSoftApStoppingState, mDefaultState);
           addState(mWaitForP2pDisableState, mDefaultState);

   。。。。。。。。。。

        start();

    }

具体状态机是如何工作的,这篇文章有很详细的介绍,我就不累赘了。

http://archive.cnblogs.com/a/2424626/

我们再回到mWifiStateMachine.setWifiEnabled(enable)函数;

   public void setWifiEnabled(boolean enable) {
       mLastEnableUid.set(Binder.getCallingUid());
       if (enable) {
           
           sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING,0));
           sendMessage(CMD_START_SUPPLICANT);
       } else {
           sendMessage(CMD_STOP_SUPPLICANT);
           
           sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_DISABLED,0));
       }
    }

它做了两个动作,向状态机发送了2个消息

sendMessage(obtainMessage(CMD_LOAD_DRIVER,WIFI_STATE_ENABLING, 0));加载驱动

sendMessage(CMD_START_SUPPLICANT);开启supplicant

它在哪里处理的呢?

状态机构造函数初始化时候,设置有个一个初始状态

       setInitialState(mInitialState);

我们进入mInitialState状态看看

       public void enter() {
           if (WifiNative.isDriverLoaded()) {
               transitionTo(mDriverLoadedState);
           }
           else {
               transitionTo(mDriverUnloadedState);
           }
因为最开始驱动都是没有加载的,所以进入transitionTo(mDriverUnloadedState);

transitionTo函数是状态切换的函数。

继续mDriverUnloadedState

    classDriverUnloadedState extends State {
        @Override
       public boolean processMessage(Message message) {
             switch (message.what) {
               case CMD_LOAD_DRIVER:
                   mWifiP2pChannel.sendMessage(WIFI_ENABLE_PENDING);
                   transitionTo(mWaitForP2pDisableState);
                   break;
               case WifiP2pService.P2P_ENABLE_PENDING:
                   mReplyChannel.replyToMessage(message, P2P_ENABLE_PROCEED);
                   break;
               default:
                   return NOT_HANDLED;
           }
           EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED,message.what);
           return HANDLED;
       }
    }

这里会处理刚才的CMD_LOAD_DRIVER这个消息,继续切换到mWaitForP2pDisableState

    classWaitForP2pDisableState extends State {
       @Override
       public boolean processMessage(Message message) {
           if (DBG) log(getName() + message.toString() + "\n");
           switch(message.what) {
               case WifiP2pService.WIFI_ENABLE_PROCEED:
                   //restore argument from original message (CMD_LOAD_DRIVER)
                   message.arg1 = mSavedArg;
                   transitionTo(mDriverLoadingState);

                   break;

    }

状态继续切换到mDriverLoadingState

    classDriverLoadingState extends State {
       @Override
       public void enter() {
 
           new Thread(new Runnable() {
               public void run() {
                   mWakeLock.acquire();
                   //enabling state
                   switch(message.arg1) {
                       case WIFI_STATE_ENABLING:
                           setWifiState(WIFI_STATE_ENABLING);
                           break;
                       case WIFI_AP_STATE_ENABLING:
                           setWifiApState(WIFI_AP_STATE_ENABLING);
                           break;
                   }

                   if(WifiNative.loadDriver()) {
                       if (DBG) log("Driver load successful");
                       sendMessage(CMD_LOAD_DRIVER_SUCCESS);
                   } else {
                       loge("Failed to load driver!");
                       switch(message.arg1) {
                           case WIFI_STATE_ENABLING:
                               setWifiState(WIFI_STATE_UNKNOWN);
                               break;
                           case WIFI_AP_STATE_ENABLING:
                               setWifiApState(WIFI_AP_STATE_FAILED);
                               break;
                       }
                       sendMessage(CMD_LOAD_DRIVER_FAILURE);
                   }
                   mWakeLock.release();
               }
           }).start();
       }

这里回调用WifiNative.loadDriver()加载驱动,成功后发送消息CMD_LOAD_DRIVER_SUCCESS,否则CMD_LOAD_DRIVER_FAILURE,进入JNI

static jboolean android_net_wifi_loadDriver(JNIEnv* env,jobject)
{
    return(jboolean)(::wifi_load_driver() == 0);
}

会继续到wifi.c处理

int wifi_load_driver()
{
#ifdef WIFI_DRIVER_MODULE_PATH
    chardriver_status[PROPERTY_VALUE_MAX];
    int count =100;
    int status =-1;

    if(is_wifi_driver_loaded()) {
       return 0;
    }
   
    if(ensure_wlan_driver_config_file_exists()) {
       return -1;
    }
   property_set(DRIVER_PROP_NAME, "loading");

   if(system(SDIO_POLLING_ON))
       LOGW("Couldn't turn on SDIO polling: %s", SDIO_POLLING_ON);

    if ('\0' !=*DRIVER_SDIO_IF_MODULE_PATH) {
      if (insmod(DRIVER_SDIO_IF_MODULE_PATH, DRIVER_SDIO_IF_MODULE_ARG)< 0) {
          goto end;
      }
    }

    if(insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) {
       if ('\0' != *DRIVER_SDIO_IF_MODULE_NAME) {
          rmmod(DRIVER_SDIO_IF_MODULE_NAME);
       }
       goto end;
    }

    if(strcmp(FIRMWARE_LOADER,"") == 0) {
       
       property_set(DRIVER_PROP_NAME, "ok");
    }
    else {
       property_set("ctl.start", FIRMWARE_LOADER);
    }

   sched_yield();
    while(count-- > 0) {
       if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) {
           if (strcmp(driver_status, "ok") == 0) {
               status = 0;
               goto end;
           }
           else if (strcmp(driver_status, "failed") == 0) {
               _wifi_unload_driver();
               goto end;
           }
       }
       usleep(200000);
    }
   property_set(DRIVER_PROP_NAME, "timeout");
   wifi_unload_driver();
end:
   system(SDIO_POLLING_OFF);
    returnstatus;
#else
   property_set(DRIVER_PROP_NAME, "ok");
    return0;
#endif
}

这里有几个比较重要的宏

#defineWIFI_DRIVER_MODULE_PATH        "/system/lib/modules/wlan.ko"驱动模块地址

static const charSUPP_CONFIG_FILE[]   = "/data/misc/wifi/wpa_supplicant.conf"; supplicant配置文件

在这里wifi.c会跟wpa_supplicant通信,加载驱动


来看另一个消息sendMessage(CMD_START_SUPPLICANT);在DriverLoadedState处理

    classDriverLoadedState extends State {
       @Override
       public boolean processMessage(Message message) {
         
               case CMD_START_SUPPLICANT:
                   try {
                       mNwService.wifiFirmwareReload(mInterfaceName, "STA");
                   } catch (Exception e) {
                       loge("Failed to reload STA firmware " + e);
                       // continue
                   }
                  try {
                        mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName,true);
                   } catch (RemoteException re) {
                       loge("Unable to change interface settings: " + re);
                   } catch (IllegalStateException ie) {
                       loge("Unable to change interface settings: " + ie);
                   }

                   if(WifiNative.startSupplicant()) {
                       if (DBG) log("Supplicant start successful");
                       mWifiMonitor.startMonitoring();
                       transitionTo(mSupplicantStartingState);
                   } else {
                       loge("Failed to start supplicant!");
                       sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN,0));
                   }
                   break;


继续调用JNI,WifiNative.startSupplicant(),过程差不多最后在wifi.c处理

int wifi_start_supplicant()
{
    returnwifi_start_supplicant_common(SUPP_CONFIG_FILE);
}

int wifi_start_supplicant_common(const char *config_file)

。。。。。。。

最后也是在这里跟Wpa_supplicant驱动通信

在wifi状态发生改变的时候,wifistatemachine会通过setwifistate发送WIFI_STATE_CHANGED_ACTION消息通知外面

    private voidsetWifiState(int wifiState) {

       final Intent intent = newIntent(WifiManager.WIFI_STATE_CHANGED_ACTION);
       intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
       intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState);
       intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE,previousWifiState);
       mContext.sendStickyBroadcast(intent);

}


例如在驱动加载状态

    classDriverLoadingState extends State {

           new Thread(new Runnable() {
               public void run() {
                   mWakeLock.acquire();
                   //enabling state
                   switch(message.arg1) {
                       case WIFI_STATE_ENABLING:
                           setWifiState(WIFI_STATE_ENABLING);
                           break;
                       case WIFI_AP_STATE_ENABLING:
                           setWifiApState(WIFI_AP_STATE_ENABLING);
                           break;
                   }

    }


    classSupplicantStartingState extends State {

       public boolean processMessage(Message message) {
           if (DBG) log(getName() + message.toString() + "\n");
           switch(message.what) {
               case WifiMonitor.SUP_CONNECTION_EVENT:
                   if (DBG) log("Supplicant connection established");
                   setWifiState(WIFI_STATE_ENABLED);

   }


在wifisettings里面也有广播监听器

    publicWifiSettings() {
       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();
    }

当接受到广播会相应处理handleEvent

    private voidhandleEvent(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));
       }
    }


更新wifi状态

    private voidupdateWifiState(int state) {
       getActivity().invalidateOptionsMenu();

       switch (state) {
           case WifiManager.WIFI_STATE_ENABLED:
               mScanner.resume();
               return; // not break, to avoid the call to pause() below

           case WifiManager.WIFI_STATE_ENABLING:
               addMessagePreference(R.string.wifi_starting);
               break;

           case WifiManager.WIFI_STATE_DISABLED:
               addMessagePreference(R.string.wifi_empty_list_wifi_off);
               break;
       }

       mLastInfo = null;
       mLastState = null;
       mScanner.pause();
    }

       比如 case WifiManager.WIFI_STATE_ENABLED:当WIFI可用通知接受到的时候
               mScanner.resume();

Scanner resume函数

       void resume() {
           if (!hasMessages(0)) {
               sendEmptyMessage(0);
           }
       }

再看处理

       @Override
       public void handleMessage(Message message) {
           if (mWifiManager.startScanActive()) {
               mRetry = 0;
           } else if (++mRetry >= 3) {
               mRetry = 0;
               Toast.makeText(getActivity(), R.string.wifi_fail_to_scan,
                       Toast.LENGTH_LONG).show();
               return;
           }
           sendEmptyMessageDelayed(0, WIFI_RESCAN_INTERVAL_MS);
       }
    }

会调用mWifiManager.startScanActive()进行ap的扫描

所以当你点击wifi按钮,到驱动加载完成,发出WIFI_STATE_ENABLED消息的时候,

设置里面会进行扫描ap的动作


原文:http://blog.sina.com.cn/s/blog_67e1c5cc0101tpba.html

你可能感兴趣的:(Android 4.0 WIFI初始化与启动流程)