Android WIFI 模块解析

Posted bug樱樱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android WIFI 模块解析相关的知识,希望对你有一定的参考价值。

SystemServer

android的大部分服务都是在SystemServer中孵化出来的,wifi也不例外,从SystemServer注册WifiService开始梳理.

//wifi 扫描 和获取相关功能 Service
private static final String WIFI_SERVICE_CLASS =
        "com.android.server.wifi.WifiService";
//wifi 感知相关功能Service
private static final String WIFI_AWARE_SERVICE_CLASS =
        "com.android.server.wifi.aware.WifiAwareService";
//wifi P2P  相关功能 Service
private static final String WIFI_P2P_SERVICE_CLASS =
        "com.android.server.wifi.p2p.WifiP2pService"; 
if (context.getPackageManager().hasSystemFeature(
        PackageManager.FEATURE_WIFI)) 
    // Wifi Service must be started first for wifi-related services.
    traceBeginAndSlog("StartWifi");
    mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
    traceEnd();
    traceBeginAndSlog("StartWifiScanning");
    mSystemServiceManager.startService(
            "com.android.server.wifi.scanner.WifiScanningService");
    traceEnd();
 

SystemServer之中主要工作就是定义WifiService,启动了WifiServiceWifiScanningService.

相关代码路径

  • com.android.server.SystemServer

相关参考文档

WifiService

public final class WifiService extends SystemService 

    final WifiServiceImpl mImpl;

    public WifiService(Context context) 
        super(context);
        //创建具体的事务类
        mImpl = new WifiServiceImpl(context, new WifiInjector(context), new WifiAsyncChannel(TAG));
    

    @Override
    public void onStart() 
        Log.i(TAG, "Registering " + Context.WIFI_SERVICE);
        //绑定事务类
        publishBinderService(Context.WIFI_SERVICE, mImpl);
    

    @Override
    public void onBootPhase(int phase) 
        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) 
            mImpl.checkAndStartWifi();
        
    
    ...
 

onBootPhase随着系统服务的进程会不断的调用到具体的Service中.在具体的Service判断进度值执行逻辑.此处调用逻辑主要是检查wifi模块是否需要启动,如果需要启动就启动wifi模块.总体来说WifiService的主要作用就是绑定了WifiServiceImpl类.

WifiServiceImpl

public class WifiServiceImpl extends IWifiManager.Stub 
   ...
 

可以看到WifiServiceImpl类继承了IWifiManager.Stub函数,熟悉aidl的已经知道它的内部主要实现的函数在aidl文件中已经定义了. 对外部暴露的类就是我们在应用中常用的WifiManager类.

往下看,首先看WifiServiceImpl的构造函数

public WifiServiceImpl(Context context, WifiInjector wifiInjector, AsyncChannel asyncChannel) 
    mContext = context;
    mWifiInjector = wifiInjector;
    mClock = wifiInjector.getClock();

    mFacade = mWifiInjector.getFrameworkFacade();
    mWifiMetrics = mWifiInjector.getWifiMetrics();
    mTrafficPoller = mWifiInjector.getWifiTrafficPoller();
    mUserManager = mWifiInjector.getUserManager();
    mCountryCode = mWifiInjector.getWifiCountryCode();
    mWifiStateMachine = mWifiInjector.getWifiStateMachine();
    mWifiStateMachinePrime = mWifiInjector.getWifiStateMachinePrime();
    mWifiStateMachine.enableRssiPolling(true);
    mScanRequestProxy = mWifiInjector.getScanRequestProxy();
    mSettingsStore = mWifiInjector.getWifiSettingsStore();
    mPowerManager = mContext.getSystemService(PowerManager.class);
    mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
    mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
    mWifiLockManager = mWifiInjector.getWifiLockManager();
    mWifiMulticastLockManager = mWifiInjector.getWifiMulticastLockManager();
    HandlerThread wifiServiceHandlerThread = mWifiInjector.getWifiServiceHandlerThread();
    mClientHandler = new ClientHandler(TAG, wifiServiceHandlerThread.getLooper());
    mWifiStateMachineHandler = new WifiStateMachineHandler(TAG,
            wifiServiceHandlerThread.getLooper(), asyncChannel);
    mWifiController = mWifiInjector.getWifiController();
    mWifiBackupRestore = mWifiInjector.getWifiBackupRestore();
    mWifiApConfigStore = mWifiInjector.getWifiApConfigStore();
    mPermissionReviewRequired = Build.PERMISSIONS_REVIEW_REQUIRED
            || context.getResources().getBoolean(
            com.android.internal.R.bool.config_permissionReviewRequired);
    mWifiPermissionsUtil = mWifiInjector.getWifiPermissionsUtil();
  ...
 

构造函数中有三个参数

  • Context 这个大家很熟悉

  • WifiInjector wifi模块相关的对象的初始化工作都在这个类里进行.没有做其他多余的事情. 包括状态机的初始化就在这里进行初始化,然后通过get函数赋值给WifiServiceImpl中.

