Android11 热点开启流程
Posted 峥嵘life
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android11 热点开启流程相关的知识,希望对你有一定的参考价值。
android11 热点开启流程
文章目录
- Android11 热点开启流程
- 一、应用中热点开启和关闭的代码:
- 二、系统源码追踪
- 1、ConnectivityManager.startTethering
- 2、TetheringManager.startTethering
- 3、TetheringService.TetheringConnector.startTethering
- 4、Tethering.startTethering(request, listener);
- 5、WifiManager.startTetheredHotspot(null /* use existing softap config */)
- 6、WifiServiceImpl.startTetheredHotspot(@Nullable SoftApConfiguration softApConfig)
- 7、ActiveModeWarden.startSoftAp(apModeConfig);
- 8、ActiveModeManager.start();
- 10、WifiNative.startSoftAp
- 11、HostapdHal.addAccessPoint
- 总结:
本文对热点framework 中上层的代码逻辑进行梳理,供大家参考学习。
一、应用中热点开启和关闭的代码:
ConnectivityManager mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
//开启
mConnectivityManager.startTethering(ConnectivityManager.TETHERING_WIFI, true /* showProvisioningUi */,
mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
//关闭
mConnectivityManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
二、系统源码追踪
1、ConnectivityManager.startTethering
frameworks\\base\\core\\java\\android\\net\\ConnectivityManager.java
public static final int TETHERING_WIFI = TetheringManager.TETHERING_WIFI;
public static final int TETHERING_USB = TetheringManager.TETHERING_USB;
public static final int TETHERING_BLUETOOTH = TetheringManager.TETHERING_BLUETOOTH;
private final TetheringManager mTetheringManager;
public void startTethering(int type, boolean showProvisioningUi,
final OnStartTetheringCallback callback, Handler handler)
Preconditions.checkNotNull(callback, "OnStartTetheringCallback cannot be null.");
final Executor executor = new Executor()
@Override
public void execute(Runnable command)
if (handler == null)
command.run();
else
handler.post(command);
;
final StartTetheringCallback tetheringCallback = new StartTetheringCallback()
@Override
public void onTetheringStarted()
callback.onTetheringStarted();
@Override
public void onTetheringFailed(final int error)
callback.onTetheringFailed();
;
final TetheringRequest request = new TetheringRequest.Builder(type)
.setShouldShowEntitlementUi(showProvisioningUi).build();
//追踪:在mTetheringManager 中 startTethering
mTetheringManager.startTethering(request, executor, tetheringCallback);
2、TetheringManager.startTethering
frameworks\\base\\packages\\Tethering\\common\\TetheringLib\\src\\android\\net\\TetheringManager.java
@RequiresPermission(anyOf =
android.Manifest.permission.TETHER_PRIVILEGED,
android.Manifest.permission.WRITE_SETTINGS
)
public void startTethering(@NonNull final TetheringRequest request,
@NonNull final Executor executor, @NonNull final StartTetheringCallback callback)
final String callerPkg = mContext.getOpPackageName();
Log.i(TAG, "startTethering caller:" + callerPkg);
final IIntResultListener listener = new IIntResultListener.Stub()
@Override
public void onResult(final int resultCode)
executor.execute(() ->
if (resultCode == TETHER_ERROR_NO_ERROR)
callback.onTetheringStarted();
else
callback.onTetheringFailed(resultCode);
);
;
//追踪:
getConnector(c -> c.startTethering(request.getParcel(), callerPkg, listener));
private void getConnector(ConnectorConsumer consumer)
final ITetheringConnector connector;
synchronized (mConnectorWaitQueue)
connector = mConnector;
if (connector == null)
mConnectorWaitQueue.add(consumer);
return;
try
consumer.onConnectorAvailable(connector);
catch (RemoteException e)
throw new IllegalStateException(e);
private interface ConnectorConsumer
void onConnectorAvailable(ITetheringConnector connector) throws RemoteException;
从上面看是 ConnectorConsumer 的回调对象调用了 startTethering 方法
查哪个应用实现了 ITetheringConnector:
3、TetheringService.TetheringConnector.startTethering
frameworks\\base\\packages\\Tethering\\src\\com\\android\\networkstack\\tethering\\TetheringService.java
TetheringService.TetheringConnector.startTethering
//内部接口类
private static class TetheringConnector extends ITetheringConnector.Stub
private final TetheringService mService;
private final Tethering mTethering;
TetheringConnector(Tethering tether, TetheringService service)
mTethering = tether;
mService = service;
@Override
public void tether(String iface, String callerPkg, IIntResultListener listener)
if (checkAndNotifyCommonError(callerPkg, listener)) return;
try
listener.onResult(mTethering.tether(iface));
catch (RemoteException e)
@Override
public void startTethering(TetheringRequestParcel request, String callerPkg,
IIntResultListener listener)
if (checkAndNotifyCommonError(callerPkg,
request.exemptFromEntitlementCheck /* onlyAllowPrivileged */,
listener))
return;
//追踪:Tethering.startTethering
mTethering.startTethering(request, listener);
@Override
public void stopTethering(int type, String callerPkg, IIntResultListener listener)
if (checkAndNotifyCommonError(callerPkg, listener)) return;
try
mTethering.stopTethering(type);
listener.onResult(TETHER_ERROR_NO_ERROR);
catch (RemoteException e)
继续追踪Tethering 的 startTethering 方法
4、Tethering.startTethering(request, listener);
frameworks\\base\\packages\\Tethering\\src\\com\\android\\networkstack\\tethering\\Tethering.java
void startTethering(final TetheringRequestParcel request, final IIntResultListener listener)
mHandler.post(() ->
final TetheringRequestParcel unfinishedRequest = mActiveTetheringRequests.get(
request.tetheringType);
// If tethering is already enabled with a different request,
// disable before re-enabling.
if (unfinishedRequest != null
&& !TetheringUtils.isTetheringRequestEquals(unfinishedRequest, request))
enableTetheringInternal(request.tetheringType, false /* disabled */, null);
mEntitlementMgr.stopProvisioningIfNeeded(request.tetheringType);
mActiveTetheringRequests.put(request.tetheringType, request);
if (request.exemptFromEntitlementCheck)
mEntitlementMgr.setExemptedDownstreamType(request.tetheringType);
else
mEntitlementMgr.startProvisioningIfNeeded(request.tetheringType,
request.showProvisioningUi);
//追踪:
enableTetheringInternal(request.tetheringType, true /* enabled */, listener);
);
private void enableTetheringInternal(int type, boolean enable,
final IIntResultListener listener)
int result = TETHER_ERROR_NO_ERROR;
switch (type)
case TETHERING_WIFI:
//追踪:
result = setWifiTethering(enable);
break;
。。。
case TETHERING_ETHERNET:
result = setEthernetTethering(enable);
break;
default:
Log.w(TAG, "Invalid tether type.");
result = TETHER_ERROR_UNKNOWN_TYPE;
// The result of Bluetooth tethering will be sent by #setBluetoothTethering.
if (type != TETHERING_BLUETOOTH)
sendTetherResult(listener, result, type);
private int setWifiTethering(final boolean enable)
final long ident = Binder.clearCallingIdentity();
try
synchronized (mPublicSync)
final WifiManager mgr = getWifiManager(); //最终还是调用了 wifiManager
if (mgr == null)
mLog.e("setWifiTethering: failed to get WifiManager!");
return TETHER_ERROR_SERVICE_UNAVAIL;
//追踪:
if ((enable && mgr.startTetheredHotspot(null /* use existing softap config */))
|| (!enable && mgr.stopSoftAp()))
mWifiTetherRequested = enable;
return TETHER_ERROR_NO_ERROR;
finally
Binder.restoreCallingIdentity(ident);
return TETHER_ERROR_INTERNAL_ERROR;
5、WifiManager.startTetheredHotspot(null /* use existing softap config */)
frameworks\\base\\wifi\\java\\android\\net\\wifi\\WifiManager.java
@SystemApi
@RequiresPermission(anyOf =
android.Manifest.permission.NETWORK_STACK,
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
)
public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig)
try
//追踪:
return mService.startTetheredHotspot(softApConfig);
catch (RemoteException e)
throw e.rethrowFromSystemServer();
继续追一下WifiMananger在里面实现的
6、WifiServiceImpl.startTetheredHotspot(@Nullable SoftApConfiguration softApConfig)
//实现类
public class BaseWifiService extends IWifiManager.Stub 。。。
WifiServiceImpl.startTetheredHotspot(@Nullable SoftApConfiguration softApConfig)
//更多实现的实现子类
/**
* WifiService handles remote WiFi operation requests by implementing
* the IWifiManager interface.
*/
public class WifiServiceImpl extends BaseWifiService
private final ActiveModeWarden mActiveModeWarden;
@Override
public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig)
// NETWORK_STACK is a signature only permission.
enforceNetworkStackPermission();
mLog.info("startTetheredHotspot uid=%").c(Binder.getCallingUid()).flush();
if (!mTetheredSoftApTracker.setEnablingIfAllowed())
mLog.err("Tethering is already active.").flush();
return false;
if (!mWifiThreadRunner.call(
() -> mActiveModeWarden.canRequestMoreSoftApManagers(), false))
// Take down LOHS if it is up.
mLohsSoftApTracker.stopAll();
if (!startSoftApInternal(new SoftApModeConfiguration(
WifiManager.IFACE_IP_MODE_TETHERED, softApConfig,
mTetheredSoftApTracker.getSoftApCapability())))
mTetheredSoftApTracker.setFailedWhileEnabling();
return false;
return true;
private boolean startSoftApInternal(SoftApModeConfiguration apConfig)
int uid = Binder.getCallingUid();
boolean privileged = isSettingsOrSuw(Binder.getCallingPid(), uid);
mLog.trace("startSoftApInternal uid=% mode=%")
.c(uid).c(apConfig.getTargetMode()).flush();
// null wifiConfig is a meaningful input for CMD_SET_AP; it means to use the persistent
// AP config.
SoftApConfiguration softApConfig = apConfig.getSoftApConfiguration();
//存在 softApConfig 为 null的情况,所以不会进这里
if (softApConfig != null
&& (!WifiApConfigStore.validateApWifiConfiguration(softApConfig, privileged)
|| !validateSoftApBand(softApConfig.getBand())))
Log.e(TAG, "Invalid SoftApConfiguration");
return false;
//追踪:
mActiveModeWarden.startSoftAp(apConfig);
return true;
值得注意的是上面的startSoftApInternal 方法中,
SoftApModeConfiguration apConfig 不为空,并且传入到后面的处理也不为空
只是SoftApConfiguration softApConfig = apConfig.getSoftApConfiguration();里面的softApConfig对象为null而已!
frameworks\\opt\\net\\wifi\\service\\java\\com\\android\\server\\wifi\\SoftApModeConfiguration.java
相当于一个普通的Bean类
class SoftApModeConfiguration
/**
* Routing mode. Either @link android.net.wifi.WifiManager#IFACE_IP_MODE_TETHERED
* or @link android.net.wifi.WifiManager#IFACE_IP_MODE_LOCAL_ONLY.
*/
private final int mTargetMode;
private final SoftApCapability mCapability;
/**
* SoftApConfiguration for internal use, or null if it hasn't been generated yet.
*/
private final @Nullable SoftApConfiguration mSoftApConfig;
SoftApModeConfiguration(int targetMode, @Nullable SoftApConfiguration config,
SoftApCapability capability)
Preconditions.checkArgument(
targetMode == WifiManager.IFACE_IP_MODE_TETHERED
|| targetMode == WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
mTargetMode = targetMode;
mSoftApConfig = config;
mCapability = capability;
public int getTargetMode()
return mTargetMode;
public SoftApConfiguration getSoftApConfiguration()
return mSoftApConfig;
public SoftApCapability getCapability()
return mCapability;
7、ActiveModeWarden.startSoftAp(apModeConfig);
frameworks\\opt\\net\\wifi\\service\\java\\com\\android\\server\\wifi\\ActiveModeWarden.java
private final WifiController mWifiController;
private final WifiInjector mWifiInjector;
/** Starts SoftAp. */
public void startSoftAp(SoftApModeConfiguration softApConfig)
//追踪:CMD_SET_AP
mWifiController.sendMessage(WifiController.CMD_SET_AP, 1, 0, softApConfig);
/**
* WifiController is the class used to manage wifi state for various operating
* modes (normal, airplane, wifi hotspot, etc.).
*/
private class WifiController extends StateMachine
private static final String TAG = "WifiController";
// Maximum limit to use for timeout delay if the value from overlay setting is too large.
private static final int MAX_RECOVERY_TIMEOUT_DELAY_MS = 4000;
private static final int BASE = Protocol.BASE_WIFI_CONTROLLER;
static final int CMD_EMERGENCY_MODE_CHANGED = BASE + 1;
static final int CMD_SCAN_ALWAYS_MODE_CHANGED = BASE + 7;
static final int CMD_WIFI_TOGGLED = BASE + 8;
static final int CMD_AIRPLANE_TOGGLED = BASE + 9;
static final int CMD_SET_AP = BASE + 10;
...
static final int CMD_RECOVERY_DISABLE_WIFI = BASE + 19;
static final int CMD_STA_STOPPED = BASE + 20;
static final int CMD_DEFERRED_RECOVERY_RESTART_WIFI = BASE + 22;
static final int CMD_AP_START_FAILURE = BASE + 23;
static final int CMD_UPDATE_AP_CAPABILITY = BASE + 24;
static final int CMD_UPDATE_AP_CONFIG = BASE + 25;
class EnabledState extends BaseState
@Override
public boolean processMessageFiltered(Message msg)
switch (msg.what)
。。。 //追踪:CMD_SET_AP
case CMD_SET_AP:
// note: CMD_SET_AP is handled/dropped in ECM mode - will not start here
if (msg.arg1 == 1)
//追踪:
startSoftApModeManager((SoftApModeConfiguration) msg.obj);
else
stopSoftApModeManagers(msg.arg2);
break;
case CMD_AP_STOPPED:
case CMD_AP_START_FAILURE:
。。。
default:
return NOT_HANDLED;
return HANDLED;
private void startSoftApModeManager(@NonNull SoftApModeConfiguration softApConfig)
Log.d(TAG, "Starting SoftApModeManager config = "
+ softApConfig.getSoftApConfiguration());
Preconditions.checkState(softApConfig.getTargetMode() == IFACE_IP_MODE_LOCAL_ONLY
|| softApConfig.getTargetMode() == IFACE_IP_MODE_TETHERED);
WifiManager.SoftApCallback callback =
softApConfig.getTargetMode() == IFACE_IP_MODE_LOCAL_ONLY
? mLohsCallback : mSoftApCallback;
SoftApListener listener = new SoftApListener();
ActiveModeManager manager =
mWifiInjector.makeSoftApManager(listener, callback, softApConfig);
listener.setActiveModeManager(manager);
manager.start();
manager.setRole(getRoleForSoftApIpMode(softApConfig.getTargetMode()));
mActiveModeManagers.add(manager);
8、ActiveModeManager.start();
frameworks\\opt\\net\\wifi\\service\\java\\com\\android\\server\\wifi\\ActiveModeManager.java
public interface ActiveModeManager
/**
* Listener for ActiveModeManager state changes.
*/
interface Listener
void onStarted();
void onStopped();
void onStartFailure();
void start();
void stop();
boolean isStopping();
frameworks\\opt\\net\\wifi\\service\\java\\com\\android\\server\\wifi\\WifiInjector.java
public SoftApManager makeSoftApManager(@NonNull ActiveModeManager.Listener listener,
@NonNull WifiManager.SoftApCallback callback,
@NonNull SoftApModeConfiguration config)
return new SoftApManager(mContext, mWifiHandlerThread.getLooper(),
mFrameworkFacade, mWifiNative, mCountryCode.getCountryCode(), listener, callback,
mWifiApConfigStore, config, mWifiMetrics, mSarManager, mWifiDiagnostics);
frameworks\\opt\\net\\wifi\\service\\java\\com\\android\\server\\wifi\\SoftApManager.java
SoftApManager 实现了 ActiveModeManager接口,
SoftApManager.startSoftAp()
里面包含了 SoftApStateMachine ,就是所谓的状态机对象
上面ActiveModeManager.start(); 就是调用到 SoftApManager.start();最终调到 startSoftAp方法
/**
* Manage WiFi in AP mode.
* The internal state machine runs under the ClientModeImpl handler thread context.
*/
public class SoftApManager implements ActiveModeManager
private static final String TAG = "SoftApManager";
private final SoftApStateMachine mStateMachine;
private final WifiApConfigStore mWifiApConfigStore;
/**
* Start soft AP, as configured in the constructor.
*/
@Override
public void start() //追踪:CMD_START
mStateMachine.sendMessage(SoftApStateMachine.CMD_START);
private class SoftApStateMachine extends StateMachine
// Commands for the state machine.
public static final int CMD_START = 0;
public static final int CMD_STOP = 1;
。。。
public static final int CMD_UPDATE_CONFIG = 11;
SoftApStateMachine(Looper looper)
super(TAG, looper);
addState(mIdleState);
addState(mStartedState);
setInitialState(mIdleState);
start();
private class IdleState extends State
@Override
public void enter()
mApInterfaceName = null;
mIfaceIsUp = false;
mIfaceIsDestroyed = false;
private class SoftApStateMachine extends StateMachine
// Commands for the state machine.
public static final int CMD_START = 0;
public static final int CMD_STOP = 1;
。。。
public static final int CMD_UPDATE_CONFIG = 11;
SoftApStateMachine(Looper looper)
super(TAG, looper);
addState(mIdleState);
addState(mStartedState);
setInitialState(mIdleState);
start();
private class IdleState extends State
@Override
public void enter()
mApInterfaceName = null;
mIfaceIsUp = false;
mIfaceIsDestroyed = false;
@Override
public boolean processMessage(Message message)
switch (message.what)
case CMD_STOP:
mStateMachine.quitNow();
break;
//追踪:CMD_START
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);
mModeListener.onStartFailure();
break;
mSoftApNotifier.dismissSoftApShutDownTimeoutExpiredNotification();
updateApState(WifiManager.WIFI_AP_STATE_ENABLING,
WifiManager.WIFI_AP_STATE_DISABLED, 0);
//追踪:重点关注!
int result = startSoftAp(); //关键流程
if (result != SUCCESS)
int failureReason = WifiManager.SAP_START_FAILURE_GENERAL;
if (result == ERROR_NO_CHANNEL)
failureReason = WifiManager.SAP_START_FAILURE_NO_CHANNEL;
else if (result == ERROR_UNSUPPORTED_CONFIGURATION)
failureReason = WifiManager
.SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION;
updateApState(WifiManager.WIFI_AP_STATE_FAILED,
WifiManager.WIFI_AP_STATE_ENABLING,
failureReason);
stopSoftAp();
mWifiMetrics.incrementSoftApStartResult(false, failureReason);
mModeListener.onStartFailure();
break;
transitionTo(mStartedState);
break;
。。。
default:
// Ignore all other commands.
break;
return HANDLED;
//整个系统热点开启最重要的地方,通过这里日志能知道是否开启热点成功
/**
* Start a soft AP instance as configured.
*
* @return integer result code
*/
private int startSoftAp()
SoftApConfiguration config = mApConfig.getSoftApConfiguration();
//(1)判断配置对话和名称是否为null
if (config == null || config.getSsid() == null)
Log.e(TAG, "Unable to start soft AP without valid configuration");
return ERROR_GENERIC;
Log.d(TAG, "band " + config.getBand() + " iface "
+ mApInterfaceName + " country " + mCountryCode);
//(2)判断是否能设置MAC地址
int result = setMacAddress();
if (result != SUCCESS)
return result;
//(3)判断是否能设置CountryCode,5G热点,band =2 的情况才要设置
result = setCountryCode();
if (result != SUCCESS)
return result;
//(4)重新创建一个热点配置对象,这个对象的数据才是传递给底层的!
// Make a copy of configuration for updating AP band and channel.
SoftApConfiguration.Builder localConfigBuilder = new SoftApConfiguration.Builder(config);
boolean acsEnabled = mCurrentSoftApCapability.areFeaturesSupported(
SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD);
//(5)重点来了!这里是有更新配置的逻辑
result = ApConfigUtil.updateApChannelConfig(
mWifiNative, mContext.getResources(), mCountryCode, localConfigBuilder, config,
acsEnabled);
if (result != SUCCESS)
Log.e(TAG, "Failed to update AP band and channel");
return result;
if (config.isHiddenSsid())
Log.d(TAG, "SoftAP is a hidden network");
//后面的都是一些基本检测和动作
//(6)检测热点配置是否支持
if (!ApConfigUtil.checkSupportAllConfiguration(config, mCurrentSoftApCapability))
Log.d(TAG, "Unsupported Configuration detect! config = " + config);
return ERROR_UNSUPPORTED_CONFIGURATION;
//(7)启动热点
if (!mWifiNative.startSoftAp(mApInterfaceName,
localConfigBuilder.build(), mSoftApListener))
Log.e(TAG, "Soft AP start failed");
return ERROR_GENERIC;
mWifiDiagnostics.startLogging(mApInterfaceName);
mStartTimestamp = FORMATTER.format(new Date(System.currentTimeMillis()));
//(8)热点启动成功的标志!
Log.d(TAG, "Soft AP is started ");
return SUCCESS;
10、WifiNative.startSoftAp
frameworks\\opt\\net\\wifi\\service\\java\\com\\android\\server\\wifi\\WifiNative.java
private final HostapdHal mHostapdHal;
public boolean startSoftAp(
@NonNull String ifaceName, SoftApConfiguration config, SoftApListener listener)
if (!mWifiCondManager.registerApCallback(ifaceName, Runnable::run, listener))
Log.e(TAG, "Failed to register ap listener");
return false;
if (!mHostapdHal.addAccessPoint(ifaceName, config, listener::onFailure))
Log.e(TAG, "Failed to add acccess point");
mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();
return false;
return true;
11、HostapdHal.addAccessPoint
frameworks\\opt\\net\\wifi\\service\\java\\com\\android\\server\\wifi\\HostapdHal.java
public boolean addAccessPoint(@NonNull String ifaceName, @NonNull SoftApConfiguration config,
@NonNull Runnable onFailureListener)
synchronized (mLock)
int band;
boolean enableAcs = ApConfigUtil.isAcsSupported(mContext) && config.getChannel() == 0
&& !mForceApChannel;
if (enableAcs)
ifaceParams.channelParams.enableAcs = true;
ifaceParams.channelParams.acsShouldExcludeDfs = !mContext.getResources()
.getBoolean(R.bool.config_wifiSoftapAcsIncludeDfs);
//可以打印下channel 和 band 的值,查看传递给底层的具体数据
ifaceParams.channelParams.channel =
mForceApChannel ? mForcedApChannel : config.getChannel();
band = mForceApChannel ? mForcedApBand : config.getBand();
//添加传入到底层的数据:
Log.i(TAG, "band = " + band + ", channel = " + ifaceParams.channelParams.channel);
android.hardware.wifi.hostapd.V1_2.IHostapd.NetworkParams nwParamsV1_2 =
prepareNetworkParams(config);
if (nwParamsV1_2 == null) return false;
if (!checkHostapdAndLogFailure(methodStr)) return false;
try
HostapdStatus status;
if (!isV1_1() && !isV1_2())
ifaceParams.channelParams.band = getHalBand(band);
status = mIHostapd.addAccessPoint(ifaceParams, nwParamsV1_2.V1_0);
if (!checkStatusAndLogFailure(status, methodStr))
return false;
else
android.hardware.wifi.hostapd.V1_1.IHostapd.IfaceParams ifaceParams1_1 =
new android.hardware.wifi.hostapd.V1_1.IHostapd.IfaceParams();
ifaceParams1_1.V1_0 = ifaceParams;
if (!isV1_2())
ifaceParams.channelParams.band = getHalBand(band);
if (ifaceParams.channelParams.enableAcs)
if ((band & SoftApConfiguration.BAND_2GHZ) != 0)
ifaceParams1_1.channelParams.acsChannelRanges.addAll(
toAcsChannelRanges(mContext.getResources().getString(
R.string.config_wifiSoftap2gChannelList)));
if ((band & SoftApConfiguration.BAND_5GHZ) != 0)
ifaceParams1_1.channelParams.acsChannelRanges.addAll(
toAcsChannelRanges(mContext.getResources().getString(
R.string.config_wifiSoftap5gChannelList)));
android.hardware.wifi.hostapd.V1_1.IHostapd iHostapdV1_1 =
getHostapdMockableV1_1();
if (iHostapdV1_1 == null) return false;
status = iHostapdV1_1.addAccessPoint_1_1(ifaceParams1_1, nwParamsV1_2.V1_0);
if (!checkStatusAndLogFailure(status, methodStr))
return false;
ifaceParams.channelParams.channel =
mForceApChannel ? mForcedApChannel : config.getChannel();
band = mForceApChannel ? mForcedApBand : config.getBand();
android.hardware.wifi.hostapd.V1_2.IHostapd.NetworkParams nwParamsV1_2 =
prepareNetworkParams(config);
else
android.hardware.wifi.hostapd.V1_2.HostapdStatus status12;
android.hardware.wifi.hostapd.V1_2.IHostapd.IfaceParams ifaceParams1_2 =
new android.hardware.wifi.hostapd.V1_2.IHostapd.IfaceParams();
ifaceParams1_2.V1_1 = ifaceParams1_1;
ifaceParams1_2.hwModeParams.enable80211AX =
mContext.getResources().getBoolean(
R.bool.config_wifiSoftapIeee80211axSupported);
ifaceParams1_2.hwModeParams.enable6GhzBand =
mContext.getResources().getBoolean(
R.bool.config_wifiSoftap6ghzSupported);
ifaceParams1_2.hwModeParams.enableHeSingleUserBeamformer =
mContext.getResources().getBoolean(
R.bool.config_wifiSoftapHeSuBeamformerSupported);
ifaceParams1_2.hwModeParams.enableHeSingleUserBeamformee =
mContext.getResources().getBoolean(
R.bool.config_wifiSoftapHeSuBeamformeeSupported);
ifaceParams1_2.hwModeParams.enableHeMultiUserBeamformer =
mContext.getResources().getBoolean(
R.bool.config_wifiSoftapHeMuBeamformerSupported);
ifaceParams1_2.hwModeParams.enableHeTargetWakeTime =
mContext.getResources().getBoolean(
R.bool.config_wifiSoftapHeTwtSupported);
ifaceParams1_2.channelParams.bandMask = getHalBandMask(band);
// Prepare freq ranges/lists if needed
if (ifaceParams.channelParams.enableAcs
&& isSendFreqRangesNeeded(band))
if ((band & SoftApConfiguration.BAND_2GHZ) != 0)
ifaceParams1_2.channelParams.acsChannelFreqRangesMhz.addAll(
toAcsFreqRanges(SoftApConfiguration.BAND_2GHZ));
if ((band & SoftApConfiguration.BAND_5GHZ) != 0)
ifaceParams1_2.channelParams.acsChannelFreqRangesMhz.addAll(
toAcsFreqRanges(SoftApConfiguration.BAND_5GHZ));
if ((band & SoftApConfiguration.BAND_6GHZ) != 0)
ifaceParams1_2.channelParams.acsChannelFreqRangesMhz.addAll(
toAcsFreqRanges(SoftApConfiguration.BAND_6GHZ));
android.hardware.wifi.hostapd.V1_2.IHostapd iHostapdV1_2 =
getHostapdMockableV1_2();
if (iHostapdV1_2 == null) return false;
status12 = iHostapdV1_2.addAccessPoint_1_2(ifaceParams1_2, nwParamsV1_2);
if (!checkStatusAndLogFailure12(status12, methodStr))
return false;
mSoftApFailureListeners.put(ifaceName, onFailureListener);
return true;
catch (IllegalArgumentException e)
Log.e(TAG, "Unrecognized apBand: " + band);
return false;
catch (RemoteException e)
handleRemoteException(e, methodStr);
return false;
总结:
1、流程总结:
(1)ConnectivityManager.startTethering
(2)TetheringManager.startTethering(request, executor, tetheringCallback)
(3)TetheringService.TetheringConnector.startTethering
(4)Tethering.startTethering(request, listener);
//方法名变化,使用null 对象开启热点
(5)WifiManager.startTetheredHotspot(null /* use existing softap config */)
(6)WifiServiceImpl.startTetheredHotspot(@Nullable SoftApConfiguration softApConfig)
//方法名再变化
(7)ActiveModeWarden.startSoftAp(apModeConfig);
(8)ActiveModeManager.start();
ActiveModeManager manager = mWifiInjector.makeSoftApManager(listener, callback, softApConfig);
listener.setActiveModeManager(manager);
manager.start();
ActiveModeManager是接口类,会调用到SoftApManager.start()
(9)SoftApManager.startSoftAp()
(10)WifiNative.startSoftAp(mApInterfaceName, localConfigBuilder.build(), mSoftApListener)
(11)HostapdHal.addAccessPoint(ifaceName, config, listener::onFailure)
(12)根据硬件版本调用不同的接口实现:addAccessPoint_X_X
2、配置参数总结
热点的配置在SoftApManager.startSoftAp() 会有一定的修改,
比如channel ==0 的情况是会在ApConfigUtil.java中,对应的band范围内随机生成一个channel值。
frameworks\\opt\\net\\wifi\\service\\java\\com\\android\\server\\wifi\\util\\ApConfigUtil.java
所以热点配置有变化,需要分析的生活,可以在SoftApManager 和相关文件中多添加日志即可。
以上是关于Android11 热点开启流程的主要内容,如果未能解决你的问题,请参考以下文章