android P wifi模块分析之wifi启动

20190706_04

流程图

wifi start 流程图

代码具体流程

app应用层

WifiSettings.java

packages/apps/settings/WifiSettings.java
在onStart()创建一个WifiEnabler对象,实现wifi开关功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Override
public void onStart() {
super.onStart();

// On/off switch is hidden for Setup Wizard (returns null)
mWifiEnabler = createWifiEnabler();

if (mIsRestricted) {
restrictUi();
return;
}

onWifiStateChanged(mWifiManager.getWifiState());
}

private WifiEnabler createWifiEnabler() {
final SettingsActivity activity = (SettingsActivity) getActivity();
return new WifiEnabler(activity, new SwitchBarController(activity.getSwitchBar()),
mMetricsFeatureProvider);
}

WifiEnabler.java

packages/apps/settings/WifiEnabler.java
开启Wifi开关变会有下面的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@Override
public boolean onSwitchToggled(boolean isChecked) {
//Do nothing if called as a result of a state machine event
if (mStateMachineEvent) {
return true;
}
// Show toast message if Wi-Fi is not allowed in airplane mode
if (isChecked && !WirelessUtils.isRadioAllowed(mContext, Settings.Global.RADIO_WIFI)) {
Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();
// Reset switch to off. No infinite check/listener loop.
mSwitchWidget.setChecked(false);
return false;
}

if (isChecked) {
mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_WIFI_ON);
} else {
// Log if user was connected at the time of switching off.
mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_WIFI_OFF,
mConnected.get());
}
if (!mWifiManager.setWifiEnabled(isChecked)) {
// Error
mSwitchWidget.setEnabled(true);
Toast.makeText(mContext, R.string.wifi_error, Toast.LENGTH_SHORT).show();
}
return true;
}

点击开关会调用mWifiManager.setWifiEnabled。

Java框架层

WifiManager.java

frameworks/base/wifi/java/android/net/wifi/WifiManager.java

1
2
3
4
5
6
7
public boolean setWifiEnabled(boolean enabled) {
try {
return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

IWifiManager.aidl

frameworks/base/wifi/java/android/net/wifi/IWifiManager.aidl

1
boolean setWifiEnabled(String packageName, boolean enable);

WifiSeviceImpl.java

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiSeviceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
@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;
}

// If SoftAp is enabled, only Settings is allowed to toggle wifi
boolean apEnabled = mWifiApState == WifiManager.WIFI_AP_STATE_ENABLED;

if (apEnabled && !isFromSettings) {
mLog.info("setWifiEnabled SoftAp not disabled: only Settings can enable wifi").flush();
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_DISABL){
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;
}

WifiManager.setWifiEnabled通过aidl跨进程调用到了WifiServiceImpl.setWifiEnabled,其中WifiServiceImpl是WifiService的实现类。在WifiServiceImpl的setWifiEnabled方法里做的一些事情:

enforceChangePermission 判断调用的进程是否有权限。想要开关wifi需要CHANGE_WIFI_STATE 权限。

isAirplaneModeOn 判断飞行模式。

handleWifiToggled 保存wifi 操作的状态。

向WifiController发送CMD_WIFI_TOGGLED消息。

WifiController.java

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiController.java

首先讲一下WifiController,它是一个状态机,可能Android每个版本的状态机不完全一样,比如Android P 和Android O比起来状态机减少了一些分支。 WifiController在WIfiServiceImpl的构造函数中初始化、并开始运行。

WifiController 和WifiStateMachine 不同,WifiStateMachine是一个复杂的状态机,它维护了Wifi的启动、扫描、连接、断开等多个状态。WifiController 是高级别的wifi状态机,因为它管理的状态是wifi开关,wifi热点开关等状态,只有在wifi开关等具体状态下,判断wifi处于启动扫描附近热点状态等才是有意义的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
WifiController(Context context, WifiStateMachine wsm, Looper                        
wifiStateMachineLooper, WifiSettingsStore wss, Looper
wifiServiceLooper, FrameworkFacade f,WifiStateMachinePrime wsmp) {
super(TAG, wifiServiceLooper);
...

// 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状态机各状态:

WifiController状态机

状态机初始状态为StaDisabledState,在该状态下对CMD_WIFI_TOGGLED消息的处理

StaDisabledState

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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); //从这儿转换到DeviceActiveState状态
} else if (checkScanOnlyModeAvailable()) {
// only go to scan mode if we aren't in airplane mode
if (mSettingsStore.isAirplaneModeOn()) {
transitionTo(mStaDisabledWithScanState);
}
}
break;
...