public WifiInjector(Context context) 
    if (context == null) 
        throw new IllegalStateException(
                "WifiInjector should not be initialized with a null Context.");
    

    if (sWifiInjector != null) 
        throw new IllegalStateException(
                "WifiInjector was already created, use getInstance instead.");
    

    sWifiInjector = this;

    mContext = context;
    mUseRealLogger = mContext.getResources().getBoolean(
            R.bool.config_wifi_enable_wifi_firmware_debugging);
    mSettingsStore = new WifiSettingsStore(mContext);
    mWifiPermissionsWrapper = new WifiPermissionsWrapper(mContext);
    mNetworkScoreManager = mContext.getSystemService(NetworkScoreManager.class);
    mWifiNetworkScoreCache = new WifiNetworkScoreCache(mContext);
    mNetworkScoreManager.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
            mWifiNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_NONE);
    mWifiPermissionsUtil = new WifiPermissionsUtil(mWifiPermissionsWrapper, mContext,
            mSettingsStore, UserManager.get(mContext), this);
    ...
    mWifiServiceHandlerThread = new HandlerThread("WifiService");
    mWifiServiceHandlerThread.start();
    mWifiStateMachineHandlerThread = new HandlerThread("WifiStateMachine");
    mWifiStateMachineHandlerThread.start();
    Looper wifiStateMachineLooper = mWifiStateMachineHandlerThread.getLooper();
    mCarrierNetworkConfig = new CarrierNetworkConfig(mContext,
        mWifiServiceHandlerThread.getLooper(), mFrameworkFacade);
    WifiAwareMetrics awareMetrics = new WifiAwareMetrics(mClock);
    RttMetrics rttMetrics = new RttMetrics(mClock);
    mWifiMetrics = new WifiMetrics(mClock, wifiStateMachineLooper, awareMetrics, rttMetrics);
    // Modules interacting with Native.  与Native 模块交互的对象,后文有见到
    mWifiMonitor = new WifiMonitor(this);
    mHalDeviceManager = new HalDeviceManager(mClock);
    mWifiVendorHal =
            new WifiVendorHal(mHalDeviceManager, mWifiStateMachineHandlerThread.getLooper());
    mSupplicantStaIfaceHal = new SupplicantStaIfaceHal(mContext, mWifiMonitor);
    mHostapdHal = new HostapdHal(mContext);
    mWificondControl = new WificondControl(this, mWifiMonitor, mCarrierNetworkConfig);
    mNwManagementService = INetworkManagementService.Stub.asInterface(
            ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
    // wifiNative 对象在此创建.
    mWifiNative = new WifiNative(
            mWifiVendorHal, mSupplicantStaIfaceHal, mHostapdHal, mWificondControl,
            mWifiMonitor, mNwManagementService, mPropertyService, mWifiMetrics);
    ...

    // Now get instances of all the objects that depend on the HandlerThreads
    mTrafficPoller = new WifiTrafficPoller(mContext, mWifiServiceHandlerThread.getLooper(),
            mWifiNative);
    mCountryCode = new WifiCountryCode(mWifiNative,
            SystemProperties.get(BOOT_DEFAULT_WIFI_COUNTRY_CODE),
            mContext.getResources()
                    .getBoolean(R.bool.config_wifi_revert_country_code_on_cellular_loss));
    mWifiApConfigStore = new WifiApConfigStore(mContext, mBackupManagerProxy);

    // WifiConfigManager/Store objects and their dependencies.
    // New config store
    mWifiKeyStore = new WifiKeyStore(mKeyStore);
    mWifiConfigStore = new WifiConfigStore(
            mContext, wifiStateMachineLooper, mClock,
            WifiConfigStore.createSharedFile());
    ...
    mWifiConfigStoreLegacy = new WifiConfigStoreLegacy(
            mWifiNetworkHistory, mWifiNative, new WifiConfigStoreLegacy.IpConfigStoreWrapper(),
            new LegacyPasspointConfigParser());
    // Config Manager
    mWifiConfigManager = new WifiConfigManager(mContext, mClock,
            UserManager.get(mContext), TelephonyManager.from(mContext),
            mWifiKeyStore, mWifiConfigStore, mWifiConfigStoreLegacy, mWifiPermissionsUtil,
            mWifiPermissionsWrapper, new NetworkListStoreData(mContext),
            new DeletedEphemeralSsidsStoreData());
    mWifiMetrics.setWifiConfigManager(mWifiConfigManager);
    mWifiConnectivityHelper = new WifiConnectivityHelper(mWifiNative);
    mConnectivityLocalLog = new LocalLog(ActivityManager.isLowRamDeviceStatic() ? 256 : 512);
    mScoringParams = new ScoringParams(mContext, mFrameworkFacade,
            new Handler(wifiStateMachineLooper));
    mWifiMetrics.setScoringParams(mScoringParams);
    mWifiNetworkSelector = new WifiNetworkSelector(mContext, mScoringParams,
            mWifiConfigManager, mClock,
            mConnectivityLocalLog);
    mWifiMetrics.setWifiNetworkSelector(mWifiNetworkSelector);
    ...
 
  • AsyncChannel 这个也是一个比较重要的概念,简单的说就是在两个Handle之间处理异步消息同步消息使用.在这里是与wifi状态机中SmHandler中建立一个通道.
/**
 * Handles interaction with WifiStateMachine
 */
private class WifiStateMachineHandler extends WifiHandler 
    private AsyncChannel mWsmChannel;

    WifiStateMachineHandler(String tag, Looper looper, AsyncChannel asyncChannel) 
        super(tag, looper);
        mWsmChannel = asyncChannel;
        //链接
        mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler());
    

    @Override
    public void handleMessage(Message msg) 
        super.handleMessage(msg);
        switch (msg.what) 
            case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 
                if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) 
                      //链接成功 赋值
                    mWifiStateMachineChannel = mWsmChannel;
                 else 
                    Slog.e(TAG, "WifiStateMachine connection failure, error=" + msg.arg1);
                    // 链接失败,置空
                    mWifiStateMachineChannel = null;
                
                break;
            
            case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 
                Slog.e(TAG, "WifiStateMachine channel lost, msg.arg1 =" + msg.arg1);
                mWifiStateMachineChannel = null;  // 置空
                //Re-establish connection to state machine  断开 重连
                mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler());
                break;
            
            default: 
                Slog.d(TAG, "WifiStateMachineHandler.handleMessage ignoring msg=" + msg);
                break;
            
        
    
 

