【Android 11 framework学习之wifi 开启】

工作原因接触到Android 11 framework wifi相关逻辑,参考一些博主的文章之后,自己也整理了一些,记录下来希望对后面的学习有所帮助。
根据下面的时序图进行分析:
在这里插入图片描述
从settings APP开始,以下应该是一个按键切换的方法,调用FW api

/*** com.android.settings.wifi.WifiEnabler.onSwitchToggled ***/

public boolean onSwitchToggled(boolean isChecked) {
    ...
    if (!mWifiManager.setWifiEnabled(isChecked)) {...}
    ...
}

正常打开WiFi是调用这个单参的函数,如果是指定打开哪个STA,就要调用双参的函数 setWifiEnabled(int staId, boolean enabled)

/*** android.net.wifi.WifiManager.setWifiEnabled ***/

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

setWifiEnabled 是 setWifiEnabled2 的一个封装

/*** com.android.server.wifi.WifiServiceImpl.setWifiEnabled2 ***/

public synchronized boolean setWifiEnabled2(String packageName, int staId,boolean enable) {
    ...
    mActiveModeWarden.wifiToggled();
    ...
}

发送 CMD_WIFI_TOGGLED 消息,通知WiFi切换

/*** com.android.server.wifi.ActiveModeWarden.wifiToggled ***/

public void wifiToggled() {
    mWifiController.sendMessage(WifiController.CMD_WIFI_TOGGLED);
}

WifiController 是 ActiveModeWarden 中的一个状态机,用来管理WiFi的操作,包括热点、飞行模式等
WiFi没开启之前状态机应该是在 DisabledState 状态,因此在 DisabledState 状态中处理CMD_WIFI_TOGGLED消息

/*** com.android.server.wifi.ActiveModeWarden.WifiController.DisabledState.processMessageFiltered ***/

    case CMD_WIFI_TOGGLED:
    case CMD_SCAN_ALWAYS_MODE_CHANGED:
        if (shouldEnableSta()) {
            startClientModeManager();
            transitionTo(mEnabledState);
        }
        break;

启动一个新的客户端管理

/*** com.android.server.wifi.ActiveModeWarden.startClientModeManager ***/

private boolean startClientModeManager() {
    Log.d(TAG, "Starting ClientModeManager");
    ClientListener listener = new ClientListener();
    ClientModeManager manager = mWifiInjector.makeClientModeManager(listener);
    listener.setActiveModeManager(manager);
    manager.start();
    if (!switchClientModeManagerRole(manager)) {
        return false;
    }
    mActiveModeManagers.add(manager);
    return true;
}

ClientModeManager 启用之后,发送了一个 CMD_START 的消息

/*** com.android.server.wifi.ClientModeManager.start ***/

public void start() {
    Log.d(TAG, "Starting with role ROLE_CLIENT_SCAN_ONLY");
    mRole = ROLE_CLIENT_SCAN_ONLY;
    mTargetRole = ROLE_CLIENT_SCAN_ONLY;
    mStateMachine.sendMessage(ClientModeStateMachine.CMD_START);
}

没开启之前应该是 IdleState ,于是处理这个 START 消息,状态机状态切换

/*** com.android.server.wifi.ClientModeManager.ClientModeStateMachine.IdleState.processMessage ***/

public boolean processMessage(Message message) {
    switch (message.what) {
        case CMD_START:
            // Always start in scan mode first.
            mClientInterfaceName = mWifiNative.setupInterfaceForClientInScanMode(mWifiNativeInterfaceCallback);
            ...
            transitionTo(mScanOnlyModeState);
            break;
        ...
    }
}

调用到了WifiNative中的 setupInterfaceForClientInScanMode() 方法开启wifi模块分配一个Iface,在 setupInterfaceForClientInScanMode() 方法中开启了wifi芯片驱动、获得芯片信息、注册回调并开始监听Iface消息等。接下来会调用WifiNl80211Manager类的 setupInterfaceForClientMode() 方法。
setupInterfaceForClientMode() 方法主要为Station模式设置接口。到这里, ClientModeStateMachine 状态机在 IdleState 状态成功处理完了 CMD_START 消息。

/*** com.android.server.wifi.WifiNative.setupInterfaceForClientInScanMode ***/

public String setupInterfaceForClientInScanMode(@NonNull InterfaceCallback interfaceCallback) {
    synchronized (mLock) {
        if (!startHal()) {
            ...
        }
        ...
        if (!mWifiCondManager.setupInterfaceForClientMode(iface.name, Runnable::run,
                new NormalScanEventCallback(iface.name),
                new PnoScanEventCallback(iface.name))) {
            Log.e(TAG, "Failed to setup iface in wificond=" + iface.name);
            teardownInterface(iface.name);
            mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();
            return null;
        }
        ...
    }
}

在step6的时候调用了 startClientModeManager 函数,start以后会执行 switchClientModeManagerRole ,step6的时候状态机切换为 ScanOnlyModeState ,由于在一开始就写入数据库中开启wifi,所以 mSettingsStore.isWifiToggleEnabled() 会返回true,于是设置 ROLE_CLIENT_PRIMARY

