Android11 热点设置永不关闭

72 篇文章 5 订阅
43 篇文章 6 订阅

Android11 热点设置永不关闭

一、前言

Android 热点默认是10 分钟后没有设备关联是会自动关闭,如果需要设置默认不关闭热点可以有几种方式。

二、framework设置热点永不超时关闭

查阅网上资料Android 的做法:

找到:
CMD_NO_ASSOCIATED_STATIONS_TIMEOUT //超时后触发消息,关闭热点 
修改:
case CMD_NO_ASSOCIATED_STATIONS_TIMEOUT: 
break;这样永远就走不到关闭热点的逻辑

在Android11 framwrok grep 遍历发现CMD_NO_ASSOCIATED_STATIONS_TIMEOUT 有的。

所以在 case CMD_NO_ASSOCIATED_STATIONS_TIMEOUT: 添加 break;跳过关闭逻辑同样是生效的

代码位置:

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

//找到如下代码进行修改即可:


case CMD_NO_ASSOCIATED_STATIONS_TIMEOUT:
    //添加break 即可完成跳过自动关闭热点逻辑。
    if (true) {
        Log.i(TAG, "timeout but no to close hotspot ap!");
        break;
    }
    if (mConnectedClients.size() != 0) {
        Log.wtf(TAG, "Timeout message received but has clients. Dropping.");
        break;
    }
    mSoftApNotifier.showSoftApShutDownTimeoutExpiredNotification();
    Log.i(TAG, "Timeout message received. Stopping soft AP.");
    updateApState(WifiManager.WIFI_AP_STATE_DISABLING,
    WifiManager.WIFI_AP_STATE_ENABLED, 0);
    transitionTo(mIdleState);
    break;

其实最好还是添加一个系统属性,可以动态设置是否自动关闭热点。


import android.os.SystemProperties;

//获取
boolean isSanitizeChannel = SystemProperties.getBoolean("persisit.hotspot_auto_close", false);

//设置
SystemProperties.set("key", bool + "");

三、基于 SoftApManager.java 研究超时逻辑

从热点开启ConnectivityManager.startTethering 到 SoftApManager.start(),
这个流程不在这里描述,有兴趣可以自己看看。
这里只看超时相关的代码。


public class SoftApManager implements ActiveModeManager {

    //内部类,不用在意里面真正消息处理,父类内部有Handler处理。
    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_FAILURE = 2;
        public static final int CMD_INTERFACE_STATUS_CHANGED = 3;
        public static final int CMD_ASSOCIATED_STATIONS_CHANGED = 4;
        public static final int CMD_NO_ASSOCIATED_STATIONS_TIMEOUT = 5; //超时消息
。。。

        //内部类的内部类!
        private class StartedState extends State {
            private WakeupMessage mSoftApTimeoutMessage;

            private void scheduleTimeoutMessage() {
            if (!mTimeoutEnabled || mConnectedClients.size() != 0) {
                    cancelTimeoutMessage();
                    return;
                }
                long timeout = mApConfig.getSoftApConfiguration().getShutdownTimeoutMillis();
                if (timeout == 0) {
                    timeout = mDefaultShutDownTimeoutMills;
                }
                //(2)发送延时消息,成功打开热点会触发
                //可以看到这里是当前时间+timeout时间,重点是研究timeout时间
                mSoftApTimeoutMessage.schedule(SystemClock.elapsedRealtime()+ timeout);
                Log.d(TAG, "Timeout message scheduled, delay = "+ timeout);
            }

            private void cancelTimeoutMessage() {
                //(3)关闭延时消息,关闭热点会触发
                mSoftApTimeoutMessage.cancel();
                Log.d(TAG, "Timeout message canceled");
            }

            @Override
            public void enter() {
                mIfaceIsUp = false;
                mIfaceIsDestroyed = false;
                onUpChanged(mWifiNative.isInterfaceUp(mApInterfaceName));

                Handler handler = mStateMachine.getHandler();
                mSoftApTimeoutMessage = new WakeupMessage(mContext, handler,
                SOFT_AP_SEND_MESSAGE_TIMEOUT_TAG,
                SoftApStateMachine.CMD_NO_ASSOCIATED_STATIONS_TIMEOUT); //(1)超时Message创建,调用启动热点会触发

                mSarManager.setSapWifiState(WifiManager.WIFI_AP_STATE_ENABLED);

                Log.d(TAG, "Resetting connected clients on start");
                mConnectedClients.clear();
                mEverReportMetricsForMaxClient = false;
                scheduleTimeoutMessage();
            }
            
