Android WIFI 模块解析(1)

3,024 阅读13分钟

Android WIFI 模块解析(2)

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 这个大家很熟悉,关于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状态机

20190504201521921.jpg

  • Android 9.0 WifiStateMachine状态机 20190504202816489.jpg

状态机模块应该是在不同的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

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

ModeStateMachine

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

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

ModeStateMachine.jpg

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

ClientModeStateMachine

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

    addState(mIdleState);
    addState(mStartedState);

    setInitialState(mIdleState);
    start();
}

ClientModeManager.jpg

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