Android14 WiFi 打开流程

06-01 1081阅读

目录

0.概览

1.App-->Framework状态机的流程

1.0 StateMachine基础知识

1.1 WifiEnabler

1.2 WifiManager

1.3 WifiServiceImpl

1.4 ActiveModeWarden

WifiController状态机

1.5 ConcreteClientModeManager

ClientModeStateMachine状态机

IdleState的处理

StartedState的处理

ConnectModeState

1.6 ClientModeImpl

2.WifiNative-->Hal流程

2.1 setupInterfaceForClientInScanMode 初始化interface

2.1.1 加载驱动和初始化vendor HAL接口

【流程概览】

【Java层的处理】

【Hal层的处理】

2.1.2 创建sta interface

【流程概览】

【Java层的处理】

【Hal层的处理】

2.1.3 wificond配置 interface

2.1.4 小结

2.2 switchClientInterfaceToConnectivityMode 启动supplicant

2.2.1 WifiNative

2.2.2 SupplicantStaIfaceHalAidlImpl.startDaemon()流程

【Java层流程】

【JNI层】

【Native层流程】

参考链接:


0.概览

本篇介绍Android14  WiFi 的 Enable流程。

        我们可以在 Settings界面上进行 开/关 Wi-Fi 的操作,打开Wi-Fi涉及的流程比较多,这里先给出大概的流程有个整体的印象,后文会结合源码进行分析。

Android14 WiFi 打开流程

① WiFi Enable 过程中,Framework层涉及3个状态机:

Android14 WiFi 打开流程

② 抛开Framework层各种状态的切换,Enable WiFi的操作最终是由 WifiNative 的两个方法触发的:

    1.setupInterfaceForClientInScanMode()启动扫描模式:加载驱动和vendor hal、wificond配置interface等;

    2.switchClientInterfaceToConnectivityMode()切换到连接模式:启动supplicant服务。

Android14 WiFi 打开流程

1.App-->Framework状态机的流程

        下面分析wifi打开过程中,从 App 到 Framework状态机的流程,下图给出了涉及的关键类:

Android14 WiFi 打开流程

1.0 StateMachine基础知识

        Android状态机的主要工作是消息处理和状态切换。它通过定义一组状态和状态之间的切换,来控制相关行为。

StateMachine路径为:

frameworks/libs/modules-utils/java/com/android/internal/util/StateMachine.java

①State基本结构:

        enter():在状态机转入这个状态时调用的方法;

        exit():在状态机转出这个状态时调用的方法。

        processMessage():用于处理当前状态的消息。如果当前状态处理不了,则将消息交给父状态处理。若根状态依然无法处理,则将事件抛弃并通知系统。

②StateMachine主要API:

        addState():添加状态

        setInitialState():设置初始状态

        start():启动状态机

        transitionTo():用于切换状态。在切换过程中,会自动调用旧状态的exit()方法和新状态的enter()方法。

        deferMessage():将消息缓存,直到下一次状态切换完成后处理。

        ...

1.1 WifiEnabler

        应用层通过 Context.getSystemService 来获取 WifiManager对象,并通过它调用wifi服务的接口:

//packages/apps/Settings/src/com/android/settings/wifi/WifiEnabler.java
public class WifiEnabler implements SwitchWidgetController.OnSwitchChangeListener  {
    ...
    private final WifiManager mWifiManager;
    WifiEnabler(Context context, SwitchWidgetController switchWidget,
            MetricsFeatureProvider metricsFeatureProvider,
            ConnectivityManager connectivityManager) {
        mContext = context;
        ...
        //1.获取 WifiManager 实例
        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        ...
    }
    
    public boolean onSwitchToggled(boolean isChecked) {
        ...
        //2.调用 WifiManager的 setWifiEnabled 函数,实现开关wifi
        if (!mWifiManager.setWifiEnabled(isChecked)) {
            // Error
            ...
        }
        return true;
    }

1.2 WifiManager

