Back to Gsyvideoplayer

Compose / Java Demo 测试参考手册

doc/COMPOSE_TEST_PLAYBOOK.md

13.1.021.3 KB
Original Source

Compose / Java Demo 测试参考手册

用途:在 emulator-5554(1080×2400)上对 GSYVideoPlayer demo app 做真实回归测试时, 不再每次重新滚屏 + dump + find_xy。本手册沉淀了:

  1. MainActivity / ComposeDemoListActivity 的 demo 列表入口与定位策略
  2. 每个 demo 的 Activity 类名、是否自动起播、关键操作步骤、真起播判定信号
  3. 配套测试脚本入口与已知坑

维护人:每发现新 demo 或 demo 行为变更时同步更新本表。 最近一次回归:2026-05-20(I 轮,17 个 Compose demo + 3 个 Java demo 全 PASS)


0. 设备 / 工具约定

ADB 设备号emulator-5554
屏幕分辨率1080 × 2400adb shell wm size
App 包名com.example.gsyvideoplayer
主入口 Activity.MainActivity
Compose 列表入口.compose.ComposeDemoListActivity
启动主页adb -s emulator-5554 shell am start -n com.example.gsyvideoplayer/.MainActivity

配套脚本

脚本用途
/tmp/find_xy.py输入 ui.xml + 文本,输出该文本节点中心点 X Ytext="..."[^>]*?bounds="..." 不跨节点。
/tmp/real_test.sh X Y EXP LABELCompose demo 真起播脚本:clear logcat → tap → 8s → 校验 topResumed==EXP + logcat 信号 + back
/tmp/locate_and_test.sh "title" EXP LABEL在 ComposeDemoListActivity 上滚屏定位 title → 调 real_test.sh
/tmp/java_test.sh X Y EXP LABELJava demo 真起播脚本:进入后自动找 resource-id 含 start 的播放按钮

真起播判定信号矩阵(logcat -d)

内核路径onPreparedCURRENT_STATE_PLAYING渲染信号进度信号
IjkPlayer(默认)≥1≥1MEDIA_INFO_VIDEO_RENDERING_STARTNet speed:
EXO(PlayerFactory.setPlayManager(Exo2PlayerManager))≥1≥1videoSizeChanged / videoWidth:无 Net speed
Audio(raw mp3)≥1≥1
Java demo(callback 设 null)可能 0≥1MEDIA_INFO_VIDEO_RENDERING_STARTNet speed:

通用统一过滤式(与 real_test.sh 一致):

bash
PREP=$(echo "$LOG"   | grep -c   "onPrepared")
PLAY=$(echo "$LOG"   | grep -c   "CURRENT_STATE_PLAYING")
RENDER=$(echo "$LOG" | grep -cE  "MEDIA_INFO_VIDEO_RENDERING_START|videoSizeChanged|videoWidth:")
NET=$(echo "$LOG"    | grep -c   "Net speed:")

1. MainActivity(Java demo 入口)

重要:item text 显示时被系统大写化("打开Video" → "打开VIDEO","List列表" → "LIST列表")。 find_xy.py 必须用大写 keyword 才能匹中。

冷启动 MainActivity,任务 ID 每次重启会变,但 demo 项 X 都是 357,cy 列出的是首次 dump 的中心 Y(如卡片高度无改动则可直接复用)。

第一屏(顶部,adb shell am start 后立刻可见)

Demo 文本跳转 Activity(X,Y)自动起播备注
简单播放SimplePlayer.SimpleActivity(357, 388)无导航 bar
打开VIDEOPlayActivity(357, 567)经典 demo,callback=null 不打 onPrepared 但 render+net 充足
带控制DEMODetailControlActivity(357, 746)
完成保留最后一帧KeepLastFrameDemoActivity(357, 925)
透明DetailTransparentActivity(357, 1104)
无UI界面PlayEmptyControlActivity(357, 1283)
滤镜DetailFilterActivity(357, 1462)GLSL 滤镜,验证 GSYVideoType GL Surface 不被污染
带广告DetailADPlayer(357, 1641)
带广告2DetailADPlayer2(357, 1820)
无缝切换SwitchListVideoActivity(357, 1999)列表,需点列表项
LIST列表ListVideoActivity(357, 2178)是(列表自动起播第一项)
LIST全屏和小窗口列表ListVideo2Activity(357, 2347)

滚屏 1 后(按 swipe 540 1900 540 700 500 × 3)

