当前位置:   article > 正文

android 13 热点启动流程_starttethering

starttethering

近期在看一个热点启动的问题。发现网上基本上都算android 9 的wifi热点启动流程。自己去看android 13 的源码的时候发现与之前相比已经有一些小改动了。

在此总结一下wifie热点的启动流程。

我们直接从setting的热点开启按钮 点击事件开始看起。

按钮的初始化在

packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherSettings.java

  1. @Override
  2. public void onActivityCreated(Bundle savedInstanceState) {
  3. super.onActivityCreated(savedInstanceState);
  4. if (mUnavailable) {
  5. return;
  6. }
  7. // Assume we are in a SettingsActivity. This is only safe because we currently use
  8. // SettingsActivity as base for all preference fragments.
  9. final SettingsActivity activity = (SettingsActivity) getActivity();
  10. final SettingsMainSwitchBar switchBar = activity.getSwitchBar();
  11. switchBar.setTitle(getContext().getString(R.string.use_wifi_hotsopt_main_switch_title));
  12. mSwitchBarController = new WifiTetherSwitchBarController(activity, switchBar);
  13. getSettingsLifecycle().addObserver(mSwitchBarController);
  14. switchBar.show();
  15. }

可以看到按钮的控制类在 WifiTetherSwitchBarController  里面。

packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java

  1. @Override
  2. public void onStart() {
  3. mDataSaverBackend.addListener(this);
  4. mSwitchBar.addOnSwitchChangeListener(this);
  5. mContext.registerReceiver(mReceiver, WIFI_INTENT_FILTER,
  6. Context.RECEIVER_EXPORTED_UNAUDITED);
  7. }
  8. @Override
  9. public void onSwitchChanged(Switch switchView, boolean isChecked) {
  10. // Filter out unnecessary callbacks when switch is disabled.
  11. if (!switchView.isEnabled()) return;
  12. if (isChecked) {
  13. startTether();
  14. } else {
  15. stopTether();
  16. }
  17. }
  18. void startTether() {
  19. if (isWifiApActivated()) return;
  20. mSwitchBar.setEnabled(false);
  21. mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */,
  22. mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
  23. }
  24. final ConnectivityManager.OnStartTetheringCallback mOnStartTetheringCallback =
  25. new ConnectivityManager.OnStartTetheringCallback() {
  26. @Override
  27. public void onTetheringFailed() {
  28. super.onTetheringFailed();
  29. Log.e(TAG, "Failed to start Wi-Fi Tethering.");
  30. handleWifiApStateChanged(mWifiManager.getWifiApState());
  31. }
  32. };

这个控制类为按钮设置的点击事件,点击事件里面就开始了开启wifi热点的流程  startTether()

startTether()  执行了 mConnectivityManager.startTethering() 然后就进入到了  ConnectivityManager  类里面。

  1. public void startTethering(int type, boolean showProvisioningUi,
  2. final OnStartTetheringCallback callback, Handler handler) {
  3. Objects.requireNonNull(callback, "OnStartTetheringCallback cannot be null.");
  4. final Executor executor = new Executor() {
  5. @Override
  6. public void execute(Runnable command) {
  7. if (handler == null) {
  8. command.run();
  9. } else {
  10. handler.post(command);
  11. }
  12. }
  13. };
  14. final StartTetheringCallback tetheringCallback = new StartTetheringCallback() {
  15. @Override
  16. public void onTetheringStarted() {
  17. callback.onTetheringStarted();
  18. }
  19. @Override
  20. public void onTetheringFailed(final int error) {
  21. callback.onTetheringFailed();
  22. }
  23. };
  24. final TetheringRequest request = new TetheringRequest.Builder(type)
  25. .setShouldShowEntitlementUi(showProvisioningUi).build();
  26. getTetheringManager().startTethering(request, executor, tetheringCallback);
  27. }

