开机向导无法刷新 WiFi 列表

问题链接https://e.gitee.com/kunyuan-hongke/projects/842189/bugs/table?issue=IJS1GK

成功日志:pid=4837,com.ohos.setupwizard,屏幕亮屏 Screen=1

失败日志:pid=4814,com.ohos.setupwizard,屏幕息屏 Screen=2


1. 问题概述

维度 详情
问题描述 开机向导页面无法搜索到 WiFi 列表
问题概率 本地自测非必现,有概率在开机向导界面刷新出 WiFi 列表,但概率很低
影响因素 与是否已连接 WiFi 再测试、等待片刻再打开均无关
平台 OpenHarmony 6.1, GK6780V100

2. 核心根因

开机时屏幕处于息屏状态(Screen=2),SystemScanProcess 走 PNO(Preferred Network Offload)路径,但首次开机无已保存网络导致 PNO 永久失败;同时 setupwizard 缺少 ohos.permission.LOCATION 预授权,主动扫描被拒绝,无法自救。两个因素叠加,WiFi 使能过程中无任何硬件扫描被发出,缓存永远为空,setupwizard 超时退出。

TIPS:一开始 setupwizard 检测到 WiFi 状态还没准备好就只进行了 GetScanInfoResults 动作,这里依赖的就是外部的 PNO 或者系统定时扫描。等到检测到 WiFi 状态准备好之后就同时进行自身触发的 ScanGetScanInfoResults 这两个动作了。


3. 关键时间线总览

3.1 失败流程时间线(Screen=2)

08:00:09 — WiFi 设备层启动

  • hdf device host wifi_host 启动

08:00:13 — WiFi Manager 服务启动

08:00:15 — WiFi HAL 启动

  • 初始判断 no need to start Wifi or scanonly

08:00:43 — 用户触发 WiFi 开启

  • Call wifi func: On

08:00:47 — setupwizard 进入 WiFi 页面

  • 第 1/2 次轮询(此时检测到 WiFi 还没准备好,只能直接获取看有没有值)
  • GetScanInfoList size=0

08:00:53 — WiFi 核心初始化阶段(ScanService + wpa_supplicant + STA)

时间戳 事件
53.698 ScanService Init
53.712 wpa_supplicant begin to start
53.805 SystemScanProcess 第1次 -> Screen=2 -> BeginPnoScan [失败]
53.898 wpa_supplicant start successfully!
53.930 wlan0: State: DISCONNECTED -> INACTIVE

08:00:54 — PNO 死锁核心段

时间戳 事件
54.087 staStatus=24 -> SystemScanProcess 第2次 -> BeginPnoScan [失败]
54.127 setupwizard 第 3 次轮询 -> GetScanInfoList size=0
54.138 DealStaOpenRes -> DisableScan(disable=0) [成功]
54.139 SystemScanProcess 第3次 -> BeginPnoScan -> pno scan is allowed [成功],但是 Have no saved network [失败] 永久死路

08:00:57 — setupwizard 6 次主动轮询(均失败)

每次轮询固定模式:

  1. Scan() -> LOCATION PERMISSION_DENIED [失败]
  2. GetScanInfoResults -> GetScanInfoList size=0

6 次轮询时间点:

次数 时间戳
第 1 次 57.112
第 2 次 02.112
第 3 次 07.113
第 4 次 12.115
第 5 次 17.115
第 6 次 22.117

ATM 日志确认:

[IsUserGrantPermPreAuthorized] Permission(ohos.permission.LOCATION) is not in the list
[IsUserGrantPermPreAuthorized] Permission(ohos.permission.APPROXIMATELY_LOCATION) is not in the list

08:01:26 — setupwizard 超时退出

  • MyAbilityStage.onDestroy

08:01:31 — 用户手动打开 Settings

  • pid=5338, com.ohos.settings

08:01:32 — Settings 触发主动扫描

  • HdiWpaStaScan success [成功]

08:01:36 — wpa_supplicant 扫描完成

  • 30 BSSes,耗时 3.76s

08:01:37 — Settings 展示 11 个过滤后的 WiFi

08:01:42 — 用户选择 WiFi 连接