可以看到构造函数中主要就是做一些全局属性的赋值.具体初始化的操作在WifiInjector中,通过get函数赋值给WifiServiceImpl的全局变量.

WifiStateMachine

wifi模块状态机,前文中已经出镜了很多次,状态机在系统的wifi,Bluetooth等模块都有很广泛的应用.

  • Android 4.4 WifiStateMachine状态机

  • Android 9.0 WifiStateMachine状态机

状态机模块应该是在不同的Android版本之间变动最大的模块,中间经历了优化层级,状态合并,p2p等功能拆分等变动.

简单的描述一下状态机是一个什么功能,举个例子:

1:假如我们接到一个需求,开发一个自动回应系统,按某些数字之后,有自动回复,或者给用户提供某些服务,c服务需要你先进入B状态,用户在你提供C服务的时候,有需要你提供E服务,E服务的前置服务是D服务,假如不够智能的话那就需要4步 C->B->D->E . 那么状态机器在你由C切换E的时候,直接帮助你把省略这些繁琐的操作,直接默认执行了这些状态的进入和退出的代码.

  • 如果需要完全的理解状态机的完整概念,请自行百度状态机.有很多文章讲这个东西.

那么回到wifi模块的状态机中,先看构造函数

public WifiStateMachine(Context context, FrameworkFacade facade, Looper looper,
                        UserManager userManager, WifiInjector wifiInjector,
                        BackupManagerProxy backupManagerProxy, WifiCountryCode countryCode,
                        WifiNative wifiNative,
                        WrongPasswordNotifier wrongPasswordNotifier,
                        SarManager sarManager) 
    super("WifiStateMachine", looper);
    mWifiInjector = wifiInjector;
    mWifiMetrics = mWifiInjector.getWifiMetrics();
    mClock = wifiInjector.getClock();
    mPropertyService = wifiInjector.getPropertyService();
    mBuildProperties = wifiInjector.getBuildProperties();
    mContext = context;
    mFacade = facade;
    mWifiNative = wifiNative;
    mBackupManagerProxy = backupManagerProxy;
    mWrongPasswordNotifier = wrongPasswordNotifier;
    mSarManager = sarManager;
    //赋值操作
    // TODO refactor WifiNative use of context out into it's own class
    mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
    mBatteryStats = IBatteryStats.Stub.asInterface(mFacade.getService(
            BatteryStats.SERVICE_NAME));
    mWifiStateTracker = wifiInjector.getWifiStateTracker();
    IBinder b = mFacade.getService(Context.NETWORKMANAGEMENT_SERVICE);

    mP2pSupported = mContext.getPackageManager().hasSystemFeature(
            PackageManager.FEATURE_WIFI_DIRECT);

    mWifiPermissionsUtil = mWifiInjector.getWifiPermissionsUtil();
    mWifiConfigManager = mWifiInjector.getWifiConfigManager();

    mPasspointManager = mWifiInjector.getPasspointManager();

    mWifiMonitor = mWifiInjector.getWifiMonitor();
    mWifiDiagnostics = mWifiInjector.getWifiDiagnostics();
    mScanRequestProxy = mWifiInjector.getScanRequestProxy();
    mWifiPermissionsWrapper = mWifiInjector.getWifiPermissionsWrapper();

    mWifiInfo = new ExtendedWifiInfo();
    mSupplicantStateTracker =
            mFacade.makeSupplicantStateTracker(context, mWifiConfigManager, getHandler());

    mLinkProperties = new LinkProperties();
    mMcastLockManagerFilterController = new McastLockManagerFilterController();

    mNetworkInfo.setIsAvailable(false);
    mLastBssid = null;
    mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
    mLastSignalLevel = -1;

      ...

    mUserWantsSuspendOpt.set(mFacade.getIntegerSetting(mContext,
            Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);

    updateConnectedMacRandomizationSetting();

    PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
    mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getName());

    mSuspendWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WifiSuspend");
    mSuspendWakeLock.setReferenceCounted(false);

    mTcpBufferSizes = mContext.getResources().getString(
            com.android.internal.R.string.config_wifi_tcp_buffers);

    // CHECKSTYLE:OFF IndentationCheck
    addState(mDefaultState);  //添加wifi模块各种状态 ,状态机就在这里
        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);

    //start the state machine//启动状态机
    start();

    // Learn the initial state of whether the screen is on.
    // We update this field when we receive broadcasts from the system.
    handleScreenStateChanged(powerManager.isInteractive());
 

然后wifi模块的各个状态的转换之间的逻辑就在DefaultState这些状态的enter(),exit()processMessage()函数之间兜兜转转.

WifiManager (应用层使用看这里)

@SystemService(Context.WIFI_SERVICE)  
public class WifiManager 
    
    /**
     * Create a new WifiManager instance.
     * Applications will almost always want to use    // 这里告诉我们应用想要使用 通过 下面的方式去获取
     * @link android.content.Context#getSystemService Context.getSystemService() to retrieve
     * the standard @link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE.
     * @param context the application context
     * @param service the Binder interface
     * @hide - hide this because it takes in a parameter of type IWifiManager, which
     * is a system private class.   // 这里使用了hide的方式去隐藏次函数,告诉我们使用这是一个系统私有类
     */
    public WifiManager(Context context, IWifiManager service, Looper looper) 
        mContext = context;
        mService = service;
        mLooper = looper;
        mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
    
 

