Android 13热点打开流程

Android 13热点打开流程

版本Android-13.0.0_r3
在Settings中打开热点 点击事件开始
按钮初始化

/packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherSettings.java
@Override
public void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);if (mUnavailable) {return;}// Assume we are in a SettingsActivity. This is only safe because we currently use// SettingsActivity as base for all preference fragments.final SettingsActivity activity = (SettingsActivity) getActivity();final SettingsMainSwitchBar switchBar = activity.getSwitchBar();switchBar.setTitle(getContext().getString(R.string.use_wifi_hotsopt_main_switch_title));mSwitchBarController = new WifiTetherSwitchBarController(activity, switchBar);getSettingsLifecycle().addObserver(mSwitchBarController);switchBar.show();
}

获取activity and switchBar,设置switchBar的Title。new WifiTetherSwitchBarController来进行控制控件。最后show显示。

来看WifiTetherSwitchBarController方法

/packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java//构造函数
WifiTetherSwitchBarController(Context context, SettingsMainSwitchBar switchBar) {mContext = context;mSwitchBar = switchBar;mSwitch = mSwitchBar.getSwitch();mDataSaverBackend = new DataSaverBackend(context);mConnectivityManager =(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);mSwitchBar.setChecked(mWifiManager.getWifiApState() == WIFI_AP_STATE_ENABLED);updateWifiSwitch();
}@Override
public void onStart() {mDataSaverBackend.addListener(this);mSwitchBar.addOnSwitchChangeListener(this);mContext.registerReceiver(mReceiver, WIFI_INTENT_FILTER,Context.RECEIVER_EXPORTED_UNAUDITED);
}@Override
public void onSwitchChanged(Switch switchView, boolean isChecked) {// Filter out unnecessary callbacks when switch is disabled.if (!switchView.isEnabled()) return;if (isChecked) {startTether();} else {stopTether();}
}void startTether() {if (isWifiApActivated()) return;mSwitchBar.setEnabled(false);mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */,mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
}final ConnectivityManager.OnStartTetheringCallback mOnStartTetheringCallback =new ConnectivityManager.OnStartTetheringCallback() {@Overridepublic void onTetheringFailed() {super.onTetheringFailed();Log.e(TAG, "Failed to start Wi-Fi Tethering.");handleWifiApStateChanged(mWifiManager.getWifiApState());}};

在这个WifiTetherSwitchBarController方法中为按钮设置了点击事件,执行的方法是startTether(),开始了开启热点的相关流程。
startTether()中if (isWifiApActivated()) return;当前状态是不是WIFI_AP_STATE_ENABLED and WIFI_AP_STATE_ENABLING,true直接return。
mSwitchBar.setEnabled(false);禁用控件
下来调用ConnectivityManager中的startTethering()

/packages/modules/Connectivity/framework/src/android/net/ConnectivityManager.java
public void startTethering(int type, boolean showProvisioningUi,final OnStartTetheringCallback callback, Handler handler) {Objects.requireNonNull(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();getTetheringManager().startTethering(request, executor, tetheringCallback);
}

又进入到getTetheringManager().startTethering(request, executor, tetheringCallback);

/packages/modules/Connectivity/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
//如果需要,启动绑定并运行给定类型的绑定配置。如果配置失败,stopTethering将被自动调用。
@RequiresPermission(anyOf = {android.Manifest.permission.TETHER_PRIVILEGED,android.Manifest.permission.WRITE_SETTINGS
})
//Executor:指定调用TetheringRequest回调函数的线程。
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();	//Success} else {callback.onTetheringFailed(resultCode);	//Failed}});}};getConnector(c -> c.startTethering(request.getParcel(), callerPkg,getAttributionTag(), listener));
}
//ConnectorConsumer是一个接口,所以consumer.onConnectorAvailable(connector)就相当于调用了
//connector.startTethering()。ITetheringConnector connector  是一个aidl 接口,跨进程到
//TetheringService.java
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);}
}
//aidl接口---》TetheringService.java
private interface ConnectorConsumer {void onConnectorAvailable(ITetheringConnector connector) throws RemoteException;
}
/packages/modules/Connectivity/Tethering/src/com/android/networkstack/tethering/TetheringService.java
@Override
public void startTethering(TetheringRequestParcel request, String callerPkg,String callingAttributionTag, IIntResultListener listener) {if (checkAndNotifyCommonError(callerPkg,callingAttributionTag,request.exemptFromEntitlementCheck /* onlyAllowPrivileged */,listener)) {return;}mTethering.startTethering(request, listener);
}

这里又调到mTethering.startTethering(request, listener); mTethering—》Tethering

