欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

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) {

最编程 2024-06-03 11:25:35
...
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()

推荐阅读