按照惯例我们贴出了它的构造函数,如果是上层App应用去简单的使用wifi模块的相关功能,那么看懂上面的代码就可以,看懂了上面的代码,我们就知道怎么去获取WifiManager对象.

WifiManager mWifiManager;
mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE); 

后面我们就需要根据 WifiManager提供的函数去设计我们的上层逻辑即可.同样具体的实现或逻辑判断是放在继承IWifiManager.StubWifiServiceImpl中去.

  • WifiManager注册
final class SystemServiceRegistry 
    ...
    static 
        ...
        registerService(Context.WIFI_SERVICE, WifiManager.class,
                new CachedServiceFetcher<WifiManager>() 
            @Override
            public WifiManager createService(ContextImpl ctx) throws ServiceNotFoundException 
                IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_SERVICE);
                IWifiManager service = IWifiManager.Stub.asInterface(b);
                return new WifiManager(ctx.getOuterContext(), service,
                        ConnectivityThread.getInstanceLooper());
            );
        ...
    
    ...
 

实际例子(开机 checkAndStartWifi())

我们以开机之后检查wifi状态是否在关机前是开启状态,然后打开wifi的例子:

1: WifiService.onBootPhase()

 @Override
    public void onBootPhase(int phase) 
        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) 
            //检查并启动wifi
            mImpl.checkAndStartWifi();
        
     

2: WifiServiceImpl.checkAndStartWifi()

/**
 * Check if we are ready to start wifi.
 *
 * First check if we will be restarting system services to decrypt the device. If the device is
 * not encrypted, check if Wi-Fi needs to be enabled and start if needed
 *
 * This function is used only at boot time.
 */
public void checkAndStartWifi() 
    // First check if we will end up restarting WifiService
    if (mFrameworkFacade.inStorageManagerCryptKeeperBounce()) 
        Log.d(TAG, "Device still encrypted. Need to restart SystemServer.  Do not start wifi.");
        return;
    

    // Check if wi-fi needs to be enabled 
    // 检查是否需要打开wifi.取决于关机时wifi状态
    boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();
    Slog.i(TAG, "WifiService starting up with Wi-Fi " +
            (wifiEnabled ? "enabled" : "disabled"));
        ... //注册广播监听
    registerForScanModeChange();
        ...
    // Adding optimizations of only receiving broadcasts when wifi is enabled
    // can result in race conditions when apps toggle wifi in the background
    // without active user involvement. Always receive broadcasts.
    registerForBroadcasts();
    mInIdleMode = mPowerManager.isDeviceIdleMode();

    if (!mWifiStateMachine.syncInitialize(mWifiStateMachineChannel)) 
        Log.wtf(TAG, "Failed to initialize WifiStateMachine");
    
    //关于wifi操作模式的状态机启动. 例如 飞行模式,wifi热点模式 等等.
    mWifiController.start();

    // If we are already disabled (could be due to airplane mode), avoid changing persist
    // state here
    if (wifiEnabled) 
        try 
            //如果上次wifi是开的,设置wifi开关.
            setWifiEnabled(mContext.getPackageName(), wifiEnabled);
         catch (RemoteException e) 
            /* ignore - local call */
        
    
 

3: WifiServiceImpl.setWifiEnabled()

/**
 * see @link android.net.wifi.WifiManager#setWifiEnabled(boolean)
 * @param enable @code true to enable, @code false to disable.
 * @return @code true if the enable/disable operation was
 *         started or is already in the queue.
 */
@Override
public synchronized boolean setWifiEnabled(String packageName, boolean enable)
        throws RemoteException 
        
        //检查应用权限
    if (enforceChangePermission(packageName) != MODE_ALLOWED) 
        return false;
    

    Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid()
                + ", uid=" + Binder.getCallingUid() + ", package=" + packageName);
    mLog.info("setWifiEnabled package=% uid=% enable=%").c(packageName)
            .c(Binder.getCallingUid()).c(enable).flush();
    //检查网络权限
    boolean isFromSettings = checkNetworkSettingsPermission(
            Binder.getCallingPid(), Binder.getCallingUid());

    // If Airplane mode is enabled, only Settings is allowed to toggle Wifi
    if (mSettingsStore.isAirplaneModeOn() && !isFromSettings) 
        mLog.info("setWifiEnabled in Airplane mode: only Settings can enable wifi").flush();
        return false;
    
    // 各种检查wifi 状态,如果已经打开了,return true.
      ...

    //权限审核.
    if (mPermissionReviewRequired) 
        final int wiFiEnabledState = getWifiEnabledState();
        if (enable) 
            if (wiFiEnabledState == WifiManager.WIFI_STATE_DISABLING
                    || wiFiEnabledState == WifiManager.WIFI_STATE_DISABLED) 
                if (startConsentUi(packageName, Binder.getCallingUid(),
                        WifiManager.ACTION_REQUEST_ENABLE)) 
                    return true;
                
            
         else if (wiFiEnabledState == WifiManager.WIFI_STATE_ENABLING
                || wiFiEnabledState == WifiManager.WIFI_STATE_ENABLED) 
            if (startConsentUi(packageName, Binder.getCallingUid(),
                    WifiManager.ACTION_REQUEST_DISABLE)) 
                return true;
            
        
    
    // 发送消息
    mWifiController.sendMessage(CMD_WIFI_TOGGLED);
    return true;
 

4 WifiController

mWifiController这个对象在wifiServiceImpl的构造函数中赋值的,我们简单看下它的构造函数,看一下CMD_WIFI_TOGGLED状态由谁接收

/**
 * WifiController is the class used to manage on/off state of WifiStateMachine for various operating
 * modes (normal, airplane, wifi hotspot, etc.).
 */