/packages/modules/Connectivity/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_USB:result = setUsbTethering(enable);break;case TETHERING_BLUETOOTH:setBluetoothTethering(enable, listener);break;case TETHERING_NCM:result = setNcmTethering(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 {final WifiManager mgr = getWifiManager();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;
}

开启热点执行TETHERING_WIFI类型,在setWifiTethering方法中getWifiManager,然后再调用WifiManager 中的startTetheredHotspot传参数是个null。
这个参数代表着在开启热点时,会根据配置文件的内容决定开启热点的参数。这个配置文件在手机的data/misc/apexdata/com.android.wifi/ 下面。一个是热点,一个是WiFi
WifiConfigStore.xml WifiConfigStoreSoftAp.xml

/packages/modules/Wifi/framework/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, mContext.getOpPackageName());} catch (RemoteException e) {throw e.rethrowFromSystemServer();}
}

这里就是打开热点的一个API,SoftApConfiguration 是nullmService—》WifiServiceImpl.startTetheredHotspot()

/packages/modules/Wifi/service/java/com/android/server/wifi/WifiServiceImpl.java
@Override
public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig,@NonNull String packageName) {// NETWORK_STACK is a signature only permission.enforceNetworkStackPermission();int callingUid = Binder.getCallingUid();mWifiPermissionsUtil.checkPackage(callingUid, packageName);// If user restriction is set, cannot start softapif (mWifiTetheringDisallowed) {mLog.err("startTetheredHotspot with user restriction: not permitted").flush();return false;}mLog.info("startTetheredHotspot uid=%").c(callingUid).flush();// TODO: b/233363886, handle timeout in general way.if (!checkSetEnablingIfAllowed()) {return false;}WorkSource requestorWs = new WorkSource(callingUid, packageName);if (!mWifiThreadRunner.call(() -> mActiveModeWarden.canRequestMoreSoftApManagers(requestorWs), false)) {// Take down LOHS if it is up.mLohsSoftApTracker.stopAll();}if (!startSoftApInternal(new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, softApConfig,mTetheredSoftApTracker.getSoftApCapability()), requestorWs)) {mTetheredSoftApTracker.setFailedWhileEnabling();return false;}mLastCallerInfoManager.put(WifiManager.API_TETHERED_HOTSPOT, Process.myTid(),callingUid, Binder.getCallingPid(), packageName, true);return true;
}

Check一些权限然后执行到startSoftApInternal

private boolean startSoftApInternal(SoftApModeConfiguration apConfig, WorkSource requestorWs) {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();if (softApConfig != null&& (!WifiApConfigStore.validateApWifiConfiguration(softApConfig, privileged, mContext))) {Log.e(TAG, "Invalid SoftApConfiguration");return false;}mActiveModeWarden.startSoftAp(apConfig, requestorWs);return true;
}

进入到ActiveModeWarden中的startSoftAp

/packages/modules/Wifi/service/java/com/android/server/wifi/ActiveModeWarden.java
/** Starts SoftAp. */
public void startSoftAp(SoftApModeConfiguration softApConfig, WorkSource requestorWs) {mWifiController.sendMessage(WifiController.CMD_SET_AP, 1, 0,Pair.create(softApConfig, requestorWs));
}

在startSoftAp方法中发送一条消息(CMD_SET_AP),在ActiveModeWarden的内部类EnabledState中处理

@Override
public boolean processMessageFiltered(Message msg) {...
case CMD_SET_AP:// note: CMD_SET_AP is handled/dropped in ECM mode - will not start hereif (msg.arg1 == 1) {Pair<SoftApModeConfiguration, WorkSource> softApConfigAndWs = (Pair) msg.obj;startSoftApModeManager(softApConfigAndWs.first, softApConfigAndWs.second);} else {stopSoftApModeManagers(msg.arg2);}break;...
}private void startSoftApModeManager(@NonNull SoftApModeConfiguration softApConfig, @NonNull WorkSource requestorWs) {Log.d(TAG, "Starting SoftApModeManager config = " + softApConfig.getSoftApConfiguration());Preconditions.checkState(softApConfig.getTargetMode() == IFACE_IP_MODE_LOCAL_ONLY|| softApConfig.getTargetMode() == IFACE_IP_MODE_TETHERED);WifiServiceImpl.SoftApCallbackInternal callback =softApConfig.getTargetMode() == IFACE_IP_MODE_LOCAL_ONLY? mLohsCallback : mSoftApCallback;SoftApManager manager = mWifiInjector.makeSoftApManager(new SoftApListener(), callback, softApConfig, requestorWs,getRoleForSoftApIpMode(softApConfig.getTargetMode()), mVerboseLoggingEnabled);mSoftApManagers.add(manager);
}

