android wifi应用层通信大致可由一图说明。
图中所调用的源文件如下,以本人的android6.0为准,其他版本可能会有不同
系统启动会开始调用SystemService,在上层的代码就不跟踪了,systemserver启动了众多server其中就有wifiservice,在我的android6.0的代码如下,其他版本有些许不同
mSystemServiceManager.startService(WIFI_P2P_SERVICE_CLASS);
mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
mSystemServiceManager.startService(
"com.android.server.wifi.WifiScanningService");
mSystemServiceManager.startService("com.android.server.wifi.RttService");
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
}
try {
Slog.i(TAG, "Connectivity Service");
connectivity = new ConnectivityService(
context, networkManagement, networkStats, networkPolicy);
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
networkStats.bindConnectivityManager(connectivity);
networkPolicy.bindConnectivityManager(connectivity);
} catch (Throwable e) {
reportWtf("starting Connectivity Service", e);
可以看到启动了wifiservice(),而wifiservice的类又很简单,只是为了实例化WifiServiceImpl类,代码如下。
public final class WifiService extends SystemService {
private static final String TAG = "WifiService";
final WifiServiceImpl mImpl;
public WifiService(Context context) {
super(context);
mImpl = new WifiServiceImpl(context);
}
@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();
}
}
接下来具体看WifiServiceImpl实现,其中会实例化三个类如上图所示,其中WifiStateMachine是核心,WifiController也是一个状态机,主要接收从wifiManage传输过来从命令,最后还是调用WifiStateMachine,来控制wpa_supplicant,这里以setWifiEnabled()开启wifi命令为例简述WifiManage直接调用WifiServiceImpl过程,当app开始wifi,则调用WifiManage的setWifiEnabled()函数,代码如下
public boolean setWifiEnabled(boolean enabled) {
try {
return mService.setWifiEnabled(enabled);
} catch (RemoteException e) {
return false;
}
}
mservice及wifimanage构造函数实例化的WifiServiceImpl,所以直接调用WifiServiceImpl下的函数,
public synchronized boolean setWifiEnabled(boolean enable) {
enforceChangePermission();
Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
if (DBG) {
Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n");
}
/*
* 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);
}
mWifiController.sendMessage(CMD_WIFI_TOGGLED);
return true;
mSettingsStore.handleWifiToggled(enable)会调用SettingsStore类的函数,给app传输wifion的值,之后发送message给WifiController状态机,handle的连接函数在WifiServiceImpl的构造函数里面完成,代码如下。
public WifiServiceImpl(Context context) {
mContext = context;
mInterfaceName = SystemProperties.get("wifi.interface", "wlan0");
mTrafficPoller = new WifiTrafficPoller(mContext, mInterfaceName);
mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName, mTrafficPoller);
mWifiStateMachine.enableRssiPolling(true);
mBatteryStats = BatteryStatsService.getService();
mPowerManager = context.getSystemService(PowerManager.class);
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
mUserManager = UserManager.get(mContext);
mNotificationController = new WifiNotificationController(mContext, mWifiStateMachine);
mSettingsStore = new WifiSettingsStore(mContext);
HandlerThread wifiThread = new HandlerThread("WifiService");
wifiThread.start();
//建立handle connect
mClientHandler = new ClientHandler(wifiThread.getLooper());
mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());
mWifiController = new WifiController(mContext, this, wifiThread.getLooper());
}
其中mClientHandler为接收wifimanage所发信息的handle函数。mWifiStateMachineHandler为接收WifiStateMachine所发信息的函数。
接下来看下WifiController构造函数。
WifiController(Context context, WifiServiceImpl service, Looper looper) {
super(TAG, looper);
mContext = context;
mWifiStateMachine = service.mWifiStateMachine;
mSettingsStore = service.mSettingsStore;
mLocks = service.mLocks;
mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null);
mIdleIntent = PendingIntent.getBroadcast(mContext, IDLE_REQUEST, idleIntent, 0);
addState(mDefaultState);
addState(mApStaDisabledState, mDefaultState);
addState(mStaEnabledState, mDefaultState);
addState(mDeviceActiveState, mStaEnabledState);
addState(mDeviceInactiveState, mStaEnabledState);
addState(mScanOnlyLockHeldState, mDeviceInactiveState);
addState(mFullLockHeldState, mDeviceInactiveState);
addState(mFullHighPerfLockHeldState, mDeviceInactiveState);
addState(mNoLockHeldState, mDeviceInactiveState);
addState(mStaDisabledWithScanState, mDefaultState);
addState(mApEnabledState, mDefaultState);
addState(mEcmState, mDefaultState);
boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn();
boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled();
boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();
log("isAirplaneModeOn = " + isAirplaneModeOn +
", isWifiEnabled = " + isWifiEnabled +
", isScanningAvailable = " + isScanningAlwaysAvailable);
if (isScanningAlwaysAvailable) {
setInitialState(mStaDisabledWithScanState);
} else {
setInitialState(mApStaDisabledState);
}
setLogRecSize(100);
setLogOnlyTransitions(false);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_DEVICE_IDLE);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(ACTION_DEVICE_IDLE)) {
sendMessage(CMD_DEVICE_IDLE);
} else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
WifiManager.EXTRA_NETWORK_INFO);
} else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
int state = intent.getIntExtra(
WifiManager.EXTRA_WIFI_AP_STATE,
WifiManager.WIFI_AP_STATE_FAILED);
if(state == WifiManager.WIFI_AP_STATE_FAILED) {
loge(TAG + "SoftAP start failed");
sendMessage(CMD_AP_START_FAILURE);
}
}
}
},
new IntentFilter(filter));
initializeAndRegisterForSettingsChange(looper);
}
实例化这两个类mWifiStateMachine ,mSettingsStore 并设置各个state,初始化起始状态为mApStaDisabledState,初始化代码如下。
synchronized boolean isScanAlwaysAvailable() {
return !mAirplaneModeOn && mScanAlwaysAvailable;
}
boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();
if (isScanningAlwaysAvailable) {
setInitialState(mStaDisabledWithScanState);
} else {
setInitialState(mApStaDisabledState);
}
最终为false所以初始化为mApStaDisabledState,状态机开启函数在
WifiService的checkAndStartWifi()函数中开启。
public void checkAndStartWifi() {
/* Check if wi-fi needs to be enabled */
boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();
Slog.i(TAG, "WifiService starting up with Wi-Fi " +
(wifiEnabled ? "enabled" : "disabled"));
registerForScanModeChange();
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (mSettingsStore.handleAirplaneModeToggled()) {
mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED);
}
if (mSettingsStore.isAirplaneModeOn()) {
Log.d(TAG, "resetting country code because Airplane mode is ON");
mWifiStateMachine.resetCountryCode();
}
}
},
new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String state = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
if (state.equals(IccCardConstants.INTENT_VALUE_ICC_ABSENT)) {
Log.d(TAG, "resetting networks because SIM was removed");
mWifiStateMachine.resetSimAuthNetworks();
Log.d(TAG, "resetting country code because SIM is removed");
mWifiStateMachine.resetCountryCode();
}
}
},
new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED));
// 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();
registerForPackageOrUserRemoval();
mInIdleMode = mPowerManager.isDeviceIdleMode();
//开启wificontrol ,启动状态机
mWifiController.start();
// If we are already disabled (could be due to airplane mode), avoid changing persist
// state here
if (wifiEnabled) setWifiEnabled(wifiEnabled);
mWifiWatchdogStateMachine = WifiWatchdogStateMachine.
makeWifiWatchdogStateMachine(mContext, mWifiStateMachine.getMessenger());
再来看下StaEnabledState state下的如何开始加载driver和开启wpa_supplicant。代码如下
class StaEnabledState extends State {
@Override
public void enter() {
mWifiStateMachine.setSupplicantRunning(true);
}
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_WIFI_TOGGLED:
if (! mSettingsStore.isWifiToggleEnabled()) {
if (mSettingsStore.isScanAlwaysAvailable()) {
transitionTo(mStaDisabled