public class WifiController extends StateMachine 
    

WifiController(Context context, WifiStateMachine wsm, Looper wifiStateMachineLooper,
WifiSettingsStore wss, Looper wifiServiceLooper, FrameworkFacade f,
WifiStateMachinePrime wsmp)
super(TAG, wifiServiceLooper);
mFacade = f;
mContext = context;
mWifiStateMachine = wsm;
mWifiStateMachineLooper = wifiStateMachineLooper;
mWifiStateMachinePrime = wsmp;
mSettingsStore = wss;

// CHECKSTYLE:OFF IndentationCheck
addState(mDefaultState);
    addState(mStaDisabledState, mDefaultState);
    addState(mStaEnabledState, mDefaultState);
        addState(mDeviceActiveState, mStaEnabledState);
    addState(mStaDisabledWithScanState, mDefaultState);
    addState(mEcmState, mDefaultState);
// CHECKSTYLE:ON IndentationCheck

boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn();
boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled();
boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();
boolean isLocationModeActive =
        mSettingsStore.getLocationModeSetting(mContext)
                == Settings.Secure.LOCATION_MODE_OFF;

log("isAirplaneModeOn = " + isAirplaneModeOn
        + ", isWifiEnabled = " + isWifiEnabled
        + ", isScanningAvailable = " + isScanningAlwaysAvailable
        + ", isLocationModeActive = " + isLocationModeActive);

//这里决定了初始的状态是那一个
if (checkScanOnlyModeAvailable()) 
    setInitialState(mStaDisabledWithScanState);
 else 
    setInitialState(mStaDisabledState);


setLogRecSize(100);
setLogOnlyTransitions(false);

// register for state updates via callbacks (vs the intents registered below)
mWifiStateMachinePrime.registerScanOnlyCallback(mScanOnlyModeCallback);
mWifiStateMachinePrime.registerClientModeCallback(mClientModeCallback);

...
readWifiReEnableDelay();

*   checkScanOnlyModeAvailable()


private boolean checkScanOnlyModeAvailable()
// first check if Location service is disabled, if so return false
// 首先看定位服务是否关闭,如果关闭,直接返回false.
if (mSettingsStore.getLocationModeSetting(mContext)
== Settings.Secure.LOCATION_MODE_OFF)
return false;

// 这个的基本通过这个值来控制 Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE 默认值为0 就是不打开
return mSettingsStore.isScanAlwaysAvailable();

由此得知默认状态为 `mStaDisabledState`

### 5: WifiController.StaDisabledState


class StaDisabledState extends State
private int mDeferredEnableSerialNumber = 0;
private boolean mHaveDeferredEnable = false;
private long mDisabledTimestamp;

@Override
public void enter() 
    mWifiStateMachinePrime.disableWifi();
    //加了一点延时,不让上层的开关操作立刻生效.
    // Supplicant can't restart right away, so note the time we switched off
    mDisabledTimestamp = SystemClock.elapsedRealtime();
    mDeferredEnableSerialNumber++;
    mHaveDeferredEnable = false;
    mWifiStateMachine.clearANQPCache();

@Override
public boolean processMessage(Message msg) 
    switch (msg.what) 
        case CMD_WIFI_TOGGLED:
            if (mSettingsStore.isWifiToggleEnabled()) 
                if (doDeferEnable(msg)) 
                    if (mHaveDeferredEnable) 
                        //  have 2 toggles now, inc serial number and ignore both
                        mDeferredEnableSerialNumber++;
                    
                    mHaveDeferredEnable = !mHaveDeferredEnable;
                    break;
                
                //这里切换状态.
                transitionTo(mDeviceActiveState);
             else if (checkScanOnlyModeAvailable()) 
                // only go to scan mode if we aren't in airplane mode
                if (mSettingsStore.isAirplaneModeOn()) 
                    transitionTo(mStaDisabledWithScanState);
                
            
            break;
        ...
    
    return HANDLED;


private boolean doDeferEnable(Message msg) 
    long delaySoFar = SystemClock.elapsedRealtime() - mDisabledTimestamp;
    if (delaySoFar >= mReEnableDelayMillis) 
        return false;
    

    log("WifiController msg " + msg + " deferred for " +
            (mReEnableDelayMillis - delaySoFar) + "ms");

    // need to defer this action.
    Message deferredMsg = obtainMessage(CMD_DEFERRED_TOGGLE);
    deferredMsg.obj = Message.obtain(msg);
    deferredMsg.arg1 = ++mDeferredEnableSerialNumber;
    sendMessageDelayed(deferredMsg, mReEnableDelayMillis - delaySoFar + DEFER_MARGIN_MS);
    return true;

### 6: WifiController.DeviceActiveState


/**

  • Parent: StaEnabledState
    *

  • TODO (b/79209870): merge DeviceActiveState and StaEnabledState into a single state
    */
    class DeviceActiveState extends State
    @Override
    public void enter()
    //这里
    mWifiStateMachinePrime.enterClientMode();
    //无效的,所以固定的写了false. 可能各个版本不同
    mWifiStateMachine.setHighPerfModeEnabled(false);

    @Override
    public boolean processMessage(Message msg)

    return NOT_HANDLED;

### 7: WifiStateMachinePrime.enterClientMode()


/**

  • Method to switch wifi into client mode where connections to configured networks will be
  • attempted.
    */
    public void enterClientMode()
    changeMode(ModeStateMachine.CMD_START_CLIENT_MODE);

private void changeMode(int newMode)
//我们看看 mModeStateMachine 是个什么东西
mModeStateMachine.sendMessage(newMode);

### 8: ModeStateMachine