08:01:48 — 连接完成

  • CTRL-EVENT-CONNECTED

3.2 成功流程时间线(Screen=1)

08:00:47 — setupwizard 进入 WiFi 页面

  • 第 1/2 次轮询,GetScanInfoList size=0

08:00:54 — WiFi 核心初始化阶段

时间戳 事件
54.051 ScanService Init(同失败)
54.151 wpa_supplicant start
54.158 SystemScanProcess 第1次 -> Screen=1 -> StartSystemTimerScan -> [失败] wifi disable(等待)
54.450 staStatus=24 -> SystemScanProcess 第2次 -> StartSystemTimerScan -> [失败] wifi disable(继续等)
54.489 DealStaOpenRes -> DisableScan(disable=0) [成功]
54.489 SystemScanProcess 第3次 -> StartSystemTimerScan -> allow system timer scan [成功]
54.492 Begin call Scan -> HdiWpaStaScan success [成功]

08:00:58 — 第 1 次扫描完成

  • 28 valid results,Save 28 scan results

08:00:57 — setupwizard 从此开始主动触发 Scan

  • 附带 3 轮询 -> 轮询的结果还是 size=0

08:01:02 — setupwizard 第 4 次轮询完成

  • 33 results

08:01:07 — setupwizard 第 5 次轮询

  • Scan() PERMISSION_DENIED GetScanInfoList size=33 [成功]
  • 显示 12 个 WiFi

4. 失败流程逐阶段分析

阶段 0:WiFi 设备层 & Manager 服务启动(08:00:09~15)

// WiFi设备层启动
08:00:09.057  hdf device host wifi_host 6 start
08:00:09.512  wifi_host start loop

// WiFi Manager服务启动
08:00:13.467  Start dynamic proc:wifi_manager_service
08:00:14.014  Scheduler proc:wifi_manager_service started
08:00:14.022  Start sta service!
08:00:15.180  Wifi HAL start enter
08:00:15.218  Wifi HAL started

// 系统初始判断(无需立即启动WiFi)
08:00:15.225  Auto start scan only!
08:00:15.227  no need to start Wifi or scanonly

阶段 1:用户触发 WiFi 开启 & setupwizard 前两次轮询(08:00:43~47)

// 用户触发WiFi开启
08:00:43.932  Call wifi func: On (start)
08:00:43.950  Start scan service!
08:00:47.013  Call wifi func: EnableWifi (start)
08:00:47.030  Should start wifi or scanonly.

// setupwizard 第1次轮询
01-01 08:00:47.034  4814  4814 I C01560/WifiNAPIUtils: Call wifi func: GetScanInfoResults (start)
01-01 08:00:47.039  4081  4086 I C01560/WifiFrameWork: WifiSettings::GetScanInfoList size = 0
01-01 08:00:47.045  4814  4827 I C01560/WifiNAPIDevice: GetScanInfoList, size: 0

// setupwizard 第2次轮询
01-01 08:00:47.104  4814  4814 I C01560/WifiNAPIUtils: Call wifi func: GetScanInfoResults (start)
01-01 08:00:47.107  4081  4086 I C01560/WifiFrameWork: WifiSettings::GetScanInfoList size = 0
01-01 08:00:47.111  4814  4814 I A00500/[Settings]: WIFIWifiModel -> scan results items length is : 0
01-01 08:00:47.113  4814  4814 I A00500/[Settings]: WIFIWifiModel -> scan list results
01-01 08:00:47.117  4814  4814 I A00500/[Settings]: WIFIWifiModel -> scan list results

WiFi 尚未使能,不主动 Scan。因 Screen=2 息屏扫描失败,setupwizard 调用 GetScanInfoResults 时,缓存为空。

阶段 2:WiFi 核心初始化 —— ScanService + wpa_supplicant + 第 1 次 SystemScanProcess(08:00:53)

// === wpa_supplicant 启动 ===
08:00:53.712  WifiHdiWpaClient StartWifi ifaceName:wlan0
08:00:53.794  wpa_supplicant begin to start
08:00:53.805  Successfully initialized wpa_supplicant
08:00:53.898  wpa_supplicant start successfully!
08:00:53.904  Initializing interface 'wlan0'
08:00:53.930  wlan0: State: DISCONNECTED -> INACTIVE

