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
- 总结:
- 1、流程总结:
- 2、配置参数总结
本文对热点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() {@Overridepublic void execute(Runnable command) {if (handler == null) {command.run();} else {handler.post(command);}}};final StartTetheringCallback tetheringCallback = new StartTetheringCallback() {@Overridepublic void onTetheringStarted() {callback.onTetheringStarted();}@Overridepublic void onTetheringFailed(final int error) {callback.onTetheringFailed();}};final TetheringRequest request = new TetheringRequest.Builder(type).setShouldShowEntitlementUi(showProvisioningUi).build();//追踪:在mTetheringManager 中 startTetheringmTetheringManager.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() {@Overridepublic 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;}@Overridepublic void tether(String iface, String callerPkg, IIntResultListener listener) {if (checkAndNotifyCommonError(callerPkg, listener)) return;try {listener.onResult(mTethering.tether(iface));} catch (RemoteException e) { }}@Overridepublic void startTethering(TetheringRequestParcel request, String callerPkg,IIntResultListener listener) {if (checkAndNotifyCommonError(callerPkg,request.exemptFromEntitlementCheck /* onlyAllowPrivileged */,listener)) {return;}//追踪:Tethering.startTetheringmTethering.startTethering(request, listener);}@Overridepublic 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(); //最终还是调用了 wifiManagerif (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;@Overridepublic 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_APmWifiController.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 {@Overridepublic boolean processMessageFiltered(Message msg) {switch (msg.what) {。。。 //追踪:CMD_SET_APcase CMD_SET_AP:// note: CMD_SET_AP is handled/dropped in ECM mode - will not start hereif (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.*/@Overridepublic void start() { //追踪:CMD_STARTmStateMachine.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 {@Overridepublic 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 {@Overridepublic void enter() {mApInterfaceName = null;mIfaceIsUp = false;mIfaceIsDestroyed = false;}@Overridepublic boolean processMessage(Message message) {switch (message.what) {case CMD_STOP:mStateMachine.quitNow();break;//追踪:CMD_STARTcase 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)判断配置对话和名称是否为nullif (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 neededif (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 热点开启流程相关推荐
- (七十一)Android O WiFi热点 开启流程梳理
前言:之前主要梳理了WiFi开启扫描连接的流程,现在梳理下WiFi 热点 的开启流程. 时序图mdj样式:https://download.csdn.net/download/sinat_200594 ...
- (九十七)Android O WiFi热点 开启流程梳理续(二)
前言:从之前WiFi的连接流程可以知道WiFi最后一步会和服务端进行dhcp以获取ip地址,那么WiFi热点开启的时候应该也要配置相关dhcp属性,以供后续WiFi连接的时候ip分配,根据这块流程继续 ...
- Android9.0Wifi热点开启流程梳理
如果你也是年轻的程序员,关注我一起学习探讨 Android9.0中对热点做了较大改动,将热点很大程度从Wifi中剥离出来了. 下面我们看一下热点是怎么开启的. 首先是在WifiTetherSettin ...
- Android11 热点配置信息保存分析
Android11 热点配置信息保存分析 文章目录 Android11 热点配置信息保存分析 一.Android11 wifi和热点 配置信息保存的文件位置 1.wifi和热点保存的实际位置 2.wi ...
- Android11 热点设置永不关闭
Android11 热点设置永不关闭 文章目录 Android11 热点设置永不关闭 一.前言 二.framework设置热点永不超时关闭 三.基于 SoftApManager.java 研究超时逻辑 ...
- android 13 热点启动流程
近期在看一个热点启动的问题.发现网上基本上都算android 9 的wifi热点启动流程.自己去看android 13 的源码的时候发现与之前相比已经有一些小改动了. 在此总结一下wifie热点的启动 ...
- Android 11 WiFi开启流程
从刚接触WiFi时跟过wifi的开启流程,当时还是android9.到了Android11代码架构有了不小的改动,在这里重新梳理一遍,便于在工作中更快速的跟踪代码. 一.Settings里改动不大,还 ...
- android8.0热点打开流程,从Setting到framework
关键函数的调用流程如下: 热点的开启能否成功,主要由以下几个因素影响 (1)WifiStateMachine.java中的状态异常,而引起状态异常的原因有很多,可能是由于我们在修改的过程中,发生了一些 ...
- 协同工作流引擎,开启流程优化新纪元
2019独角兽企业重金招聘Python工程师标准>>> 协同工作流引擎(Synchro flow)是业界领先的企业业务流程自动化的基础平台产品以及企业流程再造的核心产品,提供以业务建 ...
最新文章
- 数学建模中的matlab实例,matlab数学建模实例
- 国产光刻机正式宣布:今年出货150台
- 在线录音机 html5,recorder
- ubuntu安装USB转串口驱动(PL2303)
- JavaSE(二十二)——TCP协议的三次握手
- JSP、EL和JSTL-学习笔记04【JSTL常用标签】
- 研讨会 | “人工智能与行业知识图谱技术实战”研讨会
- 《网友世界》杂志:2010“最不给力”软件
- python写exploit采集器
- UESTC 1706 Orbital
- 【POJ1276】【多重背包】凑货币问题
- h5摄像头拍照上传php,H5调用摄像头拍照上传
- JAVA - 根据文件链接将文件下载保存到本地
- 【参数】平面光:倍增为3.5,颜色为淡蓝色/淡——daiding
- 我的世界java版骨头指令_我的世界:如何调出“啃骨头”隐藏皮肤?1个没人知道的mc彩蛋...
- 计算机网络ap参数,酒店计算机网络(含无线AP)系统主要技术参数.docx
- python实现一个web服务器
- 火狐开发----Web开发者工具
- RANSAC Spline Fitting
- 消息循环中的TranslateMessage函数和DispatchMessage函数
热门文章
- Nouveau源码分析(三):NVIDIA设备初始化之nouveau_drm_probe
- 微信群里如何屏蔽某一个人的发言
- 小程序修改单页面的背景颜色
- js月份的计算公式_JavaScript用于设置月份的方法setMonth()
- 用计算机的拓展活动总结,计算机学院心理健康节素质拓展活动圆满结束
- Java使用Tomcat服务器打开jsp等文件出现源码的解决办法
- Greenplum常用SQL——通过表名查找shema名
- java easing_[译] 动画中缓动(easing)的基础知识
- PHPUnit袖珍指南 第六章 装置器
- 什么品牌的蓝牙耳机通话音质最好?通话音质好的蓝牙耳机