Demo 文本跳转 Activity(X,Y)
多任务支持RecyclerViewActivity(357, 345)
列表详情切换RecyclerView2Activity(357, 524)
列表带广告模式ListADVideoActivity(357, 703)
硬解码支持RecyclerView3Activity(357, 882)
缓存下载支持DetailDownloadPlayer(357, 1061)
EXO特有缓存下载支持DetailDownloadExoPlayer(357, 1240)
普通 ACTIVITYDetailNormalActivityPlayer(357, 1419)
自定义EXODetailExoListPlayer(357, 1598)
EXO自适应清晰度ExoAdaptiveTrackActivity(357, 1777)
自定义EXO支持字幕ExoSubtitleActivity(357, 1956)
通用字幕非EXOSubtitleDetailPlayer(357, 2135)
音频AudioDetailPlayer(357, 2314)

滚屏 2 后(再 swipe × 3)

Demo 文本跳转 Activity(X,Y)
缓存下载支持DetailDownloadPlayer(357, 263)
EXO特有缓存下载支持DetailDownloadExoPlayer(357, 442)
普通 ACTIVITYDetailNormalActivityPlayer(357, 621)
自定义EXODetailExoListPlayer(357, 800)
EXO自适应清晰度ExoAdaptiveTrackActivity(357, 979)
自定义EXO支持字幕ExoSubtitleActivity(357, 1158)
通用字幕非EXOSubtitleDetailPlayer(357, 1337)
音频AudioDetailPlayer(357, 1516)
IJK 内核KernelDemoActivity(357, 1695)
PROXY 缓存ProxyCacheActivity(357, 1874)
CLEAR CACHE(按钮)(357, 2053)
COMPOSE DEMO 大全.compose.ComposeDemoListActivity(357, 2232)

快捷:MainActivity 任意位置后滚 2 次到底,COMPOSE DEMO 大全 永远在 (357, 2232) 附近


