fix(android): capture privacy exit states

This commit is contained in:
key
2026-07-29 03:43:30 +08:00
parent 8354e4e9c2
commit 71f005c229
4 changed files with 67 additions and 13 deletions
+1
View File
@@ -7,6 +7,7 @@
- **2026-07-28 至 2026-07-29,8 月 1 日 Android 受控内测候选包与法务链路,当前总体 No-Go**:补齐登录页协议默认不勾选与法务地址失败关闭、App-Plus 原生隐私配置生成/校验、APK 包名/版本/API/签名/哈希/包内资源一致性/敏感值门禁、DCloud 云证书自定义基座和独立测试包流程;《服务协议》《隐私政策》静态页已部署到 `/legal/`,发布前整站备份为 `/opt/wygj/backups/www-20260728224710`。客户端法务校验已移除 App-Plus 不保证支持的浏览器 `URL` 构造器,测试验证码也不再以源码常量进入安装包;五个文件选择服务与九个消费页面进一步统一“用户取消/平台失败”分流,取消后不再残留上传或转写错误;直通车首次弱网加载失败后可原位重试,失败时清空旧通道并禁止提交。当前独立 APK `com.yincheng.wygj 0.1.10 (110)` 的 `targetSdkVersion=35`,SHA-256 为 `20CB16B4E9D024DBF5EEEF577BFBA3B4DF5E5E78B597BABB99CB7450C7AE5034`;Android 原生网络安全配置经 APK 反编译确认 `usesCleartextTraffic=false`、`networkSecurityConfig` 引用和系统证书信任配置均已进入安装包。本机 `Medium_Phone` Android 15/API 35 虚拟机已完成从 `0.1.9` 保留数据覆盖升级和冷启动,真实显示原生隐私弹窗,四项敏感权限保持未授权且未见 FATAL/ANR;`0.1.6` 已在 vivo V2443A(Android 15)完成覆盖安装和冷启动。代码候选提交 `dc20b920` 已在干净工作区通过统一 RC 门禁,`releaseEligible=true`:移动端 198 项测试、类型检查、H5/App 构建、管理端构建、`ruoyi-aihr` 698 项全量测试、后端打包及 APK 强化门禁全部通过;最小交付包 SHA-256 为 `4BAA79B2CA2C4D486B6194288D90022D5F994A4D8C8E05D7C2DDD87F9BF5B3B7`,解压后 9 个文件、其中 8 个载荷逐文件复验通过。只读生产预检确认根站、租户接口、移动首页和 64/64 schema 门禁通过,但生产后端模块、管理端和移动 H5 与本地候选仍不一致;用户隐私选择、权限反例、认证态核心业务和正式内容也未完成,故 Go/No-Go 为 **No-Go**。本次没有新增生产发布、服务重启、数据库或静态资源变更。 - **2026-07-28 至 2026-07-29,8 月 1 日 Android 受控内测候选包与法务链路,当前总体 No-Go**:补齐登录页协议默认不勾选与法务地址失败关闭、App-Plus 原生隐私配置生成/校验、APK 包名/版本/API/签名/哈希/包内资源一致性/敏感值门禁、DCloud 云证书自定义基座和独立测试包流程;《服务协议》《隐私政策》静态页已部署到 `/legal/`,发布前整站备份为 `/opt/wygj/backups/www-20260728224710`。客户端法务校验已移除 App-Plus 不保证支持的浏览器 `URL` 构造器,测试验证码也不再以源码常量进入安装包;五个文件选择服务与九个消费页面进一步统一“用户取消/平台失败”分流,取消后不再残留上传或转写错误;直通车首次弱网加载失败后可原位重试,失败时清空旧通道并禁止提交。当前独立 APK `com.yincheng.wygj 0.1.10 (110)` 的 `targetSdkVersion=35`,SHA-256 为 `20CB16B4E9D024DBF5EEEF577BFBA3B4DF5E5E78B597BABB99CB7450C7AE5034`;Android 原生网络安全配置经 APK 反编译确认 `usesCleartextTraffic=false`、`networkSecurityConfig` 引用和系统证书信任配置均已进入安装包。本机 `Medium_Phone` Android 15/API 35 虚拟机已完成从 `0.1.9` 保留数据覆盖升级和冷启动,真实显示原生隐私弹窗,四项敏感权限保持未授权且未见 FATAL/ANR;`0.1.6` 已在 vivo V2443A(Android 15)完成覆盖安装和冷启动。代码候选提交 `dc20b920` 已在干净工作区通过统一 RC 门禁,`releaseEligible=true`:移动端 198 项测试、类型检查、H5/App 构建、管理端构建、`ruoyi-aihr` 698 项全量测试、后端打包及 APK 强化门禁全部通过;最小交付包 SHA-256 为 `4BAA79B2CA2C4D486B6194288D90022D5F994A4D8C8E05D7C2DDD87F9BF5B3B7`,解压后 9 个文件、其中 8 个载荷逐文件复验通过。只读生产预检确认根站、租户接口、移动首页和 64/64 schema 门禁通过,但生产后端模块、管理端和移动 H5 与本地候选仍不一致;用户隐私选择、权限反例、认证态核心业务和正式内容也未完成,故 Go/No-Go 为 **No-Go**。本次没有新增生产发布、服务重启、数据库或静态资源变更。
- **2026-07-29,发布预检支持定向后端/schema 范围和冻结物核验,未发布**:`release-preflight.sh` 不再把远端后端或 schema 核验强制绑定到管理端/H5 静态匹配;定向后端发布可只启用 `RELEASE_VERIFY_REMOTE_BACKEND=true RELEASE_VERIFY_REMOTE_SCHEMA=true`,且只要求本地后端 JAR 新鲜。完整包口径仍必须同时启用远端静态、后端和 schema 三项。新增范围回归脚本,校验缺少 `RELEASE_REMOTE_URL` 时失败关闭、定向模式不回退为静态耦合、完整模式命令仍保留;`feece9bb` 再新增 `RELEASE_ARTIFACT_COMMIT` 与 `RELEASE_LOCAL_BACKEND_PATH`,允许从后续文档提交上安全地核验冻结提交及其实际候选 JAR。提交 `566f222e` 后只重建后端并实跑生产只读定向预检:输出没有管理端/H5 哈希,根站、租户、移动首页、64/64 schema 和生产禁 DDL 门禁通过,最终仅因现网/候选 AIHR 模块哈希 `15f5513a…` / `c93460e8…` 不同而按预期失败。随后以 `dc20b920` 和发布 ZIP 解压 JAR 再跑后端只读预检,确认候选整包哈希 `8c676f2f…`,仍仅在同一模块差异处失败;这证明范围和冻结物选择正确,不代表后端已经发布。本项没有执行生产同步、重启或数据库变更。 - **2026-07-29,发布预检支持定向后端/schema 范围和冻结物核验,未发布**:`release-preflight.sh` 不再把远端后端或 schema 核验强制绑定到管理端/H5 静态匹配;定向后端发布可只启用 `RELEASE_VERIFY_REMOTE_BACKEND=true RELEASE_VERIFY_REMOTE_SCHEMA=true`,且只要求本地后端 JAR 新鲜。完整包口径仍必须同时启用远端静态、后端和 schema 三项。新增范围回归脚本,校验缺少 `RELEASE_REMOTE_URL` 时失败关闭、定向模式不回退为静态耦合、完整模式命令仍保留;`feece9bb` 再新增 `RELEASE_ARTIFACT_COMMIT` 与 `RELEASE_LOCAL_BACKEND_PATH`,允许从后续文档提交上安全地核验冻结提交及其实际候选 JAR。提交 `566f222e` 后只重建后端并实跑生产只读定向预检:输出没有管理端/H5 哈希,根站、租户、移动首页、64/64 schema 和生产禁 DDL 门禁通过,最终仅因现网/候选 AIHR 模块哈希 `15f5513a…` / `c93460e8…` 不同而按预期失败。随后以 `dc20b920` 和发布 ZIP 解压 JAR 再跑后端只读预检,确认候选整包哈希 `8c676f2f…`,仍仅在同一模块差异处失败;这证明范围和冻结物选择正确,不代表后端已经发布。本项没有执行生产同步、重启或数据库变更。
- **2026-07-29,Android 人工验收新增只读统一取证**:新增 `capture-android-acceptance.ps1`,只读取指定设备当前包版本、前台 Activity、四项敏感权限、UI 层级、截图和应用退出记录,证据限定写入 Git 已忽略的 `output/`;静态回归拒绝安装、启动、停止、清数据、授权、撤权和输入类命令。脚本已在 `emulator-5554` 实跑,确认 `0.1.10 (110)` / API 35 的原生隐私标题与拒绝/同意按钮可见、手机号登录不可见、四项权限均未授权、退出记录无 Crash/ANR。本项只记录用户选择前状态,未代替用户点击隐私选项。 - **2026-07-29,Android 人工验收新增只读统一取证**:新增 `capture-android-acceptance.ps1`,只读取指定设备当前包版本、前台 Activity、四项敏感权限、UI 层级、截图和应用退出记录,证据限定写入 Git 已忽略的 `output/`;静态回归拒绝安装、启动、停止、清数据、授权、撤权和输入类命令。脚本已在 `emulator-5554` 实跑,确认 `0.1.10 (110)` / API 35 的原生隐私标题与拒绝/同意按钮可见、手机号登录不可见、四项权限均未授权、退出记录无 Crash/ANR。本项只记录用户选择前状态,未代替用户点击隐私选项。
- **2026-07-29,Android 隐私拒绝取证补齐二次确认与退出态**:只读取证脚本现在按实际原生模板区分首次选择 `first-choice`、二次“确认提示/退出应用” `exit-confirmation` 和弹窗不可见 `not-visible`,并记录 App 进程是否存在、是否前台及当前 UI 是否属于 App。`pidof` 在用户退出后返回非零不再让取证失败,因此可分别留存“暂不同意后的二次确认”和“退出应用后的 Launcher/退出记录”证据;脚本仍不发送点击、启动/停止或权限命令。
- **2026-07-29,定向后端发布/回滚工具与只读计划,未发布**:新增固定 `YCWY:/opt/wygj/app/ruoyi-admin.jar` 和 `wygj-aihr.service` 的 `release-backend.sh`;`plan`/`rollback-plan` 默认只读,`deploy`/`rollback` 必须使用完整 SHA-256 授权串且 Git 工作区干净。执行链包含旧包与清单备份、同目录候选校验、原子切换、systemd 重启、后端 + schema 发布后预检、失败自动恢复、回滚前安全备份和恢复前目标哈希复核;发现并发改包时拒绝自动覆盖,所有备份均保留。离线回归覆盖授权前失败关闭、六段远端 Bash 语法、无删除操作,并在临时目录实跑备份→切换→恢复→并发拒绝→回滚安全备份链。冻结候选实跑只读计划确认候选 JAR `8c676f2f…`、现网 JAR `46c99cff…`、目标/服务/空间、三个公开入口、64/64 schema 和生产禁 DDL 均符合要求;只输出授权串,没有创建远端备份、上传、切换、重启或改库。 - **2026-07-29,定向后端发布/回滚工具与只读计划,未发布**:新增固定 `YCWY:/opt/wygj/app/ruoyi-admin.jar` 和 `wygj-aihr.service` 的 `release-backend.sh`;`plan`/`rollback-plan` 默认只读,`deploy`/`rollback` 必须使用完整 SHA-256 授权串且 Git 工作区干净。执行链包含旧包与清单备份、同目录候选校验、原子切换、systemd 重启、后端 + schema 发布后预检、失败自动恢复、回滚前安全备份和恢复前目标哈希复核;发现并发改包时拒绝自动覆盖,所有备份均保留。离线回归覆盖授权前失败关闭、六段远端 Bash 语法、无删除操作,并在临时目录实跑备份→切换→恢复→并发拒绝→回滚安全备份链。冻结候选实跑只读计划确认候选 JAR `8c676f2f…`、现网 JAR `46c99cff…`、目标/服务/空间、三个公开入口、64/64 schema 和生产禁 DDL 均符合要求;只输出授权串,没有创建远端备份、上传、切换、重启或改库。
- **2026-07-29,8 月 1 日生产 API 无登录探针固化**:新增 GET-only 脚本覆盖 APK 依赖的 20 个入口;实跑得到公开移动首页 `1×200`、鉴权 GET `6×401`、仅 POST 入口 `13×405`。`/api/knowledge/answer-feedback` 因同一路径另有运营 GET,按真实控制器归入鉴权组。回归禁止请求体、表单、授权头、手机号和短信验证码入口;本次未申请验证码、未登录、未上传、未发送业务 POST 或写入数据。该结果证明路由与失败关闭契约,不替代认证态业务闭环。 - **2026-07-29,8 月 1 日生产 API 无登录探针固化**:新增 GET-only 脚本覆盖 APK 依赖的 20 个入口;实跑得到公开移动首页 `1×200`、鉴权 GET `6×401`、仅 POST 入口 `13×405`。`/api/knowledge/answer-feedback` 因同一路径另有运营 GET,按真实控制器归入鉴权组。回归禁止请求体、表单、授权头、手机号和短信验证码入口;本次未申请验证码、未登录、未上传、未发送业务 POST 或写入数据。该结果证明路由与失败关闭契约,不替代认证态业务闭环。
- **2026-07-29,8 月 1 日双提交交付包取代首个最小包**:新增可复现打包器,分别冻结运行时提交 `dc20b920` 与 operations commit `414af66e`,重新校验 APK/JAR/内容哈希和提交祖先关系,并将发布、回滚、预检、GET-only API 探针、Android 只读取证和 Go/No-Go 审计快照纳入 ZIP。当前包 `bangdao-aug1-0.1.10-110-dc20b920-ops414af66e.zip` 为 `192,925,849` 字节,SHA-256 `70C0C467B7EAAF57BFA597EB01561901AEA799DF37E3DA8D006DFFF756098D5D`;14 个条目及 `SHA256SUMS.txt` 中 13 个载荷逐条通过。旧无 operations 后缀包与中间 `ops861fa0ea` 包仅保留追溯,不再作为当前交付包;运行时 APK/JAR 未重编。 - **2026-07-29,8 月 1 日双提交交付包取代首个最小包**:新增可复现打包器,分别冻结运行时提交 `dc20b920` 与 operations commit `414af66e`,重新校验 APK/JAR/内容哈希和提交祖先关系,并将发布、回滚、预检、GET-only API 探针、Android 只读取证和 Go/No-Go 审计快照纳入 ZIP。当前包 `bangdao-aug1-0.1.10-110-dc20b920-ops414af66e.zip` 为 `192,925,849` 字节,SHA-256 `70C0C467B7EAAF57BFA597EB01561901AEA799DF37E3DA8D006DFFF756098D5D`;14 个条目及 `SHA256SUMS.txt` 中 13 个载荷逐条通过。旧无 operations 后缀包与中间 `ops861fa0ea` 包仅保留追溯,不再作为当前交付包;运行时 APK/JAR 未重编。
+1 -1
View File
@@ -18,7 +18,7 @@ Android 每个人工步骤完成后,可在不改变设备状态的前提下保
-Stage privacy-before-choice -Stage privacy-before-choice
``` ```
每次手动操作后换一个简短的 `-Stage`,例如 `privacy-rejected`、`privacy-consented`、`microphone-denied`。脚本不把“拍到页面”自动判成业务通过;验收人仍须结合预期、截图和 `acceptance-evidence.json` 签认。 每次手动操作后换一个简短的 `-Stage`。首次点击“暂不同意”后会进入第二层“确认提示”,先用 `privacy-exit-confirmation` 取证;用户再亲自点击“退出应用”后用 `privacy-rejected-exited` 取证。脚本会区分 `first-choice`、`exit-confirmation` 和 `not-visible`,并在应用进程已经退出时继续记录前台 Activity、退出记录和权限,不会因 `pidof` 无结果而失败。随后重新启动并由用户点击“同意并继续”,使用 `privacy-consented`;麦克风拒绝可使用 `microphone-denied`。脚本不把“拍到页面”自动判成业务通过;验收人仍须结合预期、截图和 `acceptance-evidence.json` 签认。
## 当前证据边界 ## 当前证据边界
+60 -12
View File
@@ -56,13 +56,14 @@ function Invoke-AdbText {
param( param(
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[string[]]$Arguments, [string[]]$Arguments,
[switch]$AllowEmpty [switch]$AllowEmpty,
[switch]$AllowNonZero
) )
$output = & $script:resolvedAdbPath @Arguments 2>&1 $output = & $script:resolvedAdbPath @Arguments 2>&1
$exitCode = $LASTEXITCODE $exitCode = $LASTEXITCODE
$text = ($output | Out-String).Trim() $text = ($output | Out-String).Trim()
if ($exitCode -ne 0) { if ($exitCode -ne 0 -and -not $AllowNonZero) {
throw "adb failed with exit code $exitCode`: $($Arguments -join ' ')`n$text" throw "adb failed with exit code $exitCode`: $($Arguments -join ' ')`n$text"
} }
if (-not $AllowEmpty -and [string]::IsNullOrWhiteSpace($text)) { if (-not $AllowEmpty -and [string]::IsNullOrWhiteSpace($text)) {
@@ -119,7 +120,16 @@ function Get-FirstMatchingLine {
[string]$Text, [string]$Text,
[string]$Pattern [string]$Pattern
) )
return (($Text -split "`r?`n") | Where-Object { $_ -match $Pattern } | Select-Object -First 1).Trim() $line = ($Text -split "`r?`n") | Where-Object { $_ -match $Pattern } | Select-Object -First 1
if ($null -eq $line) {
return ''
}
return $line.Trim()
}
function ConvertFrom-CodePoints {
param([int[]]$CodePoints)
return -join @($CodePoints | ForEach-Object { [char]$_ })
} }
$script:resolvedAdbPath = Resolve-AdbPath -RequestedPath $AdbPath $script:resolvedAdbPath = Resolve-AdbPath -RequestedPath $AdbPath
@@ -160,7 +170,9 @@ New-Item -ItemType Directory -Path $evidenceDirectory | Out-Null
$activityDump = Invoke-AdbText -Arguments @('-s', $Serial, 'shell', 'dumpsys', 'activity', 'activities') $activityDump = Invoke-AdbText -Arguments @('-s', $Serial, 'shell', 'dumpsys', 'activity', 'activities')
$resumedActivity = Get-FirstMatchingLine -Text $activityDump -Pattern 'topResumedActivity=|mResumedActivity:' $resumedActivity = Get-FirstMatchingLine -Text $activityDump -Pattern 'topResumedActivity=|mResumedActivity:'
$processId = Invoke-AdbText -Arguments @('-s', $Serial, 'shell', 'pidof', $PackageName) -AllowEmpty $processId = Invoke-AdbText -Arguments @('-s', $Serial, 'shell', 'pidof', $PackageName) -AllowEmpty -AllowNonZero
$processRunning = -not [string]::IsNullOrWhiteSpace($processId)
$appForeground = $resumedActivity -match [regex]::Escape($PackageName)
$exitInfo = Invoke-AdbText -Arguments @('-s', $Serial, 'shell', 'dumpsys', 'activity', 'exit-info', $PackageName) $exitInfo = Invoke-AdbText -Arguments @('-s', $Serial, 'shell', 'dumpsys', 'activity', 'exit-info', $PackageName)
$crashOrAnrDetected = $exitInfo -match '(?m)reason=\d+\s+\((?:CRASH|CRASH_NATIVE|ANR)\)' $crashOrAnrDetected = $exitInfo -match '(?m)reason=\d+\s+\((?:CRASH|CRASH_NATIVE|ANR)\)'
@@ -179,17 +191,39 @@ $visibleTexts = @($uiDocument.SelectNodes('//node') |
$resourceIds = @($uiDocument.SelectNodes('//node') | $resourceIds = @($uiDocument.SelectNodes('//node') |
ForEach-Object { [string]$_.GetAttribute('resource-id') } | ForEach-Object { [string]$_.GetAttribute('resource-id') } |
Where-Object { -not [string]::IsNullOrWhiteSpace($_) }) Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
$uiPackages = @($uiDocument.SelectNodes('//node') |
ForEach-Object { [string]$_.GetAttribute('package') } |
Where-Object { -not [string]::IsNullOrWhiteSpace($_) } |
Select-Object -Unique)
$privacyTitleVisible = $resourceIds -contains "$PackageName`:id/tv_custom_privacy_title" $privacyTitleVisible = $resourceIds -contains "$PackageName`:id/tv_custom_privacy_title"
$privacyRejectVisible = $resourceIds -contains "$PackageName`:id/btn_custom_privacy_cancel" $privacyRejectVisible = $resourceIds -contains "$PackageName`:id/btn_custom_privacy_cancel"
$privacyConsentVisible = $resourceIds -contains "$PackageName`:id/btn_custom_privacy_sure" $privacyConsentVisible = $resourceIds -contains "$PackageName`:id/btn_custom_privacy_sure"
$loginLabel = -join @( $firstPrivacyTitle = ConvertFrom-CodePoints @(
[char]0x624B, 0x670D, 0x52A1, 0x534F, 0x8BAE, 0x548C, 0x9690, 0x79C1, 0x653F, 0x7B56
[char]0x673A,
[char]0x53F7,
[char]0x767B,
[char]0x5F55
) )
$secondPrivacyTitle = ConvertFrom-CodePoints @(0x786E, 0x8BA4, 0x63D0, 0x793A)
$firstRejectLabel = ConvertFrom-CodePoints @(0x6682, 0x4E0D, 0x540C, 0x610F)
$exitLabel = ConvertFrom-CodePoints @(0x9000, 0x51FA, 0x5E94, 0x7528)
$consentLabel = ConvertFrom-CodePoints @(0x540C, 0x610F, 0x5E76, 0x7EE7, 0x7EED)
$loginLabel = ConvertFrom-CodePoints @(0x624B, 0x673A, 0x53F7, 0x767B, 0x5F55)
$firstPrivacyTitleVisible = $visibleTexts -contains $firstPrivacyTitle
$secondPrivacyTitleVisible = $visibleTexts -contains $secondPrivacyTitle
$firstRejectLabelVisible = $visibleTexts -contains $firstRejectLabel
$exitLabelVisible = $visibleTexts -contains $exitLabel
$consentLabelVisible = $visibleTexts -contains $consentLabel
$loginVisible = $visibleTexts -contains $loginLabel $loginVisible = $visibleTexts -contains $loginLabel
$privacyDialogStage = if ($secondPrivacyTitleVisible -or $exitLabelVisible) {
'exit-confirmation'
}
elseif ($firstPrivacyTitleVisible -or $firstRejectLabelVisible) {
'first-choice'
}
elseif ($privacyTitleVisible -or $privacyRejectVisible -or $privacyConsentVisible) {
'unknown-privacy-dialog'
}
else {
'not-visible'
}
$permissionNames = @( $permissionNames = @(
'android.permission.CAMERA', 'android.permission.CAMERA',
@@ -248,12 +282,21 @@ $evidence = [ordered]@{
minSdkVersion = [int]$sdkMatch.Groups[2].Value minSdkVersion = [int]$sdkMatch.Groups[2].Value
targetSdkVersion = [int]$sdkMatch.Groups[3].Value targetSdkVersion = [int]$sdkMatch.Groups[3].Value
processId = $processId processId = $processId
processRunning = $processRunning
resumedActivity = $resumedActivity resumedActivity = $resumedActivity
foreground = $appForeground
} }
screen = [ordered]@{ screen = [ordered]@{
appUiVisible = $uiPackages -contains $PackageName
privacyDialogStage = $privacyDialogStage
privacyDialogTitleVisible = $privacyTitleVisible privacyDialogTitleVisible = $privacyTitleVisible
privacyRejectVisible = $privacyRejectVisible privacyRejectVisible = $privacyRejectVisible
privacyConsentVisible = $privacyConsentVisible privacyConsentVisible = $privacyConsentVisible
firstPrivacyTitleVisible = $firstPrivacyTitleVisible
secondPrivacyTitleVisible = $secondPrivacyTitleVisible
firstRejectLabelVisible = $firstRejectLabelVisible
exitLabelVisible = $exitLabelVisible
consentLabelVisible = $consentLabelVisible
loginVisible = $loginVisible loginVisible = $loginVisible
} }
permissions = $permissionStates permissions = $permissionStates
@@ -282,7 +325,11 @@ $markdown = @(
"- Device: $($device.manufacturer) $($device.model), Android $($device.androidRelease) / API $($device.apiLevel)", "- Device: $($device.manufacturer) $($device.model), Android $($device.androidRelease) / API $($device.apiLevel)",
"- App: $PackageName $($evidence.app.versionName) ($($evidence.app.versionCode)), target API $($evidence.app.targetSdkVersion)", "- App: $PackageName $($evidence.app.versionName) ($($evidence.app.versionCode)), target API $($evidence.app.targetSdkVersion)",
"- Resumed activity: $resumedActivity", "- Resumed activity: $resumedActivity",
"- Privacy dialog: title=$privacyTitleVisible, reject=$privacyRejectVisible, consent=$privacyConsentVisible", "- App process running: $processRunning",
"- App foreground: $appForeground",
"- Privacy dialog stage: $privacyDialogStage",
"- Privacy controls: title=$privacyTitleVisible, reject=$privacyRejectVisible, consent=$privacyConsentVisible",
"- Privacy labels: firstReject=$firstRejectLabelVisible, exit=$exitLabelVisible, consent=$consentLabelVisible",
"- Login visible: $loginVisible", "- Login visible: $loginVisible",
"- Historical crash or ANR found: $crashOrAnrDetected", "- Historical crash or ANR found: $crashOrAnrDetected",
'', '',
@@ -298,7 +345,8 @@ Write-Output "android_acceptance_evidence=$evidenceDirectory"
Write-Output "device=$Serial Android/$($device.apiLevel)" Write-Output "device=$Serial Android/$($device.apiLevel)"
Write-Output "app=$PackageName $($evidence.app.versionName) ($($evidence.app.versionCode)) targetSdk=$($evidence.app.targetSdkVersion)" Write-Output "app=$PackageName $($evidence.app.versionName) ($($evidence.app.versionCode)) targetSdk=$($evidence.app.targetSdkVersion)"
Write-Output "resumed_activity=$resumedActivity" Write-Output "resumed_activity=$resumedActivity"
Write-Output "privacy_dialog=title:$privacyTitleVisible reject:$privacyRejectVisible consent:$privacyConsentVisible login:$loginVisible" Write-Output "app_state=process:$processRunning foreground:$appForeground ui:$($uiPackages -contains $PackageName)"
Write-Output "privacy_dialog=stage:$privacyDialogStage title:$privacyTitleVisible reject:$privacyRejectVisible consent:$privacyConsentVisible firstRejectLabel:$firstRejectLabelVisible exitLabel:$exitLabelVisible login:$loginVisible"
Write-Output "historical_crash_or_anr=$crashOrAnrDetected" Write-Output "historical_crash_or_anr=$crashOrAnrDetected"
foreach ($permissionName in $permissionNames) { foreach ($permissionName in $permissionNames) {
Write-Output "permission_$permissionName=$($permissionStates[$permissionName])" Write-Output "permission_$permissionName=$($permissionStates[$permissionName])"
@@ -15,6 +15,11 @@ $requiredFragments = @(
"'android.permission.READ_MEDIA_IMAGES'", "'android.permission.READ_MEDIA_IMAGES'",
"'android.permission.READ_MEDIA_VIDEO'", "'android.permission.READ_MEDIA_VIDEO'",
"'read-only-current-state'", "'read-only-current-state'",
"'exit-confirmation'",
"'first-choice'",
'processRunning',
'appForeground',
'AllowNonZero',
"Join-Path `$projectRoot 'output'" "Join-Path `$projectRoot 'output'"
) )
foreach ($fragment in $requiredFragments) { foreach ($fragment in $requiredFragments) {