Files
Obsidian/日常文档/Android卡顿诊断报告_系统层优化版.md
T
2026-11-05 14:35:04 +08:00

19 KiB
Raw Blame History

Android 设备卡顿诊断报告(系统层+应用层综合优化版)

诊断时间:2026-04-18
应用代码路径:F:\code\git_project\xcmg\xcmg
系统代码路径:S:\znzc\034_xcmg\x9hp_xcmg\androd10_x9hp_ptg4.3p3\android10


一、诊断数据汇总

设备信息

项目 值
设备型号 x9 for arm64 (车载设备)
Android 版本 10 (API 29)
CPU 8核 arm64, 1.6GHz
总内存 4,383 MB
Swap 1,753 MB

系统状态诊断

指标 数值 状态 说明
Load Average 12.7 🔴 严重过载 8核CPU,正常应<8,当前超载1.6倍
可用内存 584 MB (13%) 🔴 紧张 低于安全阈值20%
IRQ/SIRQ 13% 🔴 过高 中断处理负担重
surfaceflinger CPU 18% 🟡 偏高 图形合成压力大

高资源占用进程

进程 CPU 内存 问题
com.yaxon.avm 89% 255MB AVM全景监控CPU异常
com.txzing.voiceassistant 76% 563MB 语音助手CPU+内存双高
surfaceflinger 18% 51MB 渲染合成压力

二、问题根因分析

🔴 根因链

┌─────────────────────────────────────────────────────────────────┐
│                      卡顿根本原因链                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  [应用层问题]                                                    │
│  ├─ AVM无限激活重试 + Native密集调用 → 89% CPU                   │
│  ├─ TXZ语音助手WebSocket失败无限重试 → 76% CPU + 563MB          │
│  └─ YX_Voice无重试限制 → 持续触发连接                            │
│                                                                 │
│            ║                                                    │
│            ║ 累计占用165%+ CPU                                   │
│            ▼                                                    │
│  [系统层压力]                                                    │
│  ├─ Load Average 12.7 → 任务队列过长                            │
│  ├─ 内存可用13% → LMKD频繁杀进程                                 │
│  ├─ surfaceflinger无法及时合成 → 18% CPU                        │
│  └─ IRQ/SIRQ 13% → 硬件中断处理慢                                │
│                                                                 │
│            ║                                                    │
│            ▼                                                    │
│  [渲染管线阻塞]                                                  │
│  ├─ Launcher主线程等待CPU → 88.89%卡顿帧                        │
│  ├─ SystemUI主线程阻塞 → 302帧跳帧                              │
│  └─ VSync丢失 → 渲染节奏紊乱                                     │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

三、系统层代码分析与优化

3.1 ProcessList.java - OOM配置分析

文件位置: frameworks/base/services/core/java/com/android/server/am/ProcessList.java

// 第285-298行:OOM adj级别定义
private final int[] mOomAdj = new int[] {
    FOREGROUND_APP_ADJ, VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ,
    PERCEPTIBLE_LOW_APP_ADJ, CACHED_APP_MIN_ADJ, CACHED_APP_LMK_FIRST_ADJ
};

// 第291-294行:低内存设备的minfree配置(KB)
private final int[] mOomMinFreeLow = new int[] {
    12288, 18432, 24576, 36864, 43008, 49152  // 12MB, 18MB, 24MB, 36MB, 42MB, 48MB
};

// 第297-299行:高内存设备的minfree配置(KB)
private final int[] mOomMinFreeHigh = new int[] {
    73728, 92160, 110592, 129024, 147456, 184320  // 72MB, 90MB, 108MB, 126MB, 144MB, 180MB
};

问题分析:

  • 当前设备4.3GB内存,使用的是动态计算的minfree值
  • 可用内存仅584MB,触发频繁的进程回收

优化方案:

// ===== 优化:调整OOM minfree阈值 =====
// 修改 ProcessList.java 第291-299行