2. ComposeDemoListActivity(Compose demo 列表,25 个

列表 LazyColumn,卡片高度随 subtitle 长度变化(多行卡 ≈ 296 px,单行卡 ≈ 178 px), 因此绝对 Y 坐标不稳定。推荐用 locate_and_test.sh 滚屏定位。

但首屏 / 第二屏 demo 在不滚动时坐标稳定,列在表里以备 emergency 直接 tap。

25 个 demo 完整索引(源:ComposeDemoListActivity.kt#L71-L191

#TitleActivity自动起播内核已知操作
0P0 · Wrapper 基础BasicWrapperActivity按钮交互("开始播放" @ 178,2074)IjkAndroidView 包装;setStartAfterPrepared(true) 但需先点 startPlayLogic
1P0 · Native 详情DetailNativeActivityIjk经典
2P0 · Native 完整控件层FullFeatureNativeActivityIjk自绘控件
3P1 · Native 列表ListPlayNativeActivityIjkautoPlay=false,需点列表项
4P1 · Native 切换 URLSwitchUrlActivityIjk
5P1 · Native 多窗口MultiWindowActivityIjkautoPlay=false,3 Surface 互斥,需点窗口
6P1 · Native 自动连播AutoPlayListActivityIjk段间 release+attach
7P1 · Native 列表 + 内层全屏ListWithFullscreenActivity列表型,需点项Ijk
8P5 · Native 滤镜DetailFilterComposeActivityIjkwithHost 注入 setEffectFilter
9P5 · Native 缓存 / 下载CacheDownloadComposeActivityIjk + ProxyderivedStateOf→remember 已修复
10P5 · Native 字幕SubtitleComposeActivity强制 Ijk(PlayerFactory.setPlayManager(IjkPlayerManager))
11P5 · Native Seamless 切换SwitchSeamlessComposeActivity列表型,需点 item1 起播Ijkcontroller 跨页复用
12P5 · Native 前贴片广告AdInListComposeActivityIjkAD→AutoComplete→正片,buffer 较慢需 16s
13P5 · Native Compose 自绘弹幕DanmakuComposeActivityIjkCanvas + textMeasurer
14P5 · Native EXO 多源切换ExoSwitchSourceComposeActivityEXO(PlayerFactory.setPlayManager(Exo2PlayerManager))onDestroy 反射还原 IjkPlayerManager(P0 防回归核心
15P5 · Wrapper 真并行多窗口MultiWindowParallelComposeActivity列表型Ijk + CustomManager
16P5-2 · 竖屏短视频 (VerticalPager)VerticalShortVideoComposeActivityIjkVerticalPager 单 controller
17P5-2 · 悬浮窗(画中画)FloatingWindowComposeActivity按钮交互Ijk需 SYSTEM_ALERT_WINDOW 权限
18P5-2 · 多类型列表MoreTypeComposeActivity列表型Ijk
19P5-2 · 图文混排(视频 + WebView)WebDetailComposeActivityIjkWebView 共存
20P5-2 · 纯音频播放AudioOnlyComposeActivity按钮交互Ijk(audio)raw://test33.mp3,进页面后点"播放"按钮;信号只有 prep+play 无 render
21P5-2 · 自定义 URL / 本地文件LocalFileComposeActivity按钮交互Ijk"▶ 起播"按钮,"Release"软释放后可再次起播(本次拆分修复点)
22P5-2 · MediaCodec 硬解切换MediaCodecComposeActivity按钮交互Ijk + MediaCodec"▶ 起播"按钮 + "切换硬解 + 重 setUp"
23P5-2 · 自定义主题 ControlsCustomControlsThemeComposeActivityIjkSlider seek + 主题切换
24P5-2 · 自定义主题 Controls(重复行?看源码确认)同上

实际是 24 个 entries(index 0..23),上表 #24 重复行可忽略。

滚屏首屏稳定坐标(仅参考,重启后可能错位)

#Title(X,Y)
0P0 · Wrapper 基础(257, 419)
1P0 · Native 详情(237, 715)
2P0 · Native 完整控件层(301, 1011)
3P1 · Native 列表(237, 1307)
4P1 · Native 切换 URL(281, 1603)
5P1 · Native 多窗口(259, 1899)
6P1 · Native 自动连播(280, 2195)

推荐定位方式

bash
# 通用:滚屏直至 dump 包含 title 文本
bash /tmp/locate_and_test.sh "P5 · Native EXO 多源切换" "ExoSwitchSourceComposeActivity" "I-EXO"

3. 已知坑(Compose 端)

位置处理方式
controller.release() 单调置 released=true 让控制器一次性失效GSYPlayerController.kt#L703-L756I 轮拆为 release() 软释放 + dispose() 永久销毁。已 commit 74c8a0eb
EXO demo 退出未还原 PlayerFactory 会污染 Java 端ExoSwitchSourceComposeActivity.kt#L66-L72onDestroy 反射写回 IjkPlayerManager,回归已验证
Audio demo 多次 release 触发崩溃AudioOnlyComposeActivityH 轮已删重复 release
Cache demo derivedStateOf 频繁重组CacheDownloadComposeActivity改为 remember
Slider 拖拽路径GSYDefaultControls.kt#L144dragging = v.coerceIn(0f, 1f) 边界已校验
zsh 不 word-split unquoted varsshell 调用awk '{print $1}' / $2 拆 X Y 再传
python regex [^/]*bounds= 跨节点失配find_xy.py[^>]*?
swipe 速率 100ms 不生效shell用 400-500ms

4. 标准回归 Checklist(下次执行直接抄)

bash
# 0. 重启 emulator app
adb -s emulator-5554 shell am force-stop com.example.gsyvideoplayer
adb -s emulator-5554 shell am start    -n com.example.gsyvideoplayer/.MainActivity

# 1. Java demo 基线(独立冷启动)
bash /tmp/java_test.sh 357 567  PlayActivity        JAVA-Play
bash /tmp/java_test.sh 357 1462 DetailFilterActivity JAVA-Filter
bash /tmp/java_test.sh 357 2178 ListVideoActivity   JAVA-List

# 2. 进 Compose demo 大全
adb -s emulator-5554 shell am start -n com.example.gsyvideoplayer/.compose.ComposeDemoListActivity

# 3. 自动起播 demo(17 个)按 locate_and_test 顺序跑
bash /tmp/locate_and_test.sh "P0 · Native 详情"            DetailNativeActivity              D2
bash /tmp/locate_and_test.sh "P5 · Native 字幕"            SubtitleComposeActivity           Sub
bash /tmp/locate_and_test.sh "P5 · Native EXO 多源切换"    ExoSwitchSourceComposeActivity    EXO
bash /tmp/locate_and_test.sh "P0 · Native 详情"            DetailNativeActivity              D2-after-EXO   # P0 防回归
bash /tmp/locate_and_test.sh "P5 · Native 滤镜"            DetailFilterComposeActivity       Filter
bash /tmp/locate_and_test.sh "P5 · Native 缓存 / 下载"     CacheDownloadComposeActivity      Cache
bash /tmp/locate_and_test.sh "P0 · Native 完整控件层"      FullFeatureNativeActivity         Full
bash /tmp/locate_and_test.sh "P0 · Wrapper 基础"           BasicWrapperActivity              Wrap
bash /tmp/locate_and_test.sh "P1 · Native 切换 URL"        SwitchUrlActivity                 SwitchUrl
bash /tmp/locate_and_test.sh "P5 · Native 前贴片广告"      AdInListComposeActivity           AD          # 16s buffer
bash /tmp/locate_and_test.sh "P5 · Native Compose 自绘弹幕" DanmakuComposeActivity            Danmaku
bash /tmp/locate_and_test.sh "P5-2 · 竖屏短视频 (VerticalPager)" VerticalShortVideoComposeActivity Vertical
bash /tmp/locate_and_test.sh "P5-2 · 图文混排(视频 + WebView)" WebDetailComposeActivity      Web
bash /tmp/locate_and_test.sh "P5-2 · 自定义主题 Controls"  CustomControlsThemeComposeActivity Theme

# 4. 手动按钮 demo(5 个):进入页面后找 "▶ 起播" / "播放" 按钮,本地脚本暂未自动化
#    Audio / LocalFile / MediaCodec / Float / Seamless(item1)
#    Audio:prep+play 即 PASS(无 render/net)
#    LocalFile:▶起播 → Release → ▶起播(验证 release/dispose 拆分)
#    MediaCodec:▶起播 → 切换硬解 + 重 setUp
#    Float:需开 SYSTEM_ALERT_WINDOW 权限

# 5. 列表型 demo(5 个):进页面后点 item1
#    List / MultiWindow / AutoPlay / ListFull / MoreType / MultiPara

# 6. 整盘 crash check
adb -s emulator-5554 logcat -d -b crash | grep -c "FATAL EXCEPTION"   # 应 == 0
adb -s emulator-5554 logcat -d         | grep -c "ANR in"             # 应 == 0

PASS 判定阈值

Demo 类别PASS 条件
普通 Ijk 自动起播prep ≥ 1 && play ≥ 1 && render ≥ 1 && net ≥ 1
EXO 自动起播prep ≥ 1 && play ≥ 1 && render ≥ 1(无 net)
Audioprep ≥ 1 && play ≥ 1
Java demo(callback=null)play ≥ 1 && render ≥ 1 && net ≥ 1
全局FATAL EXCEPTION == 0 && ANR == 0

5. 历史回归记录

轮次日期范围结果
H2026-05-19P0 修复release/dispose 设计 bug 发现
I2026-05-2017 Compose + 3 Java demo + lib 修复全 PASS, 0 crash 0 ANR. commit 74c8a0eb
I-22026-05-2013 Compose demo (Wrap/D2/FullFeat/SwitchUrl/EXO/D2-after-EXO/Filter/Cache/Subtitle/AdInList/Danmaku/Vertical/Web/Theme)全 PASS, 0 crash 0 ANR. emulator 切回 -gpu host 后 dump 正常

I-2 轮明细(2026-05-20)

DemoActivity信号状态
Wrap(手动开始播放)BasicWrapperActivityprep=1 play=1 render=9 net=16PASS
D2DetailNativeActivityprep=1 play=2 render=9 net=16PASS
FullFeatureFullFeatureNativeActivityprep=1 play=1 render=9 net=15PASS
SwitchUrlSwitchUrlActivityprep=1 play=2 render=9 net=16PASS
EXOExoSwitchSourceComposeActivityprep=1 play=2 render=9 net=0(EXO 不打 Net speed)PASS
D2-after-EXODetailNativeActivityprep=1 play=1 render=5 net=3 Ijk=4 Exo=0P0 防回归 PASS
FilterDetailFilterComposeActivityprep=1 play=1 render=9 net=15PASS
CacheCacheDownloadComposeActivityprep=1 play=1 render=9 net=16PASS
SubtitleSubtitleComposeActivityprep=1 play=1 render=9 net=13PASS
AdInListAdInListComposeActivityprep=1 play=2 render=9 net=5PASS(16s wait)
DanmakuDanmakuComposeActivityprep=1 play=1 render=9 net=15PASS
VerticalVerticalShortVideoComposeActivityprep=1 play=1 render=9 net=16PASS
WebWebDetailComposeActivityprep=1 play=3 render=13 net=3PASS
ThemeCustomControlsThemeComposeActivityprep=1 play=2 render=9 net=15PASS

本轮新发现坑:emulator AVD Pixel_7 在 swiftshader_indirect 模式下渲染失败(屏幕全黑、dump null root)。修复emulator -avd Pixel_7 -no-snapshot-save -no-boot-anim -gpu host 启动后恢复正常。 PLAYBOOK 修正:P0 · Wrapper 基础不是自动起播,需点列底部"开始播放"按钮(屏幕滚到最底,X≈178 Y≈2074)。表格中 #0 的"自动起播=是"已纠正(改为 builder.setStartAfterPrepared 配合按钮触发)。