目录
一、wifi原生setting的入口在WifiTetherSettings.java
二、改热点Setting的时候可以直接只编译Settings.apk,并且替换,
三、wifi热点貌似官方支持黑名单 和 支持设置热点支持的最大client数
四、热点的双频合一
1、那设置频段为5G的时候,也就是2的时候,什么时候系统会被改成3(双频)的呢,
wifi模块的重要的类:
【安卓Framework学习】Wifi框架学习之核心类_leeeeesss的博客-CSDN博客_android wifi框架
热点开发的官方文档:
https://source.android.google.cn/docs/core/connect/wifi-softap
https://developer.android.google.cn/reference/android/net/ConnectivityManager
https://developer.android.google.cn/guide/topics/connectivity/wifi-permissions
重要:
Wi-Fi HAL | Android 开源项目 | Android Open Source Project
packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherSettings.java
开启热点和关闭热点的最后是使用ConnectivityManager的 startTethering 和 stopTethering
packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
void stopTether() {
mSwitchBar.setEnabled(false);
mConnectivityManager.stopTethering(TETHERING_WIFI);
}
void startTether() {
mSwitchBar.setEnabled(false);
mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */,
mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
}
frameworks/base/core/java/android/net/ConnectivityManager.java
public void startTethering(int type, boolean showProvisioningUi,
final OnStartTetheringCallback callback, Handler handler) {
mTetheringManager.startTethering(request, executor, tetheringCallback);
}
public void stopTethering(int type) {
mTetheringManager.stopTethering(type);
}
frameworks/base/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
调用到Tethering
public void startTethering(@NonNull final TetheringRequest request,
@NonNull final Executor executor, @NonNull final StartTetheringCallback callback) {
getConnector(c -> c.startTethering(request.getParcel(), callerPkg, listener));
}
public void stopTethering(@TetheringType final int type) {
getConnector(c -> c.stopTethering(type, callerPkg, new IIntResultListener.Stub() {
@Override
public void onResult(int resultCode) {
}
}));
}
frameworks/base/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
最后startTethering调用到最后是WifiManager.startTetheredHotspot,
stopTethering 调用到最后是WifiManager.stopSoftAp
void startTethering(final TetheringRequestParcel request, final IIntResultListener listener) {
mHandler.post(() -> {
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;
default:
Log.w(TAG, "Invalid tether type.");
result = TETHER_ERROR_UNKNOWN_TYPE;
}
}
private int setWifiTethering(final boolean enable) {
final WifiManager mgr = getWifiManager();
if ((enable && mgr.startTetheredHotspot(null /* use existing softap config */))
|| (!enable && mgr.stopSoftAp())) {
mWifiTetherRequested = enable;
return TETHER_ERROR_NO_ERROR;
}
}
可以查看Android.bp文件
./system_ext/priv-app/Settings/Settings.apk
通过 Wi-Fi 热点(软 AP)支持网络共享 | Android 开源项目 | Android Open Source Project
在android11热点Setting的WifiTetherSoftApManager.java, 有注册SoftapCallback, 可以重写一下onCapabilityChanged, 这样就可以获取到系统支持的最大的client数量,最后日志显示,
支持的client数量为16
12-27 11:33:33.251 2884 2884 I wqy-WifiTetherPrfeCtl: onStart
12-27 11:33:33.251 2884 2884 I wqy-WifiTetherPrfeCtl: onStart, registerSoftApCallback
12-27 11:33:33.251 2884 2884 I wqy-WifiTethSoApMgr: registerSoftApCallback
12-27 11:33:33.333 2884 2884 I wqy-WifiTethSoApMgr: onStateChanged
12-27 11:33:33.333 2884 2884 I wqy-WifiTethSoApMgr: onConnectedClientsChanged
12-27 11:33:33.333 2884 2884 I wqy-WifiTethSoApMgr: onCapabilityChanged, softApCapability = SupportedFeatures=15MaximumSupportedClientNumber=16
12-27 11:33:33.334 2884 2884 I wqy-WifiTethSoApMgr: onCapabilityChanged, maxClient = 16
packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherSoftApManager.java
public void registerSoftApCallback() {
Log.i("wqy-WifiTethSoApMgr", "registerSoftApCallback");
mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
}
private WifiManager.SoftApCallback mSoftApCallback = new WifiManager.SoftApCallback() {
@Override
public void onStateChanged(int state, int failureReason) {
Log.i("wqy-WifiTethSoApMgr", "onStateChanged");
mWifiTetherSoftApCallback.onStateChanged(state, failureReason);
}
@Override
public void onConnectedClientsChanged(List clients) {
Log.i("wqy-WifiTethSoApMgr", "onConnectedClientsChanged");
mWifiTetherSoftApCallback.onConnectedClientsChanged(clients);
}
@Override
public void onCapabilityChanged(@NonNull SoftApCapability softApCapability) {
Log.i("wqy-WifiTethSoApMgr", "onCapabilityChanged, softApCapability = " + softApCapability);
int maxClient = softApCapability.getMaxSupportedClients();
Log.i("wqy-WifiTethSoApMgr", "onCapabilityChanged, maxClient = " + maxClient);
// Do nothing: can be updated to add SoftApCapability details (e.g. meximum supported
// client number) to the UI.
}
};
设置最大client数的地方是:
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java
public void updateSoftApCapability(int subId) {
Log.i(TAG, "wqy updateSoftApCapability");
synchronized (mLock) {
CarrierConfigManager carrierConfigManager =
(CarrierConfigManager) mContext.getSystemService(
Context.CARRIER_CONFIG_SERVICE);
int carrierMaxClient = carrierConfig.getInt(
CarrierConfigManager.Wifi.KEY_HOTSPOT_MAX_CLIENT_COUNT);
int finalSupportedClientNumber = mContext.getResources().getInteger(
R.integer.config_wifiHardwareSoftapMaxClientCount);
Log.i(TAG, "wqy updateSoftApCapability, config_wifiHardwareSoftapMaxClientCount = " + finalSupportedClientNumber);
if (carrierMaxClient > 0) {
finalSupportedClientNumber = Math.min(finalSupportedClientNumber,
carrierMaxClient);
}
Log.i(TAG, "wqy updateSoftApCapability, carrierMaxClient = " + carrierMaxClient);
mTetheredSoftApCapability.setMaxSupportedClients(
finalSupportedClientNumber);
}
onCapabilityChanged(mTetheredSoftApCapability);
}
config_wifiHardwareSoftapMaxClientCount 找到的有两个地方:
frameworks/opt/net/wifi/service/res/values/config.xml (根据上面打印,应该这个,因为打印出来的是16)
16
vendor/qcom/proprietary/commonsys-intf/resource-overlay/common/Wifi/res/values/config.xml (这个暂时不知道有啥用)
32
工作中遇到别人提的一个bug,android里应用层设置5G Hz频段 2,设置成功后返回的频段是3,
一开始以为系统默认给开了6G,经过打日志,发现设置5G 频段的时候,它会默认检查config配置里有有没有2.4G,没有的话,会默认加上2.4G的频段, 所有设置5G 为2的时候,会默认 2 | 1 = 3,
达标双频合一,这样可以用户连接网络较弱时会自动切换到另一个Wi-Fi频段,这就极大程度保证信号的持续稳定连接,避免了手动切换信号的麻烦。
public static final int BAND_2GHZ = 1; public static final int BAND_5GHZ = 2; public static final int BAND_6GHZ = 4; public static final int BAND_ANY = 7;
「技巧」关于Wi-Fi双频合一,你真的知道么?|频段|5G_新浪新闻
一种可能是设置的时候被修改,一种可能是重启热点的时候被修改
发现同样的链接:Android11 热点Band值为3_峥嵘life的博客-CSDN博客
经过验证:
是在设置热点配置的时候被修改的
在原生Settings里做验证:
我这儿默认是2.4G,所以先获取一下配置,发现band为1, 然后设置2为5G,设置完成后,再读取Softapconfig, 发现是3,所以可以确定是设置的时候直接被底层做了修正
packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
void startTether() {
mSwitchBar.setEnabled(false);
//验证代码
final SoftApConfiguration config = mWifiManager.getSoftApConfiguration();
Log.i("wqy-tethring-barcontrol", "wqy get local config band = " + config.getBand());
mWifiManager.setSoftApConfiguration(
new SoftApConfiguration.Builder(config).setBand(SoftApConfiguration.BAND_5GHZ)
.build());
Log.i("wqy-tethring-barcontrol", "wqy after set 5G, local config band = " + mWifiManager.getSoftApConfiguration().getBand());
mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */,
mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
}
然后设置softapconfig 流程到了WifiServiceImpl.java
经过测试和追踪,在此处做的修改
mWifiApConfigStore.setApConfiguration(softApConfig)
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java
public boolean setSoftApConfiguration(
@NonNull SoftApConfiguration softApConfig, @NonNull String packageName) {
if (WifiApConfigStore.validateApWifiConfiguration(softApConfig, privileged)) {
mActiveModeWarden.updateSoftApConfiguration(softApConfig);
mWifiThreadRunner.post(() -> mWifiApConfigStore.setApConfiguration(softApConfig));
return true;
} else {
Log.e(TAG, "Invalid SoftAp Configuration");
return false;
}
}
可以看出,WifiApConfigStore.java, 在设置2为5G的时候,并且没有设置任何信道的时候,会将2.4G也加上
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiApConfigStore.java
public synchronized void setApConfiguration(SoftApConfiguration config) {
Log.i(TAG, "wqy setApConfiguration");
if (config == null) {
config = getDefaultApConfiguration();
} else {
config = sanitizePersistentApConfig(config);
}
}
private SoftApConfiguration sanitizePersistentApConfig(SoftApConfiguration config) {
SoftApConfiguration.Builder convertedConfigBuilder = null;
Log.i(TAG, "wqy sanitizePersistentApConfig, config band = " + config.getBand());
// some countries are unable to support 5GHz only operation, always allow for 2GHz when
// config doesn't force channel
if (config.getChannel() == 0 && (config.getBand() & SoftApConfiguration.BAND_2GHZ) == 0) {
Log.w(TAG, "wqy Supplied ap config band without 2.4G, add allowing for 2.4GHz");
if (convertedConfigBuilder == null) {
Log.i(TAG, "wqy sanitizePersistentApConfig 1, convertedConfigBuilder is null");
convertedConfigBuilder = new SoftApConfiguration.Builder(config);
}
Log.i(TAG, "wqy sanitizePersistentApConfig 2, config band = " + convertedConfigBuilder.build().getBand());
convertedConfigBuilder.setBand(config.getBand() | SoftApConfiguration.BAND_2GHZ);
Log.i(TAG, "wqy sanitizePersistentApConfig 3, config band = " + convertedConfigBuilder.build().getBand());
}
return convertedConfigBuilder == null ? config : convertedConfigBuilder.build();
}
最后回到Settings这边对频宽的处理
当settings界面显示的时候,设置为5G的时候,这边也会将2.4G带上
理由是:一些国家不支持5G,所以需要包括2.4G
packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
public void updateDisplay() {
final SoftApConfiguration config = mWifiManager.getSoftApConfiguration();
boolean is5G = is5GhzBandSupported();
Log.i(TAG, "wqy updateDisplay is5G = " + is5G);
if (config == null) {
mBandIndex = SoftApConfiguration.BAND_2GHZ;
Log.d(TAG, "Updating band index to BAND_2GHZ because no config");
} else if (is5GhzBandSupported()) {
mBandIndex = validateSelection(config.getBand());
Log.d(TAG, "Updating band index to " + mBandIndex);
}
}
private int validateSelection(int band) {
// unsupported states:
// 1: BAND_5GHZ only - include 2GHZ since some of countries doesn't support 5G hotspot
// 2: no 5 GHZ support means we can't have BAND_5GHZ - default to 2GHZ
if (SoftApConfiguration.BAND_5GHZ == band) {
if (!is5GhzBandSupported()) {
return SoftApConfiguration.BAND_2GHZ;
}
return SoftApConfiguration.BAND_5GHZ | SoftApConfiguration.BAND_2GHZ;
}
return band;
}
最终解决问题的思路:
就是将WifiApConfigStore.java里的设置整改处,将设置5G时携带2.4G的逻辑删除