// 针对4GB内存车载设备,适当提高阈值避免频繁杀进程
// 原值基于1GB设备设计,对于4GB设备过于激进
private final int[] mOomMinFreeHigh = new int[] {
    122880, 153600, 184320,  // 120MB, 150MB, 180MB (前台/可见/感知)
    245760, 307200, 368640   // 240MB, 300MB, 360MB (缓存级别)
};
// 提高约33%,减少频繁杀进程导致的卡顿

3.2 ActivityManagerConstants.java - 服务管理优化

文件位置: frameworks/base/services/core/java/com/android/server/am/ActivityManagerConstants.java

// 第81行:最大缓存进程数
private static final int DEFAULT_MAX_CACHED_PROCESSES = 8;

// 第103行:服务最大不活跃时间
private static final long DEFAULT_MAX_SERVICE_INACTIVITY = 30*60*1000;  // 30分钟

// 第107行:绑定服务崩溃最大重试
private static final int DEFAULT_BOUND_SERVICE_CRASH_MAX_RETRY = 16;

问题分析:

  • MAX_CACHED_PROCESSES=8 对于车载系统偏少
  • 服务重试次数过多可能导致资源浪费

优化方案:

// ===== 优化1:增加缓存进程数 =====
// 车载系统有更多常驻服务,适当增加缓存容量
private static final int DEFAULT_MAX_CACHED_PROCESSES = 12;  // 原8改为12

// ===== 优化2:减少服务崩溃重试次数 =====
// 避免崩溃服务反复重启占用资源
private static final int DEFAULT_BOUND_SERVICE_CRASH_MAX_RETRY = 5;  // 原16改为5

3.3 lmkd.c - 低内存杀手配置优化

文件位置: system/core/lmkd/lmkd.c

// 第182-186行:PSI压力阈值配置
static struct psi_threshold psi_thresholds[VMPRESS_LEVEL_COUNT] = {
    { PSI_SOME, 70 },    // 70ms out of 1sec for partial stall
    { PSI_SOME, 100 },   // 100ms out of 1sec for partial stall
    { PSI_FULL, 70 },    // 70ms out of 1sec for complete stall
};

问题分析:

  • PSI阈值偏激进,触发过早导致频繁杀进程

优化方案:

// ===== 优化:调整PSI阈值减少过早触发 =====
// 修改 lmkd.c 第182-186行
static struct psi_threshold psi_thresholds[VMPRESS_LEVEL_COUNT] = {
    { PSI_SOME, 100 },    // 100ms(原70ms)- 放宽容忍度
    { PSI_SOME, 150 },    // 150ms(原100ms)
    { PSI_FULL, 100 },    // 100ms(原70ms)
};
// 减少内存压力误触发,避免频繁杀进程

3.4 SurfaceFlinger.cpp - 渲染管线优化

文件位置: frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

当前渲染合成占用18% CPU,问题在于:

  1. CPU过载导致SurfaceFlinger无法及时获得调度
  2. 多图层合成计算量大

优化方案(Scheduler层面):

文件位置: frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp

// ===== 优化:提高渲染线程优先级 =====
// 在 Scheduler.cpp 中添加优先级提升

// 第134-150行附近,创建EventThread时提高优先级
std::unique_ptr<EventThread> eventThread =
    makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
                    offsetThresholdForNextVsync, std::move(interceptCallback));

// 提高渲染相关线程的调度优先级
// 在EventThread创建后设置:
if (eventThread) {
    // 设置更高的调度优先级,确保渲染及时
    eventThread->setSchedPriority(SCHED_PRIORITY_REALTIME);
}

3.5 系统属性配置优化

建议添加的系统属性(build.prop或通过adb设置):

# ===== 内存管理优化 =====
# 提高LMKD阈值,减少过早触发
ro.lmk.psi_partial_stall_ms=150
ro.lmk.psi_complete_stall_ms=100
ro.lmk.low=100
ro.lmk.medium=200
ro.lmk.critical=500