getTetheringManager().startTethering() 又进入到了packages/modules/Connectivity/Tethering/common/TetheringLib/src/android/net/TetheringManager.java中。

  1. public void startTethering(@NonNull final TetheringRequest request,
  2. @NonNull final Executor executor, @NonNull final StartTetheringCallback callback) {
  3. final String callerPkg = mContext.getOpPackageName();
  4. Log.i(TAG, "startTethering caller:" + callerPkg);
  5. final IIntResultListener listener = new IIntResultListener.Stub() {
  6. @Override
  7. public void onResult(final int resultCode) {
  8. executor.execute(() -> {
  9. if (resultCode == TETHER_ERROR_NO_ERROR) {
  10. callback.onTetheringStarted();
  11. } else {
  12. callback.onTetheringFailed(resultCode);
  13. }
  14. });
  15. }
  16. };
  17. getConnector(c -> c.startTethering(request.getParcel(), callerPkg,
  18. getAttributionTag(), listener));
  19. }
  20. private void getConnector(ConnectorConsumer consumer) {
  21. final ITetheringConnector connector;
  22. synchronized (mConnectorWaitQueue) {
  23. connector = mConnector;
  24. if (connector == null) {
  25. mConnectorWaitQueue.add(consumer);
  26. return;
  27. }
  28. }
  29. try {
  30. consumer.onConnectorAvailable(connector);
  31. } catch (RemoteException e) {
  32. throw new IllegalStateException(e);
  33. }
  34. }
  35. private interface ConnectorConsumer {
  36. void onConnectorAvailable(ITetheringConnector connector) throws RemoteException;
  37. }

由于ConnectorConsumer 是一个接口,所以consumer.onConnectorAvailable(connector)就相当于

调用了   connector.startTethering()    。ITetheringConnector connector  是一个aidl 接口,跨进程进去到了

packages/modules/Connectivity/Tethering/src/com/android/networkstack/tethering/TetheringService.java

  1. @Override
  2. public void startTethering(TetheringRequestParcel request, String callerPkg,
  3. String callingAttributionTag, IIntResultListener listener) {
  4. if (checkAndNotifyCommonError(callerPkg,
  5. callingAttributionTag,
  6. request.exemptFromEntitlementCheck /* onlyAllowPrivileged */,
  7. listener)) {
  8. return;
  9. }
  10. mTethering.startTethering(request, listener);
  11. }

这个里又调用到了mTethering.startTethering(request, listener);

frameworks/base/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java

里面去了

  1. void startTethering(final TetheringRequestParcel request, final IIntResultListener listener) {
  2. mHandler.post(() -> {
  3. final TetheringRequestParcel unfinishedRequest = mActiveTetheringRequests.get(
  4. request.tetheringType);
  5. // If tethering is already enabled with a different request,
  6. // disable before re-enabling.
  7. if (unfinishedRequest != null
  8. && !TetheringUtils.isTetheringRequestEquals(unfinishedRequest, request)) {
  9. enableTetheringInternal(request.tetheringType, false /* disabled */, null);
  10. mEntitlementMgr.stopProvisioningIfNeeded(request.tetheringType);
  11. }
  12. mActiveTetheringRequests.put(request.tetheringType, request);
  13. if (request.exemptFromEntitlementCheck) {
  14. mEntitlementMgr.setExemptedDownstreamType(request.tetheringType);
  15. } else {
  16. mEntitlementMgr.startProvisioningIfNeeded(request.tetheringType,
  17. request.showProvisioningUi);
  18. }
  19. enableTetheringInternal(request.tetheringType, true /* enabled */, listener);
  20. });
  21. }

这里执行了enableTetheringInternal(request.tetheringType, true /* enabled */, listener);

  1. private void enableTetheringInternal(int type, boolean enable,
  2. final IIntResultListener listener) {
  3. int result = TETHER_ERROR_NO_ERROR;
  4. switch (type) {
  5. case TETHERING_WIFI:
  6. result = setWifiTethering(enable);
  7. break;
  8. case TETHERING_USB:
  9. result = setUsbTethering(enable);
  10. break;
  11. case TETHERING_BLUETOOTH:
  12. setBluetoothTethering(enable, listener);
  13. break;
  14. case TETHERING_NCM:
  15. result = setNcmTethering(enable);
  16. break;
  17. case TETHERING_ETHERNET:
  18. result = setEthernetTethering(enable);
  19. break;
  20. default:
  21. Log.w(TAG, "Invalid tether type.");
  22. result = TETHER_ERROR_UNKNOWN_TYPE;
  23. }
  24. // The result of Bluetooth tethering will be sent by #setBluetoothTethering.
  25. if (type != TETHERING_BLUETOOTH) {
  26. sendTetherResult(listener, result, type);
  27. }
  28. }
  29. private int setWifiTethering(final boolean enable) {
  30. final long ident = Binder.clearCallingIdentity();
  31. try {
  32. synchronized (mPublicSync) {
  33. final WifiManager mgr = getWifiManager();
  34. if (mgr == null) {
  35. mLog.e("setWifiTethering: failed to get WifiManager!");
  36. return TETHER_ERROR_SERVICE_UNAVAIL;
  37. }
  38. if ((enable && mgr.startTetheredHotspot(null /* use existing softap config */))
  39. || (!enable && mgr.stopSoftAp())) {
  40. mWifiTetherRequested = enable;
  41. return TETHER_ERROR_NO_ERROR;
  42. }
  43. }
  44. } finally {
  45. Binder.restoreCallingIdentity(ident);
  46. }
  47. return TETHER_ERROR_INTERNAL_ERROR;
  48. }