`ModeStateMachine`也是继承`StateMachine`,内部也是维和了几个状态的状态机


private class ModeStateMachine extends StateMachine

// Commands for the state machine  - these will be removed,
// along with the StateMachine itself
public static final int CMD_START_CLIENT_MODE    = 0;
public static final int CMD_START_SCAN_ONLY_MODE = 1;
public static final int CMD_DISABLE_WIFI         = 3;

private final State mWifiDisabledState = new WifiDisabledState();
private final State mClientModeActiveState = new ClientModeActiveState();
private final State mScanOnlyModeActiveState = new ScanOnlyModeActiveState();

ModeStateMachine() 
    super(TAG, mLooper);

    addState(mClientModeActiveState);
    addState(mScanOnlyModeActiveState);
    addState(mWifiDisabledState);

    Log.d(TAG, "Starting Wifi in WifiDisabledState");
    //初始状态,我们看 WifiDisabledState 状态中是怎么处理的
    setInitialState(mWifiDisabledState);
    start();

    //这里切换状态
private boolean checkForAndHandleModeChange(Message message) 
    switch(message.what) 
        case ModeStateMachine.CMD_START_CLIENT_MODE:
            Log.d(TAG, "Switching from " + getCurrentMode() + " to ClientMode");
            mModeStateMachine.transitionTo(mClientModeActiveState);
            break;
        case ModeStateMachine.CMD_START_SCAN_ONLY_MODE:
            Log.d(TAG, "Switching from " + getCurrentMode() + " to ScanOnlyMode");
            mModeStateMachine.transitionTo(mScanOnlyModeActiveState);
            break;
        case ModeStateMachine.CMD_DISABLE_WIFI:
            Log.d(TAG, "Switching from " + getCurrentMode() + " to WifiDisabled");
            mModeStateMachine.transitionTo(mWifiDisabledState);
            break;
        default:
            return NOT_HANDLED;
    
    return HANDLED;

### 9: WifiDisabledState


class WifiDisabledState extends ModeActiveState
@Override
public void enter()
Log.d(TAG, “Entering WifiDisabledState”);
//通知外界关闭状态,和清除之前的存储结果
mDefaultModeManager.sendScanAvailableBroadcast(mContext, false);
mScanRequestProxy.enableScanningForHiddenNetworks(false);
mScanRequestProxy.clearScanResults();

@Override
public boolean processMessage(Message message) 
    Log.d(TAG, "received a message in WifiDisabledState: " + message);
    //这里调用切换状态 发送的消息是 CMD_START_CLIENT_MODE. 切换到 mClientModeActiveState
    if (checkForAndHandleModeChange(message)) 
        return HANDLED;
    
    return NOT_HANDLED;


@Override
public void exit() 
    // do not have an active mode manager...  nothing to clean up

### 10: ClientModeActiveState


class ClientModeActiveState extends ModeActiveState
ClientListener mListener;
private class ClientListener implements ClientModeManager.Listener
@Override
public void onStateChanged(int state)
// make sure this listener is still active
if (this != mListener)
Log.d(TAG, “Client mode state change from previous manager”);
return;

        Log.d(TAG, "State changed from client mode. state = " + state);

        if (state == WifiManager.WIFI_STATE_UNKNOWN) 
            // error while setting up client mode or an unexpected failure.
            mModeStateMachine.sendMessage(CMD_CLIENT_MODE_FAILED, this);
         else if (state == WifiManager.WIFI_STATE_DISABLED) 
            // client mode stopped
            mModeStateMachine.sendMessage(CMD_CLIENT_MODE_STOPPED, this);
         else if (state == WifiManager.WIFI_STATE_ENABLED) 
            // client mode is ready to go
            Log.d(TAG, "client mode active");
         else 
            // only care if client mode stopped or started, dropping
        
    


@Override
public void enter() 
    Log.d(TAG, "Entering ClientModeActiveState");
    //进入状态
    mListener = new ClientListener();
    // 这里创建一个ClientModeManager,我们接着看 ClientModeManager
    mManager = mWifiInjector.makeClientModeManager(mListener);
    mManager.start();
    mActiveModeManagers.add(mManager);

    updateBatteryStatsWifiState(true);


@Override
public void exit() 
    super.exit();
    mListener = null;


@Override
public boolean processMessage(Message message) 
    if (checkForAndHandleModeChange(message)) 
        return HANDLED;
    
   ...

### 11:ClientModeManager


/**

  • Manager WiFi in Client Mode where we connect to configured networks.
    */
    public class ClientModeManager implements ActiveModeManager

    private static final String TAG = “WifiClientModeManager”;
    private final ClientModeStateMachine mStateMachine;

    ClientModeManager(Context context, @NonNull Looper looper, WifiNative wifiNative,
    Listener listener, WifiMetrics wifiMetrics, ScanRequestProxy scanRequestProxy,
    WifiStateMachine wifiStateMachine)
    mContext = context;
    mWifiNative = wifiNative;
    mListener = listener;
    mWifiMetrics = wifiMetrics;
    mScanRequestProxy = scanRequestProxy;
    mWifiStateMachine = wifiStateMachine;
    mStateMachine = new ClientModeStateMachine(looper);

    /**
     * Start client mode.
     */
    public void start() 
        // 这里看名字就知道,又是一个状态机 ,发送CMD_START 指令
        mStateMachine.sendMessage(ClientModeStateMachine.CMD_START);
    
    ...
    
    

### 12: ClientModeStateMachine


private class ClientModeStateMachine extends StateMachine
// Commands for the state machine.
public static final int CMD_START = 0;
public static final int CMD_INTERFACE_STATUS_CHANGED = 3;
public static final int CMD_INTERFACE_DESTROYED = 4;
public static final int CMD_INTERFACE_DOWN = 5;
//只有两种状态
private final State mIdleState = new IdleState();
private final State mStartedState = new StartedState();

