1 Wifi 服务
//frameworks/base/services/java/com/android/server/SystemServer.java
if (context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_WIFI)) {
// Wifi Service must be started first for wifi-related services.
t.traceBegin("StartWifi");
mSystemServiceManager.startServiceFromJar(
WIFI_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH);
t.traceEnd();
//...
}
在 SystemServer 中注册 并启动 WiFi 服务,创建了 WifiService。
//packages/modules/Wifi/service/java/com/android/server/wifi/WifiService.java
public WifiService(Context contextBase) {
super(contextBase);
mWifiContext = new WifiContext(contextBase);
WifiInjector injector = new WifiInjector(mWifiContext);
mImpl = new WifiServiceImpl(mWifiContext, injector);
}
public void onStart() {
Log.i(TAG, "Registering " + Context.WIFI_SERVICE);
publishBinderService(Context.WIFI_SERVICE, mImpl);
}
创建 WifiService 实例时创建了一些对象,WifiInjector 管理和组织与 Wi-Fi 相关的各种操作和组件,WifiServiceImpl 是 WiFi 服务的具体实现,其成员几乎全由 WifiInjector 创建。并将 WifiServiceImpl 注册到 ServiceManager 中。
简单看下Android11 相对Android9 新增加与Wifi打开相关的几个初始化类:
- ClientModeImpl 作为客户端的模式实现,作为客户端事件处理在这里完成,并所有的连接状态变化在这里初始化。
- ActiveModeWarden 提供WiFi不同操作模式的配置实现。
//packages/modules/Wifi/service/java/com/android/server/wifi/WifiService.java
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
mImpl.checkAndStartWifi();
} else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
mImpl.handleBootCompleted();
}
}
Boot 分不同阶段,与 WifiService 相关的有两个阶段:PHASE_SYSTEM_SERVICES_READY,PHASE_BOOT_COMPLETED。
2 PHASE_SYSTEM_SERVICES_READY 阶段
在 PHASE_SYSTEM_SERVICES_READY 阶段,SystemServer 将会通过其内部的 SystemServiceManager 来挨个调用自己管理的系统服务的 onBootPhase,也就包括 WifiService,接下来调用到 WifiServiceImpl 的 checkAndStartWifi 方法中。
//packages/modules/Wifi/service/java/com/android/server/wifi/WifiServiceImpl.java
public void checkAndStartWifi() {
mWifiThreadRunner.post(() -> {
if (!mWifiConfigManager.loadFromStore()) {
Log.e(TAG, "Failed to load from config store");
}
mWifiConfigManager.incrementNumRebootsSinceLastUse();
// config store is read, check if verbose logging is enabled.
enableVerboseLoggingInternal(
mWifiInjector.getSettingsConfigStore().get(WIFI_VERBOSE_LOGGING_ENABLED)
? 1 : 0);
// Check if wi-fi needs to be enabled
boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();
Log.i(TAG,
"WifiService starting up with Wi-Fi " + (wifiEnabled ? "enabled" : "disabled"));
mWifiInjector.getWifiScanAlwaysAvailableSettingsCompatibility().initialize();
mWifiInjector.getWifiNotificationManager().createNotificationChannels();
//mContext.registerReceiver(
// new BroadcastReceiver(),
// new IntentFilter(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED))
//...
registerForBroadcasts();
mInIdleMode = mPowerManager.isDeviceIdleMode();
mActiveModeWarden.start();
registerForCarrierConfigChange();
mWifiInjector.getAdaptiveConnectivityEnabledSettingObserver().initialize();
});
}
首先,代码会尝试从配置存储中加载 Wi-Fi 配置信息,如果加载失败则记录错误日志。
然后,调用 WifiConfigManager.incrementNumRebootsSinceLastUse 方法来增加自上次使用以来的重启次数。
接下来,通过 WifiInjector 获取 SettingsConfigStore 来检查是否启用了详细日志记录,并调用enableVerboseLoggingInternal 方法来设置是否启用详细日志。
然后,检查 Wi-Fi 是否需要启用。根据 SettingsStore 的 isWifiToggleEnabled 方法返回的结果来确定是否启用 Wi-Fi,并记录日志。
接着,代码初始化了一些相关的设置,如扫描常可用性设置和通知管理器的通知通道。
接下来,注册了多个广播接收器,分别用于监听 SIM 卡状态变化、SIM 卡应用状态变化、默认数据卡变化、网络国家代码变化和语言环境变化。当接收到相应的广播时,会执行相应的逻辑,如重置运营商网络、更新国家代码等。
然后,调用 registerForBroadcasts 方法注册了一个用于监听应用移除和修改事件的广播接收器。
最后,开始了一些后台任务,包括启动ActiveModeWarden、注册运营商配置更改的监听和初始化自适应网络功能的使能设置观察器对象。
//packages/modules/Wifi/service/java/com/android/server/wifi/ActiveModeWarden.java
public void start() {
mContext.registerReceiver(new BroadcastReceiver()
, new IntentFilter(LocationManager.MODE_CHANGED_ACTION));
//...
if (trackEmergencyCallState) {
mContext.registerReceiver(new BroadcastReceiver()
, new IntentFilter(TelephonyManager.ACTION_EMERGENCY_CALL_STATE_CHANGED));
}
mWifiController.start();
}
注册多个广播接收器。监听 Location mode 的变化时,以确保 Wi-Fi 处于正确的扫描模式。监听飞行模式切换。监听紧急呼叫回调模式变化时,并调用 emergencyCallbackModeChanged 方法来处理相应的变化。监听紧急呼叫状态变化,根据配置文件中是否指定需要跟踪紧急呼叫状态,判断是否调用 emergencyCallStateChanged方法进行处理。
接下来启动内部的 WifiController 状态机。
//packages/modules/Wifi/service/java/com/android/server/wifi/ActiveModeWarden.java/WifiController.class
public void start() {
boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn();
boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled();
boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();
boolean isLocationModeActive = mWifiPermissionsUtil.isLocationModeEnabled();
//log
mLastPrimaryClientModeManagerRequestorWs = mFacade.getSettingsWorkSource(mContext);
mLastScanOnlyClientModeManagerRequestorWs = INTERNAL_REQUESTOR_WS;
ActiveModeManager.ClientRole role = getRoleForPrimaryOrScanOnlyClientModeManager();
if (role == ROLE_CLIENT_PRIMARY) {
startPrimaryClientModeManager(mLastPrimaryClientModeManagerRequestorWs);
setInitialState(mEnabledState);
} else if (role == ROLE_CLIENT_SCAN_ONLY) {
startScanOnlyClientModeManager(mLastScanOnlyClientModeManagerRequestorWs);
setInitialState(mEnabledState);
} else {
setInitialState(mDisabledState);
}
mWifiMetrics.noteWifiEnabledDuringBoot(mSettingsStore.isWifiToggleEnabled());
// Initialize the lower layers before we start.
mWifiNative.initialize();
super.start();
}
根据 Log 来看,isAirplaneModeOn = false,isWifiEnabled = true,isScanningAlwaysAvailable = true,isLocationModeActive = false,role = ROLE_CLIENT_PRIMARY。所以这里创建了 PrimaryClientModeManager,并转换到 EnableState状态。创建了一个 ClientManager时向其内部状态机发送了一个 CMD_START。状态机处理这个消息时,调用了 WifiNative 的 setupInterfaceForClientInScanMode 方法,来设置 Client Interface。事实上根据日志,这里是设置失败的(在 setupInterfaceForClientMode 时,返回了 false),所以触发了 ClientListener 的 onStartFailure 回调,将WifiController 的状态切换成 DisableState,并将这个 ClientManager 删除。
WifiNative 中创建了 NetdWraper,这里和 INetd关联起来了。
3 PHASE_BOOT_COMPLETED
在 PHASE_BOOT_COMPLETED 阶段,ActivityManagerService 将会通过其内部的 SystemServiceManager 来挨个调用自己管理的系统服务的 onBootPhase,也就包括 WifiService,接下来调用到 WifiServiceImpl 的 checkAndStartWifi 方法中。
//packages/modules/Wifi/service/java/com/android/server/wifi/WifiServiceImpl.java
public void handleBootCompleted() {
mWifiThreadRunner.post(() -> {
Log.d(TAG, "Handle boot completed");
// Register for system broadcasts.
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_USER_REMOVED);
intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
intentFilter.addAction(Intent.ACTION_SHUTDOWN);
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//...
}, intentFilter);
mMemoryStoreImpl.start();
mPasspointManager.initializeProvisioner(
mWifiInjector.getPasspointProvisionerHandlerThread().getLooper());
mWifiInjector.getWifiNetworkFactory().register();
mWifiInjector.getUntrustedWifiNetworkFactory().register();
mWifiInjector.getOemWifiNetworkFactory().register();
mIsBootComplete = true;
mWifiInjector.getWifiP2pConnection().handleBootCompleted();
// Start to listen country code change.
mCountryCode.registerListener(new CountryCodeListenerProxy());
mTetheredSoftApTracker.handleBootCompleted();
mWifiInjector.getSarManager().handleBootCompleted();
});
}
注册系统广播接收器:
- 当接收到 Intent.ACTION_USER_REMOVED 广播时,获取用户句柄并调用WifiConfigManager.removeNetworksForUser 方法来移除该用户的网络配置。
- 当接收到 BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED 广播时,获取蓝牙连接状态,并更新WifiGlobals 的蓝牙连接状态,然后遍历 ActiveModeWarden.getClientModeManagers 并调用onBluetoothConnectionStateChanged 方法。
- 当接收到 BluetoothAdapter.ACTION_STATE_CHANGED 广播时,获取蓝牙状态,并更新 WifiGlobals 的蓝牙启用状态,然后遍历 ActiveModeWarden.getClientModeManagers 并调用 onBluetoothConnectionStateChanged 方法。
- 当接收到 PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED 广播时,调用 handleIdleModeChanged方法来处理设备空闲模式变化。
- 当接收到 Intent.ACTION_SHUTDOWN 广播时,调用 handleShutDown 方法来处理设备关机操作。
执行其他逻辑:
- 调用 MemoryStoreImpl.start 方法来启动内存存储实现。
- 调用 PasspointManager.initializeProvisioner 方法来初始化Passpoint的配置者。
- 注册 WifiNetworkFactory、UntrustedWifiNetworkFactory 和 OemWifiNetworkFactory。
- 设置 IsBootComplete为true,表示启动完成。
- 调用 WifiInjector.getWifiP2pConnection.handleBootCompleted方法来处理Wi-Fi P2P的启动完成。
- 注册国家代码变化的监听器。
- 调用 TetheredSoftApTracker.handleBootCompleted 方法来处理启动完成后的热点跟踪。
- 调用 WifiInjector.getSarManager.handleBootCompleted 方法来处理 SAR(Specific Absorption Rate)管理器的启动完成。
4 开启 WLAN
//packages/apps/Settings/src/com/android/settings/wifi/WifiEnabler.java
public boolean onSwitchToggled(boolean isChecked) {
//...
if (!mWifiManager.setWifiEnabled(isChecked)) {
// Error
mSwitchWidget.setEnabled(true);
Toast.makeText(mContext, R.string.wifi_error, Toast.LENGTH_SHORT).show();
}
return true;
}
从 WifiEnabler 开始,用户点击 WiFi 开关按钮打开WiFi,通过 Android 提供的 WiFiManager 的接口类,通过 AIDL 机制将事件传递至 WifiSerivce 管理服务,在 WifiServiceImpl 对象中对其处理。
//packages/modules/Wifi/service/java/com/android/server/wifi/WifiServiceImpl.java
public synchronized boolean setWifiEnabled(String packageName, boolean enable) {
if (enforceChangePermission(packageName) != MODE_ALLOWED) {
return false;
}
boolean isPrivileged = isPrivileged(Binder.getCallingPid(), Binder.getCallingUid());
if (!isPrivileged && !isDeviceOrProfileOwner(Binder.getCallingUid(), packageName)
&& !mWifiPermissionsUtil.isTargetSdkLessThan(packageName, Build.VERSION_CODES.Q,
Binder.getCallingUid())
&& !mWifiPermissionsUtil.isSystem(packageName, Binder.getCallingUid())) {
mLog.info("setWifiEnabled not allowed for uid=%")
.c(Binder.getCallingUid()).flush();
return false;
}
// If Airplane mode is enabled, only privileged apps are allowed to toggle Wifi
if (mSettingsStore.isAirplaneModeOn() && !isPrivileged) {
mLog.err("setWifiEnabled in Airplane mode: only Settings can toggle wifi").flush();
return false;
}
// If SoftAp is enabled, only privileged apps are allowed to toggle wifi
if (!isPrivileged && mTetheredSoftApTracker.getState() == WIFI_AP_STATE_ENABLED) {
mLog.err("setWifiEnabled with SoftAp enabled: only Settings can toggle wifi").flush();
return false;
}
if (contrastLastCallerPrio(LastCallerInfoManager.WIFI_ENABLED, packageName)){
return false;
}
mLog.info("setWifiEnabled package=% uid=% enable=%").c(packageName)
.c(Binder.getCallingUid()).c(enable).flush();
long ident = Binder.clearCallingIdentity();
try {
if (!mSettingsStore.handleWifiToggled(enable)) {
// Nothing to do if wifi cannot be toggled
return true;
}
} finally {
Binder.restoreCallingIdentity(ident);
}
if (mWifiPermissionsUtil.checkNetworkSettingsPermission(Binder.getCallingUid())) {
if (enable) {
mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_ON);
} else {
WifiInfo wifiInfo =
getPrimaryClientModeManagerBlockingThreadSafe().syncRequestConnectionInfo();
mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_OFF,
wifiInfo == null ? -1 : wifiInfo.getNetworkId());
}
}
mWifiMetrics.incrementNumWifiToggles(isPrivileged, enable);
mActiveModeWarden.wifiToggled(new WorkSource(Binder.getCallingUid(), packageName));
mLastCallerInfoManager.put(LastCallerInfoManager.WIFI_ENABLED, Process.myTid(),
Binder.getCallingUid(), Binder.getCallingPid(), packageName, enable);
return true;
}
- enforceChangePermission(packageName) != MODE_ALLOWED:首先,它检查调用者是否具有足够的权限来执行 Wi-Fi 启用/禁用操作。如果权限不足,将返回 false。
- isPrivileged 检查:在这里,代码判断调用者是否有特权(privileged)来执行此操作。如果不是特权调用者,它会进行一系列的权限检查。
- 权限检查:这一部分代码检查调用者是否满足特定条件,如设备管理员、系统应用程序、目标 API 等,以决定是否允许执行 Wi-Fi 启用/禁用操作。
- Airplane mode 检查:如果飞行模式开启,只有特权应用程序可以切换 Wi-Fi。其他应用无法进行切换。
- SoftAp 检查:如果共享热点(SoftAp)已启用,只有特权应用程序可以切换 Wi-Fi。这个检查避免了在启用 SoftAp 时切换 Wi-Fi。
- 切换 Wi-Fi 状态:在这一部分,代码尝试切换 Wi-Fi 的状态。如果切换成功,返回 true;如果无法切换,返回 false。
- checkNetworkSettingsPermission 检查:检查调用者是否具有网络设置权限。如果是启用操作,记录用户事件,并更新相应的指标。
- 记录指标:根据操作是否由特权调用者执行,增加 Wi-Fi 启用/禁用的计数。
- wifiToggled 调用:通过 mActiveModeWarden 触发 Wi-Fi 启用/禁用的事件。
- 记录调用者信息:记录最近的调用者信息,以便追踪最后一次执行的操作。
//packages/modules/Wifi/service/java/com/android/server/wifi/ActiveModeWarden.java
public void wifiToggled(WorkSource requestorWs) {
mWifiController.sendMessage(WifiController.CMD_WIFI_TOGGLED, requestorWs);
}
ActiveModeWarden 有一个内部类 WifiController。WifiController 是高级别的 WiFi 状态机,它管理的状态是 WiFi 开关,WiFi 热点开关等状态。wifiToggled 向 WifiController 发送一个 CMD_WIFI_TOGGLED 信号。在 DisableState 状态下来处理 CMD_WIFI_TOGGLED 消息。
处理 CMD_WIFI_TOGGLED 时调用流程:handleStaToggleChangeInDisabledState -> startPrimaryOrScanOnlyClientModeManager -> startPrimaryClientModeManager(role = ROLE_CLIENT_PRIMARY)。创建了一个 ClientManager,并向其内部状态机发送了一个 CMD_START。
//packages/modules/Wifi/service/java/com/android/server/wifi/ConcreteClientModeManager.java
case CMD_START:
// Always start in scan mode first.
RoleChangeInfo roleChangeInfo = (RoleChangeInfo) message.obj;
mClientInterfaceName = mWifiNative.setupInterfaceForClientInScanMode(
mWifiNativeInterfaceCallback, roleChangeInfo.requestorWs);
if (TextUtils.isEmpty(mClientInterfaceName)) {
Log.e(getTag(), "Failed to create ClientInterface. Sit in Idle");
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;
状态机处理这个消息时,调用了 WifiNative 的 setupInterfaceForClientInScanMode 方法。
//packages/modules/Wifi/service/java/com/android/server/wifi/WifiNative.java
public String setupInterfaceForClientInScanMode(
@NonNull InterfaceCallback interfaceCallback, @NonNull WorkSource requestorWs) {
synchronized (mLock) {
if (!startHal()) {
Log.e(TAG, "Failed to start Hal");
mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
return null;
}
Iface 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;
}
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;
}
iface.networkObserver = new NetworkObserverInternal(iface.id);
if (!registerNetworkObserver(iface.networkObserver)) {
Log.e(TAG, "Failed to register network observer for iface=" + iface.name);
teardownInterface(iface.name);
return null;
}
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));
Log.i(TAG, "Successfully setup " + iface);
iface.featureSet = getSupportedFeatureSetInternal(iface.name);
return iface.name;
}
}
- 调用 startHal() 方法启动 HAL(硬件抽象层)。如果启动失败,则记录错误日志,增加相应的统计计数,并返回 null。
- 调用 allocateIface() 方法分配一个新的 STA(站点)接口,接口类型为 IFACE_TYPE_STA_FOR_SCAN。如果分配失败,则记录错误日志并返回 null。
- 将接口的外部监听器设置为 interfaceCallback。
- 调用 createStaIface() 方法在厂商的 HAL 中创建接口,并将接口名称赋值给 iface.name。如果创建失败,则记录错误日志,移除接口,并返回 null。
- 调用 mWifiCondManager.setupInterfaceForClientMode() 方法设置接口的客户端模式,使用 iface.name 作为参数,并提供运行回调函数、普通扫描事件回调和 Pno 扫描事件回调。如果设置失败,则记录错误日志,执行接口的拆除操作,并返回 null。
- 创建一个 NetworkObserverInternal 并将其赋值给 iface.networkObserver。
- 调用 registerNetworkObserver() 方法注册网络观察器,传入 iface.networkObserver 作为参数。如果注册失败,则记录错误日志,执行接口的拆除操作,并返回 null。
- 调用 mWifiMonitor.startMonitoring() 方法开始监听该接口的事件。
- 在退出前,更新接口状态并调用 onInterfaceStateChanged() 方法,避免与接口状态改变回调之间的竞争条件。
- 记录信息日志,表示接口设置成功。
- 获取接口支持的特性集,并将其赋值给 iface.featureSet。
- 返回接口名称 iface.name。
setupInterfaceForClientInScanMode 执行完以后开始向内部 StateMachine 发送一个 CMD_SWITCH_TO_CONNECT_MODE 消息,然后转换到 StartedState。
//packages/modules/Wifi/service/java/com/android/server/wifi/ConcreteClientModeManager.java/StartedState.class
case CMD_SWITCH_TO_CONNECT_MODE: {
RoleChangeInfo roleChangeInfo = (RoleChangeInfo) message.obj;
updateConnectModeState(roleChangeInfo.role,
WifiManager.WIFI_STATE_ENABLING,
WifiManager.WIFI_STATE_DISABLED);
if (!mWifiNative.switchClientInterfaceToConnectivityMode(
mClientInterfaceName, roleChangeInfo.requestorWs)) {
//...
}
// Role set in the enter of ConnectModeState.
mConnectRoleChangeInfoToSetOnTransition = roleChangeInfo;
transitionTo(mConnectModeState);
break;
}
首先更新连接模式的状态,接着调用 WifiNative 的 switchClientInterfaceToConnectivityMode 方法将 Client Interface 切换到 connecvity 模式,接着将状态转换成 ConnectModeState。
//packages/modules/Wifi/service/java/com/android/server/wifi/WifiNative.java
public boolean switchClientInterfaceToConnectivityMode(@NonNull String ifaceName,
@NonNull WorkSource requestorWs) {
synchronized (mLock) {
final Iface iface = mIfaceMgr.getIface(ifaceName);
if (iface == null) {
Log.e(TAG, "Trying to switch to connectivity mode on an invalid iface="
+ ifaceName);
return false;
}
if (iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY) {
Log.e(TAG, "Already in connectivity mode on iface=" + ifaceName);
return true;
}
if (mWifiVendorHal.isVendorHalSupported()
&& !mWifiVendorHal.replaceStaIfaceRequestorWs(iface.name, requestorWs)) {
Log.e(TAG, "Failed to replace requestor ws on " + iface);
teardownInterface(iface.name);
return false;
}
if (!startSupplicant()) {
Log.e(TAG, "Failed to start supplicant");
teardownInterface(iface.name);
mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
return false;
}
if (!mSupplicantStaIfaceHal.setupIface(iface.name)) {
Log.e(TAG, "Failed to setup iface in supplicant on " + iface);
teardownInterface(iface.name);
mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
return false;
}
iface.type = Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY;
iface.featureSet = getSupportedFeatureSetInternal(iface.name);
mIsEnhancedOpenSupported = (iface.featureSet & WIFI_FEATURE_OWE) != 0;
Log.i(TAG, "Successfully switched to connectivity mode on iface=" + iface);
return true;
}
}
- 通过传入的接口名
ifaceName
从mIfaceMgr
(接口管理器)中获取对应的接口iface
。 - 如果获取到的接口为空(
iface == null
),则打印错误日志并返回失败。 - 如果接口的类型已经是连接模式(
iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY
),则打印错误日志并返回成功。 - 如果支持供应商硬件抽象层(Vendor HAL)且无法成功替换接口请求者的工作源(
!mWifiVendorHal.replaceStaIfaceRequestorWs(iface.name, requestorWs)
),则打印错误日志、拆除接口并返回失败。 - 如果无法成功启动Supplicant(
!startSupplicant()
),则打印错误日志、拆除接口、增加度量指标中的失败计数,并返回失败。 - 如果无法在Supplicant中成功设置接口(
!mSupplicantStaIfaceHal.setupIface(iface.name)
),则打印错误日志、拆除接口、增加度量指标中的失败计数,并返回失败。 - 将接口的类型设置为连接模式(
iface.type = Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY
)。 - 使用
getSupportedFeatureSetInternal
方法获取接口支持的特性集,并将其赋值给接口的featureSet
属性。 - 根据接口的特性集,判断是否支持增强开放(Enhanced Open)功能。
- 打印信息日志,表示成功切换到连接模式,并返回成功。
//packages/modules/Wifi/service/java/com/android/server/wifi/ConcreteClientModeManager.java/ConnectModeState.class
public void enter() {
//...
mClientModeImpl = mWifiInjector.makeClientModeImpl(
mClientInterfaceName, ConcreteClientModeManager.this,
mVerboseLoggingEnabled);
mClientModeImpl.setShouldReduceNetworkScore(mShouldReduceNetworkScore);
//...
// Could be any one of possible connect mode roles.
setRoleInternalAndInvokeCallback(mConnectRoleChangeInfoToSetOnTransition);
updateConnectModeState(mConnectRoleChangeInfoToSetOnTransition.role,
WIFI_STATE_ENABLED, WIFI_STATE_ENABLING);
}
创建了一个 ClientModeImpl 对象,设置是否需要降低网络分数,网络质量较差时,可以将shouldReduceNetworkScore设置为true,以降低网络得分,反映出较差的网络状况。设置当前的角色(primary or scan_only),并激活回调函数,更新连接状态。