开启热点当然是执行 result = setWifiTethering(enable);

setWifiTethering()里面又执行了mgr.startTetheredHotspot(null /* use existing softap config */))

这个里面传了一个空的参数,这个参数是有意义的,代表在开启热点时,会根据配置文件的内容决定开启热点的参数。这个配置文件在手机的  data/misc/apexdata/com.android.wifi/     下。里面有两个配置文件,一个是wifi的,一个是热点的。

WifiConfigStore.xml  WifiConfigStoreSoftAp.xml

执行这个方法后又进入到了packages/modules/Wifi/framework/java/android/net/wifi/WifiManager.java类。

  1. public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig) {
  2. try {
  3. return mService.startTetheredHotspot(softApConfig, mContext.getOpPackageName());
  4. } catch (RemoteException e) {
  5. throw e.rethrowFromSystemServer();
  6. }
  7. }

mService.startTetheredHotspot()又是一个aidl 接口。进入到了

packages/modules/Wifi/service/java/com/android/server/wifi/WifiServiceImpl.java 里面

  1. public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig,
  2. @NonNull String packageName) {
  3. // NETWORK_STACK is a signature only permission.
  4. enforceNetworkStackPermission();
  5. int callingUid = Binder.getCallingUid();
  6. mWifiPermissionsUtil.checkPackage(callingUid, packageName);
  7. // If user restriction is set, cannot start softap
  8. if (mWifiTetheringDisallowed) {
  9. mLog.err("startTetheredHotspot with user restriction: not permitted").flush();
  10. return false;
  11. }
  12. mLog.info("startTetheredHotspot uid=%").c(callingUid).flush();
  13. // TODO: b/233363886, handle timeout in general way.
  14. if (!checkSetEnablingIfAllowed()) {
  15. return false;
  16. }
  17. WorkSource requestorWs = new WorkSource(callingUid, packageName);
  18. if (!mWifiThreadRunner.call(
  19. () -> mActiveModeWarden.canRequestMoreSoftApManagers(requestorWs), false)) {
  20. // Take down LOHS if it is up.
  21. mLohsSoftApTracker.stopAll();
  22. }
  23. if (!startSoftApInternal(new SoftApModeConfiguration(
  24. WifiManager.IFACE_IP_MODE_TETHERED, softApConfig,
  25. mTetheredSoftApTracker.getSoftApCapability()), requestorWs)) {
  26. mTetheredSoftApTracker.setFailedWhileEnabling();
  27. return false;
  28. }
  29. mLastCallerInfoManager.put(WifiManager.API_TETHERED_HOTSPOT, Process.myTid(),
  30. callingUid, Binder.getCallingPid(), packageName, true);
  31. return true;
  32. }
执行了 startSoftApInternal()
  1. private boolean startSoftApInternal(SoftApModeConfiguration apConfig, WorkSource requestorWs) {
  2. int uid = Binder.getCallingUid();
  3. boolean privileged = isSettingsOrSuw(Binder.getCallingPid(), uid);
  4. mLog.trace("startSoftApInternal uid=% mode=%")
  5. .c(uid).c(apConfig.getTargetMode()).flush();
  6. // null wifiConfig is a meaningful input for CMD_SET_AP; it means to use the persistent
  7. // AP config.
  8. SoftApConfiguration softApConfig = apConfig.getSoftApConfiguration();
  9. if (softApConfig != null
  10. && (!WifiApConfigStore.validateApWifiConfiguration(
  11. softApConfig, privileged, mContext))) {
  12. Log.e(TAG, "Invalid SoftApConfiguration");
  13. return false;
  14. }
  15. mActiveModeWarden.startSoftAp(apConfig, requestorWs);
  16. return true;
  17. }
然后执行   mActiveModeWarden.startSoftAp(apConfig, requestorWs);  进入

packages/modules/Wifi/service/java/com/android/server/wifi/ActiveModeWarden.java

  1. public void startSoftAp(SoftApModeConfiguration softApConfig, WorkSource requestorWs) {
  2. stopStaIfRequired(softApConfig, requestorWs);
  3. mWifiController.sendMessage(WifiController.CMD_SET_AP, 1, 0,
  4. Pair.create(softApConfig, requestorWs));
  5. }

