Android O WiFi启动流程

版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/huangweiqing80/article/details/82384518
一. Android O wifi 架构:

由于Android O的Treble化,Android O上Wifi架构变动也比较大,尤其是JNI层、Hal层、HIDL层。

下图是Android O Treble HIDL大致结构:
这里写图片描述
下图是Android O wifi架构:

这里写图片描述
二.WiFi启动流程梳理
2.1 设置启动WiFi

设置这边说到底其实就是监控WiFi开关的变化,然后根据开关走对应的逻辑处理。

两个比较重要的类:

1)WifiSettings:设置中wifi主界面所对应的代码

2)WifiEnabler:设置中负责wifi开关打开和关闭事件处理的类

在wifisettings activity的onStart函数中,创建一个WifiEnabler对象,用于实现wifi开关功能。
packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java

    public void onStart() {
        super.onStart();

        // On/off switch is hidden for Setup Wizard (returns null)
        mWifiEnabler = createWifiEnabler();

        mWifiTracker.startTracking();

        if (mIsRestricted) {
            restrictUi();
            return;
        }

        onWifiStateChanged(mWifiManager.getWifiState());
    }

onStart函数调用createWifiEnabler:

    /**
     * @return new WifiEnabler or null (as overridden by WifiSettingsForSetupWizard)
     */
    private WifiEnabler createWifiEnabler() {
        final SettingsActivity activity = (SettingsActivity) getActivity();
        return new WifiEnabler(activity, new SwitchBarController(activity.getSwitchBar()),
            mMetricsFeatureProvider);
    }

下面进入
/aosp/packages/apps/Settings/src/com/android/settings/widget/SwitchBarController.java
看看SwitchBarController这个类

public class SwitchBarController extends SwitchWidgetController implements
    SwitchBar.OnSwitchChangeListener {

    private final SwitchBar mSwitchBar;

    public SwitchBarController(SwitchBar switchBar) {
        mSwitchBar = switchBar;
    }
     .
     .
     .
    @Override
    public void startListening() {
        mSwitchBar.addOnSwitchChangeListener(this);
    }
     .
     .
     .
     @Override
    public void onSwitchChanged(Switch switchView, boolean isChecked) {
        if (mListener != null) {
            mListener.onSwitchToggled(isChecked);
        }
    }
    .
    .
    .
}

上面的两个函数startListening和onSwitchChanged是重点,一个是启动SwitchBar的监听,一个监听到有变化之后的调用

然后我们再回到刚才的createWifiEnabler函数调用的WifiEnabler类
/aosp/packages/apps/Settings/src/com/android/settings/wifi/WifiEnabler.java

@VisibleForTesting
    WifiEnabler(Context context, SwitchWidgetController switchWidget,
            MetricsFeatureProvider metricsFeatureProvider,
            ConnectivityManagerWrapper connectivityManagerWrapper) {
        mContext = context;
        mSwitchWidget = switchWidget;
        mSwitchWidget.setListener(this);
        mMetricsFeatureProvider = metricsFeatureProvider;
        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        mConnectivityManager = connectivityManagerWrapper;

        mIntentFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
        // The order matters! We really should not depend on this. :(
        mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
        mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);

        setupSwitchController();
    }

WifiEnabler类我们重点看setupSwitchController这个函数

    public void setupSwitchController() {
        final int state = mWifiManager.getWifiState();
        handleWifiStateChanged(state);
        if (!mListeningToOnSwitchChange) {
            mSwitchWidget.startListening();
            mListeningToOnSwitchChange = true;
        }
        mSwitchWidget.setupView();
    }

在setupSwitchController函数中,我们看到有
if (!mListeningToOnSwitchChange) {
mSwitchWidget.startListening();
mListeningToOnSwitchChange = true;
}
这里是调用前面的启动监听将mListeningToOnSwitchChange设为true,这样当我们点击wifi开关按钮的时候就会调用前面的onSwitchChanged随即调用mListener.onSwitchToggled(isChecked);
下面再来看看onSwitchToggled这个函数

public boolean onSwitchToggled(boolean isChecked) {
        //Do nothing if called as a result of a state machine event
        if (mStateMachineEvent) {
            return true;
        }
        // Show toast message if Wi-Fi is not allowed in airplane mode
        if (isChecked && !WirelessUtils.isRadioAllowed(mContext, Settings.Global.RADIO_WIFI)) {
            Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();
            // Reset switch to off. No infinite check/listenenr loop.
            mSwitchWidget.setChecked(false);
            return false;
        }

        // Disable tethering if enabling Wifi
        if (mayDisableTethering(isChecked)) {
            mConnectivityManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
        }
        if (isChecked) {
            mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_WIFI_ON);
        } else {
            // Log if user was connected at the time of switching off.
            mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_WIFI_OFF,
                    mConnected.get());
        }
        if (!mWifiManager.setWifiEnabled(isChecked)) {
            // Error
            mSwitchWidget.setEnabled(true);
            Toast.makeText(mContext, R.string.wifi_error, Toast.LENGTH_SHORT).show();
        }
        return true;
    }