// === ScanService 初始化 ===
01-01 08:00:53.698  4081  4119 I C01560/WifiScanManager: CheckAndStartScanService scanState: 0
01-01 08:00:53.698  4081  4119 I C01560/WifiServiceManager: WifiServiceManager::LoadScanService
01-01 08:00:53.701  4081  4119 I C01562/ScanInterface: Enter ScanInterface::Init.
01-01 08:00:53.703  4081  4119 I C01562/ScanStateMachine: Enter InitScanStateMachine.
01-01 08:00:53.703  4081  4119 I C01562/ScanStateMachine: Enter InitCommonScanState.
01-01 08:00:53.703  4081  4119 I C01562/ScanStateMachine: Enter InitPnoScanState.
01-01 08:00:53.704  4081  4119 I C01562/ScanStateMachine: Enter BuildScanStateTree.
01-01 08:00:53.704  4081  4119 I C01562/ScanStateMachine: Enter EnrollScanStatusListener.

// === Country Code & AutoStartStaService ===
01-01 08:00:53.711  4081  4119 I C01560/WifiCountryCodeManager: notify wifi country code change, module name=ScanService_0
01-01 08:00:53.711  4081  4119 I C01562/ScanService: deal wifi country code changed, code=CN
01-01 08:00:53.712  4081  4119 I C01560/WifiHdiWpaStaImpl: HdiWpaStaStart enter! ifaceName = wlan0, instId = 0

// === 关键分叉点:第1次 SystemScanProcess ===
01-01 08:00:53.804  4081  5151 I C01562/ScanStateMachine: Enter LoadDriver.
01-01 08:00:53.805  4081  5151 I C01562/ScanService: Enter HandleScanStatusReport, status:0
01-01 08:00:53.805  4081  5151 I C01562/ScanService: Enter SystemScanProcess, scanAtOnce:1.      // 第1次
01-01 08:00:53.806  4081  5151 I C01562/ScanService: Screen state(1:OPEN, 2:CLOSE): 2.           // 息屏!
01-01 08:00:53.806  4081  5151 I C01562/ScanService: Enter BeginPnoScan.                        // 走 PNO 路径
01-01 08:00:53.806  4081  5151 W C01562/ScanService: pnoScan not allow when wifi disable          // WiFi未使能
01-01 08:00:53.806  4081  5151 E C01562/ScanService: BeginPnoScan failed.                        // 第1次失败
01-01 08:00:53.806  4081  5151 I C01562/ScanStateMachine: Enter HardwareReady::GoInState.
01-01 08:00:53.806  4081  5151 I C01562/ScanStateMachine: ScanStateMachine::StopPnoScanHardware.
01-01 08:00:53.808  4081  5151 E C01562/ScanStateMachine: WifiStaHalInterface::GetInstance().StopPnoScan failed.

关键分叉:Screen=2(息屏)导致 SystemScanProcessBeginPnoScan 路径,而非亮屏的 StartSystemTimerScan。PNO 在 WiFi 未使能时直接失败,无等待/重试机制

阶段 3:staStatus=24 -> 第 2 次 SystemScanProcess,仍失败(08:00:54.087~090)

// === staStatus=24 触发(STA 驱动层就绪,但 WiFi Manager 层未完成) ===
01-01 08:00:54.087  4081  4121 I C01562/ScanInterface: Enter ScanInterface::OnClientModeStatusChanged, staStatus=24.
01-01 08:00:54.087  4081  4121 I C01562/ScanService: Enter SystemScanProcess, scanAtOnce:1.      // 第2次
01-01 08:00:54.087  4081  4121 I C01562/ScanService: Screen state(1:OPEN, 2:CLOSE): 2.           // 还是息屏
01-01 08:00:54.087  4081  4121 I C01562/ScanService: Enter BeginPnoScan.                        // 还是 PNO
01-01 08:00:54.088  4081  4121 W C01562/ScanService: pnoScan not allow when wifi disable          // 仍未使能
01-01 08:00:54.088  4081  4121 I C01562/ScanService: AllowScanByType, scanType:4, scanStyle:0, allScanResult:1
01-01 08:00:54.088  4081  4121 E C01562/ScanService: BeginPnoScan failed.                        // 第2次失败
01-01 08:00:54.088  4081  4121 I C01562/ScanService: AllowScanByType, scanType:8, scanStyle:0, allScanResult:1
01-01 08:00:54.089  4081  4121 I C01562/ScanService: AllowScanByType, scanType:4, scanStyle:0, allScanResult:1

