一、点击wifi开关
默认有2种方式打开wifi
1)从设置打开
packagesappsSettingssrccomandroidsettingswifiWifiEnabler.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)从状态栏点击打开
frameworksbasepackagesSystemUIsrccomandroidsystemuiqstilesWifiTile.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);
}
}
frameworksbasepackagesSystemUIsrccomandroidsystemuistatusbarpolicyNetworkControllerImpl.java
调用了WifiManager的setWifiEnabled
@Override
public void setWifiEnabled(final boolean enabled) {
new AsyncTask() {
@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();
frameworksoptnetwifiservicejavacomandroidserverwifiActiveModeWarden.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()方法 来启动一个新的客户端管理。
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()
frameworksoptnetwifiservicejavacomandroidserverwifiClientModeManager.java
@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()
frameworksoptnetwifiservicejavacomandroidserverwifiWifiNative.java
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
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()
frameworksoptnetwifiservicejavacomandroidserverwifiWifiVendorHal.java
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()
frameworksoptnetwifiservicejavacomandroidserverwifiHalDeviceManager.java
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文件中实现。
hardwareinterfaceswifi1.0IWifi.hal 通过编译生成对应的java文件生成在
outsoong.intermediateshardwareinterfaceswifi1.0android.hardware.wifi-V1.0-java_gen_javagensrcsandroidhardwarewifiV1_0IWifi.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 , _hidl_request, _hidl_reply, 0 );
_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方法
hardwareinterfaceswifi1.4defaultwifi.cpp
ReturnWifi::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()
hardwareinterfaceswifi1.4defaultwifi_mode_controller.cpp
bool WifiModeController::deinitialize() {
if (!driver_tool_->UnloadDriver()) {
LOG(ERROR) << "Failed to unload WiFi driver";
return false;
}
return true;
}
driver_tool_->UnloadDriver()
frameworksoptnetwifilibwifi_haldriver_tool.cpp
bool DriverTool::UnloadDriver() {
return ::wifi_unload_driver() == 0;
}
frameworksoptnetwifilibwifi_halwifi_hal_common.cpp
int wifi_unload_driver() {
if (!is_wifi_driver_loaded()) {
return 0;
}
#ifdef WIFI_DRIVER_MODULE_PATH
if (rmmod(DRIVER_MODULE_NAME) == 0) {
int count = 20;
while (count-- > 0) {
if (!is_wifi_driver_loaded()) break;
usleep(500000);
}
usleep(500000);
if (count) {
return 0;
}
return -1;
} else
return -1;
#else
#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
if (is_wifi_driver_loaded()) {
if (wifi_change_driver_state(WIFI_DRIVER_STATE_OFF) < 0) return -1;
}
#endif
is_driver_loaded = false;
property_set(DRIVER_PROP_NAME, "unloaded");
return 0;
#endif
}
到此startHal() 调用结束
2)mWifiCondManager.setupInterfaceForClientMode
frameworksbasewifijavaandroidnetwifinl80211WifiNl80211Manager.java
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()
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
frameworksoptnetwifiservicejavacomandroidserverwifiWifiSettingsStore.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 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
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
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;
}
}
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()
frameworksoptnetwifiservicejavacomandroidserverwifiSupplicantStaIfaceHal.java
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;
}
}
}
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实现
outsoong.intermediateshardwareinterfaceswifisupplicant1.0android.hardware.wifi.supplicant-V1.0-java_gen_javagensrcsandroidhardwarewifisupplicantV1_0ISupplicant.java
public static ISupplicant getService() throws android.os.RemoteException {
return getService("default");
}
public static ISupplicant getService(String serviceName) throws android.os.RemoteException {
return ISupplicant.asInterface(android.os.HwBinder.getService("android.hardware.wifi.supplicant@1.0::ISupplicant", serviceName));
}
八、 在这个方法中将触发启动wpa_supplicant进程,这里需要注意,在manifest.xml中对其需要进行配置,运行时会将服务名称注册到hwservicemanager中。
wpa_supplicant目录下文件调用:
externalwpa_supplicant_8wpa_supplicantmain.c externalwpa_supplicant_8wpa_supplicantwpa_supplicant.c externalwpa_supplicant_8wpa_supplicantnotify.c externalwpa_supplicant_8wpa_supplicanthidl1.3hidl.cpp externalwpa_supplicant_8wpa_supplicanthidl1.3hidl_manager.cpp outsoong.intermediateshardwareinterfaceswifisupplicant1.3android.hardware.wifi.supplicant@1.3_genc++genandroidhardwarewifisupplicant1.3SupplicantAll.cpp systemlibhidltransportServiceManagement.cpp systemhwservicemanagerServiceManager.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 ) 触发回调
在SupplicantStaIfaceHal.java 初始化的时候注册了回调的监听
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;
}
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()
frameworksoptnetwifiservicejavacomandroidserverwifiScanRequestProxy.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
frameworksbasewifijavaandroidnetwifiWifiScanner.java
@SystemApi
@RequiresPermission(Manifest.permission.NETWORK_STACK)
public void setScanningEnabled(boolean enable) {
validateChannel();
mAsyncChannel.sendMessage(enable ? CMD_ENABLE : CMD_DISABLE);
}
之后就可就是开始扫描AP



