Android 11 WiFi开启流程-STA_PRIMARY,如果是打开其他WiFi,则参数2为传入的staId。 frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java public synchronized boolean setWifiEnabled(String packageName, boolean enable) { return setWifiEnabled2(packageName, STA_PRIMARY, enable); } public synchronized boolean setWifiEnabled2(String packageName, int staId,boolean enable) { if (enforceChangePermission(packageName) != MODE_ALLOWED) {
private class StartedState extends State {
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;
十二、可以看到这里启动了supplicant frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java
public boolean switchClientInterfaceToConnectivityMode(@NonNull String ifaceName) {
synchronized (mLock) {
final Iface iface = mIfaceMgr.getIface(ifaceName);
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;
}
}
private boolean startSupplicant() {
synchronized (mLock) {
if (!mIfaceMgr.hasAnyStaIfaceForConnectivity()) {
if (!startAndWaitForSupplicantConnection()) {
Log.e(TAG, "Failed to connect to supplicant");
return false;
}
if (!mSupplicantStaIfaceHal.registerDeathHandler(
new SupplicantDeathHandlerInternal())) {
Log.e(TAG, "Failed to register supplicant death handler");
return false;
}
}
return true;
}
}
在这里等待与supplicant建立连接
private boolean startAndWaitForSupplicantConnection() {
// Start initialization if not already started.
if (!mSupplicantStaIfaceHal.isInitializationStarted()
&& !mSupplicantStaIfaceHal.initialize()) {
return false;
}
if (!mSupplicantStaIfaceHal.startDaemon()) {
Log.e(TAG, "Failed to startup supplicant");
return false;
}
boolean connected = false;
int connectTries = 0;
while (!connected && connectTries++ < CONNECT_TO_SUPPLICANT_RETRY_TIMES) {
// Check if the initialization is complete.
connected = mSupplicantStaIfaceHal.isInitializationComplete();
if (connected) {
break;
}
try {
Thread.sleep(CONNECT_TO_SUPPLICANT_RETRY_INTERVAL_MS);
} catch (InterruptedException ignore) {
}
}
return connected;
}
十三、这里是通过HIDL来打开supplicant的 frameworks/opt/net/wifi/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
startDaemon -> startDaemon_V1_1 -> getSupplicantMockableV1_1 -> getSupplicantMockable
protected ISupplicant getSupplicantMockable() throws RemoteException, NoSuchElementException {
synchronized (mLock) {
ISupplicant iSupplicant = ISupplicant.getService();
if (iSupplicant == null) {
throw new NoSuchElementException("Cannot get root service.");
}
return iSupplicant;
}
}
android/out/soong/intermediates/hardware/interfaces/wifi/supplicant/1.0/android.hardware.wifi.supplicant-V1.0-java_gen_java/gen/srcs/android/hardware/wifi/supplicant/V1_0/ISupplicant.java
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));
}
十四、 在这个方法中将触发启动wpa_supplicant进程,这里需要注意,在manifest.xml中对其需要进行配置,运行时会将服务名称注册到hwservicemanager中。
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()
int HidlManager::registerHidlService(struct wpa_global *global)
{
// Create the main hidl service object and register it.
supplicant_object_ = new Supplicant(global);
if (supplicant_object_->registerAsService("wpa_supplicant") != android::NO_ERROR) {
return 1;
}
return 0;
}
十五、将wpa_supplicant添加注册到hwservicemanager,SupplicantStaIfaceHal.getSupplicantMockable()执行完成返回。
这里再深入看下“supplicant_object_->registerAsService(“wpa_supplicant”)”是如何通过调用注册的呢?
android/out/soong/.intermediates/hardware/interfaces/wifi/supplicant/1.3/android.hardware.wifi.supplicant@1.3_genc++/gen/android/hardware/wifi/supplicant/1.3/SupplicantAll.cpp
android/system/libhidl/transport/ServiceManagement.cpp
android/system/hwservicemanager/ServiceManager.cpp
supplicant_object_->registerAsService("wpa_supplicant") ==> ISupplicant.hal
==> ISupplicantAll.cpp->registerAsService()
==> ::android::hardware::details::registerAsServiceInternal(this, serviceName)
==> ServiceManagement.cpp->registerAsServiceInternal()
==> ServiceManager->addWithChain()
==> ServiceManager->addImpl()
十六、wpa_supplicant注册完成后,SupplicantStaIfaceHal类中将收到回调通知信息,
private final IServiceNotification mServiceNotificationCallback =
new IServiceNotification.Stub() {
public void onRegistration(String fqName, String name, boolean preexisting) {
synchronized (mLock) {
if (!initSupplicantService()) {
supplicantServiceDiedHandler(mDeathRecipientCookie);
}
返回通知的调用逻辑。
SupplicantStaIfaceHal.initSupplicantService() -> SupplicantStaIfaceHal.getSupplicantMockable()
十七、到此位置supplicant已经启动。 switchClientInterfaceToConnectivityMode会继续调用SupplicantStaIfaceHal.setupIface()方法设置接口。设置成功后,就会打印成功的日志。
Log.i(TAG, "Successfully switched to connectivity mode on iface=" + iface);
十八、CMD_SWITCH_TO_CONNECT_MODE消息处理完以后状态机就会切换到ConnectModeState。 这里会调用setOperationalMode
transitionTo(mConnectModeState);
private class ConnectModeState extends State {
@Override
public void enter() {
Log.d(TAG, "entering ConnectModeState");
mClientModeImpl.registerModeListener(mClientModeImplListener);
mClientModeImpl.setOperationalMode(ClientModeImpl.CONNECT_MODE,
mClientInterfaceName);
}
十九、这里会进入到mDisconnectedState frameworks/opt/net/wifi/service/java/com/android/server/wifi/ClientModeImpl.java
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);
}
二十、ActiveModeWarden类中设置的ClientLister将被触发回调。 wifiScaner.setScanningEnabled()发送消息CMD_ENABLE,给到WiFiscanningSerivceimpl类中。 到这里,WiFi已处于打开状态,并将进行扫描网络,待连接。WiFi打开流程分析完成。
ActiveModeWarden.ClientListener -> ScanRequestProxy.enableScanning() ->
ScanRequestProxy.enableScanningInternal() -> wifiScaner.setScanningEnabled()
上一篇: 八进制转义字符和十六进制转义字符简介