default:
return NOT_HANDLED;
}
return HANDLED;
}
}

在StaDisabledState状态下没做什么处理,接着转换到DeviceActiveState状态,StaEnabledState是它的父状态,由StateMachine的知识可知,转换到该状态时,会依次调用父、子状态的enter()函数。先看DeviceActiveState的父状态StaEnabledState

StaEnabledState

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class StaEnabledState extends State {
@Override
public void enter() {
log("StaEnabledState.enter()");
}

@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_WIFI_TOGGLED:
if (! mSettingsStore.isWifiToggleEnabled()) {
if (checkScanOnlyModeAvailable()) {
transitionTo(mStaDisabledWithScanState);
} else {
transitionTo(mStaDisabledState);
}
}
break;
...

}

DeviceActiveState

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* Parent: StaEnabledState
*
* TODO (b/79209870): merge DeviceActiveState and StaEnabledState into a single state
*/
class DeviceActiveState extends State {
@Override
public void enter() {
mWifiStateMachinePrime.enterClientMode();
mWifiStateMachine.setHighPerfModeEnabled(false);
}
...
}

可以看到在DeviceActiveState状态下主要做了两个操作mWifiStateMachinePrime.enterClientMode()和
mWifiStateMachine.setHighPerfModeEnabled(false),主要看mWifiStateMachinePrime.enterClientMode()。

WifiStateMachinePrime.java

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachinePrime.java

1
2
3
4
5
6
7
8
9
10
11
/**
* 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.sendMessage(newMode);
}

ModeStateMachine又是一个状态机,不过这个状态机比较简单只有三个状态,初始状态为WifiDisabledState。

ModeStateMachine

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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");
setInitialState(mWifiDisabledState);
start();
...
}
}

WifiDisabledState

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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);
if (checkForAndHandleModeChange(message)) {
return HANDLED;
}
return NOT_HANDLED;
}

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

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;
}

状态机从WifiDisabledState状态转向ClientModeActiveState状态,所以再继续看ClientModeActiveState

ClientModeActiveState

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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();
mManager = mWifiInjector.makeClientModeManager(mListener);
mManager.start();
mActiveModeManagers.add(mManager);

updateBatteryStatsWifiState(true);
}
...
}

这里的mManager是ActiveModeManager,是个接口,这里的ClientModeManager实现了这个接口。我们继续走下去,去看ClientModeManager,主要看mManager.start()这个调用。

ClientModeManager.java

frameworks/opt/net/wifi/service/java/com/android/server/wifi/ClientModeManager.java

1
2
3
4
5
6
/**
* Start client mode.
*/
public void start() {
mStateMachine.sendMessage(ClientModeStateMachine.CMD_START);
}

ClientModeStateMachine也是个状态机,该状态机只有两个状态,初始状态为IdleState。

ClientModeStateMachine

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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);

setInitialState(mIdleState);
start();
}
...
}

看一下初始状态Idlesate状态的处理

Idlesate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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);

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;
}
}

主要看 mWifiNative.setupInterfaceForClientMode的操作。

WifiNative.java

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/**
* 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;
}
}

到这里就可以看到一些关键性的操作:
启动Hal:startHal()
启动supplicant:startSupplicant()
加载驱动(loadDriver):setupInterfaceForClientMode()
启动WifiMonitor:WifiMonitor.startMonitoring()

WifiMonitor.startMonitoring():这一步主要是在WifiMonitor中建立与wpa_supplicant通信的socket通道、创建一个线程接收底层事件并分发处理。这里会创建两个socket通道与wpa_s通信,一个用于下发指令,另一个用于接收事件。成功后WifiMonitor会向WifiStateMachine发送一个代表socket通信建立成功的消息:SUP_CONNECTION_EVENT;收到这个消息就表示Wifi已经启动成功了。

startHal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/** Helper method invoked to start supplicant if there were no ifaces */
private boolean startHal() {
synchronized (mLock) {
if (!mIfaceMgr.hasAnyIface()) {
if (mWifiVendorHal.isVendorHalSupported()) {
if (!mWifiVendorHal.startVendorHal()) {
Log.e(TAG, "Failed to start vendor HAL");
return false;
}
} else {
Log.i(TAG, "Vendor Hal not supported, ignoring start.");
}
}
return true;
}
}

