Android11 热点开启流程

Posted 峥嵘life

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android11 热点开启流程相关的知识,希望对你有一定的参考价值。

android11 热点开启流程

文章目录


本文对热点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 热点开启流程的主要内容,如果未能解决你的问题,请参考以下文章

Android11 热点Band值为3

Android11 热点Band值为3

Android11 热点配置信息保存分析

Android11 热点配置信息保存分析

Android 11 WiFi热点打开与关闭接口

Android 11 WiFi热点打开与关闭接口