ClientModeStateMachine(Looper looper) 
    super(TAG, looper);

    addState(mIdleState);
    addState(mStartedState);
    //默认状态为 mIdleState 
    setInitialState(mIdleState);
    start();

### 13: IdleState


private class IdleState extends State

@Override
public void enter() 
    Log.d(TAG, "entering IdleState");
    //进来没有做什么事情
    mClientInterfaceName = null;
    mIfaceIsUp = false;


@Override
public boolean processMessage(Message message) 
    switch (message.what) 
        case CMD_START:
            //走这里
            updateWifiState(WifiManager.WIFI_STATE_ENABLING,
                            WifiManager.WIFI_STATE_DISABLED);
            //在这里 出现了总算是没有在跳转不同的状态机了.到了一个类似Native函数中. 
            mClientInterfaceName = mWifiNative.setupInterfaceForClientMode(
                    false /* not low priority */, mWifiNativeInterfaceCallback);
            if (TextUtils.isEmpty(mClientInterfaceName)) 
                Log.e(TAG, "Failed to create ClientInterface. Sit in Idle");
                updateWifiState(WifiManager.WIFI_STATE_UNKNOWN,
                                WifiManager.WIFI_STATE_ENABLING);
                updateWifiState(WifiManager.WIFI_STATE_DISABLED,
                                WifiManager.WIFI_STATE_UNKNOWN);
                break;
            
            sendScanAvailableBroadcast(false);
            mScanRequestProxy.enableScanningForHiddenNetworks(false);
            mScanRequestProxy.clearScanResults();
            transitionTo(mStartedState);
            break;
        default:
            Log.d(TAG, "received an invalid message: " + message);
            return NOT_HANDLED;
    
    return HANDLED;

### 14: WifiNative

到这里就开始与hal层进行交互了,后续就在分一章在去分析后面的进程.


/**

  • Native calls for bring up/shut down of the supplicant daemon and for

  • sending requests to the supplicant daemon
    *

  • @hide
    */
    public class WifiNative
    private static final String TAG = “WifiNative”;
    private final SupplicantStaIfaceHal mSupplicantStaIfaceHal;
    private final HostapdHal mHostapdHal;
    private final WifiVendorHal mWifiVendorHal;
    private final WificondControl mWificondControl;
    private final WifiMonitor mWifiMonitor;
    private final INetworkManagementService mNwManagementService;
    private final PropertyService mPropertyService;
    private final WifiMetrics mWifiMetrics;
    private boolean mVerboseLoggingEnabled = false;

    public WifiNative(WifiVendorHal vendorHal,
    SupplicantStaIfaceHal staIfaceHal, HostapdHal hostapdHal,
    WificondControl condControl, WifiMonitor wifiMonitor,
    INetworkManagementService nwService,
    PropertyService propertyService, WifiMetrics wifiMetrics)
    mWifiVendorHal = vendorHal;
    mSupplicantStaIfaceHal = staIfaceHal;
    mHostapdHal = hostapdHal;
    mWificondControl = condControl;
    mWifiMonitor = wifiMonitor;
    mNwManagementService = nwService;
    mPropertyService = propertyService;
    mWifiMetrics = wifiMetrics;

    /**

    • Setup an interface for Client mode operations.
      *
    • This method configures an interface in STA mode in all the native daemons
    • (wificond, wpa_supplicant & vendor HAL).
      *
    • @param lowPrioritySta The requested STA has a low request priority (lower probability of
    • getting created, higher probability of getting destroyed).
    • @param interfaceCallback Associated callback for notifying status changes for the iface.
    • @return Returns the name of the allocated interface, will be null on failure.
      */
      public String setupInterfaceForClientMode(boolean lowPrioritySta,
      @NonNull InterfaceCallback interfaceCallback)
      synchronized (mLock)
      if (!startHal())
      Log.e(TAG, “Failed to start Hal”);
      mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
      return null;

      if (!startSupplicant())
      Log.e(TAG, “Failed to start supplicant”);
      mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
      return null;

      Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA);
      if (iface == null)
      Log.e(TAG, “Failed to allocate new STA iface”);
      return null;

      iface.externalListener = interfaceCallback;
      iface.name = createStaIface(iface, lowPrioritySta);
      if (TextUtils.isEmpty(iface.name))
      Log.e(TAG, “Failed to create STA iface in vendor HAL”);
      mIfaceMgr.removeIface(iface.id);
      mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
      return null;

      if (mWificondControl.setupInterfaceForClientMode(iface.name) == null)
      Log.e(TAG, "Failed to setup iface in wificond on " + iface);
      teardownInterface(iface.name);
      mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();
      return null;

      if (!mSupplicantStaIfaceHal.setupIface(iface.name))
      Log.e(TAG, "Failed to setup iface in supplicant on " + iface);
      teardownInterface(iface.name);
      mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
      return null;

      iface.networkObserver = new NetworkObserverInternal(iface.id);
      if (!registerNetworkObserver(iface.networkObserver))
      Log.e(TAG, "Failed to register network observer on " + iface);
      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));
      initializeNwParamsForClientInterface(iface.name);
      Log.i(TAG, "Successfully setup " + iface);
      return iface.name;

总结
--

上面的流程中其实从最开始的`SystemServer`中启动`wifiService`之后调用 checkAndStartWifi() 之后,中间就是各种状态判断,各种权限判断,各种状态同步的问题.具体的业务逻辑呢就是在不同的状态机中兜兜转转.我把中间兜兜转转的状态机用图画一下

