Android13 Wifi启动流程分析

Android13 Wifi启动流程分析

文章目录

  • Android13 Wifi启动流程分析
    • 一、正常开关wifi 启动流程
      • 1、WifiManager
      • 2、WifiServiceImpl
      • 3、ActiveModeWarden
      • 4、ConcreteClientModeManager
      • 5、WifiNative
      • 6、WifiVendorHal
      • 7、HalDeviceManager
      • 8、wifi.cpp
    • 二、重启设备时自动开启wifi流程
      • 1、系统服务启动 SystemServer
      • 2、WifiService
      • 3、WifiServiceImpl
      • 4、ActiveModeWarden
    • 三、其他
      • 1、Android13 Wifi启动 完整流程:
      • 2、日志查看
        • 关键字和可以查看到的关键信息
        • 正常开启wifi日志:
        • 正常关闭wifi日志:
        • 缺少wifi硬件模组是开启wifi日志:
      • 3、wifi开关状态值
      • 4、之前写的一些wifi相关的知识

本文对Android13 wifi 开启流程进行梳理,有需要的可以看看。

如果遇到wifi 打不开问题,可以依照这个流程进行分析,看看具体是哪个流程出现问题。

如果后续需要分析比Android13 更新的代码可以对比参考,毕竟Android11的代码变动比较大。

本文最后有流程总结,代码分析过程还有最大一个亮点,每个类的流程分析都标志了数字,避免读着读着就迷路了。

最后还有wifi开关相关日志过程分析。

一、正常开关wifi 启动流程

1、WifiManager

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

packages\modules\Wifi\framework\java\android\net\wifi\WifiManager.java

