19 KiB
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,问题在于:
- CPU过载导致SurfaceFlinger无法及时获得调度
- 多图层合成计算量大
优化方案(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:应用层修改(需要重新编译应用)
修改以下文件并重新编译:
YX_Avm/.../V4L2CameraManager.javaYX_Avm/.../AvmService.javaYX_Voice/.../VoiceService.java
步骤3:系统层修改(需要重新编译系统)
修改以下文件并重新编译系统镜像:
system/core/lmkd/lmkd.c- PSI阈值frameworks/base/services/core/java/com/android/server/am/ProcessList.java- minfreeframeworks/base/services/core/java/com/android/server/am/ActivityManagerConstants.java- 缓存配置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调度不及时 |
解决方向
- 应用层优先:修复AVM和TXZ的CPU异常占用(预期释放165%+ CPU)
- 系统层配合:调整内存管理策略,减少进程回收导致的二次卡顿
- 渲染优化:提高SurfaceFlinger调度优先级,保障UI流畅
报告生成完毕
诊断工具:Android Lag Analyzer v1.0 + 代码静态分析 生成时间:2026-04-18