staStatus=24 只代表 STA 驱动层就绪,DisableScan(disable=0) 还未被调用。Screen=2 息屏继续走 PNO,WiFi 未使能,失败。

阶段 4:setupwizard 第 3 次轮询(08:00:54.127~146)

01-01 08:00:54.139  4814  4827 I C01560/WifiNAPIDevice: GetScanInfoList, size: 0
01-01 08:00:54.141  4814  4814 I A00500/[Settings]: WIFIWifiModel -> scan results items length is : 0
01-01 08:00:54.146  4814  4814 I A00500/[Settings]: WIFIWifiModel -> scan list results

阶段 5:DealStaOpenRes -> 第 3 次 SystemScanProcess,PNO 永久死锁(08:00:54.138~139)

// === DealStaOpenRes:WiFi 使能正式完成,DisableScan(disable=0) 解锁 ===
01-01 08:00:54.138  4081  5165 I C01560/WifiStaManager: DealStaOpenRes: wifi scan only state notify scan result!
01-01 08:00:54.138  4081  5165 I C01562/ScanInterface: Enter ScanInterface::DisableScan, disable=0.   // 解锁
01-01 08:00:54.138  4081  5165 I C01560/WifiFrameWork: Enter DisableScan

// === 致命分叉:第3次 SystemScanProcess ===
01-01 08:00:54.138  4081  5165 I C01562/ScanService: Enter BeginPnoScan.                           // Screen=2 息屏
01-01 08:00:54.139  4081  5165 I C01562/ScanService: Enter AllowScanDuringStaScene, staScene:3, scanMode:5
01-01 08:00:54.139  4081  5165 I C01562/ScanService: pno scan is allowed                           // PNO 权限通过
01-01 08:00:54.139  4081  5165 I C01562/ScanService: Enter GetSavedNetworkSsidList.
01-01 08:00:54.139  4081  5165 E C01562/ScanService: Have no saved network, not need to start PNO scan.  // 致命!
01-01 08:00:54.139  4081  5165 E C01562/ScanService: BeginPnoScan failed.                           // 永久死路

永久死锁成立:WiFi 已使能(DisableScan(disable=0) 已调用),PNO 权限通过(pno scan is allowed),但 GetSavedNetworkSsidList 发现首次开机无任何已保存 WiFi 网络。PNO 扫描只对已知网络有效,BeginPnoScan 失败后无任何重试/回退机制。从此再无任何硬件扫描被发出,缓存永远为空。

对应源码逻辑:

if (pnoScanConfig.savedNetworkSsid.size() == 0) {
    WIFI_LOGE("Have no saved network, not need to start PNO scan.\n");  //1132
    return false;                                                        // 返回false
}

如上可以发现调用 PNO scan 是一个死循环:无值不能扫描,不能扫描则无值。

阶段 6:setupwizard 连续 7 次主动轮询 —— 全部因缺权限失败(08:00:57~08:01:22)

每次轮询固定模式:

  1. check WiFi active status is : true — WiFi 已使能
  2. scan wifi started,调用 Call wifi func: Scan (start) — 主动触发扫描
  3. PERMISSION_DENIED! — 权限被拒绝(缺 LOCATION)
  4. Read result failed, code is: 2 — IPC 返回失败
  5. start scan WiFi result is : false — 主动扫描失败
  6. Call wifi func: GetScanInfoResults,结果 GetScanInfoList size: 0 — 尝试从缓存取,为空
  7. scan results items length is : 0scan list results — 界面提示无结果

第 1 次主动轮询(08:00:57.108~125)

