前言:
wifi chip 的开机初始化流程在这里我们就后面加上,本博客就暂时只有wifi的开启到wifi的连接成功.
虽然都是andriod R,但是还是有可能不同的基线版本代码还是有些许差别,所以我在设备下看了下基线和wifi的软件信息:
/system/bin # iwpriv wlan0 version
wlan0 version:Host SW:5.2.022.4Z, FW:1.0.1.0.31.0, HW:HW_VERSION=ffffffff., Board ver: 8 Ref design id: 0, Customer id: 0, Project id: 0, Board Data Rev: 1, REG DB: 0:0, BDF REG DB: 0:0
:/ # cat /vendor/firmware_mnt/verinfo/ver_info.txt
{
"Image_Build_IDs": {
"adsp": "ADSP.HT.5.3-00597-SM8250-1",
"aop": "AOP.HO.2.0-00187-SM8250_E-1",
"apps": "LA.UM.9.12.r1-09500-SMxx50.0-1",
"boot": "BOOT.XF.3.2-00310-SM8250-1",
"btfm": "BTFM.HST.2.0.0.c3-00403-QCACHROMZ-1",
"btfm_hsp": "BTFM.HSP.1.0.0.c1-00327-QCAHSPROMZ-1",
"cdsp": "CDSP.HT.2.3-00592-SM8250-1",
"common": "SM8250_SDX55.LA_TN.2-0_2-0.r1-00209-STD.PROD-3",
"cvp": "CVP.VPU.1.0-00050-PROD-1",
"glue": "GLUE.SM8250_LA_SDX55_TN.1.01-00351-NOOP_TEST-1",
"npu": "NPU.FW.2.0-00173-SM8250_NPU_PACK-1",
"qssi": "LA.QSSI.11.0.r1-08400-qssi.0-1",
"slpi": "SLPI.HY.3.0-00258-SM8250AZL-1",
"spss": "SPSS.A1.1.3.10-00020-SM8250AAAAANAZS-1",
"tz": "TZ.XF.5.8-00180-SM8250AAAAANAZT-1",
"tzapps": "TZ.APPS.2.0-00126-SM8250AAAAANAZT-1",
"video": "VIDEO.VPU.1.0-00089-PROD-1",
"wigig": "WIGIG.TLN.7.8-00008-WIGIGTLNZ-1",
"wlan_hsp": "WLAN.HSP.1.0.c1-00171-QCAHSPSWPL_V1_SILICONZ-1",
"wlan_hst": "WLAN.HST.1.0.1.r1-00900-QCAHSTSWPL_SILICONZ-1"
},
"Metabuild_Info": {
"Meta_Build_ID": "SM8250_SDX55.LA_TN.2-0_2-0.r1-00209-STD.PROD-3",
"Product_Flavor": "asic",
"Time_Stamp": "2021-05-07 12:26:16"
},
"Version": "1.0"
流程:
1:
系统启动时,systemserver进程中会启动Wifiservice服务,启动该服务在SystemServer.java中:
android/frameworks/base/services/java/com/android/server/SystemServer.java
private static final String WIFI_SERVICE_CLASS = "com.android.server.wifi.WifiService";
private static final String WIFI_SCANNING_SERVICE_CLASS ="com.android.server.wifi.scanner.WifiScanningService";
private static final String WIFI_RTT_SERVICE_CLASS ="com.android.server.wifi.rtt.RttService";
private static final String WIFI_AWARE_SERVICE_CLASS ="com.android.server.wifi.aware.WifiAwareService";
private static final String WIFI_P2P_SERVICE_CLASS ="com.android.server.wifi.p2p.WifiP2pService";
里面不仅包含WIFI_SERVICE_CLASS,还包含一些其他的服务也需要在这个时候启动.
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();
t.traceBegin("StartWifiScanning");
mSystemServiceManager.startServiceFromJar(WIFI_SCANNING_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH);
t.traceEnd();
}
在启动Wifiservice之后,会将此服务加到ServiceManager中:
protected final void publishBinderService(String name, IBinder service,boolean allowIsolated, int dumpPriority) {
ServiceManager.addService(name, service, allowIsolated, dumpPriority);}
2:
android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiService.java
Wifiservice启动时,创建WifiServiceImpl实例对象。它是整个系统WiFi服务的管理者,所有的用户端操作请求都将由它初步预处理,分发给不同的服务处理执行
public WifiService(Context contextBase) {
super(contextBase);
mWifiContext = new WifiContext(contextBase);
WifiInjector injector = new WifiInjector(mWifiContext);
WifiAsyncChannel channel = new WifiAsyncChannel(TAG);
mImpl = new WifiServiceImpl(mWifiContext, injector, channel);
}
接着将WiFiserviceimpl服务加到servicemanager中:
@Override
public void onStart() {
Log.i(TAG, "Registering " + Context.WIFI_SERVICE);
publishBinderService(Context.WIFI_SERVICE, mImpl);
}
调用到的还是这个函数:
protected final void publishBinderService(String name, IBinder service,boolean allowIsolated, int dumpPriority)
{
ServiceManager.addService(name, service, allowIsolated, dumpPriority);
}
3:
android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java
省略一些代码:
是WifiServiceImpl初始化过程,构造该类函数。
public WifiServiceImpl(Context context, WifiInjector wifiInjector, AsyncChannel asyncChannel) {
mClientModeImpl = mWifiInjector.getClientModeImpl();
mActiveModeWarden = mWifiInjector.getActiveModeWarden();
}
WifiServiceImpl做了与WiFi服务管理的相关类的初始化.
- ClientModeImpl 作为客户端的模式实现,作为客户端事件处理在这里完成,并所有的连接状态变化在这里初始化。
- ActiveModeWarden 提供WiFi不同操作模式的配置实现。
到这里,系统启动完成,WifiService服务已正常运行
用户点击WiFi开关按钮打开WiFi,通过Android提供的WiFiManager的接口类,通过AIDL机制将事件传递至WifiSerivce管理服务,在WifiServiceImpl对象中对其处理:
WifiManager --> WifiService --> WifiServiceImpl
android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/ActiveModeWarden.java
public void wifiToggled() {
mWifiController.sendMessage(WifiController.CMD_WIFI_TOGGLED);
}
WifiService服务启动后,在WifiServiceImpl中,调用mActiveModeWarden.start()对其启动。
WifiController是ActiveModeWarden的内部类,继承StateMachine类,在ActiveModeWarden构造函数中对其进行初始化;
private class WifiController extends StateMachine {private static final String TAG = "WifiController"; private boolean mWifiControllerReady = false;}
WifiController状态机状态有三个如下:
- defaultState
- mDisabledState
- mEnabledState
状态机启动时,根据WiFi开启状态进行状态机初始化。因WiFi是由关闭切换至打开,因此,状态机初始到“mDisabledState”状态。
@Override
public void start() {
boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn();
boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled();
boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();
boolean isLocationModeActive = mWifiPermissionsUtil.isLocationModeEnabled();
// Due to cyclic dependency of ActiveModeWarden and WifiApConfigStore, fetch
// WifiConfigStore object later during WifiController.start().
......
mWifiApConfigStore = mWifiInjector.getWifiApConfigStore();
if (shouldEnableSta()) {
startClientModeManager();
setInitialState(mEnabledState);
} else {
setInitialState(mDisabledState);
}
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Location mode has been toggled... trigger with the scan change
// update to make sure we are in the correct mode
scanAlwaysModeChanged();
}
}, new IntentFilter(LocationManager.MODE_CHANGED_ACTION));
super.start();
}
WifiController接收到CMD_WIFI_TOGGLED消息,将在“mDisabledState”状态进行处理:
@Override
public boolean processMessageFiltered(Message msg) {
switch (msg.what) {
case CMD_WIFI_TOGGLED:
case CMD_SCAN_ALWAYS_MODE_CHANGED:
if (shouldEnableSta()) {
startClientModeManager();
transitionTo(mEnabledState);
}
break;
case CMD_SET_AP:
// note: CMD_SET_AP is handled/dropped in ECM mode - will not start here
if (msg.arg1 == 1) {
startSoftApModeManager((SoftApModeConfiguration) msg.obj);
transitionTo(mEnabledState);
}
break;
case CMD_RECOVERY_RESTART_WIFI:
log("Recovery triggered, already in disabled state");
// intentional fallthrough
case CMD_DEFERRED_RECOVERY_RESTART_WIFI:
// wait mRecoveryDelayMillis for letting driver clean reset.
sendMessageDelayed(CMD_RECOVERY_RESTART_WIFI_CONTINUE,
readWifiRecoveryDelay());
break;
case CMD_RECOVERY_RESTART_WIFI_CONTINUE:
if (shouldEnableSta()) {
startClientModeManager();
transitionTo(mEnabledState);
}
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
在消息CMD_SCAN_ALWAYS_MODE_CHANGED中进行startClientModeManager:
android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/ActiveModeWarden.java
private boolean startClientModeManager() {
Log.d(TAG, "Starting ClientModeManager");
ClientListener listener = new ClientListener();
ClientModeManager manager = mWifiInjector.makeClientModeManager(listener);
......
}
进入makeClientModeManager:
android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiInjector.java
public ClientModeManager makeClientModeManager(ClientModeManager.Listener listener) {
return new ClientModeManager(mContext, mWifiHandlerThread.getLooper(), mClock,
mWifiNative, listener, mWifiMetrics, mSarManager, mWakeupController,
mClientModeImpl);
}
进入ClientModeManager:
android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/ClientModeManager.java
ClientModeManager(Context context, @NonNull Looper looper, Clock clock, WifiNative wifiNative,Listener listener, WifiMetrics wifiMetrics, SarManager sarManager,WakeupController wakeupController, ClientModeImpl clientModeImpl) {
mContext = context;
mClock = clock;
mWifiNative = wifiNative;
mModeListener = listener;
mWifiMetrics = wifiMetrics;
mSarManager = sarManager;
mWakeupController = wakeupController;
mClientModeImpl = clientModeImpl;
mStateMachine = new ClientModeStateMachine(looper);
mDeferStopHandler = new DeferStopHandler(TAG, looper);
TAG = "WifiClientModeManager" + TAG_COUNT++;
}
进入ClientModeStateMachine:
ClientModeStateMachine(Looper looper) {
super(TAG, looper);
// CHECKSTYLE:OFF IndentationCheck
addState(mIdleState);
addState(mStartedState, mIdleState);
addState(mScanOnlyModeState, mStartedState);
addState(mConnectModeState, mStartedState);
// CHECKSTYLE:ON IndentationCheck
setInitialState(mIdleState);
start();
}
跳转到start():发送ClientModeStateMachine.CMD_START
@Override
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);
}
ClientModeStateMachine类的状态机,并初始化到“mIdleState”状态和启动状态机。
有如下几个状态:
private final State mIdleState = new IdleState();
private final State mStartedState = new StartedState();
private final State mScanOnlyModeState = new ScanOnlyModeState();
private final State mConnectModeState = new ConnectModeState();
也就是:
- IdleState
- StartedState
- ScanOnlyModeState
- ConnectModeState
接下来在startClientModeManager()调用方法switchClientModeManagerRole(manager)切换客户端设置模式角色。
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;
}
进入ClientModeManager.java的setRole函数:
android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/ClientModeManager.java
@Override
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);
}
}
在setRole()方法中,将role设置的值保存在mTargetRole变量,并发送消息给ClientModeStateMachine状态机。 ActiveModeWarden类中WiFicontroller状态机在DisabledState状态处理完了“CMD_WIFI_TOGGLED”消息,状态机跳转至“EnabledState”。通过状态机机制可知,将会执行DisabledState.exit();执行EnabledState.enter()方法进入到EnabledState状态。WiFicontroller状态机在WiFi打开中将停留在该状态。
在ClientModeStateMachine初始状态为“IdleState”,接着将执行IdleState.enter()方法进入该状态,并开始处理CMD_START消息。
private class IdleState extends State {
@Override
public void enter() {
Log.d(TAG, "entering IdleState");
mClientInterfaceName = null;
mIfaceIsUp = false;
}
@Override
public void exit() {
mModeListener.onStopped();
}
@Override
public boolean processMessage(Message message) {
switch (message.what) {
case CMD_START:
// Always start in scan mode first.
mClientInterfaceName =
mWifiNative.setupInterfaceForClientInScanMode(
mWifiNativeInterfaceCallback);
if (TextUtils.isEmpty(mClientInterfaceName)) {
Log.e(TAG, "Failed to create ClientInterface. Sit in Idle");
mModeListener.onStartFailure();
break;
}
transitionTo(mScanOnlyModeState);
break;
default:
Log.d(TAG, "received an invalid message: " + message);
return NOT_HANDLED;
}
return HANDLED;
}
}
在处理这个消息时,会调用到WifiNative.java的setupInterfaceForClientInScanMode:
android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java
public String setupInterfaceForClientInScanMode(
@NonNull InterfaceCallback interfaceCallback) {
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);
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;
}
}
这个函数包含很多启动,一一进入梳理:
android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java
1:加载WiFi驱动的startHal():
/** Helper method invoked to start supplicant if there were no ifaces */
private boolean startHal() {
synchronized (mLock) {
if (!mIfaceMgr.hasAnyIface()) {
if (mWifiVendorHal.isVendorHalSupported()) {
if (!mWifiVendorHal.startVendorHal()) {
Log.e(TAG, "Failed to start vendor HAL");
return false;
}
} else {
Log.i(TAG, "Vendor Hal not supported, ignoring start.");
}
}
return true;
}
}
android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiVendorHal.java
在mWifiVendorHal.startVendorHal中:
public boolean startVendorHal() {
synchronized (sLock) {
if (!mHalDeviceManager.start()) {
mLog.err("Failed to start vendor HAL").flush();
return false;
}
mLog.info("Vendor Hal started successfully").flush();
return true;
}
}
android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/HalDeviceManager.java
public boolean start() {
return 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) {
WifiStatus status = mWifi.start();
if (status.code == WifiStatusCode.SUCCESS) {
initIWifiChipDebugListeners();
managerStatusListenerDispatch();
if (triedCount != 0) {
Log.d(TAG, "start IWifi succeeded after trying "
+ triedCount + " times");
}
return true;
} else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) {
// Should retry. Hal might still be stopping.
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.
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;
}
}
}
这里就到了HIDL,java层通过binder连接HIDL,下层通过HIDL连接service
通过binder调用,调用到wifi.cpp中的start().
android/hardware/interfaces/wifi/1.4/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) {
// Create the chip instance once the HAL is started.
chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_,
iface_util_, feature_flags_);
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() {
if (!mode_controller_->initialize()) {
LOG(ERROR) << "Failed to initialize firmware mode controller";
return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
}
legacy_hal::wifi_error legacy_status = legacy_hal_->initialize();
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
LOG(ERROR) << "Failed to initialize legacy HAL: "
<< legacyErrorToString(legacy_status);
return createWifiStatusFromLegacyError(legacy_status);
}
return createWifiStatus(WifiStatusCode::SUCCESS);
}
进入mode_controller_->initialize():
android/hardware/interfaces/wifi/1.4/default/wifi_mode_controller.cpp
bool WifiModeController::initialize() {
if (!driver_tool_->LoadDriver()) {
LOG(ERROR) << "Failed to load WiFi driver";
return false;
}
return true;
}
在wifi_load_driver()方法中,将调用系统接口加载WiFi驱动ko。
android/frameworks/opt/net/wifi/libwifi_hal/driver_tool.cpp
bool DriverTool::LoadDriver() {
return ::wifi_load_driver() == 0;
}
android/frameworks/opt/net/wifi/libwifi_hal/wifi_hal_common.cpp
int wifi_load_driver() {
#ifdef WIFI_DRIVER_MODULE_PATH
if (is_wifi_driver_loaded()) {
return 0;
}
int wifi_load_driver() {
#ifdef WIFI_DRIVER_MODULE_PATH
if (is_wifi_driver_loaded()) {
return 0;
}
if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) return -1;
#endif
2:梳理iface.name = createStaIface(iface);
android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java
private String createStaIface(@NonNull Iface iface) {
synchronized (mLock) {
if (mWifiVendorHal.isVendorHalSupported()) {
return mWifiVendorHal.createStaIface(
new InterfaceDestoyedListenerInternal(iface.id));
} else {
Log.i(TAG, "Vendor Hal not supported, ignoring createStaIface.");
return handleIfaceCreationWhenVendorHalNotSupported(iface);
}
}
}
3:梳理:setupInterfaceForClientMode函数
android/frameworks/base/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java
该类的主要对WiFi80211nl管理接口的封装,接口在WiFicond守护进程中呈现给WiFi框架。该类提供的接口仅使用与WiFi框架,访问权限受selinux权限保护。setupInterfaceForClientMode()方法主要为Station模式设置接口。
public boolean setupInterfaceForClientMode(@NonNull String ifaceName,
@NonNull @CallbackExecutor Executor executor,
@NonNull ScanEventCallback scanCallback, @NonNull ScanEventCallback pnoScanCallback) {
Log.d(TAG, "Setting up interface for client mode");
if (!retrieveWificondAndRegisterForDeath()) {
return false;
}
if (scanCallback == null || pnoScanCallback == null || executor == null) {
Log.e(TAG, "setupInterfaceForClientMode invoked with null callbacks");
return false;
}
IClientInterface clientInterface = null;
try {
clientInterface = mWificond.createClientInterface(ifaceName);
} catch (RemoteException e1) {
Log.e(TAG, "Failed to get IClientInterface due to remote exception");
return false;
}
if (clientInterface == null) {
Log.e(TAG, "Could not get IClientInterface instance from wificond");
return false;
}
Binder.allowBlocking(clientInterface.asBinder());
// Refresh Handlers
mClientInterfaces.put(ifaceName, clientInterface);
try {
IWifiScannerImpl wificondScanner = clientInterface.getWifiScannerImpl();
if (wificondScanner == null) {
Log.e(TAG, "Failed to get WificondScannerImpl");
return false;
}
mWificondScanners.put(ifaceName, wificondScanner);
Binder.allowBlocking(wificondScanner.asBinder());
ScanEventHandler scanEventHandler = new ScanEventHandler(executor, scanCallback);
mScanEventHandlers.put(ifaceName, scanEventHandler);
wificondScanner.subscribeScanEvents(scanEventHandler);
PnoScanEventHandler pnoScanEventHandler = new PnoScanEventHandler(executor,
pnoScanCallback);
mPnoScanEventHandlers.put(ifaceName, pnoScanEventHandler);
wificondScanner.subscribePnoScanEvents(pnoScanEventHandler);
} catch (RemoteException e) {
Log.e(TAG, "Failed to refresh wificond scanner due to remote exception");
}
return true;
}
4:ClientModeImpl状态机
android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/ClientModeImpl.java
mRoamingState
mConnectedState
mL2ConnectedState mObtainingIpState
mDefaultState mConnectModeState mDisconnectingState
mDisconnectedState
// CHECKSTYLE:OFF IndentationCheck
addState(mDefaultState);
addState(mConnectModeState, mDefaultState);
addState(mL2ConnectedState, mConnectModeState);
addState(mObtainingIpState, mL2ConnectedState);
addState(mConnectedState, mL2ConnectedState);
addState(mRoamingState, mL2ConnectedState);
addState(mDisconnectingState, mConnectModeState);
addState(mDisconnectedState, mConnectModeState);
// CHECKSTYLE:ON IndentationCheck
setInitialState(mDefaultState);
setLogRecSize(NUM_LOG_RECS_NORMAL);
setLogOnlyTransitions(false);
5:在public void setRole(@Role int role)函数中还包含另外一个消息:
List<Integer> CLIENT_CONNECTIVITY_ROLES = Arrays.asList(
ROLE_CLIENT_PRIMARY,
ROLE_CLIENT_SECONDARY,
ROLE_CLIENT_LOCAL_ONLY);
在IdleState状态中被转为ScanOnlyModeState状态:
transitionTo(mScanOnlyModeState);
流程 :IdleState.exit()->StartedState.enter()->StartedState.exit()->ScanOnlyModeState.enter()。
ClientModeStateMachine状态机已处于“ScanOnlyModeState”,接收到该消息后,并未在ScanOnlyModeStateprocessMessage方法中并未处理,而抛给父状态“StartedState”处理。在StartedState.processMessage()方法中对该消息进行了处理。
public boolean processMessage(Message message) {
switch(message.what) {
case CMD_START:
// Already started, ignore this command.
break;
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);
//切换设置clinent接口到连接模式。
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;
case CMD_SWITCH_TO_SCAN_ONLY_MODE:
updateConnectModeState(WifiManager.WIFI_STATE_DISABLING,
WifiManager.WIFI_STATE_ENABLED);
mDeferStopHandler.start(getWifiOffDeferringTimeMs());
break;
case CMD_SWITCH_TO_SCAN_ONLY_MODE_CONTINUE:
transitionTo(mScanOnlyModeState);
break;
case CMD_INTERFACE_DOWN:
Log.e(TAG, "Detected an interface down, reporting failure to "
+ "SelfRecovery");
mClientModeImpl.failureDetected(SelfRecovery.REASON_STA_IFACE_DOWN);
// once interface down, nothing else to do... stop the state machine
quitNow();
break;
case CMD_INTERFACE_STATUS_CHANGED:
boolean isUp = message.arg1 == 1;
onUpChanged(isUp);
break;
case CMD_INTERFACE_DESTROYED:
Log.e(TAG, "interface destroyed - client mode stopping");
mClientInterfaceName = null;
// once interface destroyed, nothing else to do... stop the state machine
quitNow();
break;
default:
return NOT_HANDLED;
}
updateConnectModeState: 更新WiFi打开状态,发送系统广播通知
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);
}
switchClientInterfaceToConnectivityMode:切换设置clinent接口到连接模式。
public boolean switchClientInterfaceToConnectivityMode(@NonNull String ifaceName) {
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;
}
//调用启动wpa_supplicant服务进程
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);
Log.i(TAG, "Successfully switched to connectivity mode on iface=" + iface);
return true;
}
}
进入startSupplicant函数:
一个个函数进入篇幅太多,直接用这个流程表示一下:
- WifiNative.startSupplicant()
- WifiNative.startAndWaitForSupplicantConnection()
- SupplicantStaIfaceHal.startDaemon()
- SupplicantStaIfaceHal.startDaemon_V1_1()
- SupplicantStaIfaceHal.getSupplicantMockableV1_1()
- SupplicantStaIfaceHal.getSupplicantMockable()
现在我们直接进入SupplicantStaIfaceHal.getSupplicantMockable():
在getService的时候启动wpa_supplicant进程
,通过HIDL调用获取wpa_supplicant服务。ISupplicant.getService(supplicantName)调用到ISupplicant.java。
protected ISupplicant getSupplicantMockable() throws RemoteException, NoSuchElementException {
synchronized (mLock) {
ISupplicant iSupplicant = ISupplicant.getService();
if (iSupplicant == null) {
throw new NoSuchElementException("Cannot get root service.");
}
return iSupplicant;
}
}
进入getService:运行时会将服务名称注册到hwservicemanager中
public static ISupplicant getService(String serviceName) throws android.os.RemoteException {
return ISupplicant.asInterface(android.os.HwBinder.getService("android.hardware.wifi.supplicant@1.0::ISupplicant", serviceName));
}
getService会触发启动wpa_supplicant进程:
- main.c
- wpa_supplicant.c->wpa_supplicant_init()
- notify.c->wpas_notify_supplicant_initialized()
- hidl.cpp->wpas_hidl_init()
- Hidl_manager.cpp->registerHidlService()
进入registerHidlService函数:
int HidlManager::registerHidlService(struct wpa_global *global)
{
::android::status_t status;
// Create the main hidl service object and register it.
supplicant_object_ = new Supplicant(global);
if (global->params.hidl_service_name) {
wpa_printf(MSG_DEBUG, "hidl_register service name %s", global->params.hidl_service_name);
status = supplicant_object_->registerAsService(global->params.hidl_service_name);
} else {
wpa_printf(MSG_DEBUG, "hidl_register service name default");
status = supplicant_object_->registerAsService();
}
if (status != android::NO_ERROR) {
return 1;
}
return 0;
}
- 将wpa_supplicant添加注册到hwservicemanager.
- wpa_supplicant注册完成后,SupplicantStaIfaceHal类中将收到回调通知信息
private final IServiceNotification mServiceNotificationCallback =
new IServiceNotification.Stub() {
public void onRegistration(String fqName, String name, boolean preexisting) {
synchronized (mLock) {
if (mVerboseLoggingEnabled) {
Log.i(TAG, "IServiceNotification.onRegistration for: " + fqName
+ ", " + name + " preexisting=" + preexisting);
}
if (!initSupplicantService()) {
Log.e(TAG, "initalizing ISupplicant failed.");
supplicantServiceDiedHandler(mDeathRecipientCookie);
} else {
Log.i(TAG, "Completed initialization of ISupplicant.");
}
}
}
};
wpa_supplicant进程服务已启动完成,函数执行switchClientInterfaceToConnectivityMode()结束。接着将调用SupplicantStaIfaceHal.setupIface()方法设置接口。设置成功将执行完WifiNative.switchClientInterfaceToConnectivityMode()方法并退出。
ClientModeStateMachine.CMD_SWITCH_TO_CONNECT_MODE消息是在startedstate进程中处理,switchClientInterfaceToConnectivityMode处理成功后直接切换到mConnectModeState.
private class ConnectModeState extends State {
@Override
public void enter() {
Log.d(TAG, "entering ConnectModeState");
mClientModeImpl.registerModeListener(mClientModeImplListener);
mClientModeImpl.setOperationalMode(ClientModeImpl.CONNECT_MODE,
mClientInterfaceName);
}
@Override
public boolean processMessage(Message message) {
switch (message.what) {
case CMD_CONNECT_MODE_READY:
Log.d(TAG, "ConnectMode is ready");
mModeListener.onStarted();
updateConnectModeState(WifiManager.WIFI_STATE_ENABLED,
WifiManager.WIFI_STATE_ENABLING);
// Inform sar manager that wifi is Enabled
mSarManager.setClientWifiState(WifiManager.WIFI_STATE_ENABLED);
break;
case CMD_SWITCH_TO_CONNECT_MODE:
int newRole = message.arg1;
// Already in connect mode, only switching the connectivity roles.
if (newRole != mRole) {
mRole = newRole;
mModeListener.onStarted();
}
break;
case CMD_SWITCH_TO_SCAN_ONLY_MODE:
updateConnectModeState(WifiManager.WIFI_STATE_DISABLING,
WifiManager.WIFI_STATE_ENABLED);
return NOT_HANDLED; // Handled in StartedState.
case CMD_INTERFACE_DOWN:
updateConnectModeState(WifiManager.WIFI_STATE_DISABLING,
WifiManager.WIFI_STATE_UNKNOWN);
return NOT_HANDLED; // Handled in StartedState.
case CMD_INTERFACE_STATUS_CHANGED:
boolean isUp = message.arg1 == 1;
if (isUp == mIfaceIsUp) {
break; // no change
}
if (!isUp) {
if (!mClientModeImpl.isConnectedMacRandomizationEnabled()) {
// Handle the error case where our underlying interface went down if
// we do not have mac randomization enabled (b/72459123).
// if the interface goes down we should exit and go back to idle
// state.
updateConnectModeState(WifiManager.WIFI_STATE_UNKNOWN,
WifiManager.WIFI_STATE_ENABLED);
} else {
return HANDLED; // For MAC randomization, ignore...
}
}
return NOT_HANDLED; // Handled in StartedState.
case CMD_INTERFACE_DESTROYED:
updateConnectModeState(WifiManager.WIFI_STATE_DISABLING,
WifiManager.WIFI_STATE_ENABLED);
return NOT_HANDLED; // Handled in StartedState.
default:
return NOT_HANDLED;
}
return HANDLED;
}
-
设置客户端模式为连接模式:mClientModeImpl.setOperationalMode(ClientModeImpl.CONNECT_MODE,
mClientInterfaceName); -
发送系统广播,通知WiFi已打开: updateConnectModeState(WifiManager.WIFI_STATE_ENABLED,
WifiManager.WIFI_STATE_ENABLING); -
通知SAR管理着WiFi已打开: mSarManager.setClientWifiState(WifiManager.WIFI_STATE_ENABLED);
进入 mClientModeImpl.setOperationalMode:
public void setOperationalMode(int mode, String ifaceName) {
if (mVerboseLoggingEnabled) {
log("setting operational mode to " + String.valueOf(mode) + " for iface: " + ifaceName);
}
mModeChange = true;
if (mode != CONNECT_MODE) {
// we are disabling client mode... need to exit connect mode now
transitionTo(mDefaultState);
} else {
// do a quick sanity check on the iface name, make sure it isn't null
if (ifaceName != null) {
mInterfaceName = ifaceName;
updateInterfaceCapabilities(ifaceName);
transitionTo(mDisconnectedState);
mWifiScoreReport.setInterfaceName(ifaceName);
} else {
Log.e(TAG, "supposed to enter connect mode, but iface is null -> DefaultState");
transitionTo(mDefaultState);
}
}
// use the CMD_SET_OPERATIONAL_MODE to force the transitions before other messages are
// handled.
sendMessageAtFrontOfQueue(CMD_SET_OPERATIONAL_MODE);
}
最后转到了transitionTo(mDisconnectedState).
其中:
- updateInterfaceCapabilities(ifaceName);//更新设置是否支持80211ax。
android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/ActiveModeWarden.java
private class ClientListener extends ModeCallback implements ActiveModeManager.Listener {
@Override
public void onStarted() {
updateClientScanMode();
updateBatteryStats();
}
private void updateClientScanMode() {
boolean scanEnabled = hasAnyClientModeManager();
boolean scanningForHiddenNetworksEnabled;
if (mContext.getResources().getBoolean(R.bool.config_wifiScanHiddenNetworksScanOnlyMode)) {
scanningForHiddenNetworksEnabled = hasAnyClientModeManager();
} else {
scanningForHiddenNetworksEnabled = hasAnyClientModeManagerInConnectivityRole();
}
mScanRequestProxy.enableScanning(scanEnabled, scanningForHiddenNetworksEnabled);
}
private void enableScanningInternal(boolean enable) {
if (!retrieveWifiScannerIfNecessary()) {
Log.e(TAG, "Failed to retrieve wifiscanner");
return;
}
mWifiScanner.setScanningEnabled(enable);
sendScanAvailableBroadcast(mContext, enable);
clearScanResults();
Log.i(TAG, "Scanning is " + (enable ? "enabled" : "disabled"));
}
public void setScanningEnabled(boolean enable) {
validateChannel();
mAsyncChannel.sendMessage(enable ? CMD_ENABLE : CMD_DISABLE);
}
也就是:
- ActiveModeWarden.ClientListener
- ScanRequestProxy.enableScanning()
- ScanRequestProxy.enableScanningInternal()
- wifiScaner.setScanningEnabled()
学习少不了参考模仿,希望对大家有所帮助.