            @Override
            public boolean processMessage(Message message) {
                switch (message.what) {
                case CMD_ASSOCIATED_STATIONS_CHANGED:
                    if (!(message.obj instanceof NativeWifiClient)) {
                    Log.e(TAG, "Invalid type returned for"
                    + " CMD_ASSOCIATED_STATIONS_CHANGED");
                    break;
                    case CMD_NO_ASSOCIATED_STATIONS_TIMEOUT:
                    if (!mTimeoutEnabled) {
                    Log.wtf(TAG, "Timeout message received while timeout is disabled."
                    + " Dropping.");
                break;

                case CMD_NO_ASSOCIATED_STATIONS_TIMEOUT: //真正处理超时关闭热点的代码
                    if (!mTimeoutEnabled) {
                        Log.wtf(TAG, "Timeout message received while timeout is disabled." + " Dropping.");
                        break;
                    }
。。。
                    mSoftApNotifier.showSoftApShutDownTimeoutExpiredNotification();
                    Log.i(TAG, "Timeout message received. Stopping soft AP.");
                    updateApState(WifiManager.WIFI_AP_STATE_DISABLING,
                    WifiManager.WIFI_AP_STATE_ENABLED, 0);
                    transitionTo(mIdleState);
                break;
            }
            
        }

}

从上面代码看重点是超时设置重点是看:


    long timeout = mApConfig.getSoftApConfiguration().getShutdownTimeoutMillis();
    if (timeout == 0) {
        timeout = mDefaultShutDownTimeoutMills;
    }
    //(2)发送延时消息,成功打开热点会触发
    //可以看到这里是当前时间+timeout时间,重点是研究timeout时间
    mSoftApTimeoutMessage.schedule(SystemClock.elapsedRealtime()+ timeout);

1、mApConfig.getSoftApConfiguration().getShutdownTimeoutMillis();
一看就是获取某个long数值,查看一下SoftApConfiguration.java 对象是否有相关方法,

查看确实有set 和 get方法,是hide、SystemApi方法,说明系统应用中是可以设置热点超时时间的。


    /**
    * Delay in milliseconds before shutting down soft AP when
    * there are no connected devices.
    */
    private final long mShutdownTimeoutMillis;

    @NonNull
    public Builder setShutdownTimeoutMillis(@IntRange(from = 0) long timeoutMillis) {
        if (timeoutMillis < 0) {
            throw new IllegalArgumentException("Invalid timeout value");
        }
        mShutdownTimeoutMillis = timeoutMillis;
        return this;
    }


    /**
    * Returns the shutdown timeout in milliseconds.
    * The Soft AP will shutdown when there are no devices associated to it for
    * the timeout duration. See {@link Builder#setShutdownTimeoutMillis(long)}.
    *
    * @hide
    */
    @SystemApi
    public long getShutdownTimeoutMillis() {
        return mShutdownTimeoutMillis;
    }

如果配置对象中没有设置数据的情况,那么就要看mDefaultShutDownTimeoutMills值了。

if (timeout == 0) {
    timeout = mDefaultShutDownTimeoutMills;
}

还是 SoftApManager.java的代码


    private long mDefaultShutDownTimeoutMills;

    
    //构造方法中:
    public SoftApManager (...) {
        ...
        mDefaultShutDownTimeoutMills = mContext.getResources().getInteger(R.integer.config_wifiFrameworkSoftApShutDownTimeoutMilliseconds);
    }



继续追config_wifiFrameworkSoftApShutDownTimeoutMilliseconds定义的文件:

frameworks\opt\net\wifi\service\res\values\config.xml


<!-- Integer delay in milliseconds before shutting down soft AP when there
are no connected devices. -->
<integer translatable="false" name="config_wifiFrameworkSoftApShutDownTimeoutMilliseconds">600000</integer>

所以 mDefaultShutDownTimeoutMills 的默认值是60000,600秒,即10分钟。

三、总结:

1、设置热点不关闭的方法:

(1)在SoftApManager.java 找到case CMD_NO_ASSOCIATED_STATIONS_TIMEOUT

直接break;或者retrun;跳过后续关闭热点操作。

(2)设置热点开启时间长度

在资源配置文件中设置超时时间为永久:2147483647 (Int的最大数值)


<integer translatable="false" name="config_wifiFrameworkSoftApShutDownTimeoutMilliseconds">2147483647</integer>

####(3)在代码开启热点的对象设置超时时间

    //设置无密码,10信道,2.4G的热点信号
    public void setHotspot2_4(View view) {
        private WifiManager mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
        //使用Build形式配置对象
        SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
        configBuilder.setSsid(mHotspotName);
        configBuilder.setChannel(10, SoftApConfiguration.BAND_2GHZ);
        //30 分钟:30*60*1000 = 1800000 或者永久 2147483647
        configBuilder.setShutdownTimeoutMillis(2147483647);
        mWifiManager.setSoftApConfiguration(configBuilder.build());
    }

有试过setShutdownTimeoutMillis 方法设置30 分钟的时间,发现过了30分钟没自动关闭!
具体原因,可以再源码中添加打印查看哈。

2、其他

     * 热点配置信息对象
     * Android11 使用 WifiManager.setWifiApConfiguration(config); 已经过期,使用已经不能生效!
     * 需要使用:WifiManager.setSoftApConfiguration(config);

具体实现可以看:
frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiServiceImpl.java

虽然最终都是调用:mWifiApConfigStore.setApConfiguration(softApConfig)
但是 setSoftApConfiguration 有更多的健全逻辑,比如:全局更新配置
mActiveModeWarden.updateSoftApConfiguration(softApConfig);
具体不做分析!

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

峥嵘life

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值