这里发送了一条消息进入到了ActiveModeWarden 的 内部类 EnabledState 里面。

  1. case CMD_SET_AP:
  2. // note: CMD_SET_AP is handled/dropped in ECM mode - will not start here
  3. if (msg.arg1 == 1) {
  4. Pair<SoftApModeConfiguration, WorkSource> softApConfigAndWs =
  5. (Pair) msg.obj;
  6. startSoftApModeManager(
  7. softApConfigAndWs.first, softApConfigAndWs.second);
  8. } else {
  9. stopSoftApModeManagers(msg.arg2);
  10. }
  11. break;

这里执行了

startSoftApModeManager(
        softApConfigAndWs.first, softApConfigAndWs.second);
  1. private void startSoftApModeManager(
  2. @NonNull SoftApModeConfiguration softApConfig, @NonNull WorkSource requestorWs) {
  3. Log.d(TAG, "Starting SoftApModeManager config = " + softApConfig.getSoftApConfiguration());
  4. Preconditions.checkState(softApConfig.getTargetMode() == IFACE_IP_MODE_LOCAL_ONLY
  5. || softApConfig.getTargetMode() == IFACE_IP_MODE_TETHERED);
  6. WifiServiceImpl.SoftApCallbackInternal callback =
  7. softApConfig.getTargetMode() == IFACE_IP_MODE_LOCAL_ONLY
  8. ? mLohsCallback : mSoftApCallback;
  9. SoftApManager manager = mWifiInjector.makeSoftApManager(
  10. new SoftApListener(), callback, softApConfig, requestorWs,
  11. getRoleForSoftApIpMode(softApConfig.getTargetMode()), mVerboseLoggingEnabled);
  12. mSoftApManagers.add(manager);
  13. }

这里的callback  传入的 mLohsCallback   。

后面又执行了mWifiInjector.makeSoftApManager()方法。进入到

packages/modules/Wifi/service/java/com/android/server/wifi/WifiInjector.java

  1. public SoftApManager makeSoftApManager(
  2. @NonNull ActiveModeManager.Listener<SoftApManager> listener,
  3. @NonNull WifiServiceImpl.SoftApCallbackInternal callback,
  4. @NonNull SoftApModeConfiguration config,
  5. @NonNull WorkSource requestorWs,
  6. @NonNull ActiveModeManager.SoftApRole role,
  7. boolean verboseLoggingEnabled) {
  8. return new SoftApManager(mContext, mWifiHandlerThread.getLooper(),
  9. mFrameworkFacade, mWifiNative, mCoexManager, makeBatteryManager(),
  10. mCountryCode.getCountryCode(), listener, callback, mWifiApConfigStore,
  11. config, mWifiMetrics, mSarManager, mWifiDiagnostics,
  12. new SoftApNotifier(mContext, mFrameworkFacade, mWifiNotificationManager),
  13. mCmiMonitor, mActiveModeWarden, mClock.getElapsedSinceBootMillis(),
  14. requestorWs, role, verboseLoggingEnabled);
  15. }

这里直接new了一个SoftApManger。进入到了构造方法里面。

  1. // null is a valid input and means we use the user-configured tethering settings.
  2. if (mCurrentSoftApConfiguration == null) {
  3. mCurrentSoftApConfiguration = mWifiApConfigStore.getApConfiguration();
  4. // may still be null if we fail to load the default config
  5. }
  6. mStateMachine = new SoftApStateMachine(looper); // 在这里真正的创建了热点的状态机
  7. mStateMachine.sendMessage(SoftApStateMachine.CMD_START, requestorWs);

由于之前的config  一直是空的,所以  mWifiApConfigStore.getApConfiguration()    这里面就从配置文件里,获取了热点的配置信息。

最后send一个message。由  SoftApManager  的内部类  IdleState processMessage() 捕获处理.

int result = startSoftAp();