# ===== 进程管理优化 =====
# 增加缓存进程数
ro.sys.fw.bg_apps_limit=12
ro.sys.fw.max_cached_processes=12

# ===== 渲染优化 =====
# 提高渲染线程优先级
debug.sf.set_idle_timer_ms=100
debug.sf.enable_gl_backpressure=1

# ===== CPU调度优化 =====
# 降低后台进程对CPU的影响
ro.sys.fw.bg_cpu_percent=10

四、应用层代码优化(结合之前分析)

4.1 YX_Avm模块优化

文件位置: F:\code\git_project\xcmg\xcmg\YX_Avm\src\main\java\com\android\v4l2camera\V4L2CameraManager.java

// ===== 优化1:添加激活超时机制 =====
// 修改 avmActivatedIfNeed() 方法(第166-181行)

private static final long ACTIVATION_TIMEOUT_MS = 30000; // 30秒超时
private final ExecutorService mActivationExecutor = Executors.newSingleThreadExecutor();

public void avmActivatedIfNeed() {
    if (isAvmActivated) {
        Log.i(TAG, "avmActivatedIfNeed isAvmActivated -> true");
        return;
    }
    if (mActivatedThread != null && mActivatedThread.isAlive()) {
        Log.i(TAG, "avmActivatedIfNeed mActivatedThread is alive");
        return;
    }
    
    mActivatedThread = new Thread(() -> {
        Future<Boolean> future = mActivationExecutor.submit(() -> 
            mV4L2CameraManager.activatedAvmModule());
        
        try {
            future.get(ACTIVATION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        } catch (TimeoutException e) {
            Log.w(TAG, "AVM activation timeout, cancelling");
            future.cancel(true);
            // 延迟重试,避免立即重试占用CPU
            mHandler.postDelayed(() -> avmActivatedIfNeed(), 60000);
        } catch (Exception e) {
            Log.e(TAG, "AVM activation error", e);
        }
    });
    mActivatedThread.setName("T_AvmActivated");
    mActivatedThread.start();
}

// ===== 优化2:图像处理移至子线程 =====
// 修改 saveYuvImageToFrontPng() 等方法(第695-820行)

private final ExecutorService mImageProcessExecutor = Executors.newFixedThreadPool(2);

private void saveYuvImageToFrontPng(byte[] yuvData, int width, int height) {
    if (calibDirection != AvmConstant.CalibCameraView.AVM_CALIBRATION_FRONT) {
        return;
    }
    
    // 异步处理,避免阻塞回调线程
    mImageProcessExecutor.execute(() -> {
        String filePath = AvmConstant.SDCARD_CALIBRATION_PATH;
        File file = new File(filePath);
        if (!file.exists()) file.mkdirs();
        
        String temFile = file.getAbsolutePath() + File.separator + "front.jpg";
        try {
            YuvImage image = new YuvImage(yuvData, ImageFormat.NV21, width, height, null);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            image.compressToJpeg(new Rect(0, 0, width, height), 100, baos);
            
            Bitmap bmp = BitmapFactory.decodeByteArray(baos.toByteArray(), 0, baos.toByteArray().length);
            FileOutputStream fos = new FileOutputStream(temFile);
            bmp.compress(Bitmap.CompressFormat.JPEG, 90, fos); // 降低质量减少CPU
            fos.close();
            baos.close();
            
            if (calibraResultCallBack != null) {
                mHandler.post(() -> calibraResultCallBack.onFrontCapture(temFile));
            }
        } catch (Exception e) {
            Log.e(TAG, "saveYuvImageToFrontPng error", e);
        }
    });
}

// ===== 优化3:添加ContentObserver防抖 =====
// 修改 AvmService.java 第160-217行

private ContentObserver mContentObserver = new ContentObserver(null) {
    private long mLastCallbackTime = 0;
    private static final long MIN_CALLBACK_INTERVAL = 200; // 200ms最小间隔
    
    @Override
    public void onChange(boolean selfChange, Uri uri) {
        super.onChange(selfChange, uri);
        if (uri == null) return;
        
        // 防抖处理
        long currentTime = System.currentTimeMillis();
        if (currentTime - mLastCallbackTime < MIN_CALLBACK_INTERVAL) {
            Log.d(TAG, "onChange throttled: " + uri.toString());
            return;
        }
        mLastCallbackTime = currentTime;
        
        // 原有的处理逻辑...
    }
};

4.2 YX_Voice模块优化

文件位置: F:\code\git_project\xcmg\xcmg\YX_Voice\src\main\java\com\yaxon\voice\service\VoiceService.java

// ===== 优化:添加连接重试限制 =====
// 修改 VoiceService.java

private int mConnectRetryCount = 0;
private static final int MAX_CONNECT_RETRY = 3;
private static final long[] RETRY_DELAY_MS = {5000, 15000, 60000}; // 5s, 15s, 60s

private void initTxz() {
    try {
        // 检测网络可用性
        if (!isNetworkAvailable()) {
            Log.w(TAG, "Network not available, delay connect");
            scheduleReconnect(10000);
            return;
        }
        
        // ... 原有的初始化代码
    } catch (Throwable e) {
        Log.e(TAG, "initTxz error", e);
        scheduleReconnect(RETRY_DELAY_MS[Math.min(mConnectRetryCount, RETRY_DELAY_MS.length - 1)]);
    }
}

@Override
public void onDisconnected() {
    Log.d(TAG,"TXZ onDisconnected");
    VoiceManager.getInstance().setVoiceBind(false);
    
    if (mConnectRetryCount < MAX_CONNECT_RETRY) {
        long delay = RETRY_DELAY_MS[mConnectRetryCount];
        Log.d(TAG, "Schedule reconnect in " + delay + "ms, retry=" + (mConnectRetryCount + 1));
        scheduleReconnect(delay);
        mConnectRetryCount++;
    } else {
        Log.w(TAG, "Max retry count reached (" + MAX_CONNECT_RETRY + "), stop reconnecting");
        // 网络恢复后再重试
        registerNetworkRecoveryListener();
    }
}

@Override
public void onConnected() {
    Log.d(TAG,"TXZ onConnected");
    mConnectRetryCount = 0; // 连接成功重置计数
    // ... 原有代码
}

private void scheduleReconnect(long delayMs) {
    mHandler.removeCallbacks(mReconnectRunnable);
    mHandler.postDelayed(mReconnectRunnable, delayMs);
}

private final Runnable mReconnectRunnable = () -> {
    if (isNetworkAvailable()) {
        mConnectRetryCount = 0;
        initTxz();
    }
};

private boolean isNetworkAvailable() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
}