Callback回调方法是mLohsCallback。然后通过WifiInjector new了一个softApManager

/packages/modules/Wifi/service/java/com/android/server/wifi/WifiInjector.java
public SoftApManager makeSoftApManager(@NonNull ActiveModeManager.Listener<SoftApManager> listener,@NonNull WifiServiceImpl.SoftApCallbackInternal callback,@NonNull SoftApModeConfiguration config,@NonNull WorkSource requestorWs,@NonNull ActiveModeManager.SoftApRole role,boolean verboseLoggingEnabled) {return new SoftApManager(mContext, mWifiHandlerThread.getLooper(),mFrameworkFacade, mWifiNative, mCoexManager, makeBatteryManager(),mCountryCode.getCountryCode(), listener, callback, mWifiApConfigStore,config, mWifiMetrics, mSarManager, mWifiDiagnostics,new SoftApNotifier(mContext, mFrameworkFacade, mWifiNotificationManager),mCmiMonitor, mActiveModeWarden, mClock.getElapsedSinceBootMillis(),requestorWs, role, verboseLoggingEnabled);
}

========================================================================
此构造函数有点长,直接在里面进行注释

/packages/modules/Wifi/service/java/com/android/server/wifi/SoftApManager.java
public SoftApManager(@NonNull WifiContext context,@NonNull Looper looper,@NonNull FrameworkFacade framework,@NonNull WifiNative wifiNative,@NonNull CoexManager coexManager,@NonNull BatteryManager batteryManager,String countryCode,@NonNull Listener<SoftApManager> listener,@NonNull WifiServiceImpl.SoftApCallbackInternal callback,@NonNull WifiApConfigStore wifiApConfigStore,@NonNull SoftApModeConfiguration apConfig,@NonNull WifiMetrics wifiMetrics,@NonNull SarManager sarManager,@NonNull WifiDiagnostics wifiDiagnostics,@NonNull SoftApNotifier softApNotifier,@NonNull ClientModeImplMonitor cmiMonitor,@NonNull ActiveModeWarden activeModeWarden,long id,@NonNull WorkSource requestorWs,@NonNull SoftApRole role,boolean verboseLoggingEnabled) {mContext = context;mFrameworkFacade = framework;mSoftApNotifier = softApNotifier;mWifiNative = wifiNative;mCoexManager = coexManager;mBatteryManager = batteryManager;if (SdkLevel.isAtLeastS()) {mCoexListener = new CoexListener() {@Overridepublic void onCoexUnsafeChannelsChanged() {if (mCurrentSoftApConfiguration == null) {return;}mStateMachine.sendMessage(SoftApStateMachine.CMD_SAFE_CHANNEL_FREQUENCY_CHANGED);}};} else {mCoexListener = null;}mCountryCode = countryCode;mModeListener = listener;mSoftApCallback = callback;mWifiApConfigStore = wifiApConfigStore;mCurrentSoftApConfiguration = apConfig.getSoftApConfiguration();mCurrentSoftApCapability = apConfig.getCapability();
//传递的是null,这里就会从WifiApConfigStore中AP获取相关的配置// null is a valid input and means we use the user-configured tethering settings.if (mCurrentSoftApConfiguration == null) {mCurrentSoftApConfiguration = mWifiApConfigStore.getApConfiguration();// may still be null if we fail to load the default config}// Store mode configuration before update the configuration.mOriginalModeConfiguration = new SoftApModeConfiguration(apConfig.getTargetMode(),mCurrentSoftApConfiguration, mCurrentSoftApCapability);if (mCurrentSoftApConfiguration != null) {mIsUnsetBssid = mCurrentSoftApConfiguration.getBssid() == null;if (mCurrentSoftApCapability.areFeaturesSupported(SoftApCapability.SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION)) {mCurrentSoftApConfiguration = mWifiApConfigStore.randomizeBssidIfUnset(mContext, mCurrentSoftApConfiguration);}}mWifiMetrics = wifiMetrics;mSarManager = sarManager;mWifiDiagnostics = wifiDiagnostics;
//在这里创建了状态机stateMachine,它有两个状态:mIdleState\mStartedStatemStateMachine = new SoftApStateMachine(looper);configureInternalConfiguration();mDefaultShutdownTimeoutMillis = mContext.getResources().getInteger(R.integer.config_wifiFrameworkSoftApShutDownTimeoutMilliseconds);mDefaultShutdownIdleInstanceInBridgedModeTimeoutMillis = mContext.getResources().getInteger(R.integer.config_wifiFrameworkSoftApShutDownIdleInstanceInBridgedModeTimeoutMillisecond);mIsDisableShutDownBridgedModeIdleInstanceTimerWhenCharging = mContext.getResources().getBoolean(R.bool.config_wifiFrameworkSoftApDisableBridgedModeShutdownIdleInstanceWhenCharging);mCmiMonitor = cmiMonitor;mActiveModeWarden = activeModeWarden;mCmiMonitor.registerListener(new ClientModeImplListener() {@Overridepublic void onL2Connected(@NonNull ConcreteClientModeManager clientModeManager) {SoftApManager.this.onL2Connected(clientModeManager);}});updateSafeChannelFrequencyList();mId = id;mRole = role;enableVerboseLogging(verboseLoggingEnabled);
//这里发送一条消息CMD_START让状态机stateMachine中的mIdleState来处理mStateMachine.sendMessage(SoftApStateMachine.CMD_START, requestorWs);
}
======================================================================================
case CMD_START:...int result = startSoftAp();transitionTo(mStartedState);break;

