一、点击wifi开关
默认有2种方式打开wifi
1)从设置打开
\packages\apps\Settings\src\com\android\settings\wifi\WifiEnabler.java
调用了WifiManager的setWifiEnabled
@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, SettingsEnums.ACTION_WIFI_ON);
} else {
// Log if user was connected at the time of switching off.
mMetricsFeatureProvider.action(mContext, SettingsEnums.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;
}
2)从状态栏点击打开
\frameworks\base\packages\SystemUI\src\com\android\systemui\qs\tiles\WifiTile.java
mController.setWifiEnabled
@Override
protected void handleClick() {
// Secondary clicks are header clicks, just toggle.
mState.copyTo(mStateBeforeClick);
boolean wifiEnabled = mState.value;
// Immediately enter transient state when turning on wifi.
refreshState(wifiEnabled ? null : ARG_SHOW_TRANSIENT_ENABLING);
mController.setWifiEnabled(!wifiEnabled);
mExpectDisabled = wifiEnabled;
if (mExpectDisabled) {
mHandler.postDelayed(() -> {
if (mExpectDisabled) {
mExpectDisabled = false;
refreshState();
}
}, QSIconViewImpl.QS_ANIM_LENGTH);
}
}
\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\policy\NetworkControllerImpl.java
调用了WifiManager的setWifiEnabled
@Override
public void setWifiEnabled(final boolean enabled) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... args) {
mWifiManager.setWifiEnabled(enabled);
return null;
}
}.execute();
}
两种方法最后都是调用的WifiManager.setWifiEnabled方法
二、AndroidQ 默认加入了支持双WiFi的代码。这里打开WiFi就提供了俩个接口
frameworks/base/wifi/java/android/net/wifi/WifiManager.java
正常打开WiFi是调用这个单参的函数。
@Deprecated
public boolean setWifiEnabled(boolean enabled) {
try {
return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
在service中调用setWifiEnabled 会默认传入 staId为STA_PRIMARY来调用setWifiEnabled2方法
这个方法是用来指定staId的
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java
@Override
public synchronized boolean setWifiEnabled(String packageName, boolean enable) {
return setWifiEnabled2(packageName, STA_PRIMARY, enable);
}
@Override
public synchronized boolean setWifiEnabled2(String packageName, int staId,boolean enable) {
if (enforceChangePermission(packageName) != MODE_ALLOWED) {
return false;
}
boolean isPrivileged = isPrivileged(Binder.getCallingPid(), Binder.getCallingUid());
if (!isPrivileged && !isDeviceOrProfileOwner(Binder.getCallingUid(), packageName)
&& !mWifiPermissionsUtil.isTargetSdkLessThan(packageName, Build.VERSION_CODES.Q,
Binder.getCallingUid())
&& !isSystem(packageName, Binder.getCallingUid())) {
mLog.info("setWifiEnabled not allowed for uid=%")
.c(Binder.getCallingUid()).flush();
return false;
}
// If Airplane mode is enabled, only privileged apps are allowed to toggle Wifi
if (mSettingsStore.isAirplaneModeOn() && !isPrivileged) {
mLog.err("setWifiEnabled in Airplane mode: only Settings can toggle wifi").flush();
return false;
}
// If SoftAp is enabled, only privileged apps are allowed to toggle wifi
if (!isPrivileged && mTetheredSoftApTracker.getState() == WIFI_AP_STATE_ENABLED) {
mLog.err("setWifiEnabled with SoftAp enabled: only Settings can toggle wifi").flush();
return false;
}
mLog.info("setWifiEnabled package=% uid=% enable=%").c(packageName)
.c(Binder.getCallingUid()).c(enable).flush();
long ident = Binder.clearCallingIdentity();
try {
if (staId == STA_PRIMARY && !mSettingsStore.handleWifiToggled(enable)) {
// Nothing to do if wifi cannot be toggled
return true;
}
} finally {
Binder.restoreCallingIdentity(ident);
}
if (mWifiPermissionsUtil.checkNetworkSettingsPermission(Binder.getCallingUid())) {
if (enable) {
mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_ON);
} else {
WifiInfo wifiInfo = mClientModeImpl.syncRequestConnectionInfo();
mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_OFF,
wifiInfo == null ? -1 : wifiInfo.getNetworkId());
}
}
if (!mIsControllerStarted) {
Log.e(TAG,"WifiController is not yet started, abort setWifiEnabled");
return false;
}
mWifiMetrics.incrementNumWifiToggles(isPrivileged, enable);
if(staId == STA_PRIMARY)
mActiveModeWarden.wifiToggled();
else if(staId == STA_SECONDARY && (getNumConcurrentStaSupported() > 1) && (getWifiEnabledState() == WifiManager.WIFI_STATE_ENABLED))
mActiveModeWarden.qtiWifiToggled(staId, enable);
else
Log.e(TAG,"setWifiEnabled not allowed for Id: " + staId);
return true;
}
三、看到SetWifiEnabled2方法中调用了mActiveModeWarden.wifiToggled();
\frameworks\opt\net\wifi\service\java\com\android\server\wifi\ActiveModeWarden.java
public void wifiToggled() {
mWifiController.sendMessage(WifiController.CMD_WIFI_TOGGLED);
}
发送了CMD_WIFI_TOGGLED消息通知状态改变
四、WifiController处理消息
WifiController是ActiveModeWarden.java中的一个内部类是一个状态机
因为是开启流程 所以目前默认状态是DisabledState
@Override
public boolean processMessageFiltered(Message msg) {
switch (msg.what) {
case CMD_WIFI_TOGGLED:
case CMD_SCAN_ALWAYS_MODE_CHANGED:
if (shouldEnableSta()) {
startClientModeManager();
transitionTo(mEnabledState);
}
break;
//省略
}
}
调用了startClientModeManager()方法 来启动一个新的客户端管理。
/**
* Method to enable a new client mode manager.
*/
private boolean startClientModeManager() {
Log.d(TAG, "Starting ClientModeManager");
ClientListener listener = new ClientListener();
ClientModeManager manager = mWifiInjector.makeClientModeManager(listener);
listener.setActiveModeManager(manager);
manager.start();
if (!switchClientModeManagerRole(manager)) {
manager.stop();
return false;
}
mActiveModeManagers.add(manager);
return true;
}
五、ClientModeManager.start()
\frameworks\opt\net\wifi\service\java\com\android\server\wifi\ClientModeManager.java
/**
* Start client mode.
*/
@Override
public void start() {
Log.d(TAG, "Starting with role ROLE_CLIENT_SCAN_ONLY");
mRole = ROLE_CLIENT_SCAN_ONLY;
mTargetRole = ROLE_CLIENT_SCAN_ONLY;
mStateMachine.sendMessage(ClientModeStateMachine.CMD_START);
}
start()方法发送了CMD_START 这个消息
ClientModeStateMachine是一个状态机 因为第一次打开WIFI所以默认是IdleState
@Override
public boolean processMessage(Message message) {
switch (message.what) {
case CMD_START:
// Always start in scan mode first.
mClientInterfaceName =
mWifiNative.setupInterfaceForClientInScanMode(
mWifiNativeInterfaceCallback);
if (TextUtils.isEmpty(mClientInterfaceName)) {
Log.e(TAG, "Failed to create ClientInterface. Sit in Idle");
mModeListener.onStartFailure();
break;
}
transitionTo(mScanOnlyModeState);
break;
default:
Log.d(TAG, "received an invalid message: " + message);
return NOT_HANDLED;
}
return HANDLED;
}
六、mWifiNative.setupInterfaceForClientInScanMode()
\frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiNative.java
/**
* Setup an interface for client mode (for scan) operations.
*
* This method configures an interface in STA mode in the native daemons
* (wificond, vendor HAL).
*
* @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 setupInterfaceForClientInScanMode(
@NonNull InterfaceCallback interfaceCallback) {
synchronized (mLock) {
if (!startHal()) {
Log.e(TAG, "Failed to start Hal");
mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
return null;
}
Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA_FOR_SCAN);
if (iface == null) {
Log.e(TAG, "Failed to allocate new STA iface");
return null;
}
iface.externalListener = interfaceCallback;
iface.name = createStaIface(iface);
if (TextUtils.isEmpty(iface.name)) {
Log.e(TAG, "Failed to create iface in vendor HAL");
mIfaceMgr.removeIface(iface.id);
mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
return null;
}
if (!mWifiCondManager.setupInterfaceForClientMode(iface.name, Runnable::run,
new NormalScanEventCallback(iface.name),
new PnoScanEventCallback(iface.name))) {
Log.e(TAG, "Failed to setup iface in wificond=" + iface.name);
teardownInterface(iface.name);
mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();
return null;
}
iface.networkObserver = new NetworkObserverInternal(iface.id);
if (!registerNetworkObserver(iface.networkObserver)) {
Log.e(TAG, "Failed to register network observer for iface=" + iface.name);
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));
Log.i(TAG, "Successfully setup " + iface);
iface.featureSet = getSupportedFeatureSetInternal(iface.name);
return iface.name;
}
}
1)WifiNative 这里首先去打开HAL
/** 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;
}
}
mWifiVendorHal.startVendorHal()
\frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiVendorHal.java
/**
* 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;
}
}
mHalDeviceManager.start()
\frameworks\opt\net\wifi\service\java\com\android\server\wifi\HalDeviceManager.java
/**
* 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");
initIWifiIfNecessary();
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;
}
}
}
mWifi.start()方法是启动实际加载WiFi动作的调用,这里涉及HIDL机制调用。通过获取IWifi接口对象,调用其方法。这里IWifi接口对象是IWifi.hal文件中实现。
hardware\interfaces\wifi\1.0\IWifi.hal 通过编译生成对应的java文件生成在
out\soong\.intermediates\hardware\interfaces\wifi\1.0\android.hardware.wifi-V1.0-java_gen_java\gen\srcs\android\hardware\wifi\V1_0\IWifi.java
@Override
public android.hardware.wifi.V1_0.WifiStatus start()
throws android.os.RemoteException {
android.os.HwParcel _hidl_request = new android.os.HwParcel();
_hidl_request.writeInterfaceToken(android.hardware.wifi.V1_0.IWifi.kInterfaceName);
android.os.HwParcel _hidl_reply = new android.os.HwParcel();
try {
mRemote.transact(3 /* start */, _hidl_request, _hidl_reply, 0 /* flags */);
_hidl_reply.verifySuccess();
_hidl_request.releaseTemporaryStorage();
android.hardware.wifi.V1_0.WifiStatus _hidl_out_status = new android.hardware.wifi.V1_0.WifiStatus();
((android.hardware.wifi.V1_0.WifiStatus) _hidl_out_status).readFromParcel(_hidl_reply);
return _hidl_out_status;
} finally {
_hidl_reply.release();
}
}
通过binder调用到wifi.cpp的start方法
hardware\interfaces\wifi\1.4\default\wifi.cpp
Return<void> Wifi::start(start_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
&Wifi::startInternal, hidl_status_cb);
}
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_,
iface_util_, 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";
// Clear the event callback objects since the HAL start failed.
event_cb_handler_.invalidate();
}
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);
}
mode_controller_->initialize()
hardware\interfaces\wifi\1.4\default\wifi_mode_controller.cpp
bool WifiModeController::initialize() {
if (!driver_tool_->LoadDriver()) {
LOG(ERROR) << "Failed to load WiFi driver";
return false;
}
return true;
}
driver_tool_->LoadDriver()
frameworks\opt\net\wifi\libwifi_hal\driver_tool.cpp
bool DriverTool::LoadDriver() {
return ::wifi_load_driver() == 0;
}
frameworks\opt\net\wifi\libwifi_hal\wifi_hal_common.cpp
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) {
#ifdef WIFI_DRIVER_MODULE_PATH
PLOG(WARNING) << "Driver unloading, err='fail to change driver state'";
if (rmmod(DRIVER_MODULE_NAME) == 0) {
PLOG(DEBUG) << "Driver unloaded";
} else {
// Set driver prop to "ok", expect HL to restart Wi-Fi.
PLOG(DEBUG) << "Driver unload failed! set driver prop to 'ok'.";
property_set(DRIVER_PROP_NAME, "ok");
}
#endif
return -1;
}
#endif
is_driver_loaded = true;
return 0;
}
到此startHal() 调用结束
2)mWifiCondManager.setupInterfaceForClientMode
frameworks\base\wifi\java\android\net\wifi\nl80211\WifiNl80211Manager.java
/**
* Set up an interface for client (STA) mode.
*
* @param ifaceName Name of the interface to configure.
* @param executor The Executor on which to execute the callbacks.
* @param scanCallback A callback for framework initiated scans.
* @param pnoScanCallback A callback for PNO (offloaded) scans.
* @return true on success.
*/
public boolean setupInterfaceForClientMode(@NonNull String ifaceName,
@NonNull @CallbackExecutor Executor executor,
@NonNull ScanEventCallback scanCallback, @NonNull ScanEventCallback pnoScanCallback) {
Log.d(TAG, "Setting up interface for client mode");
if (!retrieveWificondAndRegisterForDeath()) {
return false;
}
if (scanCallback == null || pnoScanCallback == null || executor == null) {
Log.e(TAG, "setupInterfaceForClientMode invoked with null callbacks");
return false;
}
IClientInterface clientInterface = null;
try {
clientInterface = mWificond.createClientInterface(ifaceName);
} catch (RemoteException e1) {
Log.e(TAG, "Failed to get IClientInterface due to remote exception");
return false;
}
if (clientInterface == null) {
Log.e(TAG, "Could not get IClientInterface instance from wificond");
return false;
}
Binder.allowBlocking(clientInterface.asBinder());
// Refresh Handlers
mClientInterfaces.put(ifaceName, clientInterface);
try {
IWifiScannerImpl wificondScanner = clientInterface.getWifiScannerImpl();
if (wificondScanner == null) {
Log.e(TAG, "Failed to get WificondScannerImpl");
return false;
}
mWificondScanners.put(ifaceName, wificondScanner);
Binder.allowBlocking(wificondScanner.asBinder());
ScanEventHandler scanEventHandler = new ScanEventHandler(executor, scanCallback);
mScanEventHandlers.put(ifaceName, scanEventHandler);
wificondScanner.subscribeScanEvents(scanEventHandler);
PnoScanEventHandler pnoScanEventHandler = new PnoScanEventHandler(executor,
pnoScanCallback);
mPnoScanEventHandlers.put(ifaceName, pnoScanEventHandler);
wificondScanner.subscribePnoScanEvents(pnoScanEventHandler);
} catch (RemoteException e) {
Log.e(TAG, "Failed to refresh wificond scanner due to remote exception");
}
return true;
}
这个方法主要作用是为了底层添加了一下接口.createClientInterface
七、之后回到了IdelState 继续执行transitionTo(mScanOnlyModeState);
这个作用是将状态机的状态置成ScanOnlyModeState
状态机初始化状态如下
ClientModeStateMachine(Looper looper) {
super(TAG, looper);
// CHECKSTYLE:OFF IndentationCheck
addState(mIdleState);
addState(mStartedState, mIdleState);
addState(mScanOnlyModeState, mStartedState);
addState(mConnectModeState, mStartedState);
// CHECKSTYLE:ON IndentationCheck
setInitialState(mIdleState);
start();
}
所以状态机会按照下面的方法执行
IdleState.exit()->StartedState.enter()->StartedState.exit()->ScanOnlyModeState.enter()
这个之后回到了第四步 start()之后
继续执行switchClientModeManagerRole()
/**
* Method to switch a client mode manager mode of operation (from ScanOnly To Connect &
* vice-versa) based on the toggle state.
*/
private boolean switchClientModeManagerRole(@NonNull ClientModeManager modeManager) {
if (mSettingsStore.isWifiToggleEnabled()) {
modeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY);
} else if (checkScanOnlyModeAvailable()) {
modeManager.setRole(ActiveModeManager.ROLE_CLIENT_SCAN_ONLY);
} else {
Log.e(TAG, "Something is wrong, no client mode toggles enabled");
return false;
}
return true;
}
查看isWifiToggleEnabled
frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiSettingsStore.java
public synchronized boolean isWifiToggleEnabled() {
if (mAirplaneModeOn) {
return mPersistWifiState == WIFI_ENABLED_AIRPLANE_OVERRIDE;
} else {
return mPersistWifiState != WIFI_DISABLED;//需要判断这个值
}
}
在setWifiEnabled2的时候会调用handleWifiToggled
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 {
// When wifi state is disabled, we do not care
// if airplane mode is on or not. The scenario of
// wifi being disabled due to airplane mode being turned on
// is handled handleAirplaneModeToggled()
persistWifiState(WIFI_DISABLED);
}
return true;
}
private void persistWifiState(int state) {
final ContentResolver cr = mContext.getContentResolver();
mPersistWifiState = state;//将这个是变成了WIFI_ENABLED
Settings.Global.putInt(cr, Settings.Global.WIFI_ON, state);
}
所以isWifiToggleEnabled这个方法在此返回了ture
因此执行modeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY);
@Override
public void setRole(@Role int role) {
Preconditions.checkState(CLIENT_ROLES.contains(role));
if (role == ROLE_CLIENT_SCAN_ONLY) {
mTargetRole = role;
// Switch client mode manager to scan only mode.
mStateMachine.sendMessage(ClientModeStateMachine.CMD_SWITCH_TO_SCAN_ONLY_MODE);
} else if (CLIENT_CONNECTIVITY_ROLES.contains(role)) {
mTargetRole = role;
// Switch client mode manager to connect mode.
mStateMachine.sendMessage(ClientModeStateMachine.CMD_SWITCH_TO_CONNECT_MODE, role);
}
}
//CLIENT_CONNECTIVITY_ROLES 定义在 ActiveModeManager.java中
List<Integer> CLIENT_CONNECTIVITY_ROLES = Arrays.asList(
ROLE_CLIENT_PRIMARY,
ROLE_CLIENT_SECONDARY,
ROLE_CLIENT_LOCAL_ONLY);
ROLE_CLIENT_PRIMARY包含在CLIENT_CONNECTIVITY_ROLES 数组中
所以会执行 mStateMachine.sendMessage(ClientModeStateMachine.CMD_SWITCH_TO_CONNECT_MODE, role);
查看发现有 StartedState 和ConnectModeState状态处理 CMD_SWITCH_TO_CONNECT_MODE消息
但是现在还没有到ConnectModeState状态所以会由StartedState 处理
@Override
public boolean processMessage(Message message) {
switch(message.what) {
case CMD_START:
// Already started, ignore this command.
break;
case CMD_SWITCH_TO_CONNECT_MODE:
mRole = message.arg1; // could be any one of possible connect mode roles.
updateConnectModeState(WifiManager.WIFI_STATE_ENABLING,
WifiManager.WIFI_STATE_DISABLED);
if (!mWifiNative.switchClientInterfaceToConnectivityMode(
mClientInterfaceName)) {
updateConnectModeState(WifiManager.WIFI_STATE_UNKNOWN,
WifiManager.WIFI_STATE_ENABLING);
updateConnectModeState(WifiManager.WIFI_STATE_DISABLED,
WifiManager.WIFI_STATE_UNKNOWN);
mModeListener.onStartFailure();
break;
}
transitionTo(mConnectModeState);
break;
//省略
}
}
mWifiNative.switchClientInterfaceToConnectivityMode
/**
* Switches an existing Client mode interface from scan mode
* {@link Iface#IFACE_TYPE_STA_FOR_SCAN} to connectivity mode
* {@link Iface#IFACE_TYPE_STA_FOR_CONNECTIVITY}.
*
* @param ifaceName Name of the interface.
* @return true if the operation succeeded, false if there is an error or the iface is already
* in scan mode.
*/
public boolean switchClientInterfaceToConnectivityMode(@NonNull String ifaceName) {
synchronized (mLock) {
final Iface iface = mIfaceMgr.getIface(ifaceName);
if (iface == null) {
Log.e(TAG, "Trying to switch to connectivity mode on an invalid iface="
+ ifaceName);
return false;
}
if (iface.type == Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY) {
Log.e(TAG, "Already in connectivity mode on iface=" + ifaceName);
return true;
}
if (!startSupplicant()) {
Log.e(TAG, "Failed to start supplicant");
teardownInterface(iface.name);
mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
return false;
}
if (!mSupplicantStaIfaceHal.setupIface(iface.name)) {
Log.e(TAG, "Failed to setup iface in supplicant on " + iface);
teardownInterface(iface.name);
mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
return false;
}
iface.type = Iface.IFACE_TYPE_STA_FOR_CONNECTIVITY;
iface.featureSet = getSupportedFeatureSetInternal(iface.name);
Log.i(TAG, "Successfully switched to connectivity mode on iface=" + iface);
return true;
}
}
启动了startSupplicant
/** Helper method invoked to start supplicant if there were no STA ifaces */
private boolean startSupplicant() {
synchronized (mLock) {
if (!mIfaceMgr.hasAnyStaIfaceForConnectivity()) {
if (!startAndWaitForSupplicantConnection()) {
Log.e(TAG, "Failed to connect to supplicant");
return false;
}
if (!mSupplicantStaIfaceHal.registerDeathHandler(
new SupplicantDeathHandlerInternal())) {
Log.e(TAG, "Failed to register supplicant death handler");
return false;
}
}
return true;
}
}
/**
* This method is called to wait for establishing connection to wpa_supplicant.
*
* @return true if connection is established, false otherwise.
*/
private boolean startAndWaitForSupplicantConnection() {//在这里等待与supplicant建立连接
// Start initialization if not already started.
if (!mSupplicantStaIfaceHal.isInitializationStarted()
&& !mSupplicantStaIfaceHal.initialize()) {
return false;
}
if (!mSupplicantStaIfaceHal.startDaemon()) {
Log.e(TAG, "Failed to startup supplicant");
return false;
}
boolean connected = false;
int connectTries = 0;
while (!connected && connectTries++ < CONNECT_TO_SUPPLICANT_RETRY_TIMES) {
// Check if the initialization is complete.
connected = mSupplicantStaIfaceHal.isInitializationComplete();
if (connected) {
break;
}
try {
Thread.sleep(CONNECT_TO_SUPPLICANT_RETRY_INTERVAL_MS);
} catch (InterruptedException ignore) {
}
}
return connected;
}
mSupplicantStaIfaceHal.startDaemon()
frameworks\opt\net\wifi\service\java\com\android\server\wifi\SupplicantStaIfaceHal.java
/**
* Start the supplicant daemon.
*
* @return true on success, false otherwise.
*/
public boolean startDaemon() {
synchronized (mLock) {
if (isV1_1()) {
Log.i(TAG, "Starting supplicant using HIDL");
return startDaemon_V1_1();
} else {
Log.i(TAG, "Starting supplicant using init");
mFrameworkFacade.startSupplicant();
return true;
}
}
}
/**
* Start the supplicant daemon for V1_1 service.
*
* @return true on success, false otherwise.
*/
private boolean startDaemon_V1_1() {
synchronized (mLock) {
try {
// This should startup supplicant daemon using the lazy start HAL mechanism.
getSupplicantMockableV1_1();
} catch (RemoteException e) {
Log.e(TAG, "Exception while trying to start supplicant: "
+ e);
supplicantServiceDiedHandler(mDeathRecipientCookie);
return false;
} catch (NoSuchElementException e) {
// We're starting the daemon, so expect |NoSuchElementException|.
Log.d(TAG, "Successfully triggered start of supplicant using HIDL");
}
return true;
}
}
protected android.hardware.wifi.supplicant.V1_1.ISupplicant getSupplicantMockableV1_1()
throws RemoteException, NoSuchElementException {
synchronized (mLock) {
android.hardware.wifi.supplicant.V1_1.ISupplicant iSupplicantDerived =
android.hardware.wifi.supplicant.V1_1.ISupplicant.castFrom(
getSupplicantMockable());
if (iSupplicantDerived == null) {
throw new NoSuchElementException("Cannot cast to V1.1 service.");
}
return iSupplicantDerived;
}
}
protected ISupplicant getSupplicantMockable() throws RemoteException, NoSuchElementException {
synchronized (mLock) {
ISupplicant iSupplicant = ISupplicant.getService();
if (iSupplicant == null) {
throw new NoSuchElementException("Cannot get root service.");
}
return iSupplicant;
}
}
ISupplicant.getService(); 这个也是通过HIDL实现
out\soong\.intermediates\hardware\interfaces\wifi\supplicant\1.0\android.hardware.wifi.supplicant-V1.0-java_gen_java\gen\srcs\android\hardware\wifi\supplicant\V1_0\ISupplicant.java
/**
* Warning: this will not wait for the interface to come up if it hasn't yet started. See getService(String,boolean) instead.
*/
public static ISupplicant getService() throws android.os.RemoteException {
return getService("default");
}
/**
* Warning: this will not wait for the interface to come up if it hasn't yet
* started. See getService(String,boolean) instead.
*/
public static ISupplicant getService(String serviceName) throws android.os.RemoteException {
return ISupplicant.asInterface(android.os.HwBinder.getService("[email protected]::ISupplicant", serviceName));
}
八、 在这个方法中将触发启动wpa_supplicant进程,这里需要注意,在manifest.xml中对其需要进行配置,运行时会将服务名称注册到hwservicemanager中。
wpa_supplicant目录下文件调用:
external\wpa_supplicant_8\wpa_supplicant\main.c
external\wpa_supplicant_8\wpa_supplicant\wpa_supplicant.c
external\wpa_supplicant_8\wpa_supplicant\notify.c
external\wpa_supplicant_8\wpa_supplicant\hidl\1.3\hidl.cpp
external\wpa_supplicant_8\wpa_supplicant\hidl\1.3\hidl_manager.cpp
out\soong\.intermediates\hardware\interfaces\wifi\supplicant\1.3\android.hardware.wifi.supplicant@1.3_genc++\gen\android\hardware\wifi\supplicant\1.3\SupplicantAll.cpp
system\libhidl\transport\ServiceManagement.cpp
system\hwservicemanager\ServiceManager.cpp
main.c -> main() ==> main.c -> wpa_supplicant_init()
==> wpa_supplicant.c -> wpa_supplicant_init() ==> notify.c -> wpas_notify_supplicant_initialized()
==> hidl.cpp -> wpas_hidl_init() ==> hidl_manager.cpp -> registerHidlService()
==> SupplicantAll.cpp -> registerAsService() ==> ServiceManagement.cpp -> registerAsServiceInternal()
==> ServiceManager.cpp -> addWithChain() ==> ServiceManager.cpp -> addImpl()
==> ServiceManager.cpp -> sendPackageRegistrationNotification()
==> onRegistration(fqName, instanceName, false /* preexisting */) 触发回调
在SupplicantStaIfaceHal.java 初始化的时候注册了回调的监听
/**
* Registers a service notification for the ISupplicant service, which triggers initialization
* of the ISupplicantStaIface
* @return true if the service notification was successfully registered
*/
public boolean initialize() {
synchronized (mLock) {
if (mVerboseLoggingEnabled) {
Log.i(TAG, "Registering ISupplicant service ready callback.");
}
mISupplicant = null;
mISupplicantVendor = null;
mISupplicantStaIfaces.clear();
mISupplicantVendorStaIfaces.clear();
if (mIServiceManager != null) {
// Already have an IServiceManager and serviceNotification registered, don't
// don't register another.
return true;
}
try {
mIServiceManager = getServiceManagerMockable();
if (mIServiceManager == null) {
Log.e(TAG, "Failed to get HIDL Service Manager");
return false;
}
if (!linkToServiceManagerDeath()) {
return false;
}
/* TODO(b/33639391) : Use the new ISupplicant.registerForNotifications() once it
exists */
if (!mIServiceManager.registerForNotifications(
ISupplicant.kInterfaceName, "default", mServiceNotificationCallback)) {
Log.e(TAG, "Failed to register for notifications to "
+ ISupplicant.kInterfaceName);
mIServiceManager = null; // Will need to register a new ServiceNotification
return false;
}
} catch (RemoteException e) {
Log.e(TAG, "Exception while trying to register a listener for ISupplicant service: "
+ e);
supplicantServiceDiedHandler(mDeathRecipientCookie);
}
return true;
}
}
private final IServiceNotification mServiceNotificationCallback =
new IServiceNotification.Stub() {
public void onRegistration(String fqName, String name, boolean preexisting) {
synchronized (mLock) {
if (mVerboseLoggingEnabled) {
Log.i(TAG, "IServiceNotification.onRegistration for: " + fqName
+ ", " + name + " preexisting=" + preexisting);
}
if (!initSupplicantService()) {
Log.e(TAG, "initalizing ISupplicant failed.");
supplicantServiceDiedHandler(mDeathRecipientCookie);
} else {
Log.i(TAG, "Completed initialization of ISupplicant.");
}
}
}
};
private boolean initSupplicantService() {
synchronized (mLock) {
try {
mISupplicant = getSupplicantMockable();
} catch (RemoteException e) {
Log.e(TAG, "ISupplicant.getService exception: " + e);
return false;
} catch (NoSuchElementException e) {
Log.e(TAG, "ISupplicant.getService exception: " + e);
return false;
}
if (mISupplicant == null) {
Log.e(TAG, "Got null ISupplicant service. Stopping supplicant HIDL startup");
return false;
}
if (!linkToSupplicantDeath(mSupplicantDeathRecipient, ++mDeathRecipientCookie)) {
return false;
}
}
if (!initSupplicantVendorService())
Log.e(TAG, "Failed to init SupplicantVendor service");
return true;
}
到此supplicant已经启动
九、switchClientInterfaceToConnectivityMode 之后会继续执行mSupplicantStaIfaceHal.setupIface(iface.name) 来设置接口,完成后打印
Log.i(TAG, "Successfully switched to connectivity mode on iface=" + iface);
十、StartedState 继续处理 CMD_SWITCH_TO_CONNECT_MODE 消息
执行transitionTo(mConnectModeState); 方法 进入 ConnectModeState状态
@Override
public void enter() {
Log.d(TAG, "entering ConnectModeState");
mClientModeImpl.registerModeListener(mClientModeImplListener);
mClientModeImpl.setOperationalMode(ClientModeImpl.CONNECT_MODE,
mClientInterfaceName);
}
继续处理CMD_SWITCH_TO_CONNECT_MODE 消息
@Override
public boolean processMessage(Message message) {
switch (message.what) {
//省略
case CMD_SWITCH_TO_CONNECT_MODE:
int newRole = message.arg1;
// Already in connect mode, only switching the connectivity roles.
if (newRole != mRole) {
mRole = newRole;
mModeListener.onStarted();
}
break;
//省略
}
}
触发onStarted()回调
onStarted()在ActiveModeWarden.java中定义
private class ClientListener extends ModeCallback implements ActiveModeManager.Listener {
@Override
public void onStarted() {
updateClientScanMode();
updateBatteryStats();
}
@Override
public void onStopped() {
mActiveModeManagers.remove(getActiveModeManager());
updateClientScanMode();
updateBatteryStats();
mWifiController.sendMessage(WifiController.CMD_STA_STOPPED);
}
@Override
public void onStartFailure() {
mActiveModeManagers.remove(getActiveModeManager());
updateClientScanMode();
updateBatteryStats();
mWifiController.sendMessage(WifiController.CMD_STA_START_FAILURE);
}
}
然后执行updateClientScanMode
// Update the scan state based on all active mode managers.
private void updateClientScanMode() {
boolean scanEnabled = hasAnyClientModeManager();
boolean scanningForHiddenNetworksEnabled;
if (mContext.getResources().getBoolean(R.bool.config_wifiScanHiddenNetworksScanOnlyMode)) {
scanningForHiddenNetworksEnabled = hasAnyClientModeManager();
} else {
scanningForHiddenNetworksEnabled = hasAnyClientModeManagerInConnectivityRole();
}
mScanRequestProxy.enableScanning(scanEnabled, scanningForHiddenNetworksEnabled);
}
mScanRequestProxy.enableScanning()
frameworks\opt\net\wifi\service\java\com\android\server\wifi\ScanRequestProxy.java
private void enableScanningInternal(boolean enable) {
if (!retrieveWifiScannerIfNecessary()) {
Log.e(TAG, "Failed to retrieve wifiscanner");
return;
}
mWifiScanner.setScanningEnabled(enable);
sendScanAvailableBroadcast(mContext, enable);
clearScanResults();
Log.i(TAG, "Scanning is " + (enable ? "enabled" : "disabled"));
}
private void enableScanningInternal(boolean enable) {
if (!retrieveWifiScannerIfNecessary()) {
Log.e(TAG, "Failed to retrieve wifiscanner");
return;
}
mWifiScanner.setScanningEnabled(enable);
sendScanAvailableBroadcast(mContext, enable);
clearScanResults();
Log.i(TAG, "Scanning is " + (enable ? "enabled" : "disabled"));
}
mWifiScanner.setScanningEnabled
frameworks\base\wifi\java\android\net\wifi\WifiScanner.java
/**
* Enable/Disable wifi scanning.
*
* @param enable set to true to enable scanning, set to false to disable all types of scanning.
*
* @see WifiManager#ACTION_WIFI_SCAN_AVAILABILITY_CHANGED
* {@hide}
*/
@SystemApi
@RequiresPermission(Manifest.permission.NETWORK_STACK)
public void setScanningEnabled(boolean enable) {
validateChannel();
mAsyncChannel.sendMessage(enable ? CMD_ENABLE : CMD_DISABLE);
}
之后就可就是开始扫描AP