Android13 命令启用WLAN详细日志分析

Android13 命令启用WLAN详细日志分析

一、前言

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 enabled
            boolean 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开
    @Override
    public 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开
    @Override
    public 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
        @Readable
        public 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.java

public 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">&quot;NO-BUG&quot;WPA_PSK</string> //Wifi名称
<string name="SSID">&quot;NO-BUG&quot;</string> //Wifi名称
<string name="PreSharedKey">&quot;qwertyuiop&quot;</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
     */
    @SystemApi
    public static final int VERBOSE_LOGGING_LEVEL_DISABLED = 0;

    /**
     * Verbose logging mode: ENABLED.
     * @hide
     */
    @SystemApi
    public 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();
        }
    }
    
    @SystemApi
    public 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 WifiNetworkSelector

09-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 等等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

峥嵘life

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

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

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

打赏作者

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

抵扣说明:

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

余额充值