里面有一段,调用了startSoftAp()方法。

  1. private int startSoftAp() {
  2. if (SdkLevel.isAtLeastS()) {
  3. Log.d(getTag(), "startSoftAp: channels " + mCurrentSoftApConfiguration.getChannels()
  4. + " iface " + mApInterfaceName + " country " + mCountryCode);
  5. } else {
  6. Log.d(getTag(), "startSoftAp: band " + mCurrentSoftApConfiguration.getBand());
  7. }
  8. int result = setMacAddress();
  9. if (result != SUCCESS) {
  10. return result;
  11. }
  12. result = setCountryCode();
  13. if (result != SUCCESS) {
  14. return result;
  15. }
  16. // Make a copy of configuration for updating AP band and channel.
  17. SoftApConfiguration.Builder localConfigBuilder =
  18. new SoftApConfiguration.Builder(mCurrentSoftApConfiguration);
  19. result = ApConfigUtil.updateApChannelConfig(
  20. mWifiNative, mCoexManager, mContext.getResources(), mCountryCode,
  21. localConfigBuilder, mCurrentSoftApConfiguration, mCurrentSoftApCapability);
  22. if (result != SUCCESS) {
  23. Log.e(getTag(), "Failed to update AP band and channel");
  24. return result;
  25. }
  26. if (mCurrentSoftApConfiguration.isHiddenSsid()) {
  27. Log.d(getTag(), "SoftAP is a hidden network");
  28. }
  29. if (!ApConfigUtil.checkSupportAllConfiguration(
  30. mCurrentSoftApConfiguration, mCurrentSoftApCapability)) {
  31. Log.d(getTag(), "Unsupported Configuration detect! config = "
  32. + mCurrentSoftApConfiguration);
  33. return ERROR_UNSUPPORTED_CONFIGURATION;
  34. }
  35. if (!mWifiNative.startSoftAp(mApInterfaceName,
  36. localConfigBuilder.build(),
  37. mOriginalModeConfiguration.getTargetMode() == WifiManager.IFACE_IP_MODE_TETHERED,
  38. mSoftApHalCallback)) {
  39. Log.e(getTag(), "Soft AP start failed");
  40. return ERROR_GENERIC;
  41. }
  42. mWifiDiagnostics.startLogging(mApInterfaceName);
  43. mStartTimestamp = FORMATTER.format(new Date(System.currentTimeMillis()));
  44. Log.d(getTag(), "Soft AP is started ");
  45. return SUCCESS;
  46. }

主要是调用mWifiNative.startSoftAp()方法

  1. public boolean startSoftAp(
  2. @NonNull String ifaceName, SoftApConfiguration config, boolean isMetered,
  3. SoftApHalCallback callback) {
  4. if (mHostapdHal.isApInfoCallbackSupported()) {
  5. if (!mHostapdHal.registerApCallback(ifaceName, callback)) {
  6. Log.e(TAG, "Failed to register ap hal event callback");
  7. return false;
  8. }
  9. } else {
  10. SoftApHalCallbackFromWificond softApHalCallbackFromWificond =
  11. new SoftApHalCallbackFromWificond(ifaceName, callback);
  12. if (!mWifiCondManager.registerApCallback(ifaceName,
  13. Runnable::run, softApHalCallbackFromWificond)) {
  14. Log.e(TAG, "Failed to register ap hal event callback from wificond");
  15. return false;
  16. }
  17. }
  18. if (!addAccessPoint(ifaceName, config, isMetered, callback)) {
  19. Log.e(TAG, "Failed to add acccess point");
  20. mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();
  21. return false;
  22. }
  23. return true;
  24. }

后面会进入到

frameworks\opt\net\wifi\service\java\com\android\server\wifi\HostapdHal.java

  1. @Override
  2. public boolean addAccessPoint(@NonNull String ifaceName, @NonNull SoftApConfiguration config,
  3. boolean isMetered, Runnable onFailureListener) {
  4. synchronized (mLock) {
  5. final String methodStr = "addAccessPoint";
  6. Log.d(TAG, methodStr + ": " + ifaceName);
  7. if (!checkHostapdAndLogFailure(methodStr)) {
  8. return false;
  9. }
  10. try {
  11. IfaceParams ifaceParams = prepareIfaceParams(ifaceName, config);
  12. NetworkParams nwParams = prepareNetworkParams(isMetered, config);
  13. if (ifaceParams == null || nwParams == null) {
  14. Log.e(TAG, "addAccessPoint parameters could not be prepared.");
  15. return false;
  16. }
  17. mIHostapd.addAccessPoint(ifaceParams, nwParams);
  18. mSoftApFailureListeners.put(ifaceName, onFailureListener);
  19. return true;
  20. } catch (IllegalArgumentException e) {
  21. Log.e(TAG, "Unrecognized apBand: " + config.getBand());
  22. } catch (RemoteException e) {
  23. handleRemoteException(e, methodStr);
  24. } catch (ServiceSpecificException e) {
  25. handleServiceSpecificException(e, methodStr);
  26. }
  27. return false;
  28. }
  29. }

然后会调用到Hal层的方法。

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/301693
推荐阅读
相关标签
  

闽ICP备14008679号