### WifiController

// CHECKSTYLE:OFF IndentationCheck
addState(mDefaultState);
addState(mStaDisabledState, mDefaultState);
addState(mStaEnabledState, mDefaultState);
addState(mDeviceActiveState, mStaEnabledState);
addState(mStaDisabledWithScanState, mDefaultState);
addState(mEcmState, mDefaultState);
// CHECKSTYLE:ON IndentationCheck
if (checkScanOnlyModeAvailable())
setInitialState(mStaDisabledWithScanState);
else
setInitialState(mStaDisabledState);

![WifiController.jpg](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7cd634d8290648c693bc5eb228b3448c~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)

这里的流程就是从`StaDisabledState`切换到`DeviceActiveState`之后调用`enterClientMode()`进入 `ModeStateMachine`,也是一个状态机器如下图

### ModeStateMachine

addState(mClientModeActiveState);
addState(mScanOnlyModeActiveState);
addState(mWifiDisabledState);

Log.d(TAG, “Starting Wifi in WifiDisabledState”);
setInitialState(mWifiDisabledState);

![ModeStateMachine.jpg](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4d64fe1cd6954e62a39cdd22881d97b2~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)

这里的流程是从`WifiDisabledState`转到`ClientModeActiveState`.然后进入`ClientModeManager`,`ClientModeManager`中的`start()`启动了`ClientModeStateMachine`状态机 如下图

### ClientModeStateMachine

ClientModeStateMachine(Looper looper)
super(TAG, looper);

addState(mIdleState);
addState(mStartedState);

setInitialState(mIdleState);
start();

![ClientModeManager.jpg](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0d15f98b2d99447c9f724d8790fa73a1~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)

在`IdleState`调用`wifiNative`判断底层是否已经启动,启动成功之后就会转入`StartedState`.之后就是通过回调函数,或者`Handle`将wifi扫描结果和状态在一层层返回.

文末

要想成为架构师,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。

相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

一、架构师筑基必备技能

1、深入理解Java泛型
2、注解深入浅出
3、并发编程
4、数据传输与序列化
5、Java虚拟机原理
6、高效IO
……

二、Android百大框架源码解析

1.Retrofit 2.0源码解析
2.Okhttp3源码解析
3.ButterKnife源码解析
4.MPAndroidChart 源码解析
5.Glide源码解析
6.Leakcanary 源码解析
7.Universal-lmage-Loader源码解析
8.EventBus 3.0源码解析
9.zxing源码分析
10.Picasso源码解析
11.LottieAndroid使用详解及源码解析
12.Fresco 源码分析——图片加载流程

三、Android性能优化实战解析

  • 腾讯Bugly:对字符串匹配算法的一点理解
  • 爱奇艺:安卓APP崩溃捕获方案——xCrash
  • 字节跳动:深入理解Gradle框架之一:Plugin, Extension, buildSrc
  • 百度APP技术:Android H5首屏优化实践
  • 支付宝客户端架构解析:Android 客户端启动速度优化之「垃圾回收」
  • 携程:从智行 Android 项目看组件化架构实践
  • 网易新闻构建优化:如何让你的构建速度“势如闪电”?

四、高级kotlin强化实战

1、Kotlin入门教程
2、Kotlin 实战避坑指南
3、项目实战《Kotlin Jetpack 实战》

  • 从一个膜拜大神的 Demo 开始

  • Kotlin 写 Gradle 脚本是一种什么体验?

  • Kotlin 编程的三重境界

  • Kotlin 高阶函数

  • Kotlin 泛型

  • Kotlin 扩展

  • Kotlin 委托

  • 协程“不为人知”的调试技巧

  • 图解协程:suspend

五、Android高级UI开源框架进阶解密

1.SmartRefreshLayout的使用
2.Android之PullToRefresh控件源码解析
3.Android-PullToRefresh下拉刷新库基本用法
4.LoadSir-高效易用的加载反馈页管理框架
5.Android通用LoadingView加载框架详解
6.MPAndroidChart实现LineChart(折线图)
7.hellocharts-android使用指南
8.SmartTable使用指南
9.开源项目android-uitableview介绍
10.ExcelPanel 使用指南
11.Android开源项目SlidingMenu深切解析
12.MaterialDrawer使用指南

六、NDK模块开发

1、NDK 模块开发
2、JNI 模块
3、Native 开发工具
4、Linux 编程
5、底层图片处理
6、音视频开发
7、机器学习

七、Flutter技术进阶

1、Flutter跨平台开发概述
2、Windows中Flutter开发环境搭建
3、编写你的第一个Flutter APP
4、Flutter开发环境搭建和调试
5、Dart语法篇之基础语法(一)
6、Dart语法篇之集合的使用与源码解析(二)
7、Dart语法篇之集合操作符函数与源码分析(三)

八、微信小程序开发

1、小程序概述及入门
2、小程序UI开发
3、API操作
4、购物商场项目实战……

全套视频资料:

一、面试合集

二、源码解析合集


三、开源框架合集


欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证微信卡片免费领取【保证100%免费】↓↓↓

以上是关于Android WIFI 模块解析的主要内容,如果未能解决你的问题,请参考以下文章

Android WIFI模块分析

借助ESP8266 WIFI模块,实现Android手机有人网络调试助手(或Android手机网络调试助手)与单片机互相通信。

解析-ESP01模块开发Arduino物联网wifi开关模块

[android开发篇][ wifi模块] [3] wifiConnectAndCheck

借助ESP8266 WIFI模块,实现Android手机APP控制单片机来驱动硬件。

[android开发篇][ wifi模块] [2] wifibase