WifiVendorHal.java

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiVendorHal.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* Bring up the HIDL Vendor HAL.
* @return true on success, false otherwise.
*/
public boolean startVendorHal() {
synchronized (sLock) {
if (!mHalDeviceManager.start()) {
mLog.err("Failed to start vendor HAL").flush();
return false;
}
mLog.info("Vendor Hal started successfully").flush();
return true;
}
}

mHalDeviceaManager.start()

frameworks/opt/net/wifi/service/java/com/android/server/wifi/HalDeviceManager.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/**
* Attempts to start Wi-Fi (using HIDL). Returns the success (true) or failure (false) or
* the start operation. Will also dispatch any registered ManagerStatusCallback.onStart() on
* success.
*
* Note: direct call to HIDL.
*/
public boolean start() {
return startWifi();
}

private boolean startWifi() {
if (VDBG) Log.d(TAG, "startWifi");

synchronized (mLock) {
try {
if (mWifi == null) {
Log.w(TAG, "startWifi called but mWifi is null!?");
return false;
} else {
int triedCount = 0;
while (triedCount <= START_HAL_RETRY_TIMES) {
WifiStatus status = mWifi.start();
if (status.code == WifiStatusCode.SUCCESS) {
initIWifiChipDebugListeners();
managerStatusListenerDispatch();
if (triedCount != 0) {
Log.d(TAG, "start IWifi succeeded after trying "
+ triedCount + " times");
}
return true;
} else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) {
// Should retry. Hal might still be stopping.
Log.e(TAG, "Cannot start IWifi: " + statusString(status)
+ ", Retrying...");
try {
Thread.sleep(START_HAL_RETRY_INTERVAL_MS);
} catch (InterruptedException ignore) {
// no-op
}
triedCount++;
} else {
// Should not retry on other failures.
Log.e(TAG, "Cannot start IWifi: " + statusString(status));
return false;
}
}
Log.e(TAG, "Cannot start IWifi after trying " + triedCount + " times");
return false;
}
} catch (RemoteException e) {
Log.e(TAG, "startWifi exception: " + e);
return false;
}
}
}

主要看WifiStatus status = mWifi.start(),先看下mWifi是什么。

1
2
3
4
5
6
7
8
9
10
11
/**
* Wrapper function to access the HIDL services. Created to be mockable in unit-tests.
*/
protected IWifi getWifiServiceMockable() {
try {
return IWifi.getService();
} catch (RemoteException e) {
Log.e(TAG, "Exception getting IWifi service: " + e);
return null;
}
}

这里返回的是IWifi的服务端。至此我们开始进入HIDL。

HIDL

IWifi.hal

hardware/interfaces/wifi/1.0/IWifi.hal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* Perform any setup that is required to make use of the module. If the module
* is already started then this must be a noop.
* Must trigger |IWifiEventCallback.onStart| on success.
*
* @return status WifiStatus of the operation.
* Possible status codes:
* |WifiStatusCode.SUCCESS|,
* |WifiStatusCode.NOT_AVAILABLE|,
* |WifiStatusCode.UNKNOWN|
*/
@entry
@callflow(next={"registerEventCallback", "start", "stop", "getChip"})
start() generates (WifiStatus status);

系统编译的时候会自动产生IWifi.java文件

out/soong/.intermediates/hardware/interfaces/wifi/1.0/android.hardware.wifi_V1.0-java_gen_java/gen/android/hardware/wifi/V1_0/IWifi.java

IWifi.java的getService方法

1
2
3
public static IWifi getService(String serviceName) throws android.os.RemoteException {
return IWifi.asInterface(android.os.HwBinder.getService("android.hardware.wifi@1.0::IWifi",serviceName));
}

再看一下 IWifi.java的asInterface方法

1
IWifi.asInterface(android.os.HwBinder.getService("android.hardware.wifi@1.0::IWifi",serviceName));

从而我们就可以知道IWifi对应的服务端了

wifi.cpp

hardware/interfaces/wifi/1.2/default/wifi.cpp

按照IWifi.java的代码接下来的调用路径应该在hardware/interfaces/wifi/1.0/default/,但没有发现这个路径下有wifi.cpp这个文件,hardware/interfaces/wifi/1.2/default/倒是有wifi.cpp,这个我也不清楚为什么。那就先按这个调用流程走下去吧。

wifi.start

1
2
3
4
Return<void> Wifi::start(start_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
&Wifi::startInternal, hidl_status_cb);
}