01-01 08:00:57.108  4814  4814 I C01560/WifiDeviceProxy: IsWifiActive bActive=1
01-01 08:00:57.108  4814  4814 I A00500/[Settings]: WIFIWifiModel -> check WiFi active status is : true
01-01 08:00:57.108  4814  4814 I A00500/[Settings]: WIFIWifiModel -> scan wifi started
01-01 08:00:57.108  4814  4814 I C01560/WifiNAPIUtils: Call wifi func: Scan (start)
01-01 08:00:57.111  4814  4814 I C01560/WifiCommonUtil: Get bundle name uid[20010047]: com.ohos.setupwizard
01-01 08:00:57.112  4081  5166 I C01562/WifiScanServiceImpl: Scan with bundleName: com.ohos.setupwizard, compatible: 1
01-01 08:00:57.112  4081  5166 E C01560/OHWIFI_MANAGER_PERMISSION_HELPE: has no permission_name=ohos.permission.LOCATION, pid=4814, uid=20010047
01-01 08:00:57.112  4081  5166 E C01562/WifiScanServiceImpl: Scan:VerifyGetScanInfosPermission PERMISSION_DENIED!
01-01 08:00:57.113  4814  4814 E C01560/WifiScanIpc: Read result failed, code is: 2.
01-01 08:00:57.113  4814  4814 I C01560/WifiNAPIUtils: Call wifi func: Scan (end), time cost:5059us, 5ms
01-01 08:00:57.114  4814  4814 I A00500/[Settings]: WIFIWifiModel -> start scan WiFi result is : false
01-01 08:00:57.114  4814  4814 I C01560/WifiNAPIUtils: Call wifi func: GetScanInfoResults (start)
01-01 08:00:57.117  4081  4081 I C01560/WifiFrameWork: WifiSettings::GetScanInfoList size = 0
01-01 08:00:57.121  4814  5108 I C01560/WifiNAPIDevice: GetScanInfoList, size: 0
01-01 08:00:57.122  4814  4814 I A00500/[Settings]: WIFIWifiModel -> scan results items length is : 0
01-01 08:00:57.125  4814  4814 I A00500/[Settings]: WIFIWifiModel -> scan list results

后续 6 次尝试时间点

次数 时间 关键结果
第 2 次 08:01:02.112~126 GetScanInfoList size: 0, scan results items length is: 0
第 3 次 08:01:07.113~124 PERMISSION_DENIED!, GetScanInfoList size: 0
第 4 次 08:01:12.115~129 PERMISSION_DENIED!, scan results items length is: 0
第 5 次 08:01:17.115~126 PERMISSION_DENIED!, scan results items length is: 0
第 6 次 08:01:22.117~129 PERMISSION_DENIED!, scan results items length is: 0
// ATM 日志确认:setupwizard 缺少 LOCATION 预授权
ATM: [IsUserGrantPermPreAuthorized]Permission(ohos.permission.LOCATION) is not in the list
ATM: [IsUserGrantPermPreAuthorized]Permission(ohos.permission.APPROXIMATELY_LOCATION) is not in the list

ATM 日志确认:AccessToken Manager 在初始化 HAP token 时检查 preAuthorizationInfo(预授权信息),is not in the list 说明系统预授权配置文件中没有为 setupwizard 授予 LOCATION 权限。两份日志(成功和失败)中 ATM 检查结果完全相同——都是 not in the list,说明权限缺失在两轮测试中同等存在,setupwizard 的 Scan() 调用必然失败

阶段 7:setupwizard 超时退出(08:01:26.997)

01-01 08:01:26.997  4814  4814 I A03d00/JSAPP: MyAbilityStage.onDestroy is called

setupwizard 从进入 WiFi 页面(08:00:47)到超时退出(08:01:26),等了约 39 秒,未拿到任何 WiFi 扫描结果。

阶段 8:用户手动打开 Settings,首次硬件扫描始发出(08:01:31~36)

// === Settings 打开 ===
01-01 08:01:31.875  5338  5338 I A00500/[Settings]: Settings WifiModel -> start register wifi status observer
01-01 08:01:31.961  5338  5338 I C01560/WifiNAPIUtils: Call wifi func: GetScanInfoList (start)
01-01 08:01:31.966  5338  5338 I C01560/WifiNAPIDevice: GetScanInfoList, size: 0  // 缓存仍为空
01-01 08:01:31.967  5338  5338 I A00500/[Settings]: Settings WifiModel ->  refreshApScanResults start
01-01 08:01:31.971  5338  5338 I A00500/[Settings]: Settings WifiModel ->  Refresh completed, final count: 0