        WifiManager是暴露给应用的api接口类:

//packages/modules/Wifi/framework/java/android/net/wifi/WifiManager.java
package android.net.wifi;
...
@SystemService(Context.WIFI_SERVICE)
public class WifiManager {
    ...
    IWifiManager mService;
    ...
    public boolean setWifiEnabled(boolean enabled) {
        try {
            //通过AIDL调用 WifiServiceImpl 的方法
            return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

1.3 WifiServiceImpl

//packages/modules/Wifi/service/java/com/android/server/wifi/WifiServiceImpl.java
/**
 * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)}
 * @param enable {@code true} to enable, {@code false} to disable.
 * @return {@code true} if the enable/disable operation was
 *         started or is already in the queue.
 */
@Override
public synchronized boolean setWifiEnabled(String packageName, boolean enable) {
    ...
    setWifiEnabledInternal(packageName, enable, callingUid, callingPid, isPrivileged);
    return true;
}
private void setWifiEnabledInternal(String packageName, boolean enable,
        int callingUid, int callingPid, boolean isPrivileged) {
    //打印关键信息:
    mLog.info("setWifiEnabled package=% uid=% enable=% isPrivileged=%").c(packageName)
            .c(callingUid).c(enable).c(isPrivileged).flush();
    ...
    //关注点:调用 ActiveModeWarden 的方法
    mActiveModeWarden.wifiToggled(new WorkSource(callingUid, packageName));
    ...
}

1.4 ActiveModeWarden

//packages/modules/Wifi/service/java/com/android/server/wifi/ActiveModeWarden.java
/**
 * This class provides the implementation for different WiFi operating modes.
 */
public class ActiveModeWarden {
    private static final String TAG = "WifiActiveModeWarden";
    ...
    /** Wifi has been toggled. */
    public void wifiToggled(WorkSource requestorWs) {
        //1.向 WifiController 状态机发送 CMD_WIFI_TOGGLED 消息:
        mWifiController.sendMessage(WifiController.CMD_WIFI_TOGGLED, requestorWs);
    }

WifiController状态机

        WifiController 是ActiveModeWarden的内部类,是一个状态机,来看下它的构造函数:

/**
 * WifiController is the class used to manage wifi state for various operating
 * modes (normal, airplane, wifi hotspot, etc.).
 */
private class WifiController extends StateMachine {
    ...
    //                       DefaultState
    //                      /           \
    //   DisabledState(初始状态)        EnabledState
    // 在 WifiController.start方法中,会设置初始状态为 DisabledState
    // wifi打开过程中的状态切换:DisabledState --> EnabledState
    WifiController() {
        super(TAG, mLooper);
        final int threshold = mContext.getResources().getInteger(
                R.integer.config_wifiConfigurationWifiRunnerThresholdInMs);
        DefaultState defaultState = new DefaultState(threshold);
        mEnabledState = new EnabledState(threshold);
        mDisabledState = new DisabledState(threshold);
        addState(defaultState); {
            addState(mDisabledState, defaultState);
            addState(mEnabledState, defaultState);
        }
        ...
    }

当前处于DisabledState状态, 来看下 CMD_WIFI_TOGGLED 消息的处理:

class DisabledState extends BaseState {
    ...
    @Override
    public boolean processMessageFiltered(Message msg) {
        switch (msg.what) {
            case CMD_WIFI_TOGGLED:
            case CMD_SCAN_ALWAYS_MODE_CHANGED:
                handleStaToggleChangeInDisabledState((WorkSource) msg.obj);
                break;
            ...
            default:
                return NOT_HANDLED;
        }
        return HANDLED;
    }
    ...
}
private void handleStaToggleChangeInDisabledState(WorkSource requestorWs) {
    if (shouldEnableSta()) {
        //1.会触发启动wifi流程
        startPrimaryOrScanOnlyClientModeManager(requestorWs);
        //2.状态切换到EnabledState
        transitionTo(mEnabledState);
    }
}
/**
 * Method to enable a new primary client mode manager.
 */
private boolean startPrimaryOrScanOnlyClientModeManager(WorkSource requestorWs) {
    ActiveModeManager.ClientRole role = getRoleForPrimaryOrScanOnlyClientModeManager();
    if (role == ROLE_CLIENT_PRIMARY) {//走这个分支
        return startPrimaryClientModeManager(requestorWs);
    } else if (role == ROLE_CLIENT_SCAN_ONLY) {
        return startScanOnlyClientModeManager(requestorWs);
    } else {
        return false;
    }
}  
/**
 * Method to enable a new primary client mode manager in connect mode.
 */
private boolean startPrimaryClientModeManager(WorkSource requestorWs) {
    ...
    Log.d(TAG, "Starting primary ClientModeManager in connect mode");
    //创建 ConcreteClientModeManager 对象(会去启动wifi)
    ConcreteClientModeManager manager = mWifiInjector.makeClientModeManager(
            new ClientListener(), requestorWs, ROLE_CLIENT_PRIMARY, mVerboseLoggingEnabled);
    mClientModeManagers.add(manager);
    mLastPrimaryClientModeManagerRequestorWs = requestorWs;
    return true;
}
//packages/modules/Wifi/service/java/com/android/server/wifi/WifiInjector.java
/**
 * Create a ClientModeManager
 *
 * @param listener listener for ClientModeManager state changes
 * @return a new instance of ClientModeManager
 */
public ConcreteClientModeManager makeClientModeManager(
        @NonNull ClientModeManager.Listener listener,
        @NonNull WorkSource requestorWs,
        @NonNull ActiveModeManager.ClientRole role,
        boolean verboseLoggingEnabled) {
    return new ConcreteClientModeManager(
            mContext, mWifiHandlerThread.getLooper(), mClock,
            mWifiNative, listener, mWifiMetrics, mWakeupController,
            this, mSelfRecovery, mWifiGlobals, mDefaultClientModeManager,
            mClock.getElapsedSinceBootMillis(), requestorWs, role, mBroadcastQueue,
            verboseLoggingEnabled);
}

1.5 ConcreteClientModeManager

来看下ConcreteClientModeManager 的构造函数:

//packages/modules/Wifi/service/java/com/android/server/wifi/ConcreteClientModeManager.java
ConcreteClientModeManager(
        Context context, @NonNull Looper looper, Clock clock,
        WifiNative wifiNative, @NonNull Listener listener,
        WifiMetrics wifiMetrics,
        WakeupController wakeupController, WifiInjector wifiInjector,
        SelfRecovery selfRecovery, WifiGlobals wifiGlobals,
        DefaultClientModeManager defaultClientModeManager, long id,
        @NonNull WorkSource requestorWs, @NonNull ClientRole role,
        @NonNull ClientModeManagerBroadcastQueue broadcastQueue,
        boolean verboseLoggingEnabled) {
    ...
    //1.创建并启动 ClientModeStateMachine 状态机
    mStateMachine = new ClientModeStateMachine(looper);
    ...
    //2.向状态机发送CMD_START的消息
    mStateMachine.sendMessage(ClientModeStateMachine.CMD_START, mTargetRoleChangeInfo);
}

ClientModeStateMachine状态机

        ClientModeStateMachine 是 ConcreteClientModeManager的内部类,来看下它的构造函数:

//packages/modules/Wifi/service/java/com/android/server/wifi/ConcreteClientModeManager.java
//                IdleState(初始状态)
//                     |
//                StartedState
//              /               \
//      ScanOnlyModeState       ConnectModeState
//Wifi打开过程中的状态切换:IdleState-->StartedState-->ConnectModeState
ClientModeStateMachine(Looper looper) {
    super(TAG, looper);
    final int threshold = mContext.getResources().getInteger(
            R.integer.config_wifiConfigurationWifiRunnerThresholdInMs);
    mIdleState = new IdleState(threshold);
    mStartedState = new StartedState(threshold);
    mScanOnlyModeState = new ScanOnlyModeState(threshold);
    mConnectModeState = new ConnectModeState(threshold);
    addState(mIdleState);
        addState(mStartedState, mIdleState);
            addState(mScanOnlyModeState, mStartedState);
            addState(mConnectModeState, mStartedState);
    //设置初始状态
    setInitialState(mIdleState);
    start();
}
IdleState的处理

        当前处于 IdleState 状态, 来看下 CMD_START 消息的处理:

//packages/modules/Wifi/service/java/com/android/server/wifi/ConcreteClientModeManager.java
private class IdleState extends RunnerState {
    ...
    @Override
    public boolean processMessageImpl(Message message) {
        if (mVerboseLoggingEnabled) {
            Log.d(getTag(),
                    getName() + " cmd = " + getWhatToString(message.what) + " "
                            + message.toString());
        }
        switch (message.what) {
            case CMD_START:
                // Always start in scan mode first.
                RoleChangeInfo roleChangeInfo = (RoleChangeInfo) message.obj;
                //1.调用WifiNative方法去创建wlan接口(会加载驱动和vendor hal)
                mClientInterfaceName = mWifiNative.setupInterfaceForClientInScanMode(
                        mWifiNativeInterfaceCallback, roleChangeInfo.requestorWs,
                        ConcreteClientModeManager.this);
                ...
                mWifiNative.setWifiNativeInterfaceEventCallback(
                        mWifiNativeInterfaceEventCallback);
                if (roleChangeInfo.role instanceof ClientConnectivityRole) {//进入这个分支
                    //2.发送 CMD_SWITCH_TO_CONNECT_MODE,会触发supplicant的启动
                    sendMessage(CMD_SWITCH_TO_CONNECT_MODE, roleChangeInfo);
                    // 切换到 StartedState 状态
                    transitionTo(mStartedState);
                } else {
                    mScanRoleChangeInfoToSetOnTransition = roleChangeInfo;
                    transitionTo(mScanOnlyModeState);
                }
                break;
            ...
        }
        return HANDLED;
    }

从上面看出,IdleState 处理CMD_START消息过程中:

        1.会调用 WifiNative.setupInterfaceForClientInScanMode()去创建 wlan 接口进入扫描模式,具体流程会放到下一节进行分析。

        2.会切换到 StartedState 状态,来看下 CMD_SWITCH_TO_CONNECT_MODE 消息的处理:

StartedState的处理
//packages/modules/Wifi/service/java/com/android/server/wifi/ConcreteClientModeManager.java
private class StartedState extends RunnerState {
    ...
    @Override
    public boolean processMessageImpl(Message message) {
        if (mVerboseLoggingEnabled) {
            Log.d(getTag(),
                    getName() + " cmd = " + getWhatToString(message.what) + " "
                            + message.toString());
        }
        switch (message.what) {
            ...
            case CMD_SWITCH_TO_CONNECT_MODE: {
                RoleChangeInfo roleChangeInfo = (RoleChangeInfo) message.obj;
                updateConnectModeState(roleChangeInfo.role,
                       
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码