startInternal()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
WifiStatus Wifi::startInternal() {
if (run_state_ == RunState::STARTED) {
return createWifiStatus(WifiStatusCode::SUCCESS);
} else if (run_state_ == RunState::STOPPING) {
return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
"HAL is stopping");
}
WifiStatus wifi_status = initializeModeControllerAndLegacyHal();
if (wifi_status.code == WifiStatusCode::SUCCESS) {
// Create the chip instance once the HAL is started.
chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_,
feature_flags_);
run_state_ = RunState::STARTED;
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onStart().isOk()) {
LOG(ERROR) << "Failed to invoke onStart callback";
};
}
LOG(INFO) << "Wifi HAL started";
} else {
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onFailure(wifi_status).isOk()) {
LOG(ERROR) << "Failed to invoke onFailure callback";
}
}
LOG(ERROR) << "Wifi HAL start failed";
}
return wifi_status;
}

WifiStatus Wifi::initializeModeControllerAndLegacyHal() {
if (!mode_controller_->initialize()) {
LOG(ERROR) << "Failed to initialize firmware mode controller";
return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
}
legacy_hal::wifi_error legacy_status = legacy_hal_->initialize();
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
LOG(ERROR) << "Failed to initialize legacy HAL: "
<< legacyErrorToString(legacy_status);
return createWifiStatusFromLegacyError(legacy_status);
}
return createWifiStatus(WifiStatusCode::SUCCESS);
}

接着看wifi_mode_controller.cpp得initialize()方法。

wifi_mode_controller.cpp

hardware/interfaces/wifi/1.2/default/wifi_mode_controller.cpp

1
2
3
4
5
6
7
 bool WifiModeController::initialize() {
if (!driver_tool_->LoadDriver()) {
LOG(ERROR) << "Failed to load WiFi driver";
return false;
}
return true;
}

WPA适配层(硬件抽象层 HAL)

HAL 可定义一个标准接口以供硬件供应商实现,这可让 Android 忽略较低级别的驱动程序实现。借助 HAL,可以顺利实现相关功能,而不会影响或更改更高级别的系统。HAL 实现会被封装成模块,并由 Android 系统适时地加载。

driver_tool.cpp

frameworks/opt/net/wifi/libwifi_hal/driver_tool.cpp

1
2
3
bool DriverTool::LoadDriver() {
return ::wifi_load_driver() == 0;
}

wifi_hal_common.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
int wifi_load_driver() {
#ifdef WIFI_DRIVER_MODULE_PATH
if (is_wifi_driver_loaded()) {
return 0;
}

if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) return -1;
#endif

#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
if (is_wifi_driver_loaded()) {
return 0;
}

if (wifi_change_driver_state(WIFI_DRIVER_STATE_ON) < 0) return -1;
#endif
property_set(DRIVER_PROP_NAME, "ok");
return 0;
}

int is_wifi_driver_loaded() {
char driver_status[PROPERTY_VALUE_MAX];
#ifdef WIFI_DRIVER_MODULE_PATH
FILE *proc;
char line[sizeof(DRIVER_MODULE_TAG) + 10];
#endif

if (!property_get(DRIVER_PROP_NAME, driver_status, NULL) ||
strcmp(driver_status, "ok") != 0) {
return 0; /* driver not loaded */
}
#ifdef WIFI_DRIVER_MODULE_PATH
/*
* If the property says the driver is loaded, check to
* make sure that the property setting isn't just left
* over from a previous manual shutdown or a runtime
* crash.
*/
if ((proc = fopen(MODULE_FILE, "r")) == NULL) {
PLOG(WARNING) << "Could not open " << MODULE_FILE;
property_set(DRIVER_PROP_NAME, "unloaded");
return 0;
}
while ((fgets(line, sizeof(line), proc)) != NULL) {
if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0) {
fclose(proc);
return 1;
}
}
fclose(proc);
property_set(DRIVER_PROP_NAME, "unloaded");
return 0;
#else
return 1;
#endif
}

wpa_supplicant

wpa_supplicant是一个开源项目,已经被移植到Linux,Windows以及很多嵌入式系统上。它是WPA的应用层认证客户端,负责完成认证相关的登录、加密等工作。wpa_supplicant的源代码目录为:/external/wpa_supplicant_8/
wpa_supplicant是一个独立运行的守护进程,其核心是一个消息循环,在消息循环中处理WPA状态机、控制命令、驱动事件、配置信息等。wpa_supplicant有很多控制接口,也提供命令行和通行界面的控制模式:而Android与wpa_supplicant的通信通过Socket完成

后续我会专门写一系列关于wpa_supplicant相关的流程相关的文章,到时候会给出索引

Linux Kernel

kernel/driver/net/wireless/

vendor/gcom/opensource/wlan/