/*** com.android.server.wifi.ActiveModeWarden.switchClientModeManagerRole ***/

private boolean switchClientModeManagerRole(@NonNull ClientModeManager modeManager) {
    if (mSettingsStore.isWifiToggleEnabled()) {
        modeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY);
    } else if (checkScanOnlyModeAvailable()) {
        modeManager.setRole(ActiveModeManager.ROLE_CLIENT_SCAN_ONLY);
    } else {
        Log.e(TAG, "Something is wrong, no client mode toggles enabled");
        return false;
    }
    return true;
}

上一步 setRole 的参数为 ROLE_CLIENT_PRIMARY ,所以这里发送的是 CMD_SWITCH_TO_CONNECT_MODE 广播

/*** com.android.server.wifi.ClientModeManager.setRole ***/

public void setRole(@Role int role) {
    Preconditions.checkState(CLIENT_ROLES.contains(role));
    if (role == ROLE_CLIENT_SCAN_ONLY) {
        mTargetRole = role;
        // Switch client mode manager to scan only mode.
        mStateMachine.sendMessage(ClientModeStateMachine.CMD_SWITCH_TO_SCAN_ONLY_MODE);
    } else if (CLIENT_CONNECTIVITY_ROLES.contains(role)) {
        mTargetRole = role;
        // Switch client mode manager to connect mode.
        mStateMachine.sendMessage(ClientModeStateMachine.CMD_SWITCH_TO_CONNECT_MODE, role);
    }
}

StartedState 是 ScanOnlyModeState 的父状态, ScanOnlyModeState 中不作处理,于是到 StartedState 看一下 CMD_SWITCH_TO_CONNECT_MODE 的处理,这里先执行了 switchClientInterfaceToConnectivityMode ,随后将状态切换到 ConnectModeState

/*** com.android.server.wifi.ClientModeManager.ClientModeStateMachine.StartedState.processMessage ***/

public boolean processMessage(Message message) {
    switch(message.what) {
        case CMD_SWITCH_TO_CONNECT_MODE:
            mRole = message.arg1; // could be any one of possible connect mode roles.
            updateConnectModeState(WifiManager.WIFI_STATE_ENABLING, WifiManager.WIFI_STATE_DISABLED);
            if (!mWifiNative.switchClientInterfaceToConnectivityMode(mClientInterfaceName)) {
                updateConnectModeState(WifiManager.WIFI_STATE_UNKNOWN, WifiManager.WIFI_STATE_ENABLING);
                updateConnectModeState(WifiManager.WIFI_STATE_DISABLED, WifiManager.WIFI_STATE_UNKNOWN);
                mModeListener.onStartFailure();
                break;
            }
            transitionTo(mConnectModeState);
            break;
        ...
    }
}

更新wifi的状态,并且对外发送广播,这不正是发送的wifi开启或关闭状态的广播么 WifiManager.WIFI_STATE_CHANGED_ACTION

/*** com.android.server.wifi.ClientModeManager.updateConnectModeState ***/

private void updateConnectModeState(int newState, int currentState) {
    if (newState == WifiManager.WIFI_STATE_UNKNOWN) {
        // do not need to broadcast failure to system
        return;
    }
    if (mRole != ROLE_CLIENT_PRIMARY) {
        // do not raise public broadcast unless this is the primary client mode manager
        return;
    }
    mClientModeImpl.setWifiStateForApiCalls(newState);
    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, newState);
    intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, currentState);
    mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}

Native之后
调用hal层接口去启用请求接口

/*** com.android.server.wifi.WifiNative.switchClientInterfaceToConnectivityMode ***/

public boolean switchClientInterfaceToConnectivityMode(@NonNull String ifaceName) {
    ...
    if (!startSupplicant) {...}
    if (!mSupplicantStaIfaceHal.setupIface(iface.name)) {...}
    ...
}
/*** com.android.server.wifi.WifiNative.startSupplicant ***/

public boolean startSupplicant() {
    ...
    if (!mIfaceMgr.hasAnyStaIfaceForConnectivity()) {
        if (!startAndWaitForSupplicantConnection()) {...}
        if (!mSupplicantStaIfaceHal.registerDeathHandler(new SupplicantDeathHandlerInternal)) {...}
    }
    ...
}

先用addIfaceV1_1或addIfaceV1_0方法来获得一个ISupplicantIface的Binder对象,然后将调用setupStaIface方法

/*** com.android.server.wifi.SupplicantStaIfaceHal.setupIface ***/

public boolean setupIface(@NonNull String ifaceName) {
    ...
    ISupplicantIface ifaceHwBinder;
	    if (isV1_1()) {
	        ifaceHwBinder = addIfaceV1_1(ifaceName);
	    } else {
	        ifaceHwBinder = getIfaceV1_0(ifaceName);
	    }
    ...
    ISupplicantStaIface iface = setupStaIface(ifaceName, ifaceHwBinder);
    mISupplicantStaIfaces.put(ifaceName, iface);
    ...
    SupplicantStaIfaceHalCallback callback = new SupplicantStaIfaceHalCallback(ifaceName);
    ...
}

