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
,启动了WifiService
和WifiScanningService
.
相关代码路径
- 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.Stub
的WifiServiceImpl
中去.
- 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 ActiveModeManagerprivate 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;
- Setup an interface for Client mode operations.
总结
--
上面的流程中其实从最开始的`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 模块解析的主要内容,如果未能解决你的问题,请参考以下文章
借助ESP8266 WIFI模块,实现Android手机有人网络调试助手(或Android手机网络调试助手)与单片机互相通信。
解析-ESP01模块开发Arduino物联网wifi开关模块
[android开发篇][ wifi模块] [3] wifiConnectAndCheck