@SystemService(Context.WIFI_SERVICE)
public class WifiManager {public boolean setWifiEnabled(boolean enabled) {try {// (1)调用 Service 的 setWifiEnabled 方法return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}
}

2、WifiServiceImpl

WifiServiceImpl 是Manager接口具体实现类

packages\modules\Wifi\service\java\com\android\server\wifi\WifiServiceImpl.java

public class WifiServiceImpl extends BaseWifiService {private static final String TAG = "WifiService";// (1) setWifiEnabled 方法public synchronized boolean setWifiEnabled(String packageName, boolean enable) {// If Airplane mode is enabled, only privileged apps are allowed to toggle Wifiif (mSettingsStore.isAirplaneModeOn() && !isPrivileged) {mLog.err("setWifiEnabled in Airplane mode: only Settings can toggle wifi").flush(); //异常日志return false;}
...// (2)  继续追踪setWifiEnabledInternal 方法setWifiEnabledInternal(packageName, enable, callingUid, callingPid, isPrivileged);return true;}// (3)  查看 setWifiEnabledInternal 方法实现private void setWifiEnabledInternal(String packageName, boolean enable,int callingUid, int callingPid, boolean isPrivileged) {// (4) 这里有打印哦,打印哪个应用打开还是关闭wifi 的日志 mLog.info("setWifiEnabled package=% uid=% enable=% isPrivileged=%").c(packageName).c(callingUid).c(enable).c(isPrivileged).flush(); //wifi 打开日志。。。// (5) 继续追踪 ActiveModeWarden.wifiToggledmActiveModeWarden.wifiToggled(new WorkSource(callingUid, packageName));mLastCallerInfoManager.put(WifiManager.API_WIFI_ENABLED, Process.myTid(),callingUid, callingPid, packageName, enable); //一些属性的保存,可以不用管}}

WifiServiceImpl 的打印TAG 是 WifiService,wifi 开关有比较多相关日志,主要是看出开关日志和哪个应用调用的开关。

3、ActiveModeWarden

里面有一些关键日志,调试可以查看该日志。

packages\modules\Wifi\service\java\com\android\server\wifi\ActiveModeWarden.java

public class ActiveModeWarden {private static final String TAG = "WifiActiveModeWarden";//(1) wifi打开消息发送方法public void wifiToggled(WorkSource requestorWs) {mWifiController.sendMessage(WifiController.CMD_WIFI_TOGGLED, requestorWs);}//(2) wifi打开消息的接收//内部类,wifi执行打开是Disable 的状态class DisabledState extends BaseState {@Overridepublic void enter() {log("DisabledState.enter()");super.enter();if (hasAnyModeManager()) {Log.e(TAG, "Entered DisabledState, but has active mode managers");}}@Overridepublic boolean processMessageFiltered(Message msg) {switch (msg.what) {//(3) wifi打开消息处理case CMD_WIFI_TOGGLED:case CMD_SCAN_ALWAYS_MODE_CHANGED:handleStaToggleChangeInDisabledState((WorkSource) msg.obj);break;}default:return NOT_HANDLED;}return HANDLED;}//(4) 内部类的处理方法 handleStaToggleChangeInDisabledStateprivate void handleStaToggleChangeInDisabledState(WorkSource requestorWs) {if (shouldEnableSta()) {startPrimaryOrScanOnlyClientModeManager(requestorWs);transitionTo(mEnabledState);}}}//(4) 具体的处理方法 startPrimaryOrScanOnlyClientModeManagerprivate boolean startPrimaryOrScanOnlyClientModeManager(WorkSource requestorWs) {//(5)这里其实是判断了wifi_on那个Settings属性ActiveModeManager.ClientRole role = getRoleForPrimaryOrScanOnlyClientModeManager();if (role == ROLE_CLIENT_PRIMARY) { //(6)wifi 打开是进这里return startPrimaryClientModeManager(requestorWs);} else if (role == ROLE_CLIENT_SCAN_ONLY) {return startScanOnlyClientModeManager(requestorWs);} else {return false;}}// (7)继续追踪方法private boolean startPrimaryClientModeManager(WorkSource requestorWs) {Log.d(TAG, "Starting primary ClientModeManager in connect mode");//(8)这里创建了 ConcreteClientModeManager 对象,看起来没做啥,其实创建对象会做事情ConcreteClientModeManager manager = mWifiInjector.makeClientModeManager(new ClientListener(), requestorWs, ROLE_CLIENT_PRIMARY, mVerboseLoggingEnabled);mClientModeManagers.add(manager); //连接对象被接入队列管理,可以不用关注,断开会被移除mLastPrimaryClientModeManagerRequestorWs = requestorWs;return true;}}

ActiveModeWarden 的日志 TAG 是 WifiActiveModeWarden,该文件的日志有打印目前wifi是从哪个状态进入进行操作的日志。

往下走的 ConcreteClientModeManager 对象 比较特殊,你只要创建它,它就会默认执行开启wifi,往下看它的代码实现就可以看到,所以这里manager 未调用方法,只是加入到队列管理中,很多人可能会看懵,但是继续往下看它的构造方法就明白了。

4、ConcreteClientModeManager

ConcreteClientModeManager 相关一个系统层的wifi Manager,系统内部使用;

Android11 中没有 ConcreteClientModeManager ,只有 ClientModeManager。

packages\modules\Wifi\service\java\com\android\server\wifi\ConcreteClientModeManager.java

public class ConcreteClientModeManager implements ClientModeManager {private static final String TAG = "WifiClientModeManager";//(1) ConcreteClientModeManager 构造方法ConcreteClientModeManager(Context context,...) {mContext = context;mWifiNative = wifiNative;
...//(2)构造方法中,发送wifi开启mStateMachine.sendMessage(ClientModeStateMachine.CMD_START, mTargetRoleChangeInfo);}//(3)内部状态类,接收消息//内部类,未开启wifi前是IdleState状态private class IdleState extends State {@Overridepublic void enter() {Log.d(getTag(), "entering IdleState");mClientInterfaceName = null;mIfaceIsUp = false;}@Overridepublic boolean processMessage(Message message) {switch (message.what) {//(3)接收消息case CMD_START:// Always start in scan mode first.RoleChangeInfo roleChangeInfo = (RoleChangeInfo) message.obj;// (4) native 方法调用,拉起节点,一般是wlan0mClientInterfaceName = mWifiNative.setupInterfaceForClientInScanMode(mWifiNativeInterfaceCallback, roleChangeInfo.requestorWs);if (TextUtils.isEmpty(mClientInterfaceName)) {Log.e(getTag(), "Failed to create ClientInterface. Sit in Idle");takeBugReportInterfaceFailureIfNeeded("Wi-Fi scan STA interface HAL failure");mModeListener.onStartFailure(ConcreteClientModeManager.this);break;}if (roleChangeInfo.role instanceof ClientConnectivityRole) { //默认是进入这里sendMessage(CMD_SWITCH_TO_CONNECT_MODE, roleChangeInfo);transitionTo(mStartedState);} else {mScanRoleChangeInfoToSetOnTransition = roleChangeInfo;transitionTo(mScanOnlyModeState);}break;default:Log.d(getTag(), "received an invalid message: " + message);return NOT_HANDLED;}return HANDLED;}}}

ConcreteClientModeManager 的日志 TAG 是 WifiClientModeManager,

该文件的日志有也是包含了一些状态下的操作信息。

Android11 中 ClientModeManager 的日志 TAG 是 WifiClientModeManager。

5、WifiNative

WifiNative 是一个统筹调用底层接口的类,这个类往下的逻辑看起来好像没有太大修改。

packages\modules\Wifi\service\java\com\android\server\wifi\WifiNative.java

public class WifiNative {private static final String TAG = "WifiNative";private final WifiVendorHal mWifiVendorHal;private final IfaceManager mIfaceMgr = new IfaceManager(); //内部类,调用的Ifacepublic String setupInterfaceForClientInScanMode(@NonNull InterfaceCallback interfaceCallback, @NonNull WorkSource requestorWs) {synchronized (mLock) {if (!startHal()) { //(1) 初始化驱动和vendor halLog.e(TAG, "Failed to start Hal");mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();return null;}// (2) 初始化interfaceIface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA_FOR_SCAN);if (iface == null) {Log.e(TAG, "Failed to allocate new STA iface");return null;}iface.externalListener = interfaceCallback;iface.name = createStaIface(iface, requestorWs);if (TextUtils.isEmpty(iface.name)) {Log.e(TAG, "Failed to create iface in vendor HAL");mIfaceMgr.removeIface(iface.id);mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();return null;}// (3)初始化wificondif (!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;}iface.networkObserver = new NetworkObserverInternal(iface.id);//(4)监听interface的down/upif (!registerNetworkObserver(iface.networkObserver)) {Log.e(TAG, "Failed to register network observer for iface=" + iface.name);teardownInterface(iface.name);return null;}//(5)启动supplicant监听(但是此时supplicant进程还未启动)mWifiMonitor.startMonitoring(iface.name);// Just to avoid any race conditions with interface state change callbacks,// update the interface state before we exit.onInterfaceStateChanged(iface, isInterfaceUp(iface.name));mWifiVendorHal.enableLinkLayerStats(iface.name);Log.i(TAG, "Successfully setup " + iface); //成功启动wifi节点//(6)获取芯片支持的wifi featureiface.featureSet = getSupportedFeatureSetInternal(iface.name);return iface.name;}}//(7) 继续分析:初始化驱动private boolean startHal() {synchronized (mLock) {if (!mIfaceMgr.hasAnyIface()) { //(8) 判断节点是否存在if (mWifiVendorHal.isVendorHalSupported()) { //(9) 判断底层是否支持if (!mWifiVendorHal.startVendorHal()) { //(10) **重点:判断是否可以正常启动节点Log.e(TAG, "Failed to start vendor HAL");return false;}if (SdkLevel.isAtLeastS()) {mWifiVendorHal.setCoexUnsafeChannels(mCachedCoexUnsafeChannels, mCachedCoexRestrictions);}} else {Log.i(TAG, "Vendor Hal not supported, ignoring start.");}}registerWificondListenerIfNecessary();return true;}}}

6、WifiVendorHal

packages\modules\Wifi\service\java\com\android\server\wifi\WifiVendorHal.java

/*** Vendor HAL via HIDL*/
public class WifiVendorHal {private final HalDeviceManager mHalDeviceManager;// (1)追踪 startVendorHalpublic boolean startVendorHal() {synchronized (sLock) {//(2) 关键 mHalDeviceManager.startif (!mHalDeviceManager.start()) {mLog.err("Failed to start vendor HAL").flush();return false;}mLog.info("Vendor Hal started successfully").flush();return true;}}
}

7、HalDeviceManager

import android.hardware.wifi.V1_0.IWifi;/*** Handles device management through the HAL (HIDL) interface.*/
public class HalDeviceManager {private static final String TAG = "HalDevMgr";private IWifi mWifi;//(1) 继续追踪 HalDeviceManager.startpublic boolean start() {return startWifi();}//(2) startWifi 实现private boolean startWifi() {if (VDBG) Log.d(TAG, "startWifi");initIWifiIfNecessary();synchronized (mLock) {try {if (mWifi == null) {Log.w(TAG, "startWifi called but mWifi is null!?");return false;} else {int triedCount = 0;while (triedCount <= START_HAL_RETRY_TIMES) { //最多启动start三次WifiStatus status = mWifi.start();if (status.code == WifiStatusCode.SUCCESS) {initIWifiChipDebugListeners();managerStatusListenerDispatch();if (triedCount != 0) { //(3)启动慢,一次没有启动成功的情况,这里才会有日志!Log.d(TAG, "start IWifi succeeded after trying " + triedCount + " times");}WifiChipInfo[] wifiChipInfos = getAllChipInfo();if (wifiChipInfos != null) {mCachedStaticChipInfos =convertWifiChipInfoToStaticChipInfos(getAllChipInfo());saveStaticChipInfoToStore(mCachedStaticChipInfos);} else {Log.e(TAG, "Started wifi but could not get current chip info.");}return true;} else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) {// Should retry. Hal might still be stopping. the registered event// callback will not be cleared.Log.e(TAG, "Cannot start IWifi: " + statusString(status)+ ", Retrying...");try {Thread.sleep(START_HAL_RETRY_INTERVAL_MS);} catch (InterruptedException ignore) {// no-op}triedCount++;} else {// Should not retry on other failures.// Will be handled in the onFailure event.Log.e(TAG, "Cannot start IWifi: " + statusString(status));return false;}}Log.e(TAG, "Cannot start IWifi after trying " + triedCount + " times");return false;}} catch (RemoteException e) {Log.e(TAG, "startWifi exception: " + e);return false;}}}}

WifiNative往下大致流程:

WifiNative -> WifiVendorHal -> HalDeviceManagerWifiNative.startHal() -> 
WifiVendorHal.startVendorHal() ->
HalDeviceManager.start() -> 
HalDeviceManager.startWifi()

HalDeviceManager 往下的 Hal 层代码是直接调用硬件接口的了。
并且 IWifi 这些 接口类是系统编译生成的,没有具体的IWifi.java 文件,只有相关的class文件。

8、wifi.cpp

Hal 层代码

hardware\interfaces\wifi\1.6\default\wifi.cpp

Return<void> Wifi::start(start_cb hidl_status_cb) {return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::startInternal,hidl_status_cb);
}WifiStatus Wifi::startInternal() {if (run_state_ == RunState::STARTED) {return createWifiStatus(WifiStatusCode::SUCCESS);} else if (run_state_ == RunState::STOPPING) {return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, "HAL is stopping");}WifiStatus wifi_status = initializeModeControllerAndLegacyHal();if (wifi_status.code == WifiStatusCode::SUCCESS) {// Register the callback for subsystem restartconst auto& on_subsystem_restart_callback = [this](const std::string& error) {WifiStatus wifi_status = createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, error);for (const auto& callback : event_cb_handler_.getCallbacks()) {LOG(INFO) << "Attempting to invoke onSubsystemRestart ""callback";if (!callback->onSubsystemRestart(wifi_status).isOk()) {LOG(ERROR) << "Failed to invoke onSubsystemRestart callback";} else {LOG(INFO) << "Succeeded to invoke onSubsystemRestart ""callback";}}};// Create the chip instance once the HAL is started.android::hardware::wifi::V1_0::ChipId chipId = kPrimaryChipId;for (auto& hal : legacy_hals_) {chips_.push_back(new WifiChip(chipId, chipId == kPrimaryChipId, hal, mode_controller_,std::make_shared<iface_util::WifiIfaceUtil>(iface_tool_, hal),feature_flags_, on_subsystem_restart_callback));chipId++;}run_state_ = RunState::STARTED;for (const auto& callback : event_cb_handler_.getCallbacks()) {if (!callback->onStart().isOk()) {LOG(ERROR) << "Failed to invoke onStart callback";};}LOG(INFO) << "Wifi HAL started";} else {for (const auto& callback : event_cb_handler_.getCallbacks()) {if (!callback->onFailure(wifi_status).isOk()) {LOG(ERROR) << "Failed to invoke onFailure callback";}}LOG(ERROR) << "Wifi HAL start failed";// Clear the event callback objects since the HAL start failed.event_cb_handler_.invalidate();}return wifi_status;
}WifiStatus Wifi::initializeModeControllerAndLegacyHal() {// ... ...mode_controller_->initialize();				// 加载驱动 driver_tool_->LoadDriver()legacy_hals_ = legacy_hal_factory_->getHals();for (auto& hal : legacy_hals_) {legacy_hal::wifi_error legacy_status = hal->initialize();// ... ...}// ... ...
}std::vector<std::shared_ptr<WifiLegacyHal>> WifiLegacyHalFactory::getHals() {if (legacy_hals_.empty()) {// 先从已链接的so库中初始化vendor hal的接口(函数指针赋值)// 如果失败,证明是多wifi芯片的设备,需要从descriptor.xml初始化if (!initVendorHalDescriptorFromLinked()) initVendorHalsDescriptorList();for (auto& desc : descs_) {std::shared_ptr<WifiLegacyHal> hal =std::make_shared<WifiLegacyHal>(iface_tool_, desc.fn, desc.primary);legacy_hals_.push_back(hal);}}return legacy_hals_;
}

wifi.cpp 主要工作:

通过wifi_mode_controller加载驱动
初始化所有的HAL接口(legacy_hal_factory_->getHals())
initVendorHalDescriptorFromLinked
initVendorHalsDescriptorList

wifi.cpp 已经是底层硬件实现了,这块代码其实我也不怎么了解,再往下不做具体分析了。

这篇文章对底层逻辑讲得详细一下:
https://blog.csdn.net/weixin_40588186/article/details/132837372

二、重启设备时自动开启wifi流程

系统启动时,其实就多了startServer的过程,并且在startOtherService中打开wifi。

init.rc那些就不说了,直接从Java部分说起。

1、系统服务启动 SystemServer

SystemServer 是包含Java入口的类,并且启动了很多Android 关键服务。

frameworks\base\services\java\com\android\server\SystemServer.java

/*** Entry point to {@code system_server}.*/
public final class SystemServer implements Dumpable {private static final String WIFI_SERVICE_CLASS =        "com.android.server.wifi.WifiService";/*** The main entry point from zygote.*///(1)Java 端启动入口public static void main(String[] args) {new SystemServer().run();}//(2)启动系统服务private void run() {// Start services.try {t.traceBegin("StartServices");startBootstrapServices(t);//设备启动服务,电源管理和设备管理服务startCoreServices(t); //核心服务startOtherServices(t);//(3)其他服务,AMS、WIFI、蓝牙那些startApexServices(t);//启动app相关服务,这个是Android13 才有的。} catch (Throwable ex) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting system services", ex);throw ex;} finally {t.traceEnd(); // StartServices}}//(4)other服务启动private void startOtherServices(@NonNull TimingsTraceAndSlog t) {//(5)wifi服务启动if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) {// Wifi Service must be started first for wifi-related services.t.traceBegin("StartWifi");  //(6)刚开机可以看到这些日志mSystemServiceManager.startServiceFromJar(WIFI_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH);t.traceEnd();t.traceBegin("StartWifiScanning");mSystemServiceManager.startServiceFromJar(WIFI_SCANNING_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH);t.traceEnd();}。。。}}

2、WifiService

wifi服务类,并不是对外暴露的,对接的是SystemServer

packages\modules\Wifi\service\java\com\android\server\wifi\WifiService.java

public final class WifiService extends SystemService {private final WifiServiceImpl mImpl;@Overridepublic void onBootPhase(int phase) {if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {mImpl.checkAndStartWifi(); // (1)检查是否需要启动wifi} else if (phase == SystemService.PHASE_BOOT_COMPLETED) {mImpl.handleBootCompleted();}}
}

3、WifiServiceImpl

wifi 启动的具体实现类,对接的是WifiManager 接口方法。

packages\modules\Wifi\service\java\com\android\server\wifi\WifiServiceImpl.java

public class WifiServiceImpl extends BaseWifiService {private static final String TAG = "WifiService";// (1)检查是否需要启动wifipublic void checkAndStartWifi() {mWifiThreadRunner.post(() -> {//这里有打印wifi是否需要启动,具体实现是判断Settings.Global.WIFI_ON//但是这个方法内并未使用这个属性// Check if wi-fi needs to be enabledboolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();Log.i(TAG,"WifiService starting up with Wi-Fi " + (wifiEnabled ? "enabled" : "disabled"));...mActiveModeWarden.start(); //(2)在这里判断是否开启registerForCarrierConfigChange();mWifiInjector.getAdaptiveConnectivityEnabledSettingObserver().initialize();mIsWifiServiceStarted = true;});}
}

4、ActiveModeWarden

wifi 状态处理,比较中间的

packages\modules\Wifi\service\java\com\android\server\wifi\ActiveModeWarden.java

public class ActiveModeWarden {private static final String TAG = "WifiActiveModeWarden";private final WifiController mWifiController;/** Begin listening to broadcasts and start the internal state machine. *///(1)ActiveModeWarden.startpublic void start() {...//(2) 调用Controller 状态机 startmWifiController.start();}private class WifiController extends StateMachine {private static final String TAG = "WifiController";@Overridepublic void start() {boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn();boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled();boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();boolean isLocationModeActive = mWifiPermissionsUtil.isLocationModeEnabled();//(3) 这里也有打开wifi 是否需要开启wifi的日志log("isAirplaneModeOn = " + isAirplaneModeOn+ ", isWifiEnabled = " + isWifiEnabled+ ", isScanningAvailable = " + isScanningAlwaysAvailable+ ", isLocationModeActive = " + isLocationModeActive);ActiveModeManager.ClientRole role = getRoleForPrimaryOrScanOnlyClientModeManager();if (role == ROLE_CLIENT_PRIMARY) { //**(4)这个比较隐蔽,wifi开启是开启就是进入这里startPrimaryClientModeManager(mLastPrimaryClientModeManagerRequestorWs);setInitialState(mEnabledState);} else if (role == ROLE_CLIENT_SCAN_ONLY) {startScanOnlyClientModeManager(mLastScanOnlyClientModeManagerRequestorWs);setInitialState(mEnabledState);} else { //如果是不需要开启wifi,就是默认进入Disabled状态setInitialState(mDisabledState);}mWifiMetrics.noteWifiEnabledDuringBoot(mSettingsStore.isWifiToggleEnabled());// Initialize the lower layers before we start.mWifiNative.initialize();super.start();}}//(5) 具体的处理方法 startPrimaryOrScanOnlyClientModeManagerprivate boolean startPrimaryOrScanOnlyClientModeManager(WorkSource requestorWs) {//(6)这里其实是判断了wifi_on那个Settings属性ActiveModeManager.ClientRole role = getRoleForPrimaryOrScanOnlyClientModeManager();if (role == ROLE_CLIENT_PRIMARY) { //(7)wifi 打开是进这里return startPrimaryClientModeManager(requestorWs);} else if (role == ROLE_CLIENT_SCAN_ONLY) {return startScanOnlyClientModeManager(requestorWs);} else {return false;}}// (8)继续追踪方法private boolean startPrimaryClientModeManager(WorkSource requestorWs) {Log.d(TAG, "Starting primary ClientModeManager in connect mode");//(9)这里创建了 ConcreteClientModeManager 对象,看起来没做啥,其实创建对象会做事情ConcreteClientModeManager manager = mWifiInjector.makeClientModeManager(new ClientListener(), requestorWs, ROLE_CLIENT_PRIMARY, mVerboseLoggingEnabled);mClientModeManagers.add(manager); //连接对象被接入队列管理,可以不用关注,断开会被移除mLastPrimaryClientModeManagerRequestorWs = requestorWs;return true;}}

上面第4点看到,wifi开启是调用到 startPrimaryClientModeManager 方法和上面正常开启wifi调用到的第3步的ActiveModeWarden.wifiToggled里面后面调用到的方法是一个方法。

所以往后的流程接着往ConcreteClientModeManager看就可以看到了。

三、其他

1、Android13 Wifi启动 完整流程:

(1) WifiManager.java
(2) WifiServiceImpl.java
(3) ActivityModenWarden.java
(4) ConcreteClientModeManager.java
(5) WifiNative.java
(6) WIfiVendorHar.java
(7) HalDeviceManager.java
(8) wifi.cpp //HAl层
(9) HAl 往下

Android11 完整流程图:

在这里插入图片描述

Android13 完整流程图:

在这里插入图片描述

不同Android11 部分用黄色标记出来了。

其实正常情况,流程大多是没啥用处的,除非有特殊需求要需要改,但是wifi异常分析是经常遇到的,这种情况就要查看日志,需要找到关键时间点,进一步确定异常原因了,下面的日志可能会有一些帮助。

2、日志查看

关键字和可以查看到的关键信息
关键字 : 关键信息
WifiService:查看WifiServiceImpl调用信息,一些api调用日志和wifi 开关日志
WifiController:ActiveModeWarden 内部状态机的一些信息
WifiActiveModeWarden:ActiveModeWarden 过程日志
WifiClientModeManager:ConcreteClientModeManager的过程日志
WifiNative:底层调用情况日志,异常情况会有明显日志
(底层)
HalDevMgr:HalDeviceManager 过程日志,和异常提示
WifiVendorHal:Hal过程日志和异常日志
android.hardware.wifi:底层hardware包相关日志

一般情况关键日志主要看 WifiService 和 WifiNative , 根据发生问题时间点再仔细研究即可。

多个日志打印的命令:

logcat | grep -E "WifiService|WifiController|WifiActiveModeWarden|WifiClientModeManager|WifiNative"

测试打印部分日志如下:

正常开启wifi日志:
//(1)清除一下日志
bsp:/ $ logcat -c//(2)过滤关键字日志
bsp:/ $logcat | grep -E "WifiService|WifiController|WifiActiveModeWarden|WifiClientModeManager|WifiNative" //(3)打开wifi 的应用包名和uid, uid =1000 表示普通的系统应用, enable=true 表示打开
12-21 16:57:37.448   979  1393 I WifiService: setWifiEnabled package=com.skg.settings uid=1000 enable=true isPrivileged=true//(4)其他一下状态信息
12-21 16:57:37.453   979  1275 D WifiActiveModeWarden: Starting primary ClientModeManager in connect mode
12-21 16:57:37.453   979  1275 D WifiController: DisabledState.exit()
12-21 16:57:37.453   979  1275 D WifiController: EnabledState.enter()//(5) wlan0 节点开始打开
12-21 16:57:37.582   979  1275 I WifiNative: Successfully setup Iface:{Name=wlan0,Id=13,Type=STA_SCAN}
12-21 16:57:37.585   979  1275 D WifiClientModeManager[wlan0]: entering StartedState
12-21 16:57:37.599   979  1275 D WifiActiveModeWarden: setting wifi state to: 2//(6)系统发送wifi 开关状态广播, 说明系统发出wifi 开关状态变化的广播 WIFI_STATE_CHANGED_ACTION 是 ConcreteClientModeManager 发出的
12-21 16:57:37.600   979  1275 D WifiClientModeManager[wlan0]: Sending broadcast=WIFI_STATE_CHANGED_ACTION EXTRA_WIFI_STATE=2 EXTRA_PREVIOUS_WIFI_STATE=1//(7) 应用查询wifi状态日志, uid=1000 是uid系统apk
12-21 16:57:37.610   979  9543 I WifiService: getWifiEnabledState uid=10097
12-21 16:57:37.637   979 24139 I WifiService: getWifiEnabledState uid=1000
12-21 16:57:37.641   979 24139 I WifiService: getWifiEnabledState uid=1000//(8) wlan0 节点成功打开
12-21 16:57:37.674   979  1275 I WifiNative: Successfully switched to connectivity mode on iface=Iface:{Name=wlan0,Id=13,Type=STA_CONNECTIVITY}//(9)中间一些信息
12-21 16:57:37.674   979  1275 D WifiClientModeManager[wlan0]: entering ConnectModeState, starting ClientModeImpl
12-21 16:57:37.679   979  1275 V WifiClientModeManager[wlan0]: ClientModeManager started in role: Role: ROLE_CLIENT_PRIMARY, RequestorWs: WorkSource{1000 com.skg.settings}, ModeListener: com.android.server.wifi.ActiveModeWarden$ClientListener@ded9fb6
12-21 16:57:37.685   979  1275 V WifiActiveModeWarden: ModeManager added ConcreteClientModeManager{id=10580945 iface=wlan0 role=ROLE_CLIENT_PRIMARY}//(11)设置  CountryCode ,00 应该是无效的,CN,US 那些才有用的,不过wifi 开启对CountryCode 没有要求,热点才有要求
12-21 16:57:37.695   979  1275 D WifiNative: onSetCountryCodeSucceeded: 00
12-21 16:57:37.699   979  1275 V WifiActiveModeWarden: Primary ClientModeManager changed from null to ConcreteClientModeManager{id=10580945 iface=wlan0 role=ROLE_CLIENT_PRIMARY}//(12) wifi 完成打开的状态
12-21 16:57:37.699   979  1275 D WifiActiveModeWarden: setting wifi state to: 3

这里看到wifi 从打开标识 setWifiEnabled 开始,到完成打开一般只用一秒不到。

重点可以关注:WifiService 和 WifiNative 相关的日志,其中 WifiService 在后续扫描过程也是会有一些日志。

正常关闭wifi日志:
bsp:/ $logcat | grep -E "WifiService|WifiController|WifiActiveModeWarden|WifiClientModeManager|WifiNative"//(1)关闭 wifi 的应用包名和uid, uid =1000 表示普通的系统应用, enable=false 表示关闭
12-21 18:24:01.039   967  1554 I WifiService: setWifiEnabled package=com.skg.settings uid=1000 enable=false isPrivileged=true//(2)状态机那些准备关闭wifi
12-21 18:24:01.044   967  1212 D WifiActiveModeWarden: Shutting down all client mode managers
12-21 18:24:01.051   967  1212 D WifiClientModeManager[wlan0]:  currentstate: ConnectModeState//(3)进入正在关闭wifi状态0
12-21 18:24:01.055   967  1212 D WifiActiveModeWarden: setting wifi state to: 0//(4)发送广播 正在关闭WiFi,EXTRA_WIFI_STATE=0 当前状态是正在关闭, EXTRA_PREVIOUS_WIFI_STATE=3 之前状态是打开
12-21 18:24:01.059   967  1212 D WifiClientModeManager[wlan0]: Sending broadcast=WIFI_STATE_CHANGED_ACTION EXTRA_WIFI_STATE=0 EXTRA_PREVIOUS_WIFI_STATE=3
12-21 18:24:01.065   967  1212 D WifiClientModeManager[wlan0]: The target role change info null
12-21 18:24:01.065   967  1212 D WifiClientModeManager[wlan0]: Continue to stop wifi//(5)进入已关闭wifi状态1
12-21 18:24:01.065   967  1212 D WifiActiveModeWarden: setting wifi state to: 1
//发送广播 正在已WiFi,EXTRA_WIFI_STATE=1 是当前进入已关闭wifi状态,EXTRA_PREVIOUS_WIFI_STATE=0 表示上一个状态是正在关闭wifi状态
12-21 18:24:01.066   967  1212 D WifiClientModeManager[wlan0]: Sending broadcast=WIFI_STATE_CHANGED_ACTION EXTRA_WIFI_STATE=1 EXTRA_PREVIOUS_WIFI_STATE=0//(6)移除节点信息
12-21 18:24:01.094   967  1212 D WifiNative: IfaceManager#removeIface: id=1, pre-map={1=Iface:{Name=wlan0,Id=1,Type=STA_CONNECTIVITY}}
12-21 18:24:01.127   967  1212 D WifiClientModeManager[wlan0]: STA iface wlan0 was destroyed, stopping client mode
12-21 18:24:01.127   967  1212 W WifiClientModeManager[wlan0]: Received mWifiNativeInterfaceCallback.onDestroyed callback when no ClientModeImpl instance is active.//(7)完成节点关闭
12-21 18:24:01.127   967  1212 I WifiNative: Successfully torn down Iface:{Name=wlan0,Id=1,Type=STA_CONNECTIVITY}
12-21 18:24:01.128   967  1212 I WifiNative: Successfully initiated teardown for iface=wlan0
缺少wifi硬件模组是开启wifi日志:
bsp:/ $logcat | grep -E "WifiService|WifiController|WifiActiveModeWarden|WifiClientModeManager|WifiNative"//(1)打开wifi 的应用包名和uid, uid =1000 表示普通的系统应用, enable=true 表示打开
12-21 18:56:50.905   967  2954 I WifiService: setWifiEnabled package=com.skg.settings uid=1000 enable=true isPrivileged=true//(2)准备打开 wifi
12-21 18:56:50.907   967  1212 D WifiActiveModeWarden: Starting primary ClientModeManager in connect mode
12-21 18:56:50.908   967  1212 D WifiController: DisabledState.exit()
12-21 18:56:50.908   967  1212 D WifiController: EnabledState.enter()//(3)无法打开,进入闲置状态
12-21 18:56:50.908   967  1212 D WifiClientModeManager[unknown]: entering IdleState
12-21 18:56:50.966   967  1212 D WifiNative: IfaceManager#allocateIface: type=2, pre-map={}//(4)Hal 层有异常 died
12-21 18:56:50.969   967  1212 I WifiNative: Vendor HAL died. Cleaning up internal state.//(5)Hal 层无法创建节点
12-21 18:56:50.970   967  1212 E WifiNative: Failed to create iface in vendor HAL//(6)移除节点
12-21 18:56:50.970   967  1212 D WifiNative: IfaceManager#removeIface: id=2, pre-map={2=Iface:{Name=null,Id=2,Type=STA_SCAN}}
12-21 18:56:50.970   967  1212 E WifiClientModeManager[unknown]: Failed to create ClientInterface. Sit in Idle
12-21 18:56:50.970   967  1212 E WifiActiveModeWarden: ClientModeManager start failed!ConcreteClientModeManager{id=6808585 iface=null role=null}
12-21 18:56:50.970   967  1212 V WifiActiveModeWarden: ModeManager removed ConcreteClientModeManager{id=6808585 iface=null role=null}
12-21 18:56:50.978   967  1212 E WifiActiveModeWarden: One of the native daemons died. Triggering recovery
12-21 18:56:50.979   967  1212 E WifiSelfRecovery: Triggering recovery for reason: WifiNative Failure
12-21 18:56:50.979   967  1212 E WifiSelfRecovery: Restarting wifi for reason: WifiNative Failure
12-21 18:56:50.979   967  1212 D WifiController: STA disabled, return to DisabledState.//(7)有可能多次循环该异常日志
12-21 18:56:50.979   967  1212 D WifiController: EnabledState.exit()
12-21 18:56:50.979   967  1212 D WifiController: DisabledState.enter()
12-21 18:56:50.979   967  1212 D WifiController: Recovery triggered, already in disabled state
12-21 18:56:50.995   967  1212 I WifiNative: Vendor HAL died. Cleaning up internal state.
12-21 18:56:50.995   967  1212 E WifiActiveModeWarden: One of the native daemons died. Triggering recovery
12-21 18:56:50.995   967  1212 E WifiSelfRecovery: Triggering recovery for reason: WifiNative Failure
12-21 18:56:50.995   967  1212 E WifiSelfRecovery: Restarting wifi for reason: WifiNative Failure
12-21 18:56:50.995   967  1212 D WifiController: Recovery triggered, already in disabled state
12-21 18:56:52.981   967  1212 D WifiController: Recovery in progress, start wifi
12-21 18:56:52.984   967  1212 D WifiActiveModeWarden: Starting primary ClientModeManager in connect mode
12-21 18:56:52.985   967  1212 D WifiController: DisabledState.exit()
12-21 18:56:52.985   967  1212 D WifiController: EnabledState.enter()
12-21 18:56:52.985   967  1212 D WifiClientModeManager[unknown]: entering IdleState
。。。

重新测试看从(2)准备打开到(3)异常情况,查看整个logcat日志,发现还有部分底层的打印:

12-21 19:14:26.660   967  1212 D HalDevMgr: initIWifiIfNecessary
12-21 19:14:26.664   967  1212 I android_os_HwBinder: HwBinder: Starting thread pool for getting: android.hardware.wifi@1.0::IWifi/default
12-21 19:14:26.666   442   442 I android.hardware.wifi@1.0-service-lazy: Wifi HAL stopped
12-21 19:14:26.667   967  1212 I WifiVendorHal: Device Manager onStatusChanged. isReady(): false, isStarted(): false
12-21 19:14:26.667   967  1212 I WifiNative: Vendor HAL died. Cleaning up internal state.

3、wifi开关状态值

从WifiManager.java 代码看wifi 开关、关闭是有过程状态的:

    /*** The lookup key for an int that indicates whether Wi-Fi is enabled,* disabled, enabling, disabling, or unknown.  Retrieve it with* {@link android.content.Intent#getIntExtra(String,int)}.** @see #WIFI_STATE_DISABLED //1* @see #WIFI_STATE_DISABLING //0 * @see #WIFI_STATE_ENABLED //3* @see #WIFI_STATE_ENABLING //2* @see #WIFI_STATE_UNKNOWN //4*/public static final String EXTRA_WIFI_STATE = "wifi_state";/*** Broadcast intent action indicating that Wi-Fi has been enabled, disabled,* enabling, disabling, or unknown. One extra provides this state as an int.* Another extra provides the previous state, if available.  No network-related* permissions are required to subscribe to this broadcast.** <p class="note">This broadcast is not delivered to manifest receivers in* applications that target API version 26 or later.** @see #EXTRA_WIFI_STATE //广播的wifi状态值数据* @see #EXTRA_PREVIOUS_WIFI_STATE*/@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)public static final String WIFI_STATE_CHANGED_ACTION ="android.net.wifi.WIFI_STATE_CHANGED";

这里可以看到从wifi开关状态广播变化中的额外信息可以看到:

1 是关闭状态,3是打开状态,0 是正在关闭,2是正在打开;

这几个状态变化的过程,正常都是有广播的。

4、之前写的一些wifi相关的知识

汇总:

https://so.csdn.net/so/search?q=wifi&t=blog&u=wenzhi20102321

Android10 系统应用wifi连接和静态ip代理设置:

https://blog.csdn.net/wenzhi20102321/article/details/123675077

Android adb shell svc 知识详解:

https://blog.csdn.net/wenzhi20102321/article/details/132779708

Android无线Wifi开发:

https://blog.csdn.net/wenzhi20102321/article/details/53871216

Android13 wifi状态问题分析:

https://blog.csdn.net/wenzhi20102321/article/details/130411508

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/238132.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

centos(linux)安装jenkins

官网&#xff1a;https://pkg.jenkins.io/redhat/ jdk版本要和jenkins对上&#xff01; 安装官网进行操作&#xff1a; sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat/jenkins.reposudo rpm --import https://pkg.jenkins.io/redhat/jenkins.io-…

Vue表格中鼠标移入移出input显示隐藏 ,有输入值不再隐藏

Vue表格中鼠标移入移出input显示隐藏 , 不再隐藏的效果 <el-tableref"table":data"tableDatas"borderstyle"width: 100%":span-method"arraySpanMethod"id"table"row-key"id"cell-mouse-enter"editCell&q…

如何把透明OLED显示屏介绍给用户人群

透明OLED显示屏是一种新型的显示技术&#xff0c;它具有透明度高、色彩鲜艳、对比度高、响应速度快等优点。下面是一些介绍透明OLED显示屏的要点&#xff1a; 透明度&#xff1a;透明OLED显示屏的最大特点是其透明度&#xff0c;它可以让光线透过显示屏&#xff0c;使得屏幕背后…

案例101:基于微信小程序的停车共享小程序

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

node实现简单的数据爬虫

前言 我使用的是墨迹天气的页面&#xff0c;因为这个使用的链接简单 页面结构简单并且大都是文字形式 第一步 打开墨迹天气网址 随便点开一个页面 点击F12或者鼠标右键点击检查 查看页面的信息 分析页面内容 使用文字所在的class和标签来定位 编写代码 配置express环境 …

景区气象站:旅游体验的新升级

随着科技的发展和人们生活水平的提高&#xff0c;越来越多的人选择在节假日或周末外出旅游&#xff0c;感受大自然的美好。然而&#xff0c;在享受大自然的同时&#xff0c;天气因素成为了影响旅游体验的关键因素之一。为了更好地服务游客&#xff0c;许多景区开始引入气象站&a…

多层负载均衡实现

1、单节点负载均衡 1&#xff09;站点层与浏览器层之间加入了一个反向代理层&#xff0c;利用高性能的nginx来做反向代理 2&#xff09;nginx将http请求分发给后端多个web-server 优点&#xff1a; 1&#xff09;DNS-server不需要动 2&#xff09;负载均衡&#xff1a;通过ngi…

【每日一题】得到山形数组的最少删除次数

文章目录 Tag题目来源解题思路方法一&#xff1a;最长递增子序列 写在最后 Tag 【最长递增子序列】【数组】【2023-12-22】 题目来源 1671. 得到山形数组的最少删除次数 解题思路 方法一&#xff1a;最长递增子序列 前后缀分解 根据前后缀思想&#xff0c;以 nums[i] 为山…

用C#也能做机器学习?

前言✨ 说到机器学习&#xff0c;大家可能都不陌生&#xff0c;但是用C#来做机器学习&#xff0c;可能很多人还第一次听说。其实在C#中基于ML.NET也是可以做机器学习的&#xff0c;这种方式比较适合.NET程序员在项目中集成机器学习模型&#xff0c;不太适合专门学习机器学习&a…

大规模采用奇点临近?Web3应用爆发离不开这个“支撑”赛道

作者&#xff5c;Jason Jiang 数据是当今世界最具价值的资源&#xff0c;也是数字掘金的必争之地。尽管Web3迄今仍有诸多争议&#xff0c;但随着铭文、Gamefi、DeFi等链上生态的多样化发展&#xff0c;我们正身处Web3应用爆发的洪流之中&#xff0c;区块链数据赛道也因此备受关…

vue关闭当前路由页面并跳转到其父页面

1.dom中添加关闭或取消按钮 <el-button type"primary" class"blueLinearbg cancelBtn" click"cancel" >取 消</el-button>2.cancel方法中 /*取消或关闭*/cancel(){this.$store.dispatch("tagsView/delView", this.$route)…

电梯机房【摊鸡蛋】

小伍&#xff1a;大家好&#xff0c;今天小伍给大家表演个机房【摊鸡蛋】&#xff1b; &#xff08; 哈哈哈 &#x1f602;&#x1f602;&#x1f602; &#xff09; 523能源&#xff1a;别闹了&#xff0c;机房里连个锅都没有&#xff0c;怎么摊鸡蛋啊&#xff1f; 小伍&am…

基于javaWeb的長安智慧医疗管理系统设计与实现论文

長安智慧医疗管理系统 摘 要&#xff1a;如今社会上各行各业&#xff0c;都在用属于自己专用的软件来进行工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。互联网的发展&#xff0c;离不开一些新的技术&#xff0c;而新技术的产生往往是为了解决…

Centos7在安装Graylog时新安装MongoDB报错端口不监听服务不启动无法运行启动失败

由于虚拟机服务器上需要安装Graylog需要安装MongoDB&#xff0c;尝试官网下载安装包&#xff0c;和yum安装均无法正常启动&#xff0c;折腾了好几天&#xff0c;重装了十几次&#xff0c;网上搜索了很多很多资料&#xff0c;均无法正常运行&#xff0c;百度上搜索各种文档&…

Java代码审计Mybatis注入文件上传下载读取(非常详细!!)

目录 0x00 前言 0x01 Mybatis注入审计 - 若依&#xff08;Ruoyi&#xff09;后台管理系统 4.6.0 1、项目介绍与部署 - Ruoyi 2、若依 Ruoyi - Mybatis注入 - 代码审计 3、代审常搜词 - Java SQL 注入 0x02 文件上传漏洞审计 - Inxedu && Tmall 1、项目介绍与部署…

Java智慧工地源码 SAAS智慧工地源码 智慧工地管理可视化平台源码 带移动APP

一、系统主要功能介绍 系统功能介绍&#xff1a; 【项目人员管理】 1. 项目管理&#xff1a;项目名称、施工单位名称、项目地址、项目地址、总造价、总面积、施工准可证、开工日期、计划竣工日期、项目状态等。 2. 人员信息管理&#xff1a;支持身份证及人脸信息采集&#…

MyBatis:动态 SQL 标签

MyBatis 动态 SQL 标签if 标签where 标签trim 标签choose 、when 、otherwise 标签foreach 标签附 动态 SQL 标签 MyBatis 动态 SQL 标签&#xff0c;是一组预定义的标签&#xff0c;用于构建动态的 SQL 语句&#xff0c;允许在 SQL 语句中使用条件、循环和迭代等逻辑。通过使…

利用Matplotlib画简单的线形图

实验题目&#xff1a;简单的线形图 实验目的&#xff1a;利用Matplotlib画简单的线形图 实验环境&#xff1a;海豚大数据和人工智能实验室&#xff0c;使用的Python库 名称 版本 简介 numpy 1.16.0 线性代数 Pandas 0.25.0 数据分析 Matplotlib 3.1.0 数据可视化 …

备份至关重要!如何解决iCloud的上次备份无法完成的问题

将iPhone和iPad备份到iCloud对于在设备发生故障或丢失时确保数据安全至关重要。但iOS用户有时会收到一条令人不安的消息&#xff0c;“上次备份无法完成。”下面我们来看看可能导致此问题的原因&#xff0c;如何解决此问题&#xff0c;并使你的iCloud备份再次顺利运行。 这些故…

技术分享-Jenkins

持续集成及Jenkins介绍 软件开发生命周期叫SDLC&#xff08;Software Development Life Cycle&#xff09;&#xff0c;集合了计划、开发、测试、部署过程。 在平常的开发过程中&#xff0c; 需要频繁地&#xff08;一天多次&#xff09;将代码集成到主干&#xff0c;这个叫持…