设为首页 收藏本站
查看: 1407|回复: 0

[经验分享] Android 4.0 WIFI初始化与启动流程(转载)

[复制链接]

尚未签到

发表于 2015-10-2 08:37:10 | 显示全部楼层 |阅读模式
  http://blog.iyunv.com/dnfchan/article/details/7793695
  十分感谢原作者!
  =============================================================
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 void checkAndStartWifi() {
        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 void onActivityCreated(Bundle savedInstanceState) {
                mWifiEnabler = new WifiEnabler(activity, actionBarSwitch);
  }
  当用户点击wifi的开启按钮时候,会触发WifiEnabler里面的onCheckedChanged函数
  public void onCheckedChanged(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方法
  public boolean 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
  public synchronized 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构造函数里面,它把所有状态都添加进状态机去,形成一个状态树,并在结尾出启动这个状态机工作。
  public WifiStateMachine(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) {
            /* Argument is the state that is entered prior to load */
            sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING, 0));
            sendMessage(CMD_START_SUPPLICANT);
        } else {
            sendMessage(CMD_STOP_SUPPLICANT);
            /* Argument is the state that is entered upon success */
            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
  class DriverUnloadedState 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
  class WaitForP2pDisableState 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
  class DriverLoadingState 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
    char driver_status[PROPERTY_VALUE_MAX];
    int count = 100; /* wait at most 20 seconds for completion */
    int status = -1;
    if (is_wifi_driver_loaded()) {
        return 0;
    }
    /* ensure that wlan driver config file exists (if specified) */
    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) {
        /* usleep(WIFI_DRIVER_LOADER_DELAY); */
        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);
    return status;
#else
    property_set(DRIVER_PROP_NAME, "ok");
    return 0;
#endif
}
  这里有几个比较重要的宏
  #define WIFI_DRIVER_MODULE_PATH         "/system/lib/modules/wlan.ko"驱动模块地址
  static const char SUPP_CONFIG_FILE[]    = "/data/misc/wifi/wpa_supplicant.conf";  supplicant配置文件
  在这里wifi.c会跟wpa_supplicant通信,加载驱动
  
  来看另一个消息sendMessage(CMD_START_SUPPLICANT);在DriverLoadedState处理
  class DriverLoadedState 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()
{
    return wifi_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 void setWifiState(int wifiState) {
  final Intent intent = new Intent(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);
}
  
  例如在驱动加载状态
  class DriverLoadingState 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;
                    }
    }
  
  class SupplicantStartingState 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里面也有广播监听器
  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();
    }
当接受到广播会相应处理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));
        }
    }
  
  更新wifi状态
  private void updateWifiState(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的动作

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-121552-1-1.html 上篇帖子: Connectify – 没有无线路由器也能让手机和笔记本通过WIFI共享上网 下篇帖子: 多基站定位wifi混合定位
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表