4.3 TXZ语音助手SDK优化需求

需联系TXZ技术支持(同舟行科技)提出以下需求:

序号 问题描述 优化要求 优先级
1 WebSocket连接失败后无限重试 添加重试次数限制(最多3次) P0
2 重试间隔固定约3秒 添加指数退避(5s→15s→60s) P0
3 网络不可达时仍重试 检测网络状态,不可达时暂停 P0
4 内存占用563MB过高 优化内存使用,减少缓存 P1
5 CPU占用76%异常 检查SDK内部循环/定时器 P0

五、综合优化方案实施清单

优先级排序

优先级 层级 模块 优化内容 预期效果
P0 应用 TXZ SDK 重试限制、指数退避 释放76% CPU
P0 应用 YX_Avm 激活超时、图像异步 降低CPU峰值
P0 应用 YX_Voice 重试限制、网络检测 降低重试频率
P1 系统 lmkd.c PSI阈值调整 减少频繁杀进程
P1 系统 ProcessList minfree调整 增加缓存容量
P1 系统 ActivityManagerConstants 缓存进程数 减少进程重建
P2 系统 Scheduler 渲染优先级 提升UI响应
P2 系统 build.prop 系统属性 全局优化

实施步骤

步骤1:立即生效(无需重新编译系统)

