700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Android9设备打开WIFI热点 Android9.0Wifi热点开启流程梳理

Android9设备打开WIFI热点 Android9.0Wifi热点开启流程梳理

时间:2018-09-25 02:34:40

相关推荐

Android9设备打开WIFI热点 Android9.0Wifi热点开启流程梳理

Android9.0中对热点做了较大改动,将热点很大程度从Wifi中剥离出来了。

下面我们看一下热点是怎么开启的。

首先是在WifiTetherSettings中,调用startTether()函数,可以看到startTether函数中主要是调用了WifiTetherSwitchBarController.java中的startTether()函数。

源码路径:

/9.0.0_r3/xref/packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherSettings.java#174

private void startTether() {

mRestartWifiApAfterConfigChange = false;

mSwitchBarController.startTether();

}

然后我们看WifiTetherSwitchBarController里的startTether函数,WifiTetherSwitchBarController是用来控制开关栏切换的,可以看到他调用了ConnectivityManager的startTethering函数。

源码路径:

/9.0.0_r3/xref/packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java#107

void startTether() {

mSwitchBar.setEnabled(false);

mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */,

mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));

}

然后在这里调用了ConnectivityService的startTethering函数。

源码路径:

/9.0.0_r3/xref/frameworks/base/core/java/android/net/ConnectivityManager.java#2261

public void startTethering(int type, boolean showProvisioningUi,

final OnStartTetheringCallback callback, Handler handler) {

try {

String pkgName = mContext.getOpPackageName();

Log.i(TAG, "startTethering caller:" + pkgName);

mService.startTethering(type, wrappedCallback, showProvisioningUi, pkgName);

} catch (RemoteException e) {

Log.e(TAG, "Exception trying to start tethering.", e);

wrappedCallback.send(TETHER_ERROR_SERVICE_UNAVAIL, null);

}

}

在ConnectivityService中,会跳到Tethering.java的startTethering函数。

源码路径:

/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/ConnectivityService.java#3232

public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi,

String callerPkg) {

ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);

if (!isTetheringSupported()) {

receiver.send(ConnectivityManager.TETHER_ERROR_UNSUPPORTED, null);

return;

}

mTethering.startTethering(type, receiver, showProvisioningUi);

}

在Tethering.java中,函数的调用顺序如下:startTethering—>enableTetheringInternal—>setWifiTethering。在setWifiTethering中,调用了WifiManager的startSoftAp函数。

源码路径:

/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/connectivity/Tethering.java#368

368 public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {

if (!isTetherProvisioningRequired()) {

enableTetheringInternal(type, true, receiver);

return;

}

if (showProvisioningUi) {

runUiTetherProvisioningAndEnable(type, receiver);

} else {

runSilentTetherProvisioningAndEnable(type, receiver);

}

}