我们可以看到WifiEnabler开关SwitchToggled中会调用WifiManager.setWifiEnabled方法。
看到这里其实发现应用层打开和关闭WiFi就是调用了WifiManager的setWifiEabled(boolean)接口。

2.2 WiFi framework

看下WifiManager的setWifiEabled(boolean)接口

framework/base/wifi/java/android/net/wifi/WifiManager.java

public boolean setWifiEnabled(boolean enabled) {
        try {
            return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

应用层的WifiManager都是怎么来的呢

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

2.2.1 mService是什么

而WifiManager.setWifiEnabled函数中的mService是啥呢

IWifiManager mService;
 public WifiManager(Context context, IWifiManager service, Looper looper) {
        mContext = context;
        mService = service;
        mLooper = looper;
        mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
    }

其实WiFiManager使用aidl方式和WifiService进行通信。

frameworks/base/wifi/java/android/net/wifi/IWifiManager.aidl

     boolean setWifiEnabled(String packageName, boolean enable);

2.3.最终调用的的是WifiServiceImpl中的setWifiEnabled方法:
WifiServiceImpl中实现WifiService的方法,像WifiController发消息:CMD_WIFI_TOGGLED.

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java

public synchronized boolean setWifiEnabled(String packageName, boolean enable)

    mWifiController.sendMessage(CMD_WIFI_TOGGLED);

2.4. WifiController状态机处理消息:CMD_WIFI_TOGGLED

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiController.java

WifiController状态机的状态变化,这里我们只说softap关闭状态下打开sta的情况;有时间的话,可以跟一下softap打开状态下打开sta的流程。这里只需关注“Turn ON STA” .

2.4.1 ApStaDisabledState 状态下,不对CMD_WIFI_TOGGLED消息处理

2.4.2 转向StaEnabledState状态,在该状态的enter()函数中启动supplicant, processMessage中会根据扫描、sta/ap共存等条件做相应的状态处理。

class StaEnabledState extends State {
        @Override
        public void enter() {
            mWifiStateMachine.setSupplicantRunning(true);
        }
        @Override
        public boolean processMessage(Message msg) {
            switch (msg.what) {
                case CMD_WIFI_TOGGLED:
                    if (! mSettingsStore.isWifiToggleEnabled()) {
                        if (mSettingsStore.isScanAlwaysAvailable()) {
                            transitionTo(mStaDisabledWithScanState);
                        } else {
                            transitionTo(mApStaDisabledState);
                        }
                    }
                    break;

可以看到WifiController再让mWifiStateMachine状态机去启动Supplicant
下面看看mWifiStateMachine.setSupplicantRunning(true);

2.5. frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java

  public void setSupplicantRunning(boolean enable) {
        if (enable) {
            sendMessage(CMD_START_SUPPLICANT);
        } else {
            sendMessage(CMD_STOP_SUPPLICANT);
        }
    }

从上面可以看到setSupplicantRunning发送了一个消息CMD_START_SUPPLICANT,那么我们就到WifiStateMachine的InitialState状态里面去看看processMessage函数
2.6. frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java

这里先简单给出wifi状态机WifiStateMachine的各状态及结构。

WifiStateMachine state:

    |- DefaultState

        |-- InitialState

        |-- SupplicantStartingState

        |-- SupplicantStartedState

            |--- ScanModeState

            |--- ConnectModeState

                |---- L2ConnectedState

                    |----- ObtainingIpState

                    |----- ConnectedState

                    |----- RoamingState

                |---- DisconnectingState

                |---- DisconnectedState

                |---- WpsRunningState

                |---- FilsState

            |--- WaitForP2pDisableState

        |-- SupplicantStoppingState

        |-- SoftApstate

InitialState状态中处理消息:CMD_START_SUPPLICANT, 做加载驱动、启动supplicant操作,mWifiMonitor.startMonitoring然后转向SupplicantStartingState状态。

    class InitialState extends State {
        @Override
        public boolean processMessage(Message message) {
            logStateAndMessage(message, this);
        switch (message.what) {
        case CMD_START_SUPPLICANT:
           ...
            mClientInterface = mWifiNative.setupForClientMode();                              // loadDriver
           ...
                               if (!mWifiNative.enableSupplicant()) {                         // start supplicant
                        loge("Failed to start supplicant!");
                        setWifiState(WifiManager.WIFI_STATE_UNKNOWN);
                        cleanup();
                        break;
                    }
                    if (mVerboseLoggingEnabled) log("Supplicant start successful");
                    mWifiMonitor.startMonitoring(mInterfaceName, true);                      //startMonitoring
                    mWifiInjector.getWifiLastResortWatchdog().clearAllFailureCounts();
                    setSupplicantLogLevel();
                    transitionTo(mSupplicantStartingState);
                    break;

2.7. frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java

    public Pair<Integer, IClientInterface> setupForClientMode() {
        if (!startHalIfNecessary(true)) {                                                              // start Hal
            Log.e(mTAG, "Failed to start HAL for client mode");
            return Pair.create(SETUP_FAILURE_HAL, null);
        }
        IClientInterface iClientInterface = mWificondControl.setupDriverForClientMode();
        if (iClientInterface == null) {
            return Pair.create(SETUP_FAILURE_WIFICOND, null);
        }
        return Pair.create(SETUP_SUCCESS, iClientInterface);
    }

//启动Hal层。如果支持STA/AP共存,startConcurrentVendorHal;如果不支持共存:isStaMode=true启动sta模式,isStaMode=false启动ap模式。

    private boolean startHalIfNecessary(boolean isStaMode)

        if (mStaAndAPConcurrency)

              // start ap & sta Concurrent Hal

               return mWifiVendorHal.startConcurrentVendorHal(isStaMode);

        return mWifiVendorHal.startVendorHal(isStaMode); // start Hal. Here

2.8. 不同于android N,wifinative会调用JNI层com_android_server_wifi_WifiNative.cpp. Android O在framework增加了调用Hal层的相关接口及hal设备管理接口。

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiVendorHal.java

    public boolean startVendorHal(boolean isStaMode)

        mHalDeviceManager.start()  //start wifi vendor hal

        mIWifiStaIface = mHalDeviceManager.createStaIface(null, null); //loadDriver

2.9. 继续跟mIWifiStaIface = mHalDeviceManager.createStaIface(null, null);

frameworks/opt/net/wifi/service/java/com/android/server/wifi/HalDeviceManager.java

    public IWifiStaIface createStaIface(InterfaceDestroyedListener destroyedListener,

            Looper looper) {

        return (IWifiStaIface) createIface(IfaceType.STA, destroyedListener, looper);

    }
    private IWifiIface createIface(int ifaceType, InterfaceDestroyedListener destroyedListener, Looper looper)

         IWifiIface iface = createIfaceIfPossible(chipInfos, ifaceType, destroyedListener, looper);
  private IWifiIface createIfaceIfPossible(WifiChipInfo[] chipInfos, int ifaceType, InterfaceDestroyedListener destroyedListener, Looper looper)

         IWifiIface iface = executeChipReconfiguration(bestIfaceCreationProposal, ifaceType);
   private IWifiIface executeChipReconfiguration(IfaceCreationData ifaceCreationData, int ifaceType) 

        WifiStatus status = ifaceCreationData.chipInfo.chip.configureChip(ifaceCreationData.chipModeId);

2.10. Android O不在使用之前版本的JNI com_android_server_wifi_WifiNative.cpp。而是用HIDL,其实现在/hardware/interfaces/.

hardware/interfaces/wifi/1.1/default/wifi_chip.cpp

    Return<void> WifiChip::configureChip(ChipModeId mode_id, configureChip_cb hidl_status_cb) 

        return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, &WifiChip::configureChipInternal, hidl_status_cb, mode_id);
 WifiStatus WifiChip::configureChipInternal(ChipModeId mode_id) 

         WifiStatus status = handleChipConfiguration(mode_id);
    WifiStatus WifiChip::handleChipConfiguration(ChipModeId mode_id)

        if (mode_id == kStaChipModeId) {

            success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA);

        } else {

            success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP);

        }

2.11. hardware/interfaces/wifi/1.0/default/wifi_mode_controller.cpp

 bool WifiModeController::changeFirmwareMode(IfaceType type) 

        driver_tool_->LoadDriver()

        driver_tool_->ChangeFirmwareMode(convertIfaceTypeToFirmwareMode(type))

2.12. 最后调到hal层,android O的hal层也进行了重写。位置也从之前的版本中的hardware/libhardware_legacy/wifi/移到了frameworks/opt/net/wifi/libwifi_hal/

frameworks/opt/net/wifi/libwifi_hal/driver_tool.cpp

    bool DriverTool::LoadDriver() 

        return ::wifi_load_driver() == 0;

2.13 frameworks/opt/net/wifi/libwifi_hal/wifi_hal_common.cpp

int wifi_load_driver() 

if (is_wifi_driver_loaded())  return 0;

        insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG)

除了一些打开wifi时的消息通知、广播、状态变化,这里没有详细描述;至此,wifi打开的相关工作已经完成。

有些平台把加载wifi驱动的动作放在了开机时,在init.$(target).rc文件中:

insmod /vendor/lib/modules/wlan.ko

根据实际情况,可能需要将开机加载驱动改为原来的动态加载。只需要做两处改动:

A. init脚本中删除加载wlan driver的行

B. 确认如下几个宏是打开和正确定义,在产品平台对应的makefile文件中加入即可:

   WIFI_DRIVER_MODULE_PATH := "/vendor/lib/modules/wlan.ko"

    WIFI_DRIVER_MODULE_NAME := "wlan"

    WIFI_DRIVER_MODULE_ARG := ""

参考https://blog.csdn.net/h784707460/article/details/79572861

猜你喜欢

转载自blog.csdn.net/huangweiqing80/article/details/82384518