Android13 命令启用WLAN详细日志分析
Android13 命令启用WLAN详细日志分析
文章目录
- Android13 命令启用WLAN详细日志分析
- 一、前言
- 二、开启“启动WLAN详细日志记录功能”分析过程
- 1、settings和prop属性分析
- 2、查看wifi服务开始的地方 WifiServiceImpl.java
- 3、WifiSettingsConfigStore.get分析
- 4、 WifiConfigStore.xml 保存属性的地方
- 5、WifiManager 打开“启动WLAN详细日志记录功能”
- 三、其他
- 1、“启动WLAN详细日志记录功能”小结
- 2、开启“启动WLAN详细日志记录功能” 状态cmd命令
- 3、Android 使用adb操作WiFi连接扫描等相关指令
- 4、Android 拉起开发者设置界面命令和代码实现
- 5、开启“启动WLAN详细日志记录功能” 状态的日志区别
- (1)WifiService日志:
- (2) WifiNetworkSelector 日志
一、前言
Android 如果遇到wifi问题,比如无法联网,连接wifi失败,热点异常等问题;
如果查看wifi相关日志未发现具体异常,可以通过更加详细的wifi日志,
查看wifi具体过程,可以使用“启动WLAN详细日志记录功能”,看看是否能发现有用的线程。
Android开发者模式“启动WLAN详细日志记录功能”,这个没啥好说的,
原生Settings,进入开发者界面,打开开关就行了。
如下图所示(英文):
中文:
本文主要介绍一下,如果没有原生Settings,或者没有界面的情况,如何打开“启动WLAN详细日志记录功能”功能呢?
网上搜索到的说法:
# 查询WLAN详细日志开关值
adb shell settings get global wifi_verbose_logging_enabled# 启用WLAN详细日志
adb shell settings put global wifi_verbose_logging_enabled 1# 禁用WLAN详细日志
adb shell settings put global wifi_verbose_logging_enabled 0
看起来是挺ok 的,但是试了下不行,可能Android9之前的系统可以。
并且在原生设置的开发者界面打开“启动WLAN详细日志记录功能”,上面的Settings属性查询是没有变化的。
所以本文分析一下是哪个属性或者命令可以控制“启动WLAN详细日志记录功能”。
目前网上没看到任何一个文章对这个开关属性进行分析。
整体还是比较有用的,收藏一下是没错的。
二、开启“启动WLAN详细日志记录功能”分析过程
如果不想看分析过程可以直接看后面总结!
因为“启动WLAN详细日志记录功能” 开启后,重启是记忆的,那么一般是settings属性或者prop属性记忆。
1、settings和prop属性分析
通过对比“启动WLAN详细日志记录功能” 开、关状态的prop属性,和settings发现居然没有差别。
获取开、关不同状态的属性做对比:
获取prop属性,获取系统所有prop属性:
getprop获取settings的 各个属性:
settings list global
settings list system
settings list secury查看settings属性的源文件
cat /data/system/users/0/settings_global.xml
说明:settings global wifi_verbose_logging_enabled 属性并不是“启动WLAN详细日志记录功能”相关的。
并且设置命令:adb shell settings put global wifi_verbose_logging_enabled 1
发现“启动WLAN详细日志记录功能”开关还是关闭的,重启s设备验证查看也是关闭的。
通过logcat查看wifi相关日志并没有增加日志。
难道不是通过属性记忆的,直接保存在某个文件?奇怪!
2、查看wifi服务开始的地方 WifiServiceImpl.java
packages/modules/Wifi/service/java/com/android/server/wifi/WifiServiceImpl.java
//(1)准备启动wifi前的基本判断public void checkAndStartWifi() {mWifiThreadRunner.post(() -> {//(2)这里是最关键的“启动WLAN详细日志记录功能”读取属性,并设置全局属性的代码// config store is read, check if verbose logging is enabled.enableVerboseLoggingInternal(
mWifiInjector.getSettingsConfigStore().get(WIFI_VERBOSE_LOGGING_ENABLED)? 1 : 0);// Check if wi-fi needs to be enabledboolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();Log.i(TAG,"WifiService starting up with Wi-Fi " + (wifiEnabled ? "enabled" : "disabled"));
...}//(3)类型各处打印都是通过这个判断后决定是否打印的, mVerboseLoggingLevel 属性是关键private boolean isVerboseLoggingEnabled() {return mFrameworkFacade.isVerboseLoggingAlwaysOn(getVerboseAlwaysOnLevel(), mBuildProperties)|| WifiManager.VERBOSE_LOGGING_LEVEL_DISABLED != mVerboseLoggingLevel;}//(4)获取res属性的值(默认0)!这个是固定的需要编译apk,所以这个不是开关的关键。private int getVerboseAlwaysOnLevel() {if (mVerboseAlwaysOnLevel == -1) {mVerboseAlwaysOnLevel = mContext.getResources().getInteger(R.integer.config_wifiVerboseLoggingAlwaysOnLevel);}return mVerboseAlwaysOnLevel;}//(5)设置wifi调试等级的暴露方法,0关,1开@Overridepublic void enableVerboseLogging(int verbose) {enforceAccessPermission();enforceNetworkSettingsPermission();mLog.info("enableVerboseLogging uid=% verbose=%").c(Binder.getCallingUid()).c(verbose).flush();boolean enabled = verbose > 0;mWifiInjector.getSettingsConfigStore().put(WIFI_VERBOSE_LOGGING_ENABLED, enabled);onVerboseLoggingStatusChanged(enabled);enableVerboseLoggingInternal(verbose); //这里是设置wifi相关的类都打开debug日志。}//获取wifi调试等级的暴露方法,0关,1开@Overridepublic int getVerboseLoggingLevel() {if (isVerboseLoggingEnabled()) {mLog.info("getVerboseLoggingLevel uid=%").c(Binder.getCallingUid()).flush();}return mVerboseLoggingLevel;}
从上面第二点(2)查看,getSettingsConfigStore().get(WIFI_VERBOSE_LOGGING_ENABLED)
看起来就是从Settings里面获取 WIFI_VERBOSE_LOGGING_ENABLED 属性。
看下Settings 的源码:
frameworks/base/core/java/android/provider/Settings.java/*** Setting to enable verbose logging in Wi-Fi; disabled by default, and setting to 1* will enable it. In the future, additional values may be supported.* @hide* @deprecated Use {@link WifiManager#setVerboseLoggingEnabled(boolean)} for setting the* value and {@link WifiManager#isVerboseLoggingEnabled()} for query.*/@Deprecated@Readablepublic static final String WIFI_VERBOSE_LOGGING_ENABLED ="wifi_verbose_logging_enabled";...
MOVED_TO_GLOBAL.add(Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED);
这个不就是 settings global wifi_verbose_logging_enabled 属性吗,为啥实际没有作用!!!
具体原因还要分析:WifiServiceImpl 的 getSettingsConfigStore().get(WIFI_VERBOSE_LOGGING_ENABLED) 的具体实现。
3、WifiSettingsConfigStore.get分析
这里的 getSettingsConfigStore() 获取的是 WifiSettingsConfigStore 对象。
WifiSettingsConfigStore.java 源码查看:
packages/modules/Wifi/service/java/com/android/server/wifi/WifiSettingsConfigStore.javapublic class WifiSettingsConfigStore {private static final String TAG = "WifiSettingsConfigStore";// List of all allowed keys.private static final ArrayList<Key> sKeys = new ArrayList<>();private final Map<String, Object> mSettings = new HashMap<>();/*** Setting to enable verbose logging in Wi-Fi; disabled by default, and setting to 1* will enable it. In the future, additional values may be supported.*/public static final Key<Boolean> WIFI_VERBOSE_LOGGING_ENABLED =new Key<>("wifi_verbose_logging_enabled", false);/*** The Wi-Fi peer-to-peer device name*/public static final Key<String> WIFI_P2P_DEVICE_NAME =new Key<>("wifi_p2p_device_name", null);...public <T> void put(@NonNull Key<T> key, @Nullable T value) {synchronized (mLock) {mSettings.put(key.key, value);}triggerSaveToStoreAndInvokeListeners(key);}public @Nullable <T> T get(@NonNull Key<T> key) {synchronized (mLock) {return (T) mSettings.getOrDefault(key.key, key.defaultValue);}}private <T> void triggerSaveToStoreAndInvokeListeners(@NonNull Key<T> key) {mHandler.post(() -> {mHasNewDataToSerialize = true;mWifiConfigManager.saveToStore(true); //wifi配置保存的关键!invokeListeners(key);});}
}
从上面源码可以看出:
1、getSettingsConfigStore().get(WIFI_VERBOSE_LOGGING_ENABLED)并不是直接从Settings里面获取的属性值;
2、get(WIFI_VERBOSE_LOGGING_ENABLED)是从键值对中获取到属性值;
3、键值对的属性值,就要看put调用了,哪些过程初始化会调用put?
4、还有种情况就是没有默认put,直接获取到就是false的。
分析了WifiSettingsConfigStore.java 好像看不出 WIFI_VERBOSE_LOGGING_ENABLED 属性的获取是从哪里来的。
再分析了:WifiService、WifiServiceImpl、WifiInjector、WifiMetrics 初始化和设置Settings属性过程;
还是没看到 WIFI_VERBOSE_LOGGING_ENABLED 初始化的地方。
所以大概可以得出结论,WIFI_VERBOSE_LOGGING_ENABLED 属性默认是没有设置的,默认为false。
但是如果设置的了一次true,他是保存到哪里的呢?
重点就是上面的 WifiSettingsConfigStore 的代码了:
mWifiConfigManager.saveToStore(true); //wifi配置保存的关键!
这里看不出文件保存的路径,但是一直追溯是可以发现保存文件的,就是Wifi的配置文件;
Wifi的连接、断开、Wifi配置信息都会调用这个进行数据保存到本地配置文件 WifiConfigStore.xml 。
所以基本可以确定: “启动WLAN详细日志记录功能” 的开关状态就是保存在 WifiConfigStore.xml 文件中。
4、 WifiConfigStore.xml 保存属性的地方
在运行环境中wifi保存配置属性查看:
cat /data/misc/apexdata/com.android.wifi/WifiConfigStore.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<WifiConfigStoreData>
<NetworkList> //多个保存的Wifi
<Network> //其中一个
<WifiConfiguration>
<string name="ConfigKey">"NO-BUG"WPA_PSK</string> //Wifi名称
<string name="SSID">"NO-BUG"</string> //Wifi名称
<string name="PreSharedKey">"qwertyuiop"</string> //Wifi密码...
//“启动WLAN详细日志记录功能”状态,默认是没有的!
<boolean name="wifi_verbose_logging_enabled" value="true" />
<string name="wifi_last_country_code">US</string>
<int name="supplicant_hal_aidl_service_version" value="2" />
</WifiConfigStoreData>
所以可以得出结论 “启动WLAN详细日志记录功能” 的开关状态就是保存在 WifiConfigStore.xml 文件中。
另外还可以在 WifiConfigStore.xml 文件看到Wifi的密码,这个Wifi密码在系统API中是没有暴露的,只能校验。
所以如果需要获取已保存的Wifi的密码也是可以通过获取 WifiConfigStore.xml 文件内容得到。
分析的过程完了?
差不多吧,但是还是差点!
因为这里还没说怎么设置默认开启!
5、WifiManager 打开“启动WLAN详细日志记录功能”
上面在 WifiServiceImpl.java 源码中看到有暴露的方法 enableVerboseLogging,所以猜测 WifiManager 是有api的。
源码查看:
packages/modules/Wifi/framework/java/android/net/wifi/WifiManager.java
/*** Verbose logging mode: DISABLED.* @hide*/@SystemApipublic static final int VERBOSE_LOGGING_LEVEL_DISABLED = 0;/*** Verbose logging mode: ENABLED.* @hide*/@SystemApipublic static final int VERBOSE_LOGGING_LEVEL_ENABLED = 1;@SystemApi@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)public void setVerboseLoggingLevel(@VerboseLoggingLevel int verbose) {enableVerboseLogging(verbose);}@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)public void enableVerboseLogging(@VerboseLoggingLevel int verbose) {try {mService.enableVerboseLogging(verbose);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}@SystemApipublic boolean isVerboseLoggingEnabled() {return getVerboseLoggingLevel() > 0;}
上面源码看到有查看和设置 “启动WLAN详细日志记录功能” 的暴露api方法。
所以系统应用调用 WifiManager.enableVerboseLogging(1) 就可以设置打开“启动WLAN详细日志记录功能” 。
因为这个设置后是保存在本地文件的,所以重启是会生效的。
wifi服务开始的地方 WifiServiceImpl.java 会判断是否 “启动WLAN详细日志记录功能” ,进行打印一些详细数据。
上面一顿分析发现, “启动WLAN详细日志记录功能” 状态 是保存在 WifiConfigStore.xml 文件。
但是没有好像没有命令可以直接修改 WifiConfigStore.xml 的内容,难道要pull 出来,修改后,push进去?
其实是有方法的,cmd wifi命令就可以,往后看看。
三、其他
1、“启动WLAN详细日志记录功能”小结
(1)adb shell settings put global wifi_verbose_logging_enabled 1 //并不能启用WLAN详细日志
(2)“启动WLAN详细日志记录功能” 状态属性并未保存在settings文件中
(3)“启动WLAN详细日志记录功能” 状态 是保存在 WifiConfigStore.xml 文件
(4)WifiManager.enableVerboseLogging(1) 开启“启动WLAN详细日志记录功能” 状态
2、开启“启动WLAN详细日志记录功能” 状态cmd命令
查询、开启和关闭 wifi详情日志开关的命令示例:
console:/ # cmd wifi is-verbose-logging //查询wifi详情日志开关 ,显示关闭
disabled
console:/ # console:/ # cmd wifi set-verbose-logging enabled //开启wifi详情日志开关
console:/ # cmd wifi is-verbose-logging //查询wifi详情日志开关,显示开启
enabled
console:/ #console:/ # cmd wifi set-verbose-logging disabled //关闭wifi详情日志开关
console:/ #
console:/ # cmd wifi is-verbose-logging//查询wifi详情日志开关 ,显示关闭
disabled
console:/ #
为啥 cmd wifi 命令可以控制 开启“启动WLAN详细日志记录功能” ?
因为 系统中定义了 WifiShellCommand 一直在监听 cmd wifi的命令,
输入对应的参数后就可以调用 WifiManager 暴露的大部分api方法。
下面是控制wifi的adb命令详细介绍。
3、Android 使用adb操作WiFi连接扫描等相关指令
Android系统自带有组很强大的shell指令集,
这里记录下平时使用的cmd wifi 相关指令。
系统初期开发或者定位一下wifi、热点问题会比较有用。
本文不仅详细介绍cmd wifi相关用法,并且后续有介绍系统Java代码中具体控制位置,
如果有特殊需求可以对命令进行扩展定制。
原文链接:https://blog.csdn.net/wenzhi20102321/article/details/140043930
4、Android 拉起开发者设置界面命令和代码实现
Android进入Android开发者选项,一般步骤是:
1、原生设置--》关于--》点击七次“版本号”条目 (会提示:已打开开发者选项)
2、返回主界面--》系统设置--》开发者设置界面
命令:
//(1)打开开发者选项开关:
settings put global development_settings_enabled 1 //(2)am通过action或者fragment拉起开发者设置界面
am start -a android.settings.APPLICATION_DEVELOPMENT_SETTINGS
//或者
am start -a com.android.settings.APPLICATION_DEVELOPMENT_SETTINGS
文链接:https://blog.csdn.net/wenzhi20102321/article/details/146985730
5、开启“启动WLAN详细日志记录功能” 状态的日志区别
上面只是一顿分析,但是没看到实际效果日志,下面简单举例一下logcat日志。
(1)WifiService日志:
logcat | grep WifiService//未开启详细日志打印开关前日志:
09-09 21:20:48.890 924 2424 I WifiService: setWifiEnabled package=com.skg.settings uid=1000 enable=true isPrivileged=true
09-09 21:20:48.995 924 2161 I WifiService: startScan uid=1000
09-09 21:20:59.004 924 2161 I WifiService: startScan uid=1000//打开wifi详情的日志:
09-09 21:26:45.394 924 1916 I WifiService: enableVerboseLogging uid=1000 verbose=1//开启详细日志打印开关后日志:
09-09 21:26:45.919 924 2425 I WifiService: getWifiEnabledState uid=1000 state=1
09-09 21:26:46.423 924 1690 I WifiService: setWifiEnabled package=com.skg.settings uid=1000 enable=true isPrivileged=true
09-09 21:26:46.425 924 1690 I WifiService: getWifiEnabledState uid=10127 state=2
09-09 21:26:46.426 924 1690 I WifiService: getWifiEnabledState uid=1000 state=2
09-09 21:26:46.426 924 1690 I WifiService: getWifiEnabledState uid=1000 state=2
09-09 21:26:46.514 924 2425 I WifiService: getWifiEnabledState uid=1000 state=3
09-09 21:26:46.514 924 1054 I WifiService: startScan uid=1000
09-09 21:26:46.515 924 1690 I WifiService: getWifiApEnabledState uid=1000
...
未打开“启动WLAN详细日志记录功能”前,WifiService 只会打印Wifi开关状态的变化等简单日志;
打开“启动WLAN详细日志记录功能”后,WifiService 会打印Wifi开关状态的过程日志,正常是:打开中,打开完成;
如果发现只有打开中,未看到打开完成状态,那么就可以从打开中的状态往后看看,具体是哪里异常导致未打开完成。
(2) WifiNetworkSelector 日志
WifiNetworkSelector 是从wifi列表中选择哪个wifi进行默认连接的重要类。
日过没有打开“启动WLAN详细日志记录功能” 是没有 WifiNetworkSelector 相关日志打印的,
打开了“启动WLAN详细日志记录功能” ,才会有相关日志。
console:/ # logcat | grep WifiNetworkSelector09-11 06:33:40.496 925 1154 D WifiNetworkSelector: Networks filtered out due to low signal strength: AndroidAP-5301:9e:b8:b4:82:a3:14(5GHz)-82 /
...
09-11 06:33:40.502 925 1154 D WifiNetworkSelector: removeAutoUpgradeSecurityParamsIfNecessary: SSID: "xm5G" baseSecurityType: 0 upgradableSecurityType: 6 isLegacyNetworkInRange: true isUpgradableTypeOnlyInRange: false isAutoUpgradeEnabled: true
09-11 06:33:40.504 925 1154 D WifiNetworkSelector: ThroughputScorer chooses 0 score 3624.962+/-10.0 expid 42330058
还有其他Wifi相关类也是根据是否打开“启动WLAN详细日志记录功能”,决定是否打印一些详细日志,
比如:WifiConnectivityManager、NetworkProviderSettings、WifiSettings、AccessPoint、WifiP2pServiceImpl 等等等。