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

571 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`
```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,触发频繁的进程回收
**优化方案:**
```java
// ===== 优化:调整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`
```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 对于车载系统偏少
- 服务重试次数过多可能导致资源浪费
**优化方案:**
```java
// ===== 优化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`
```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阈值偏激进,触发过早导致频繁杀进程
**优化方案:**
```c
// ===== 优化:调整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`
```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设置):**
```bash
# ===== 内存管理优化 =====
# 提高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`
```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`
```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:立即生效(无需重新编译系统)
```bash
# 通过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` | 系统属性配置 | 待修改 |
---
## 七、验证与监控
### 优化效果验证命令
```bash
# 检查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"
```
### 持续监控脚本
```bash
# 创建监控脚本 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