private void enableTetheringInternal(int type, boolean enable, ResultReceiver receiver) {

boolean isProvisioningRequired = enable && isTetherProvisioningRequired();

int result;

switch (type) {

case TETHERING_WIFI:

result = setWifiTethering(enable);

if (isProvisioningRequired && result == TETHER_ERROR_NO_ERROR) {

scheduleProvisioningRechecks(type);

}

sendTetherResult(receiver, result);

break;

private int setWifiTethering(final boolean enable) {

int rval = TETHER_ERROR_MASTER_ERROR;

final long ident = Binder.clearCallingIdentity();

try {

synchronized (mPublicSync) {

mWifiTetherRequested = enable;

final WifiManager mgr = getWifiManager();

if ((enable && mgr.startSoftAp(null /* use existing wifi config */)) ||

(!enable && mgr.stopSoftAp())) {

rval = TETHER_ERROR_NO_ERROR;

}

}

} finally {

Binder.restoreCallingIdentity(ident);

}

return rval;

}

在这里调用了WifiServiceImpl.java的startSoftAp函数。

源码路径:

/9.0.0_r3/xref/frameworks/base/wifi/java/android/net/wifi/WifiManager.java#1909

public boolean startSoftAp(@Nullable WifiConfiguration wifiConfig) {

try {

return mService.startSoftAp(wifiConfig);

} catch (RemoteException e) {

throw e.rethrowFromSystemServer();

}

}

在这里调用了startSoftApInternal函数,然后向WifiController的状态机发送了CMD_SET_AP消息。

源码路径:

/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java#1004

public boolean startSoftAp(WifiConfiguration wifiConfig) {

// NETWORK_STACK is a signature only permission.

enforceNetworkStackPermission();

mLog.info("startSoftAp uid=%").c(Binder.getCallingUid()).flush();

synchronized (mLocalOnlyHotspotRequests) {

// If a tethering request comes in while we have LOHS running (or requested), call stop

// for softap mode and restart softap with the tethering config.

if (!mLocalOnlyHotspotRequests.isEmpty()) {

stopSoftApInternal();

}

return startSoftApInternal(wifiConfig, WifiManager.IFACE_IP_MODE_TETHERED);

}

}

private boolean startSoftApInternal(WifiConfiguration wifiConfig, int mode) {

mLog.trace("startSoftApInternal uid=% mode=%")

.c(Binder.getCallingUid()).c(mode).flush();

// null wifiConfig is a meaningful input for CMD_SET_AP

if (wifiConfig == null || WifiApConfigStore.validateApWifiConfiguration(wifiConfig)) {

SoftApModeConfiguration softApConfig = new SoftApModeConfiguration(mode, wifiConfig);

mWifiController.sendMessage(CMD_SET_AP, 1, 0, softApConfig);

return true;

}

Slog.e(TAG, "Invalid WifiConfiguration");

return false;

}

在这里,处理结果是调用WifiStateMachinePrime的enterSoftAPMode方法。

源码路径:

/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiController.java#593

class DefaultState extends State {

case CMD_SET_AP:

// note: CMD_SET_AP is handled/dropped in ECM mode - will not start here

// first make sure we aren't in airplane mode

if (mSettingsStore.isAirplaneModeOn()) {

log("drop softap requests when in airplane mode");

break;

}

if (msg.arg1 == 1) {

SoftApModeConfiguration config = (SoftApModeConfiguration) msg.obj;

mWifiStateMachinePrime.enterSoftAPMode((SoftApModeConfiguration) msg.obj);

} else {

mWifiStateMachinePrime.stopSoftAPMode();

}

break;

在WifiStateMachinePrime中,创建了SoftApManager对象,并且调用了start方法。

源码路径:

/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachinePrime.java#549

public void enterSoftAPMode(@NonNull SoftApModeConfiguration wifiConfig) {

mHandler.post(() -> {

startSoftAp(wifiConfig);

});

}

private void startSoftAp(SoftApModeConfiguration softapConfig) {

Log.d(TAG, "Starting SoftApModeManager");

WifiConfiguration config = softapConfig.getWifiConfiguration();

if (config != null && config.SSID != null) {

Log.d(TAG, "Passing config to SoftApManager! " + config);

} else {

config = null;

}

SoftApCallbackImpl callback = new SoftApCallbackImpl();

ActiveModeManager manager = mWifiInjector.makeSoftApManager(callback, softapConfig);

callback.setActiveModeManager(manager);

manager.start();

mActiveModeManagers.add(manager);

updateBatteryStatsWifiState(true);

}

在这里,StateMachine发送了消息CMD_START,然后由IdleState 处理,这里主要的处理结果就是调用startSoftAp方法。在startSoftAp里,调用了WifiNative.java的startSoftAp方法。

源码路径:

/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/SoftApManager.java#142

public void start() {

mStateMachine.sendMessage(SoftApStateMachine.CMD_START, mApConfig);

}

private class IdleState extends State {

public boolean processMessage(Message message) {

switch (message.what) {

case CMD_START:

mApInterfaceName = mWifiNative.setupInterfaceForSoftApMode(

mWifiNativeInterfaceCallback);

if (TextUtils.isEmpty(mApInterfaceName)) {

Log.e(TAG, "setup failure when creating ap interface.");

updateApState(WifiManager.WIFI_AP_STATE_FAILED,

WifiManager.WIFI_AP_STATE_DISABLED,

WifiManager.SAP_START_FAILURE_GENERAL);

mWifiMetrics.incrementSoftApStartResult(

false, WifiManager.SAP_START_FAILURE_GENERAL);

break;

}

updateApState(WifiManager.WIFI_AP_STATE_ENABLING,

WifiManager.WIFI_AP_STATE_DISABLED, 0);

int result = startSoftAp((WifiConfiguration) message.obj);

if (result != SUCCESS) {

int failureReason = WifiManager.SAP_START_FAILURE_GENERAL;

if (result == ERROR_NO_CHANNEL) {

failureReason = WifiManager.SAP_START_FAILURE_NO_CHANNEL;

}

updateApState(WifiManager.WIFI_AP_STATE_FAILED,

WifiManager.WIFI_AP_STATE_ENABLING,

failureReason);

stopSoftAp();

mWifiMetrics.incrementSoftApStartResult(false, failureReason);

break;

}

transitionTo(mStartedState);

break;

private int startSoftAp(WifiConfiguration config) {

if (config == null || config.SSID == null) {

Log.e(TAG, "Unable to start soft AP without valid configuration");

return ERROR_GENERIC;

}

// Make a copy of configuration for updating AP band and channel.

WifiConfiguration localConfig = new WifiConfiguration(config);

int result = ApConfigUtil.updateApChannelConfig(

mWifiNative, mCountryCode,

mWifiApConfigStore.getAllowed2GChannel(), localConfig);

if (result != SUCCESS) {

Log.e(TAG, "Failed to update AP band and channel");

return result;

}

// Setup country code if it is provided.

if (mCountryCode != null) {

// Country code is mandatory for 5GHz band, return an error if failed to set

// country code when AP is configured for 5GHz band.

if (!mWifiNative.setCountryCodeHal(

mApInterfaceName, mCountryCode.toUpperCase(Locale.ROOT))

&& config.apBand == WifiConfiguration.AP_BAND_5GHZ) {

Log.e(TAG, "Failed to set country code, required for setting up "

+ "soft ap in 5GHz");

return ERROR_GENERIC;

}

}

if (localConfig.hiddenSSID) {

Log.d(TAG, "SoftAP is a hidden network");

}

if (!mWifiNative.startSoftAp(mApInterfaceName, localConfig, mSoftApListener)) {

Log.e(TAG, "Soft AP start failed");

return ERROR_GENERIC;

}

Log.d(TAG, "Soft AP is started");

return SUCCESS;

}

在这里,主要是调用WificondControl.java的startHostapd方法。

源码路径:

/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java#1250

public boolean startSoftAp(

@NonNull String ifaceName, WifiConfiguration config, SoftApListener listener) {

if (!mWificondControl.startHostapd(ifaceName, listener)) {

Log.e(TAG, "Failed to start hostapd");

mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();

return false;

}

if (!waitForHostapdConnection()) {

Log.e(TAG, "Failed to establish connection to hostapd");

mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();

return false;

}

if (!mHostapdHal.registerDeathHandler(new HostapdDeathHandlerInternal())) {

Log.e(TAG, "Failed to register hostapd death handler");

mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();

return false;

}

if (!mHostapdHal.addAccessPoint(ifaceName, config)) {

Log.e(TAG, "Failed to add acccess point");

mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();

return false;

}

return true;

}

在这里可以看到创建了IApInterface 对象,然后调用了他的startHostapd方法。而IApInterface 是由ap_interface_impl.cpp实现的。

源码路径:

/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WificondControl.java#787

public boolean startHostapd(@NonNull String ifaceName,

SoftApListener listener) {

IApInterface iface = getApInterface(ifaceName);

if (iface == null) {

Log.e(TAG, "No valid ap interface handler");

return false;

}

try {

IApInterfaceEventCallback callback = new ApInterfaceEventCallback(listener);

mApInterfaceListeners.put(ifaceName, callback);

boolean success = iface.startHostapd(callback);

if (!success) {

Log.e(TAG, "Failed to start hostapd.");

return false;

}

} catch (RemoteException e) {

Log.e(TAG, "Exception in starting soft AP: " + e);

return false;

}

return true;

}

在这里又调用了hostapd_manager的StartHostapd函数。

源码路径:

/9.0.0_r3/xref/system/connectivity/wificond/ap_interface_impl.cpp#86

bool ApInterfaceImpl::StartHostapd() {

return hostapd_manager_->StartHostapd();

}

然后在hostapd_manager.cpp里调用了StartHostapd方法。

源码路径:

/9.0.0_r3/xref/frameworks/opt/net/wifi/libwifi_system/hostapd_manager.cpp#26

bool HostapdManager::StartHostapd() {

if (property_set("ctl.start", kHostapdServiceName) != 0) {

LOG(ERROR) << "Failed to start SoftAP";

return false;

LOG(DEBUG) << "SoftAP started successfully";

return true;

}

再往后就是底层C的代码了,不是特别看得懂。然后返回success的话,热点就成功打开了,状态也变为started。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。