// === Settings 触发主动扫描(com.ohos.settings 拥有 LOCATION 权限) ===
01-01 08:01:32.950  5338  5338 I A00500/[Settings]: Settings WifiModel -> check WiFi isActive : true
01-01 08:01:32.951  5338  5338 I C01560/WifiNAPIUtils: Call wifi func: StartScan (start)
01-01 08:01:32.955  4081  5166 I C01562/WifiScanServiceImpl: Scan with bundleName: com.ohos.settings, compatible: 0
01-01 08:01:32.960  4081  5152 I C01562/ScanStateMachine: Enter StartNewCommonScan.
01-01 08:01:32.960  4081  5152 I C01562/ScanStateMachine: Begin call Scan.
01-01 08:01:32.962  4081  5152 I C01560/WifiHdiWpaStaImpl: HdiWpaStaScan enter
01-01 08:01:32.964  3358  5157 I C05200/wpa_supplicant: Ready to start scan
01-01 08:01:32.965  3358  5153 I C01566/HDF_LOG_TAG: WpaInterfaceScan: StartScan successfully!
01-01 08:01:32.968  3358  5157 I C05200/wpa_supplicant: wlan0: Starting AP scan for wildcard SSID

// === wpa_supplicant 扫描完成 ===
01-01 08:01:36.733  3358  5157 I C05200/wpa_supplicant: nl80211: Drv Event 34 (NL80211_CMD_NEW_SCAN_RESULTS) received for wlan0
01-01 08:01:36.733  3358  5157 I C05200/wpa_supplicant: wlan0: Scan completed in 3.763077 seconds
01-01 08:01:36.735  3358  5157 I C05200/wpa_supplicant: nl80211: Received scan results (30 BSSes)
01-01 08:01:36.750  3358  5157 I C05200/wpa_supplicant: wlan0: Radio work 'scan'@0x7faf1f1bf0 done in 3.782080 seconds

// === ScanService 缓存写入 ===
01-01 08:01:36.791  4081  4119 I C01562/ScanService: Save 30 scan results.                    // 存入
01-01 08:01:36.794  4081  4119 I C01560/WifiFrameWork: WifiSettings::GetScanInfoList size = 30

// === Settings 展示结果 ===
01-01 08:01:36.954  5338  5338 I A00500/[Settings]: Settings WifiModel ->  refreshApScanResults start
01-01 08:01:37.004  5338  5338 I A00500/[Settings]: Settings WifiModel ->  Refresh completed, final count: 11

Settings 拥有 LOCATION 权限,其 StartScan() 顺利通过权限检查,HdiWpaStaScan success,wpa_supplicant 扫描到 30 个 BSSes,Save 30 scan results,过滤后展示 11 个 WiFi。但此时 setupwizard 已于 08:01:26 销毁(早约 5 秒),永远无法展示这些结果。


5. 成功流程对照分析(作为参考基线)

成功的关键:Screen=1 亮屏,StartSystemTimerScan 有等待机制

与失败流程相同,SystemScanProcess 前两次也遇到 WiFi disable(第 1 次 08:00:54.159,第 2 次 08:00:54.451),但由于走的是 StartSystemTimerScan 路径,该路径有等待机制——WiFi disable 时不放弃,等 DealStaOpenRes 触发 DisableScan(disable=0) 后自动重试。