========================================================================
这里主要是调用startSoftAp()方法,然后让stateMachine状态机从mIdleState切换到mStartedState。
我们来看看startSoftAp()

/*** Start a soft AP instance as configured.** @return integer result code*/
private int startSoftAp() {Log.d(getTag(), "startSoftAp: band " + mCurrentSoftApConfiguration.getBand()+ " iface " + mApInterfaceName + " country " + mCountryCode);int result = setMacAddress();if (result != SUCCESS) {return result;}result = setCountryCode();if (result != SUCCESS) {return result;}// Make a copy of configuration for updating AP band and channel.SoftApConfiguration.Builder localConfigBuilder =new SoftApConfiguration.Builder(mCurrentSoftApConfiguration);result = ApConfigUtil.updateApChannelConfig(mWifiNative, mCoexManager, mContext.getResources(), mCountryCode,localConfigBuilder, mCurrentSoftApConfiguration, mCurrentSoftApCapability);if (result != SUCCESS) {Log.e(getTag(), "Failed to update AP band and channel");return result;}if (mCurrentSoftApConfiguration.isHiddenSsid()) {Log.d(getTag(), "SoftAP is a hidden network");}if (!ApConfigUtil.checkSupportAllConfiguration(mCurrentSoftApConfiguration, mCurrentSoftApCapability)) {Log.d(getTag(), "Unsupported Configuration detect! config = "+ mCurrentSoftApConfiguration);return ERROR_UNSUPPORTED_CONFIGURATION;
}if (!mWifiNative.startSoftAp(mApInterfaceName,localConfigBuilder.build(),mOriginalModeConfiguration.getTargetMode() ==  WifiManager.IFACE_IP_MODE_TETHERED,mSoftApHalCallback)) {Log.e(getTag(), "Soft AP start failed");return ERROR_GENERIC;}mWifiDiagnostics.startLogging(mApInterfaceName);mStartTimestamp = FORMATTER.format(new Date(System.currentTimeMillis()));Log.d(getTag(), "Soft AP is started ");return SUCCESS;
}

从配置中获取Band and channel,进行一些配置上的判断。主要是调用mWifiNative.startSoftAp()方法

public boolean startSoftAp(@NonNull String ifaceName, SoftApConfiguration config, boolean isMetered,SoftApHalCallback callback) {if (mHostapdHal.isApInfoCallbackSupported()) {if (!mHostapdHal.registerApCallback(ifaceName, callback)) {Log.e(TAG, "Failed to register ap hal event callback");return false;}} else {SoftApHalCallbackFromWificond softApHalCallbackFromWificond =new SoftApHalCallbackFromWificond(ifaceName, callback);if (!mWifiCondManager.registerApCallback(ifaceName,Runnable::run, softApHalCallbackFromWificond)) {Log.e(TAG, "Failed to register ap hal event callback from wificond");return false;}}if (!mHostapdHal.addAccessPoint(ifaceName, config, isMetered, callback::onFailure)) {Log.e(TAG, "Failed to add acccess point");mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();return false;}return true;
}
/packages/modules/Wifi/service/java/com/android/server/wifi/HostapdHal.java
public boolean addAccessPoint(@NonNull String ifaceName, @NonNull SoftApConfiguration config,boolean isMetered, @NonNull Runnable onFailureListener) {synchronized (mLock) {String methodStr = "addAccessPoint";if (mIHostapd == null) {return handleNullIHostapd(methodStr);}return mIHostapd.addAccessPoint(ifaceName, config, isMetered, onFailureListener);}
}

添加并启动一个AccessPoint,调用HAL层的方法;IHostapdHal HAL interface object


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部