根据状态机的特点,消息处理完后会进入到新的状态,并且调用enter()方法。进入到ConnectModeState.enter()中

/*** com.android.server.wifi.ClientModeManager.ClientModeStateMachine.ConnectModeState.enter ***/

public void enter() {
    Log.d(TAG, "entering ConnectModeState");
    mClientModeImpl.setOperationalMode(ClientModeImpl.CONNECT_MODE,
            mClientInterfaceName);
    mModeListener.onStarted();
    updateConnectModeState(WifiManager.WIFI_STATE_ENABLED,
            WifiManager.WIFI_STATE_ENABLING);
    // Inform sar manager that wifi is Enabled
    mSarManager.setClientWifiState(WifiManager.WIFI_STATE_ENABLED);
}

上面这里可以看到,先将ClientModeImpl状态机切换了,然后继续调用了updateConnectModeState()对外发送了一个广播,表示当前的wifi状态处于WifiManager.WIFI_STATE_ENABLED状态,至此ClientModeManager对CMD_SWITCH_TO_CONNECT_MODE消息处理完成了。
那么step6 ActiveModeWarden.startClientModeManager()方法也执行完并返回true。
再次回到ActiveModeWarden中状态机的DisabledState状态中的消息处理方法processMessageFiltered中(step5),将状态机WifiController的状态切换到了EnabledState,而EnabledState的enter()方法没有再次对外发送消息或其他操作,所以step5 WifiController状态机对消息CMD_WIFI_TOGGLED也处理完毕了。
至此step3 WifiServiceImpl.setWifiEnabled()方法执行完毕,wifi成功打开,并对外发送了两次开启状态的广播。

参考:
https://blog.csdn.net/qq_43804080/article/details/118763791
https://blog.csdn.net/qq_39036223/article/details/124164745

  • 24
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要设置WiFi静态模式,您需要在Android 10的framework代码中进行以下步骤: 1. 打开WifiManager.java文件并添加以下代码: ``` /** * Set the IP address, gateway, and subnet mask for a static IP configuration. * * @param ipAddress the IP address in integer form * @param gateway the gateway in integer form * @param subnetMask the subnet mask in integer form * @param dns the DNS server addresses in integer form * @return {@code true} if the operation succeeded, {@code false} otherwise * @hide */ public boolean setWifiStaticIpConfiguration(int ipAddress, int gateway, int subnetMask, int[] dns) { WifiConfiguration config = getCurrentWifiConfiguration(); if (config == null) { return false; } config.setIpAssignment(IpAssignment.STATIC); config.setIpAddress(InetAddress.getByAddress(intToByteArray(ipAddress)).getHostAddress()); config.setGateway(InetAddress.getByAddress(intToByteArray(gateway)).getHostAddress()); config.setNetmask(InetAddress.getByAddress(intToByteArray(subnetMask)).getHostAddress()); config.setDns(dns); return saveWifiConfiguration(config); } private byte[] intToByteArray(int value) { return new byte[] { (byte)(value >>> 24), (byte)(value >>> 16), (byte)(value >>> 8), (byte)value}; } ``` 2. 在WifiConfiguration.java文件中,添加以下代码: ``` /** * Set the IP assignment mode. * * @param ipAssignment the IP assignment mode to set * @hide */ public void setIpAssignment(IpAssignment ipAssignment) { mIpAssignment = ipAssignment; } /** * Set the IP address. * * @param ipAddress the IP address to set * @hide */ public void setIpAddress(String ipAddress) { mIpAddress = ipAddress; } /** * Set the gateway. * * @param gateway the gateway to set * @hide */ public void setGateway(String gateway) { mGateway = gateway; } /** * Set the subnet mask. * * @param netmask the subnet mask to set * @hide */ public void setNetmask(String netmask) { mNetmask = netmask; } /** * Set the DNS server addresses. * * @param dns the DNS server addresses to set * @hide */ public void setDns(int[] dns) { mDnsServers.clear(); for (int i = 0; i < dns.length; i++) { mDnsServers.add(InetAddress.getByAddress(intToByteArray(dns[i]))); } } ``` 3. 最后,在Settings app中添加WiFi的静态IP配置。打开WifiSettings.java文件并添加以下代码: ``` /** * Show the dialog for configuring a static IP address. * * @param config the WifiConfiguration to configure * @hide */ public void showWifiStaticIpConfigDialog(WifiConfiguration config) { StaticIpConfigDialogFragment fragment = StaticIpConfigDialogFragment.newInstance(config); fragment.show(getFragmentManager(), StaticIpConfigDialogFragment.TAG); } ``` 这些代码将允许您在Android 10中设置WiFi的静态IP地址。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值