// 第3次 SystemScanProcess —— 成功
01-01 08:00:54.489  4103  5138 I C01560/WifiStaManager: DealStaOpenRes: wifi scan only state notify scan result!
01-01 08:00:54.489  4103  5138 I C01562/ScanInterface: Enter ScanInterface::DisableScan, disable=0.   // 解锁
01-01 08:00:54.489  4103  5138 I C01562/ScanService: Enter SystemScanProcess, scanAtOnce:1.           // 第3次
01-01 08:00:54.489  4103  5138 I C01562/ScanService: Screen state(1:OPEN, 2:CLOSE): 1.                // 亮屏
01-01 08:00:54.489  4103  5138 I C01562/ScanService: Enter StartSystemTimerScan, scanAtOnce: 1.        // 走定时扫描
01-01 08:00:54.489  4103  5138 I C01562/ScanService: allow system timer scan                           // 通过!
01-01 08:00:54.490  4103  5138 I C01562/ScanService: Enter Scan, scanType:3, scanStyle:0.
01-01 08:00:54.490  4103  4136 I C01562/ScanStateMachine: Begin call Scan.
01-01 08:00:54.492  4103  4136 I C01560/WifiHdiWpaStaImpl: HdiWpaStaScan enter
01-01 08:00:54.504  4103  4136 I C01560/WifiHdiWpaStaImpl: HdiWpaStaScan success.                     // 硬件扫描发出

扫描完成后:

01-01 08:00:58.285  total number of valid scan results: 28       //1次扫描 2801-01 08:00:58.291  Save 28 scan results.                        // 写入缓存
01-01 08:01:02.102  total number of valid scan results: 33       //2次扫描 33// setupwizard 第4次轮询拿到结果
01-01 08:01:02.477  GetScanInfoList, size: 33                    // 拿到结果
01-01 08:01:02.499  scan results items length is : 12            // 展示12个WiFi

6. 成功 vs 失败流程对比

6.1 关键决策点对比表

序号 时间 事件 成功 (Screen=1) 失败 (Screen=2)
第 1 次 08:00:54 HandleScanStatusReport(status:0) Screen: 1 -> StartSystemTimerScan -> system timer scan not allow when wifi disable(等待重试) Screen: 2 -> BeginPnoScan -> pnoScan not allow when wifi disable(放弃)
第 2 次 08:00:54 staStatus=24 HandleStaStatusChanged Screen: 1 -> StartSystemTimerScan -> 继续等待 Screen: 2 -> BeginPnoScan -> 再次放弃
第 3 次 08:00:54 DealStaOpenRes Screen: 1 -> StartSystemTimerScan -> allow system timer scan [成功] -> HdiWpaStaScan success Screen: 2 -> BeginPnoScan -> pno scan is allowed [成功] -> Have no saved network [失败] 永久死路
结果 硬件扫描 08:00:54.492 发出,28 条结果 [成功] 从未发出硬件扫描 [失败](直到 08:01:32 Settings 手动触发)

6.2 两条路径的本质差异

SystemScanProcess 内部决策逻辑:

if (Screen == OPEN/1)
    -> StartSystemTimerScan    // 亮屏:主动定时扫描
else (Screen == CLOSE/2)
    -> BeginPnoScan            // 息屏:PNO 省电扫描

StartSystemTimerScan(亮屏路径):

  • [成功] 有等待机制:wifi disable 期间不放弃,等 DealStaOpenRes 后自动重试
  • [成功] 扫描所有可见 AP(wildcard SSID)
  • [成功] 结果写入 WifiSettings 缓存供所有进程读取

BeginPnoScan(息屏/PNO 路径):

  • [失败] 无等待/重试机制:失败即永久放弃
  • [失败] 只扫描已保存网络(Preferred Network Offload)
  • [失败] 首次开机无已保存网络,永久死路
  • [失败] 无回退到普通扫描的逻辑

6.3 权限问题一致性

日志 ATM 检查结果 setupwizard Scan() 结果
成功(Screen=1) LOCATION not in the list PERMISSION_DENIED
失败(Screen=2) LOCATION not in the list PERMISSION_DENIED

两份日志中 ATM 预授权检查结果完全一致,setupwizard 的 Scan() 调用在两轮测试中都因权限被拒。差别仅在于:

  • 成功场景:后台 StartSystemTimerScan 已自动完成扫描,setupwizard 通过 GetScanInfoResults(读取缓存)拿到了结果
  • 失败场景:后台 PNO 从未下发扫描,setupwizard 读缓存为空

7. 根因分析

7.1 直接原因(双因素叠加)

