[Android]Android P(9) WIFI学习笔记 - Framework (1)
前言
- 基于Android P源码学习;
- 代码片为了方便阅读段经过删、裁减,请以实际源码为准;
初始化流程
SystemServer
在调用到startOtherServices
时,会通过
mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
启动WIFI的SystemService
,对应类为:
com.android.server.wifi.WifiService
- 构造
WifiService
时会同时构造出WifiServiceImpl
:
public WifiService(Context context) {
super(context);
mImpl = new WifiServiceImpl(context, new WifiInjector(context), new WifiAsyncChannel(TAG));
}
并在onStart
的回调中将构造出的WifiServiceImpl
对象注册到SystemService
的表中;
@Override
public void onStart() {
publishBinderService(Context.WIFI_SERVICE, mImpl);
}
WifiServiceImpl
为IWifiManager.Stub
的实现类,因此WifiServiceImpl
是WifiManager
大部分方法调用的JAVA层实现、表达:
public class WifiServiceImpl extends IWifiManager.Stub {
...
}
- WIFI相关服务的API通过
WifiManager
暴露给App调用,而WifiManager
的构造是在SystemServiceRegistry
的静态代码块中注册的回调,并在第一次调用getSystemService(Context.WIFI_SERVICE)
时进行懒加载(构造);
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());
}});
时序图如下:
常用方法
public boolean setWifiEnabled(boolean enabled);
public int getWifiState();
public boolean isWifiEnabled();
public void connect(int networkId, ActionListener listener);
@SystemApi
public void connect(WifiConfiguration config, ActionListener listener);
...
(TO BE UPDATED)
调用栈
以WifiManager.setWifiEnabled()
为例:
public boolean setWifiEnabled(boolean enabled) {
try {
return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
1. 通过Binder调用到IWifiManager实例(即WifiServiceImpl)的setWifiEnabled方法:
@Override
public synchronized boolean setWifiEnabled(String packageName, boolean enable)
throws RemoteException {
if (enforceChangePermission(packageName) != MODE_ALLOWED) {
return false;
}
boolean isFromSettings = checkNetworkSettingsPermission(
Binder.getCallingPid(), Binder.getCallingUid());
// If Airplane mode is enabled, only Settings is allowed to toggle Wifi
if (mSettingsStore.isAirplaneModeOn() && !isFromSettings) {
return false;
}
// If SoftAp is enabled, only Settings is allowed to toggle wifi
boolean apEnabled = mWifiApState == WifiManager.WIFI_AP_STATE_ENABLED;
if (apEnabled && !isFromSettings) {
return false;
}
/*
* Caller might not have WRITE_SECURE_SETTINGS,
* only CHANGE_WIFI_STATE is enforced
*/
long ident = Binder.clearCallingIdentity();
try {
if (! mSettingsStore.handleWifiToggled(enable)) {
// Nothing to do if wifi cannot be toggled
return true;
}
} finally {
Binder.restoreCallingIdentity(ident);
}
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;
}
整个方法中,除去权限、状态检查等,真正执行WIFI开关的只有如下两个地方:
mSettingsStore.handleWifiToggled(enable);
mWifiController.sendMessage(CMD_WIFI_TOGGLED);
mSettingsStore
为WifiSettingsStore
的实例,由WifiServiceImpl
构造时通过mWifiInjector.getWifiSettingsStore()
获取; mWifiInjector
为WifiInjector
的实例,同样由WifiServiceImpl
构造时传入;
注意:WifiInjector
为单例设计,此处为首次构造,其余部分仅能通过WifiInjector.getInstance()
获取;
而回到mSettingsStore.handleWifiToggled()
这句调用本身。其本质只是在判断了当前设备是否处于飞行模式,从而将不同状态写入到Settings.Global中:
public synchronized boolean handleWifiToggled(boolean wifiEnabled) {
// Can Wi-Fi be toggled in airplane mode ?
if (mAirplaneModeOn && !isAirplaneToggleable()) {
return false;
}
if (wifiEnabled) {
if (mAirplaneModeOn) {
persistWifiState(WIFI_ENABLED_AIRPLANE_OVERRIDE);
} else {
persistWifiState(WIFI_ENABLED);
}
} else {
persistWifiState(WIFI_DISABLED);
}
return true;
}
private void persistWifiState(int state) {
final ContentResolver cr = mContext.getContentResolver();
mPersistWifiState = state;
Settings.Global.putInt(cr, Settings.Global.WIFI_ON, state);
}
至于mWifiController
,则是负责处理WIFI行为的控制器,系WifiServiceImpl
与WifiStateMachine
的交互中间件;
与mSettingsStore
变量一样,mWifiController
同样是由mInjector
提供;
WifiController
继承自StateMachine
,关于StateMachine
的更多信息,详见:
内部维护了如下几种State,其层级关系如图:
2. StateMachine
是以State为驱动的状态机,在处于不同State
时,向StateMachine
发送不同的消息,可以得到不同的响应;
因此,要确认这里mWifiController.sendMessage(CMD_WIFI_TOGGLED);
的具体实现,就需要先确认现在工作的State:
if (checkScanOnlyModeAvailable()) {
setInitialState(mStaDisabledWithScanState);
} else {
setInitialState(mStaDisabledState);
}
可见WifiController
的初始状态为StaDisabledWithScanState
或StaDisabledState
(取决于是否开启“WIFI始终扫描”选项)
Android P上默认没有开启“WIFI始终扫描”,因此初始状态为StaDisabledState
;
那么查看StaDisabledState
的processMessage
可以看到,处理CMD_WIFI_TOGGLED
消息的逻辑如下:
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_WIFI_TOGGLED:
//读取刚才mSettingsStore设置的键值对,因为这里是StaDisabledState,所以不需要处理
//disable的消息,只需专注于enable即可;
if (mSettingsStore.isWifiToggleEnabled()) {
if (doDeferEnable(msg)) {
if (mHaveDeferredEnable) {
//此时表示有两个延时enable发送了,需要再让计数自增
//使之前发送的msg无效;
mDeferredEnableSerialNumber++;
}
mHaveDeferredEnable = !mHaveDeferredEnable;
//如果要发送延迟消息,则此次不切换状态
break;
}
//由于当前方法调用栈在handleMessage中,且早于performTransitions,
//因此此处transitionTo调用后会立即调用StaDisabledState的exit与
//DeviceActiveState的enter方法
transitionTo(mDeviceActiveState);
} else if (checkScanOnlyModeAvailable()) {
// only go to scan mode if we aren't in airplane mode
if (mSettingsStore.isAirplaneModeOn()) {
transitionTo(mStaDisabledWithScanState);
}
}
break;
...
case CMD_DEFERRED_TOGGLE:
//如果检测到延时过程中发送了两个enable消息,mDeferredEnableSerialNumber
//检测不匹配;则不进行任何操作
if (msg.arg1 != mDeferredEnableSerialNumber) {
break;
}
//重发CMD_WIFI_TOGGLED,并执行上方transitionTo(mDeviceActiveState)的逻辑
sendMessage((Message)(msg.obj));
break;
...
}
return HANDLED;
}
由于快速开关WIFI开关可能会导致上下层的状态紊乱,因此doDeferEnable
方法就是用于给快速开关WIFI开关的场景添加一个延时:
private boolean doDeferEnable(Message msg) {
long delaySoFar = SystemClock.elapsedRealtime() - mDisabledTimestamp;
//mReEnableDelayMillis默认500ms,可通过WIFI_REENABLE_DELAY_MS修改
if (delaySoFar >= mReEnableDelayMillis) {
//如果距离上次disable已经过去一段时间,则无需延时操作
return false;
}
...
//注意,此处返回值恒为true,因此返回到processMessage后不会执行transitionTo
//因此负责处理CMD_DEFERRED_TOGGLE消息的还是StaDisabledState.
Message deferredMsg = obtainMessage(CMD_DEFERRED_TOGGLE);
deferredMsg.obj = Message.obtain(msg);
//这个是一个自增的计数,用来保证一些消息处理的时序,通过msg传递给下一个State
deferredMsg.arg1 = ++mDeferredEnableSerialNumber;
//以mReEnableDelayMillis默认500ms为例,此处确保延时从上次disable开始500+5ms
sendMessageDelayed(deferredMsg, mReEnableDelayMillis - delaySoFar + DEFER_MARGIN_MS);
return true;
}
可以看到,无论是否进行消息延时,最终都会通过切换State到DeviceActiveState
,并调用其enter()
方法:
class DeviceActiveState extends State {
@Override
public void enter() {
mWifiStateMachinePrime.enterClientMode();
mWifiStateMachine.setHighPerfModeEnabled(false);
}
...
}
这里牵扯到了WifiStateMachinePrime
与WifiStateMachine
两个类:
WifiStateMachinePrime
内部维护了一个ModeStateMachine
继承自StateMachine
;WifiStateMachine
直接继承自StateMachine
;
注意:
WifiStateMachinePrime
与WifiStateMachine
两个类的构造方法中,使用第三个参数(即wifiStateMachineLooper
)作为SmHandler
构造的Looper
;- 而
WifiController
使用的是第五个参数(即mWifiServiceHandlerThread.getLooper()
); - 因此
WifiStateMachinePrime
与WifiStateMachine
的SmHandler
工作在同一线程,WifiController
的SmHandler
工作在WifiServiceHandlerThread
线程上;
mWifiStateMachine = new WifiStateMachine(mContext, mFrameworkFacade,
wifiStateMachineLooper, UserManager.get(mContext),
this, mBackupManagerProxy, mCountryCode, mWifiNative,
new WrongPasswordNotifier(mContext, mFrameworkFacade),
mSarManager);
mWifiStateMachinePrime = new WifiStateMachinePrime(this, mContext, wifiStateMachineLooper,
mWifiNative, new DefaultModeManager(mContext, wifiStateMachineLooper),
mBatteryStats);
...
mWifiController = new WifiController(mContext, mWifiStateMachine, wifiStateMachineLooper,
mSettingsStore, mWifiServiceHandlerThread.getLooper(), mFrameworkFacade,
mWifiStateMachinePrime);
WifiStateMachine
负责处理WIFI的Client模式(即STA模式)下各个状态的切换,其内部的State层级关系如下图:
WifiStateMachinePrime
目前根据注释可知,还处于WIP阶段(Work In Progress),待重构后,会用来替代WifiStateMachine
;
WifiStateMachinePrime
内部的ModeStateMachine
管理了三种状态,且三者并列,没有层级关系:
ClientModeActiveState
ScanOnlyModeActiveState
WifiDisabledState
初始状态为WifiDisabledState
回到WifiController
中的DeviceActiveState.enter()
方法:
class DeviceActiveState extends State {
@Override
public void enter() {
mWifiStateMachinePrime.enterClientMode();
mWifiStateMachine.setHighPerfModeEnabled(false);
}
...
}
WifiStateMachinePrime.enterClientMode()
方法用于切换WifiStateMachinePrime
内部ModeStateMachine
的状态到ModeStateMachine.CMD_START_CLIENT_MODE
;
以默认状态WifiDisabledState
为例,会在processMessage
方法中走到如下这里:
private boolean checkForAndHandleModeChange(Message message) {
switch(message.what) {
case ModeStateMachine.CMD_START_CLIENT_MODE:
mModeStateMachine.transitionTo(mClientModeActiveState);
break;
...
default:
return NOT_HANDLED;
}
return HANDLED;
}
从而状态切换到ClientModeActiveState
;
继续跟踪ClientModeActiveState
的enter
方法,可以发现这里通过WifiInjector
构造了一个ClientModeManager
:
class ClientModeActiveState extends ModeActiveState {
@Override
public void enter() {
mListener = new ClientListener();
mManager = mWifiInjector.makeClientModeManager(mListener);
mManager.start();
mActiveModeManagers.add(mManager);
updateBatteryStatsWifiState(true);
}
ClientListener mListener;
private class ClientListener implements ClientModeManager.Listener {
@Override
public void onStateChanged(int state) {
...
if (state == WifiManager.WIFI_STATE_UNKNOWN) {
mModeStateMachine.sendMessage(CMD_CLIENT_MODE_FAILED, this);
} else if (state == WifiManager.WIFI_STATE_DISABLED) {
mModeStateMachine.sendMessage(CMD_CLIENT_MODE_STOPPED, this);
} else if (state == WifiManager.WIFI_STATE_ENABLED) {
}
...
}
}
...
}
而ClientModeManager
的构造方法中构造了一个ClientModeStateMachine
,后者又是一个StateMachine
的子类。
不过这个状态机比较简单,只有两个状态:
IdleState
StartedState
初始状态是IdleState
;
在ClientModeStateMachine
的构造方法中调用了start()方法,因而直接进入IdleState
,并执行IdleState的enter方法:
private class IdleState extends State {
@Override
public void enter() {
mClientInterfaceName = null;
mIfaceIsUp = false;
}
...
}
执行完ClientModeStateMachine
的构造方法后,ClientModeManager
的构造方法也就结束了,实例对象通过WifiInjector.makeClientModeManager()
返回;
随后调用ClientModeManager
的enter()
方法:
注意,ClientModeManager
本身并非继承StateMachine
,而是实现了ActiveModeManager
接口,实现了单独的start()方法,而非StateMachine
的start()
方法,注意区分
public void start() {
mStateMachine.sendMessage(ClientModeStateMachine.CMD_START);
}
发送CMD_START
到当前状态,即:IdleState
:
@Override
public boolean processMessage(Message message) {
switch (message.what) {
case CMD_START:
updateWifiState(WifiManager.WIFI_STATE_ENABLING,
WifiManager.WIFI_STATE_DISABLED);
String hostname = Settings.Global.getString(mContext.getContentResolver(), Settings.Global.DEVICE_NAME);
SystemProperties.set("net.hostname", hostname);
mClientInterfaceName = mWifiNative.setupInterfaceForClientMode(
false /* not low priority */, mWifiNativeInterfaceCallback);
if (TextUtils.isEmpty(mClientInterfaceName)) {
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:
return NOT_HANDLED;
}
return HANDLED;
}
其中重点关注如下几个方法:
updateWifiState(WifiManager.WIFI_STATE_ENABLING, WifiManager.WIFI_STATE_DISABLED);
mWifiNative.setupInterfaceForClientMode(false, mWifiNativeInterfaceCallback)
sendScanAvailableBroadcast(false);
mScanRequestProxy.enableScanningForHiddenNetworks(false);
mScanRequestProxy.clearScanResults();
transitionTo(mStartedState);
updateWifiState
方法主要用于处理状态的回调,以及广播的发送:
private void updateWifiState(int newState, int currentState) {
if (!mExpectedStop) {
mListener.onStateChanged(newState);
}
//状态异常时标记,后续updateWifiState则不会再执行mListener的onStateChanged回调
if (newState == WifiManager.WIFI_STATE_UNKNOWN
|| newState == WifiManager.WIFI_STATE_DISABLED) {
mExpectedStop = true;
}
//状态未知时不发送广播
if (newState == WifiManager.WIFI_STATE_UNKNOWN) {
return;
}
//通知WifiStateMachine同步状态
mWifiStateMachine.setWifiStateForApiCalls(newState);
//发送WIFI_STATE_CHANGED_ACTION广播
final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(WifiManager.EXTRA_WIFI_STATE, newState);
intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, currentState);
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
sendScanAvailableBroadcast(false)
表示发送WIFI_SCAN_AVAILABLE
广播,且EXTRA_SCAN_AVAILABLE
的值为WIFI_STATE_DISABLED
:
private void sendScanAvailableBroadcast(boolean available) {
final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
if (available) {
intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WifiManager.WIFI_STATE_ENABLED);
} else {
intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WifiManager.WIFI_STATE_DISABLED);
}
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
mScanRequestProxy.enableScanningForHiddenNetworks(false)
表示通知ScanRequestProxy
设置成员变量mScanRequestProxy,以停用隐藏网络扫描功能:
public void enableScanningForHiddenNetworks(boolean enable) {
mScanningForHiddenNetworksEnabled = enable;
}
mScanRequestProxy.clearScanResults()
则是清空已经缓存的扫描结果:
public void clearScanResults() {
mLastScanResults.clear();
mLastScanTimestampForBgApps = 0;
mLastScanTimestampsForFgApps.clear();
}
mWifiNative.setupInterfaceForClientMode
方法则会与HAL(supplicant)交互,会在下一章节继续分析;
如果所有调用正常,最后会调用transitionTo(mStartedState)
进行状态切换:
private class StartedState extends State {
private void onUpChanged(boolean isUp) {
if (isUp == mIfaceIsUp) {
return; // no change
}
mIfaceIsUp = isUp;
if (isUp) {
sendScanAvailableBroadcast(true);
mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE,
mClientInterfaceName);
updateWifiState(WifiManager.WIFI_STATE_ENABLED,
WifiManager.WIFI_STATE_ENABLING);
} else {
if (mWifiStateMachine.isConnectedMacRandomizationEnabled()) {
return;
}
updateWifiState(WifiManager.WIFI_STATE_UNKNOWN,
WifiManager.WIFI_STATE_ENABLED);
mStateMachine.sendMessage(CMD_INTERFACE_DOWN);
}
}
public void enter() {
mIfaceIsUp = false;
onUpChanged(mWifiNative.isInterfaceUp(mClientInterfaceName));
mScanRequestProxy.enableScanningForHiddenNetworks(true);
}
...
}
如果之前mWifiNative.setupInterfaceForClientMode
调用没有异常的话,这里mWifiNative.isInterfaceUp(mClientInterfaceName)
为true,因而调用updateWifiState(WifiManager.WIFI_STATE_ENABLED)
可完成WIFI开启的整个流程;
最后附上一副总结性质的时序图,其中部分非关键调用已经略去,关键调用加粗显示;