# 通过adb设置临时属性验证效果
adb shell "setprop ro.lmk.psi_partial_stall_ms 150"
adb shell "setprop ro.lmk.psi_complete_stall_ms 100"
adb shell "setprop ro.sys.fw.bg_apps_limit 12"

# 强制停止问题应用
adb shell "am force-stop com.yaxon.avm"
adb shell "am force-stop com.txzing.voiceassistant"

步骤2:应用层修改(需要重新编译应用)

修改以下文件并重新编译:

  1. YX_Avm/.../V4L2CameraManager.java
  2. YX_Avm/.../AvmService.java
  3. YX_Voice/.../VoiceService.java

步骤3:系统层修改(需要重新编译系统)

修改以下文件并重新编译系统镜像:

  1. system/core/lmkd/lmkd.c - PSI阈值
  2. frameworks/base/services/core/java/com/android/server/am/ProcessList.java - minfree
  3. frameworks/base/services/core/java/com/android/server/am/ActivityManagerConstants.java - 缓存配置
  4. device/.../build.prop - 系统属性

六、代码修改文件清单

应用层修改

文件路径 修改内容 状态
YX_Avm/src/.../V4L2CameraManager.java 激活超时、图像异步处理 待修改
YX_Avm/src/.../AvmService.java ContentObserver防抖 待修改
YX_Voice/src/.../VoiceService.java 连接重试限制、网络检测 待修改

系统层修改

文件路径 修改内容 状态
system/core/lmkd/lmkd.c PSI阈值调整 待修改
frameworks/base/services/.../ProcessList.java minfree阈值调整 待修改
frameworks/base/services/.../ActivityManagerConstants.java 缓存配置调整 待修改
frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp 渲染优先级 待修改
device/.../system.prop 或 build.prop 系统属性配置 待修改

七、验证与监控

优化效果验证命令

# 检查CPU负载
adb shell "top -n 1 | head -15"

# 检查内存状态
adb shell "cat /proc/meminfo | grep -E 'MemTotal|MemAvailable'"

# 检查进程杀次数
adb shell "cat /proc/vmstat | grep -i kill"

# 检查渲染性能
adb shell "dumpsys gfxinfo com.yaxon.launcher"

# 检查LMKD状态
adb shell "logcat -d | grep lmkd | tail -20"

持续监控脚本

# 创建监控脚本 monitor.sh
#!/bin/bash
while true; do
    echo "=== $(date) ==="
    echo "CPU Load:"
    adb shell "top -n 1 | head -5"
    echo "Memory:"
    adb shell "cat /proc/meminfo | grep -E 'MemTotal|MemFree|MemAvailable'"
    echo "Janky frames:"
    adb shell "dumpsys gfxinfo com.yaxon.launcher | grep 'Janky frames'"
    sleep 10
done

八、结论

核心问题

层级 问题 占用 根因
应用层 AVM 89% CPU 激活无超时、图像处理阻塞
应用层 TXZ语音助手 76% CPU WebSocket失败无限重试
系统层 内存紧张 13%可用 PSI阈值激进、频繁杀进程
系统层 渲染阻塞 18% CPU surfaceflinger调度不及时

解决方向

  1. 应用层优先:修复AVM和TXZ的CPU异常占用(预期释放165%+ CPU)
  2. 系统层配合:调整内存管理策略,减少进程回收导致的二次卡顿
  3. 渲染优化:提高SurfaceFlinger调度优先级,保障UI流畅

报告生成完毕

诊断工具:Android Lag Analyzer v1.0 + 代码静态分析 生成时间:2026-04-18