因素一:息屏走 PNO 路径 + 首次开机无已保存网络,硬件扫描从未发出

  1. Screen=2 息屏,SystemScanProcessBeginPnoScan
  2. WiFi 未使能时:pnoScan not allow when wifi disable(无等待)
  3. WiFi 使能后:pno scan is allowed [成功],但是 Have no saved network, not need to start PNO scan [失败]
  4. BeginPnoScan failed,无回退、无重试
  5. 整个 WiFi 使能过程中 0 次硬件扫描被发出

因素二:setupwizard 缺 LOCATION 权限预授权,自救失败

  1. ATM preAuthorizationInfo 中无 LOCATION 权限
  2. setupwizard Scan() -> PERMISSION_DENIED(必然失败)
  3. setupwizard 无法自行触发硬件扫描自救
  4. 只能等待后台扫描结果落入缓存
  5. 但因素一导致缓存永远为空

叠加效果:WiFi 使能了,但谁都没有完成一次扫描,这就是死锁

7.2 条件触发分析

条件 开机即发生 说明
首次开机 无已保存 WiFi 网络,PNO 无目标
屏幕息屏 大概率 开机过程屏幕通常为息屏状态
setupwizard 缺权限 ATM 预授权配置中未包含 LOCATION

三个条件在开机流程中同时满足的概率极高,因此问题在首次开机场景下几乎必现。

7.3 PNO 路径的设计缺陷

息屏状态下,WiFi 扫描流程的设计意图是省电——用 PNO(硬件级别已知网络扫描)替代完整扫描。但对于首次开机场景,这个设计存在缺陷:

  1. 无降级策略:PNO 失败后应回退到普通扫描,或至少等待亮屏后触发
  2. 无超时重试BeginPnoScan 是一次性调用,失败即终止
  3. 无外部触发通道:如果此时有应用(如 Settings)主动触发扫描,硬件扫描仍可发生——但 setupwizard 恰好缺权限

8. 修复方案

8.1 推荐方案:添加 setupwizard 的 LOCATION 权限预授权

修改系统配置文件 install_list_permissions.json,为 com.ohos.setupwizard 添加 ohos.permission.LOCATION 预授权:

{
  "bundle_name": "com.ohos.setupwizard",
  "permissions": [
    {
      "name": "ohos.permission.LOCATION",
      "user_cancellable": false
    }
  ]
}

注:原有权限保持不变,此处仅展示新增项。

修复效果

  • setupwizard Scan() 调用不再被 PERMISSION_DENIED 拒绝
  • 即使 PNO 死锁(息屏无已保存网络),setupwizard 也能主动触发完整扫描
  • 兼容亮屏/息屏两种场景

8.2 可选的底层增强方案

以下方案可作为长期改进参考,不要求本次修复实现:

方案 思路 影响范围
PNO 失败后回退到普通扫描 BeginPnoScan 失败时(Have no saved network)回退到 StartSingleCommonScan ScanService 层
息屏下首次 WiFi 使能强制走一次普通扫描 DealStaOpenRes 后,若未连接且缓存为空,忽略 Screen 状态强制扫描 WiFi Manager 层
PNO 增加超时重试 PNO 失败后设置定时器,亮屏时自动触发完整扫描 ScanStateMachine 层

9. 修改验证

  1. 修改 install_list_permissions.json 并重新烧录系统镜像
  2. 验证步骤:
    • 首次开机,进入开机向导 WiFi 页面
    • 确认 setupwizard 不再报 PERMISSION_DENIED
    • 确认 WiFi 列表在 10 秒内正常刷新
  3. 验证结果:OK,问题解决 [成功]

附录 A:涉及的模块与日志标签

模块 PID Tag 功能
setupwizard 4814/4837 A00500/[Settings] 开机向导 WiFi 页面
Settings 5338 A00500/[Settings] 设置应用 WiFi 页面
wifi_manager_service 4081/4103 C01560/WifiFrameWork WiFi 框架服务
wifi_scan_service 4081/4103 C01562/ScanService 扫描服务
wifi_scan_state_machine 4081/4103 C01562/ScanStateMachine 扫描状态机
wpa_supplicant 3358/3368 C05200/wpa_supplicant WPA 请求者
WifiHdiWpaStaImpl 4081/4103 C01560/WifiHdiWpaStaImpl HDI WPA STA 实现
ATM ATM AccessToken Manager
Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