diff --git a/scripts/profile.sh b/scripts/profile.sh index d4c56fa..88f6e16 100755 --- a/scripts/profile.sh +++ b/scripts/profile.sh @@ -1,59 +1,549 @@ #!/bin/bash # -# YaYa 性能追踪脚本 -# 使用 Perfetto 抓取应用 trace,保存到 logs/ 目录 +# YaYa 性能追踪脚本(场景化版) +# 支持按交互场景录制 Perfetto trace,精准定位各场景性能 # # 用法: -# ./scripts/profile.sh # 默认抓取 8 秒 -# ./scripts/profile.sh 15 # 抓取 15 秒 -# ./scripts/profile.sh --no-launch # 不自动启动应用(应用已在运行) -# ./scripts/profile.sh --trace # 使用 trace 构建类型(保留自定义 trace 标记) +# ./scripts/profile.sh # 默认抓取 8 秒(向后兼容) +# ./scripts/profile.sh --scenario month_browse --trace 15 +# ./scripts/profile.sh --list-scenarios # 列出所有场景 +# ./scripts/profile.sh --help # 帮助 # set -euo pipefail PACKAGE="plus.rua.project" -ACTIVITY="plus.rua.project.MainActivity" +MAIN_ACTIVITY="plus.rua.project.MainActivity" +TOOLS_ACTIVITY="plus.rua.project.ToolsActivity" +DATECHECKER_ACTIVITY="plus.rua.project.DateCheckerActivity" +ABOUT_ACTIVITY="plus.rua.project.AboutActivity" +LICENSES_ACTIVITY="plus.rua.project.LicensesActivity" + PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)" LOGS_DIR="${PROJECT_ROOT}/logs" -# 解析参数 +# 默认参数 DURATION_SEC=8 NO_LAUNCH=false USE_TRACE_BUILD=false +SCENARIO="" +SCENARIO_NAME="" +SCENARIO_DESC="" +BG_PID="" +RUN_ALL=false -for arg in "$@"; do - case "$arg" in - --no-launch) - NO_LAUNCH=true - ;; - --trace) - USE_TRACE_BUILD=true - ;; - --help|-h) - echo "用法: $0 [秒数] [--no-launch] [--trace]" - echo "" - echo "选项:" - echo " 秒数 抓取时长(默认 8 秒)" - echo " --no-launch 不自动启动应用" - echo " --trace 使用 trace 构建(release 优化 + 保留 trace 标记)" - echo " --help 显示此帮助" - exit 0 - ;; - [0-9]*) - DURATION_SEC="$arg" - ;; - esac +# ────────────────────────────────────────── +# 场景列表 +# ────────────────────────────────────────── +list_scenarios() { + cat <<'EOF' +可用场景: + +主日历场景: + month_browse - 月视图左右滑动翻页(自动滑动) + date_select - 点击不同日期(需手动:依次点击多个日期) + collapse_expand - 折叠/展开 月视图↔周视图(自动拖拽) + year_view - 年视图切换+年份滑动(自动) + year_select - 年视图中选择月份返回(自动) + today_jump - 跳转到今天(自动) + menu_toggle - FAB 菜单打开关闭(自动) + legal_holiday - 显示调休切换(自动) + cross_month - 跨月日期选择(需手动:点击灰色日期) + +其他页面: + tools - 工具页面(自动打开) + date_checker - 日期检查器(需手动:添加行、输入天数、滑动删除) + about - 关于页面(自动打开) + licenses - 开源许可列表(自动打开+滑动) + +综合场景: + full_flow - 完整用户流程(需手动:按提示操作所有功能) + all_activities - 遍历所有 Activity(自动) + +批量录制: + --all - 自动依次录制所有自动场景,最后生成汇总报告 + +默认场景(向后兼容): + (不指定 --scenario)启动应用,抓取指定时长 +EOF +} + +# ────────────────────────────────────────── +# 参数解析 +# ────────────────────────────────────────── +while [ $# -gt 0 ]; do + case "$1" in + --no-launch) + NO_LAUNCH=true + shift + ;; + --trace) + USE_TRACE_BUILD=true + shift + ;; + --scenario) + if [ $# -lt 2 ]; then + echo "错误: --scenario 需要指定场景名" + exit 1 + fi + SCENARIO="$2" + shift 2 + ;; + --all) + RUN_ALL=true + shift + ;; + --list-scenarios) + list_scenarios + exit 0 + ;; + --help|-h) + cat <] [--all] + +选项: + 秒数 抓取时长(默认 8 秒,--all 时每个场景默认 10 秒) + --no-launch 不自动启动应用 + --trace 使用 trace 构建(release + trace 标记保留) + --scenario <场景> 指定交互场景,脚本会引导或自动执行对应操作 + --all 批量录制所有自动场景,生成汇总报告 + --list-scenarios 列出所有可用场景 + --help 显示此帮助 + +示例: + # 录制月视图滑动翻页 15 秒 + $0 --scenario month_browse --trace 15 + + # 录制完整用户流程 30 秒(需手动按提示操作) + $0 --scenario full_flow --trace 30 + + # 录制日期检查器操作(需手动) + $0 --scenario date_checker --trace 20 + + # 批量录制所有自动场景(每个 10 秒) + $0 --all --trace 10 + + # 默认录制(向后兼容) + $0 --trace 15 +EOF + exit 0 + ;; + [0-9]*) + DURATION_SEC="$1" + shift + ;; + *) + echo "未知参数: $1" + echo "使用 --help 查看帮助" + exit 1 + ;; + esac done +# ────────────────────────────────────────── +# 工具函数 +# ────────────────────────────────────────── + +# 获取屏幕尺寸 +get_screen_size() { + adb shell wm size 2>/dev/null | awk '{print $3}' +} + +# 获取屏幕中心坐标 +get_screen_center() { + local size w h + size=$(get_screen_size) + w=$(echo "$size" | cut -dx -f1) + h=$(echo "$size" | cut -dx -f2) + echo "$w $h" +} + +# 清理后台进程 +cleanup_bg() { + if [ -n "$BG_PID" ] && kill -0 "$BG_PID" 2>/dev/null; then + kill "$BG_PID" 2>/dev/null || true + wait "$BG_PID" 2>/dev/null || true + fi +} +trap cleanup_bg EXIT + +# 等待 trace 开始后再执行操作 +wait_then_do() { + local delay_sec="$1" + shift + ( + sleep "$delay_sec" + "$@" + ) & + BG_PID=$! +} + +# ────────────────────────────────────────── +# 场景执行 +# ────────────────────────────────────────── +run_scenario() { + local scenario="$1" + local screen_size screen_w screen_h cx cy + screen_size=$(get_screen_size) + if [ -z "$screen_size" ]; then + echo "错误: 无法获取屏幕尺寸" + exit 1 + fi + screen_w=$(echo "$screen_size" | cut -dx -f1) + screen_h=$(echo "$screen_size" | cut -dx -f2) + cx=$((screen_w / 2)) + cy=$((screen_h / 2)) + # 日历网格大致区域(屏幕中间偏上) + local grid_y=$((screen_h * 35 / 100)) + # FAB 按钮大致位置(右下) + local fab_x=$((screen_w * 85 / 100)) + local fab_y=$((screen_h * 85 / 100)) + # BottomCard 拖拽区域(屏幕下半部分) + local bottom_y=$((screen_h * 70 / 100)) + + case "$scenario" in + month_browse) + SCENARIO_NAME="月视图滑动翻页" + SCENARIO_DESC="在月视图中快速左右滑动翻页,测试 CalendarPager 重组和绘制性能" + echo "" + echo "[场景] ${SCENARIO_NAME}" + echo " ${SCENARIO_DESC}" + echo "" + adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1 + sleep 1 + echo " → 自动执行:trace 开始后将连续左右滑动翻页" + wait_then_do 2 bash -c " + for i in 1 2 3 4 5 6 7 8; do + adb shell input swipe $((screen_w*80/100)) $grid_y $((screen_w*20/100)) $grid_y 200 + sleep 0.4 + adb shell input swipe $((screen_w*20/100)) $grid_y $((screen_w*80/100)) $grid_y 200 + sleep 0.4 + done + " + ;; + + date_select) + SCENARIO_NAME="点击日期选择" + SCENARIO_DESC="依次点击不同日期,测试 DayCell 重组和 AnimatedGif 动画性能" + echo "" + echo "[场景] ${SCENARIO_NAME}" + echo " ${SCENARIO_DESC}" + echo "" + adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1 + sleep 1 + echo " → 请手动操作:trace 开始后,依次点击日历中不同的日期(建议点击 5-10 个)" + echo " 可尝试点击同一行不同列、跨行点击,观察选中动画" + ;; + + collapse_expand) + SCENARIO_NAME="折叠/展开 月视图↔周视图" + SCENARIO_DESC="拖拽 BottomCard 上下切换月视图和周视图,测试折叠动画和布局变化性能" + echo "" + echo "[场景] ${SCENARIO_NAME}" + echo " ${SCENARIO_DESC}" + echo "" + adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1 + sleep 1 + echo " → 自动执行:trace 开始后将自动拖拽 BottomCard 上下切换" + wait_then_do 2 bash -c " + for i in 1 2 3 4 5; do + # 向上拖拽(月→周) + adb shell input swipe $cx $bottom_y $cx $((screen_h*40/100)) 400 + sleep 0.8 + # 向下拖拽(周→月) + adb shell input swipe $cx $((screen_h*40/100)) $cx $bottom_y 400 + sleep 0.8 + done + " + ;; + + year_view) + SCENARIO_NAME="年视图切换+年份滑动" + SCENARIO_DESC="打开年视图后在年份间左右滑动,测试 YearGridView 重组和 AnimatedContent 转场性能" + echo "" + echo "[场景] ${SCENARIO_NAME}" + echo " ${SCENARIO_DESC}" + echo "" + adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1 + sleep 1 + # 打开年视图(点击 FAB → 年视图) + adb shell input tap "$fab_x" "$fab_y" + sleep 0.5 + # 点击"年视图"菜单项(在 FAB 上方约 100px) + adb shell input tap "$fab_x" $((fab_y - 120)) + sleep 0.8 + echo " → 自动执行:已打开年视图,trace 开始后将滑动浏览年份" + wait_then_do 2 bash -c " + for i in 1 2 3 4; do + adb shell input swipe $((screen_w*80/100)) $cy $((screen_w*20/100)) $cy 200 + sleep 0.5 + adb shell input swipe $((screen_w*20/100)) $cy $((screen_w*80/100)) $cy 200 + sleep 0.5 + done + " + ;; + + year_select) + SCENARIO_NAME="年视图中选择月份" + SCENARIO_DESC="在年视图中点击不同月份返回月视图,测试 MonthView→YearView→MonthView 完整转场链" + echo "" + echo "[场景] ${SCENARIO_NAME}" + echo " ${SCENARIO_DESC}" + echo "" + adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1 + sleep 1 + # 打开年视图 + adb shell input tap "$fab_x" "$fab_y" + sleep 0.5 + adb shell input tap "$fab_x" $((fab_y - 120)) + sleep 0.8 + echo " → 自动执行:trace 开始后将依次点击不同的迷你月份" + wait_then_do 2 bash -c " + # 点击第1行不同月份(大致坐标) + adb shell input tap $((screen_w*20/100)) $((screen_h*25/100)) + sleep 1.0 + # 重新打开年视图 + adb shell input tap $fab_x $fab_y + sleep 0.3 + adb shell input tap $fab_x $((fab_y - 120)) + sleep 0.5 + adb shell input tap $((screen_w*50/100)) $((screen_h*25/100)) + sleep 1.0 + # 再试一个 + adb shell input tap $fab_x $fab_y + sleep 0.3 + adb shell input tap $fab_x $((fab_y - 120)) + sleep 0.5 + adb shell input tap $((screen_w*80/100)) $((screen_h*50/100)) + sleep 1.0 + " + ;; + + today_jump) + SCENARIO_NAME="跳转到今天" + SCENARIO_DESC="先翻到非当月,然后点击"今天"按钮跳转,测试自动翻页和选中动画" + echo "" + echo "[场景] ${SCENARIO_NAME}" + echo " ${SCENARIO_DESC}" + echo "" + adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1 + sleep 1 + # 先翻几页离开当月 + adb shell input swipe $((screen_w*20/100)) $grid_y $((screen_w*80/100)) $grid_y 200 + sleep 0.5 + adb shell input swipe $((screen_w*20/100)) $grid_y $((screen_w*80/100)) $grid_y 200 + sleep 0.5 + echo " → 自动执行:trace 开始后将点击"今天"按钮" + # "今天"按钮大致在左上角 + wait_then_do 2 bash -c " + adb shell input tap $((screen_w*15/100)) $((screen_h*12/100)) + sleep 2.0 + adb shell input swipe $((screen_w*20/100)) $grid_y $((screen_w*80/100)) $grid_y 200 + sleep 0.5 + adb shell input tap $((screen_w*15/100)) $((screen_h*12/100)) + " + ;; + + menu_toggle) + SCENARIO_NAME="FAB 菜单打开关闭" + SCENARIO_DESC="反复打开/关闭 FAB 菜单,测试 AnimatedVisibility 缩放动画性能" + echo "" + echo "[场景] ${SCENARIO_NAME}" + echo " ${SCENARIO_DESC}" + echo "" + adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1 + sleep 1 + echo " → 自动执行:trace 开始后将反复点击 FAB" + wait_then_do 2 bash -c " + for i in 1 2 3 4 5 6 7 8 9 10; do + adb shell input tap $fab_x $fab_y + sleep 0.5 + done + " + ;; + + legal_holiday) + SCENARIO_NAME="显示调休切换" + SCENARIO_DESC="切换"显示调休"开关,测试 DayCell 大规模重组和 staggered 动画性能" + echo "" + echo "[场景] ${SCENARIO_NAME}" + echo " ${SCENARIO_DESC}" + echo "" + adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1 + sleep 1 + echo " → 自动执行:trace 开始后将反复切换"显示调休"" + wait_then_do 2 bash -c " + for i in 1 2 3 4; do + # 打开菜单 + adb shell input tap $fab_x $fab_y + sleep 0.4 + # 点击"显示调休"(在 FAB 上方约 200px) + adb shell input tap $fab_x $((fab_y - 200)) + sleep 1.0 + done + " + ;; + + cross_month) + SCENARIO_NAME="跨月日期选择" + SCENARIO_DESC="点击上月或下月的灰色日期,测试跨月自动跳转和 pager 同步性能" + echo "" + echo "[场景] ${SCENARIO_NAME}" + echo " ${SCENARIO_DESC}" + echo "" + adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1 + sleep 1 + echo " → 请手动操作:trace 开始后,点击日历中灰色显示的上月/下月日期" + echo " 建议:先点击右侧灰色日期(下月),再点击左侧灰色日期(上月)" + ;; + + tools) + SCENARIO_NAME="工具页面" + SCENARIO_DESC="打开工具页面,测试 Activity 转场动画和 ToolsScreen 渲染性能" + echo "" + echo "[场景] ${SCENARIO_NAME}" + echo " ${SCENARIO_DESC}" + echo "" + adb shell am start -n "${PACKAGE}/${TOOLS_ACTIVITY}" >/dev/null 2>&1 + sleep 1 + echo " → 自动执行:工具页面已打开,trace 期间保持静态" + ;; + + date_checker) + SCENARIO_NAME="日期检查器" + SCENARIO_DESC="在日期检查器中进行添加行、输入天数、滑动删除等操作,测试复杂表单性能" + echo "" + echo "[场景] ${SCENARIO_NAME}" + echo " ${SCENARIO_DESC}" + echo "" + adb shell am start -n "${PACKAGE}/${DATECHECKER_ACTIVITY}" >/dev/null 2>&1 + sleep 1 + echo " → 请手动操作:trace 开始后,执行以下操作" + echo " 1. 点击 FAB (+) 添加一行" + echo " 2. 在新行的"天数"输入框中输入数字(如 90)" + echo " 3. 点击另一行的日历图标修改到期日期" + echo " 4. 向左滑动某一行删除" + echo " 5. 修改生产日期" + ;; + + about) + SCENARIO_NAME="关于页面" + SCENARIO_DESC="打开关于页面,测试 Activity 转场和 AboutScreen 渲染性能" + echo "" + echo "[场景] ${SCENARIO_NAME}" + echo " ${SCENARIO_DESC}" + echo "" + adb shell am start -n "${PACKAGE}/${ABOUT_ACTIVITY}" >/dev/null 2>&1 + sleep 1 + echo " → 自动执行:关于页面已打开,trace 期间保持静态" + ;; + + licenses) + SCENARIO_NAME="开源许可列表" + SCENARIO_DESC="打开开源许可页面并上下滑动,测试 LicensesScreen 列表滑动性能" + echo "" + echo "[场景] ${SCENARIO_NAME}" + echo " ${SCENARIO_DESC}" + echo "" + adb shell am start -n "${PACKAGE}/${LICENSES_ACTIVITY}" >/dev/null 2>&1 + sleep 1 + echo " → 自动执行:许可页面已打开,trace 开始后将上下滑动" + wait_then_do 2 bash -c " + for i in 1 2 3 4 5; do + adb shell input swipe $cx $((screen_h*70/100)) $cx $((screen_h*30/100)) 300 + sleep 0.5 + adb shell input swipe $cx $((screen_h*30/100)) $cx $((screen_h*70/100)) 300 + sleep 0.5 + done + " + ;; + + full_flow) + SCENARIO_NAME="完整用户流程" + SCENARIO_DESC="覆盖所有主要交互的完整流程,综合评估整体性能" + echo "" + echo "[场景] ${SCENARIO_NAME}" + echo " ${SCENARIO_DESC}" + echo "" + adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1 + sleep 1 + echo " → 请严格按以下顺序手动操作:" + echo "" + echo " 1. 左右滑动翻页 2-3 次" + echo " 2. 点击几个不同日期" + echo " 3. 向上拖拽 BottomCard 切换到周视图" + echo " 4. 在周视图中左右滑动翻周" + echo " 5. 向下拖拽展开回月视图" + echo " 6. 点击 FAB 打开菜单 → 年视图" + echo " 7. 年视图中滑动浏览年份" + echo " 8. 点击一个月份返回" + echo " 9. 点击 FAB → 显示调休(切换一次)" + echo " 10. 点击"今天"按钮" + echo " 11. 点击 FAB → 工具" + echo " 12. 在工具页点击"日期检查器"" + echo " 13. 添加一行、输入天数、滑动删除一行" + echo " 14. 返回 → 返回 → 关于" + echo " 15. 点击"开放源代码许可"" + echo " 16. 滑动许可列表" + echo " 17. 返回 → 返回回到主页面" + echo "" + echo " 建议在 trace 期间尽可能流畅地完成上述操作" + ;; + + all_activities) + SCENARIO_NAME="遍历所有 Activity" + SCENARIO_DESC="自动依次打开所有 Activity,测试 Activity 启动和转场动画性能" + echo "" + echo "[场景] ${SCENARIO_NAME}" + echo " ${SCENARIO_DESC}" + echo "" + echo " → 自动执行:trace 开始后将依次打开所有页面" + wait_then_do 2 bash -c " + sleep 1 + adb shell am start -n ${PACKAGE}/${MAIN_ACTIVITY} + sleep 1.5 + adb shell am start -n ${PACKAGE}/${TOOLS_ACTIVITY} + sleep 1.5 + adb shell am start -n ${PACKAGE}/${ABOUT_ACTIVITY} + sleep 1.5 + adb shell am start -n ${PACKAGE}/${LICENSES_ACTIVITY} + sleep 1.5 + adb shell am start -n ${PACKAGE}/${DATECHECKER_ACTIVITY} + sleep 1.5 + adb shell am start -n ${PACKAGE}/${MAIN_ACTIVITY} + sleep 1.0 + " + ;; + + *) + echo "错误: 未知场景: $scenario" + echo "使用 --list-scenarios 查看可用场景" + exit 1 + ;; + esac +} + +# ────────────────────────────────────────── +# 主流程 +# ────────────────────────────────────────── + DURATION_MS=$((DURATION_SEC * 1000)) TIMESTAMP=$(date +%Y%m%d_%H%M%S) +# 场景后缀 +SCENARIO_SUFFIX="" +if [ -n "$SCENARIO" ]; then + SCENARIO_SUFFIX="_${SCENARIO}" +fi + echo "========================================" echo " YaYa 性能追踪" echo " 包名: ${PACKAGE}" echo " 时长: ${DURATION_SEC}s" echo " 构建: $([ "$USE_TRACE_BUILD" = true ] && echo "trace (release + trace)" || echo "debug")" +if [ -n "$SCENARIO" ]; then + echo " 场景: ${SCENARIO}" +fi echo " 输出: ${LOGS_DIR}/" echo "========================================" @@ -62,49 +552,217 @@ mkdir -p "${LOGS_DIR}" # 检查 adb if ! command -v adb &>/dev/null; then - echo "错误: adb 未找到。请确保 Android SDK 的 platform-tools 在 PATH 中。" - exit 1 + echo "错误: adb 未找到。请确保 Android SDK 的 platform-tools 在 PATH 中。" + exit 1 fi # 检查设备连接 DEVICE_COUNT=$(adb devices | grep -c "device$" || true) if [ "$DEVICE_COUNT" -eq 0 ]; then - echo "错误: 没有已连接的 Android 设备。" - exit 1 + echo "错误: 没有已连接的 Android 设备。" + exit 1 fi if [ "$DEVICE_COUNT" -gt 1 ]; then - echo "警告: 检测到多个设备,将使用默认设备。" + echo "警告: 检测到多个设备,将使用默认设备。" fi # 检查应用是否已安装 if ! adb shell pm list packages | grep -q "${PACKAGE}"; then - echo "错误: 应用 ${PACKAGE} 未安装。请先运行 ./gradlew :app:installDebug" - if [ "$USE_TRACE_BUILD" = true ]; then - echo " 或使用 ./gradlew :app:installTrace 安装 trace 构建" - fi - exit 1 + echo "错误: 应用 ${PACKAGE} 未安装。请先运行 ./gradlew :app:installDebug" + if [ "$USE_TRACE_BUILD" = true ]; then + echo " 或使用 ./gradlew :app:installTrace 安装 trace 构建" + fi + exit 1 fi -# 启动应用(如果未禁用) -if [ "$NO_LAUNCH" = false ]; then - echo "" - echo "[1/5] 启动应用..." - adb shell am start -n "${PACKAGE}/${ACTIVITY}" >/dev/null 2>&1 || true - sleep 2 +# ────────────────────────────────────────── +# 批量录制所有自动场景 +# ────────────────────────────────────────── +run_all_scenarios() { + local script="$0" + local per_scene_duration="${DURATION_SEC}" + # --all 模式下默认每个场景 10 秒 + if [ "$per_scene_duration" -eq 8 ]; then + per_scene_duration=10 + fi + + local auto_scenarios=( + month_browse + collapse_expand + year_view + year_select + today_jump + menu_toggle + legal_holiday + tools + about + licenses + all_activities + ) + local total=${#auto_scenarios[@]} + local build_flag="" + [ "$USE_TRACE_BUILD" = true ] && build_flag="--trace" + + echo "" + echo "========================================" + echo " 批量录制模式" + echo " 共 ${total} 个自动场景" + echo " 每个场景 ${per_scene_duration} 秒" + echo "========================================" + echo "" + + local i=0 + for s in "${auto_scenarios[@]}"; do + i=$((i + 1)) + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo " [${i}/${total}] 录制场景: ${s}" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + "$script" --scenario "$s" $build_flag "$per_scene_duration" + if [ "$i" -lt "$total" ]; then + echo "" + echo " 休息 2 秒,准备下一个场景..." + sleep 2 + fi + done + + # 生成汇总报告 + generate_summary_report "$total" "$per_scene_duration" +} + +# 生成批量录制汇总报告 +generate_summary_report() { + local total="$1" + local duration="$2" + local summary_time + summary_time=$(date +%Y%m%d_%H%M%S) + local summary_file="${LOGS_DIR}/report_${summary_time}_ALL_SUMMARY.md" + + echo "" + echo "========================================" + echo " 生成批量录制汇总报告" + echo "========================================" + + cat > "$summary_file" </dev/null | head -1) + if [ -n "$report" ]; then + local tf jf jp p50 p90 p99 sd tp + tf=$(awk '/Total frames rendered:/{print $4; exit}' "${report}") + jf=$(awk '/掉帧数/{getline; print $2; exit}' "${report}") + jp=$(awk '/掉帧比例/{getline; print $2; exit}' "${report}") + p50=$(awk '/50th percentile/{getline; print $2; exit}' "${report}") + p90=$(awk '/90th percentile/{getline; print $2; exit}' "${report}") + p99=$(awk '/99th percentile/{getline; print $2; exit}' "${report}") + sd=$(awk '/Slow draw commands/{getline; print $2; exit}' "${report}") + tp=$(awk '/Total PSS/{getline; print $2; exit}' "${report}") + printf "| %s | %s | %s | %s | %s | %s | %s | %s | %s |\n" "$s" "${tf:-N/A}" "${jf:-N/A}" "${jp:-N/A}" "${p50:-N/A}" "${p90:-N/A}" "${p99:-N/A}" "${sd:-N/A}" "${tp:-N/A}" >> "$summary_file" + fi + done + + cat >> "$summary_file" </dev/null | head -1) + report=$(ls -t "${LOGS_DIR}"/report_*"_${s}".md 2>/dev/null | head -1) + if [ -n "$trace" ]; then + echo "- \`$(basename "$trace")\` + \`$(basename "$report")\` — ${s}" >> "$summary_file" + fi + done + + echo "" >> "$summary_file" + echo "---" >> "$summary_file" + echo "生成时间: $(date '+%Y-%m-%d %H:%M:%S')" >> "$summary_file" + + echo "" + echo "========================================" + echo " 批量录制完成!" + echo "========================================" + echo "" + echo "汇总报告: ${summary_file}" + echo "" +} + +# ────────────────────────────────────────── +# 如果是 --all 模式,直接执行批量录制 +# ────────────────────────────────────────── +if [ "$RUN_ALL" = true ]; then + run_all_scenarios + exit 0 +fi + +# ────────────────────────────────────────── +# 场景准备 +# ────────────────────────────────────────── +if [ -n "$SCENARIO" ]; then + run_scenario "$SCENARIO" else - echo "" - echo "[1/5] 跳过启动 (--no-launch)" + # 默认场景:仅启动应用 + if [ "$NO_LAUNCH" = false ]; then + echo "" + echo "[1/5] 启动应用..." + adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1 || true + sleep 2 + else + echo "" + echo "[1/5] 跳过启动 (--no-launch)" + fi fi +# 如果不是自动场景,给用户一点准备时间 +if [ -n "$SCENARIO" ] && [ "$SCENARIO" = "full_flow" ] || [ "$SCENARIO" = "date_select" ] || [ "$SCENARIO" = "cross_month" ] || [ "$SCENARIO" = "date_checker" ]; then + echo "" + echo "准备开始 trace,请在倒计时结束后立即操作..." + for i in 3 2 1; do + echo " $i..." + sleep 1 + done +fi + +# ────────────────────────────────────────── # 抓取 Perfetto trace +# ────────────────────────────────────────── echo "" echo "[2/5] 抓取 Perfetto trace (${DURATION_SEC}s)..." -echo " 请在设备上操作应用,trace 正在记录..." +if [ -n "$SCENARIO" ]; then + echo " 场景: ${SCENARIO_NAME}" + echo " 自动操作已启动,请按提示完成手动操作..." +else + echo " 请在设备上操作应用,trace 正在记录..." +fi -TRACE_FILE="/data/misc/perfetto-traces/yaya_${TIMESTAMP}.perfetto-trace" -LOCAL_TRACE="${LOGS_DIR}/trace_${TIMESTAMP}.perfetto-trace" -LOCAL_CONFIG="${LOGS_DIR}/.perfetto_config_${TIMESTAMP}.txt" -DEVICE_CONFIG="/data/misc/perfetto-configs/yaya_config_${TIMESTAMP}.txt" +TRACE_FILE="/data/misc/perfetto-traces/yaya_${TIMESTAMP}${SCENARIO_SUFFIX}.perfetto-trace" +LOCAL_TRACE="${LOGS_DIR}/trace_${TIMESTAMP}${SCENARIO_SUFFIX}.perfetto-trace" +LOCAL_CONFIG="${LOGS_DIR}/.perfetto_config_${TIMESTAMP}${SCENARIO_SUFFIX}.txt" +DEVICE_CONFIG="/data/misc/perfetto-configs/yaya_config_${TIMESTAMP}${SCENARIO_SUFFIX}.txt" # 生成本地配置文件,然后 push 到设备 cat > "${LOCAL_CONFIG}" < "${FRAMESTATS_FILE}" # 抓取内存信息 echo "" echo "[4/5] 抓取内存信息..." -MEMINFO_FILE="${LOGS_DIR}/meminfo_${TIMESTAMP}.txt" +MEMINFO_FILE="${LOGS_DIR}/meminfo_${TIMESTAMP}${SCENARIO_SUFFIX}.txt" adb shell dumpsys meminfo "${PACKAGE}" > "${MEMINFO_FILE}" +# ────────────────────────────────────────── # 生成报告摘要 +# ────────────────────────────────────────── echo "" echo "[5/5] 生成摘要..." -REPORT_FILE="${LOGS_DIR}/report_${TIMESTAMP}.md" +REPORT_FILE="${LOGS_DIR}/report_${TIMESTAMP}${SCENARIO_SUFFIX}.md" # 计算帧率相关数据 FRAME_COUNT=$(grep -c "FrameTimeline" "${FRAMESTATS_FILE}" 2>/dev/null || echo "0") @@ -210,7 +873,7 @@ APP_VERSION=$(adb shell dumpsys package "${PACKAGE}" | grep versionName | head - DEVICE_MODEL=$(adb shell getprop ro.product.model 2>/dev/null | tr -d '\r') ANDROID_VERSION=$(adb shell getprop ro.build.version.release 2>/dev/null | tr -d '\r') -# 获取内存摘要($NF 取最后一个字段,避免中间空格导致的列错位) +# 获取内存摘要 TOTAL_PSS=$(awk '/TOTAL PSS:/{print $3; exit}' "${MEMINFO_FILE}") JAVA_HEAP=$(awk '/^ *Java Heap:/{print $3; exit}' "${MEMINFO_FILE}") NATIVE_HEAP=$(awk '/^ *Native Heap:/{print $3; exit}' "${MEMINFO_FILE}") @@ -224,15 +887,27 @@ cat > "${REPORT_FILE}" <> "${REPORT_FILE}" <> "${REPORT_FILE}" < "${REPORT_FILE}" <> "${REPORT_FILE}" <> "${REPORT_FILE}" <> "${REPORT_FILE}" <> "${REPORT_FILE}" <> "${REPORT_FILE}" <> "${REPORT_FILE}" <> "${REPORT_FILE}" <> "${REPORT_FILE}" <> "${REPORT_FILE}" <> "${REPORT_FILE}" <> "${REPORT_FILE}" <> "${REPORT_FILE}" < "${REPORT_FILE}" <