SWT 重启案例分析(一)

 

极力推荐文章:欢迎收藏
Android 干货分享 

 

本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:

1.MTK AEE Log分析工具
2.AEE Log分析流程
3.system_server 卡死案例分析及解决

本文主要针对 Exception Type: system_server_watchdog , system_server卡死找出的分析以及解决方案。

一、MTK AEE Log分析工具

MTK AEE Log 获取方式:

关注微信公众号: 程序员Android
回复 aee 即可获取解析重启db log的工具。

二、AEE Log分析流程

1. 使用AEE 工具解析 dbg 文件。

使用解析db.fatal.02.SWT.dbg

AEE Log 解析出来的文件

2.分析解析出来的exp_main等文件

exp_main 文件会记录发生重启时候的 log 打印信息。

部分重启异常 Log信息如下:

$** *** *** *** *** *** *** *** Fatal *** *** *** *** *** *** *** **$
Build Info: 'alps-mp-o1.mp7:alps-mp-o1.mp7:mt6765:S01,ACE/AS0618/AS0618:8.1.0/O11019/1548123508:user/release-keys'
Flavor Info: 'None'
Exception Log Time:[Thu Mar 14 14:00:03 CST 2019] [38684.729626]

Exception Class: SWT
Exception Type: system_server_watchdog

Current Executing Process: 
system_server


Trigger time:[2019-03-14 14:00:03.711844] pid:1029

Backtrace: 
Process: system_server
Subject: Blocked in handler on ActivityManager (ActivityManager)
Build: ACE/AS0618/AS0618:8.1.0/O11019/1548123508:user/release-keys

**exp_main 文件解析 **
从开头的Log总体信息概览,我们可以看到 发生重启的时间类型触发重启的进程以及PID系统Blocked 的地方

结合exp_main以及 trace分析重启 Log
Log分析如下:

// 1.重启触发时间,以及PID 
Trigger time:[2019-03-14 14:00:03.711844] pid:1029
// 2.Blocked 的进程
Backtrace: 
Process: system_server
Subject: Blocked in handler on ActivityManager (ActivityManager)
// 3.根据PID 查看Trace信息
----- pid 1029 at 2019-03-14 13:59:58 -----
Cmd line: system_server

... ...
// 4.根据Backtrace 查看Blocked的信息
"ActivityManager" prio=5 tid=11 Blocked

... ...
// 5.tid=11 等待 tid=106的线程释放资源锁
  - waiting to lock <0x090691f3> (a android.util.ArrayMap) held by thread 106  
... ...

// 6.查看tid = 106 持锁情况
"backup" prio=5 tid=106 Waiting
... ... 

  at java.lang.Object.wait(Native method)
  - waiting on <0x06a44c62> (a com.android.server.am.ContentProviderRecord)
// 7.死锁卡住的地方
  at com.android.server.am.ActivityManagerService.getContentProviderImpl(ActivityManagerService.java:12127)
  - locked <0x06a44c62> (a com.android.server.am.ContentProviderRecord)
  
  ...  ...

"Binder:1029_8" prio=5 tid=107 Blocked
// 8.log中  tid=107 被 106 Blocked 进一步问题的加重
  at com.android.server.notification.RankingHelper.getRecord(RankingHelper.java:258)
  - waiting to lock <0x090691f3> (a android.util.ArrayMap) held by thread 106
  
$** *** *** *** *** *** *** *** Fatal *** *** *** *** *** *** *** **$

Log 分析大致过程截图

完整 log 请在公众号上获取

3.system_server 卡死案例分析及解决

通过 Log 找到卡死原因后,解决此问题。
需要修改ActivityManagerService类。

代码路径如下:alps/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

解决思路:
避免 provider 长时间持锁触发MTK 60s 的SWT 重启机制,设置超时时间,超过时间就要释放资源锁,避免发生此问题。

diff 修改方案如下:

--- a/[alps/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java](http://192.168.11.104/gitweb/?p=alps-mp-o1.mp1-V1.git;a=blob;f=alps/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java;h=d5e2e1411f3698a829e997d402c7482ec277fa8c;hb=d5e2e1411f3698a829e997d402c7482ec277fa8c)

+++ b/[alps/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java](http://192.168.11.104/gitweb/?p=alps-mp-o1.mp1-V1.git;a=blob;f=alps/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java;h=03208f78a2bf3167b4f0790019326e3939cc5444;hb=03208f78a2bf3167b4f0790019326e3939cc5444)

@@ [-545,7](http://192.168.11.104/gitweb/?p=alps-mp-o1.mp1-V1.git;a=blob;f=alps/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java;h=d5e2e1411f3698a829e997d402c7482ec277fa8c;hb=d5e2e1411f3698a829e997d402c7482ec277fa8c#l545) [+545,9](http://192.168.11.104/gitweb/?p=alps-mp-o1.mp1-V1.git;a=blob;f=alps/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java;h=03208f78a2bf3167b4f0790019326e3939cc5444;hb=03208f78a2bf3167b4f0790019326e3939cc5444#l545) @@ public class ActivityManagerService extends IActivityManager.Stub

     // How long we wait for an attached process to publish its content providers

     // before we decide it must be hung.

     static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000;

-

+    // How long we wait for provider to be notify before we decide it may be hung.

+    static final int CONTENT_PROVIDER_WAIT_TIMEOUT = 20*1000;

+       

     // How long we wait for a launched process to attach to the activity manager

     // before we decide it's never going to come up for real, when the process was

     // started with a wrapper for instrumentation (such as Valgrind) because it

@@ [-1745,6](http://192.168.11.104/gitweb/?p=alps-mp-o1.mp1-V1.git;a=blob;f=alps/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java;h=d5e2e1411f3698a829e997d402c7482ec277fa8c;hb=d5e2e1411f3698a829e997d402c7482ec277fa8c#l1745) [+1747,7](http://192.168.11.104/gitweb/?p=alps-mp-o1.mp1-V1.git;a=blob;f=alps/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java;h=03208f78a2bf3167b4f0790019326e3939cc5444;hb=03208f78a2bf3167b4f0790019326e3939cc5444#l1747) @@ public class ActivityManagerService extends IActivityManager.Stub

     static final int PUSH_TEMP_WHITELIST_UI_MSG = 68;

     static final int SERVICE_FOREGROUND_CRASH_MSG = 69;

     static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70;

+        static final int CONTENT_PROVIDER_WAIT_TIMEOUT_MSG = 71;

     static final int START_USER_SWITCH_FG_MSG = 712;

     static final int NOTIFY_VR_KEYGUARD_MSG = 74;

@@ [-2108,6](http://192.168.11.104/gitweb/?p=alps-mp-o1.mp1-V1.git;a=blob;f=alps/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java;h=d5e2e1411f3698a829e997d402c7482ec277fa8c;hb=d5e2e1411f3698a829e997d402c7482ec277fa8c#l2108) [+2111,12](http://192.168.11.104/gitweb/?p=alps-mp-o1.mp1-V1.git;a=blob;f=alps/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java;h=03208f78a2bf3167b4f0790019326e3939cc5444;hb=03208f78a2bf3167b4f0790019326e3939cc5444#l2111) @@ public class ActivityManagerService extends IActivityManager.Stub

                 synchronized (ActivityManagerService.this) {

                     mActivityStarter.doPendingActivityLaunchesLocked(true);

                 }

+            } break;

+                       case CONTENT_PROVIDER_WAIT_TIMEOUT_MSG: {

+                ContentProviderRecord cpr = (ContentProviderRecord)msg.obj;

+                synchronized (ActivityManagerService.this) {

+                    processContentProviderWaitTimedOutLocked(cpr);

+                }

             } break;

             case KILL_APPLICATION_MSG: {

                 synchronized (ActivityManagerService.this) {

@@ [-7029,7](http://192.168.11.104/gitweb/?p=alps-mp-o1.mp1-V1.git;a=blob;f=alps/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java;h=d5e2e1411f3698a829e997d402c7482ec277fa8c;hb=d5e2e1411f3698a829e997d402c7482ec277fa8c#l7029) [+7038,31](http://192.168.11.104/gitweb/?p=alps-mp-o1.mp1-V1.git;a=blob;f=alps/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java;h=03208f78a2bf3167b4f0790019326e3939cc5444;hb=03208f78a2bf3167b4f0790019326e3939cc5444#l7038) @@ public class ActivityManagerService extends IActivityManager.Stub

         cleanupAppInLaunchingProvidersLocked(app, true);

         removeProcessLocked(app, false, true, "timeout publishing content providers");

     }

+       

+    @GuardedBy("this")

+    private final void processContentProviderWaitTimedOutLocked(ContentProviderRecord cpr) {

+        try {

+            if (mLaunchingProviders.contains(cpr)) {

+                if (DEBUG_MU) Slog.v(TAG_MU,

+                    "Remove from mLaunchingProviders, " + cpr

+                    + " launchingApp=" + cpr.launchingApp);

+                mLaunchingProviders.remove(cpr);

+            }

+            if (DEBUG_MU) Slog.v(TAG_MU,

+                "RemoveMessages CONTENT_PROVIDER_WAIT_TIMEOUT_MSG, " + cpr

+                + " launchingApp=" + cpr.launchingApp);

+            mHandler.removeMessages(CONTENT_PROVIDER_WAIT_TIMEOUT_MSG, cpr);

+            synchronized (cpr) {

+                cpr.notifyAll();

+                cpr.launchingApp = null;

+            }

+        } catch (Exception e) {

+            if (DEBUG_MU) Slog.v(TAG_MU,

+                "processContentProviderWaitTimedOutLocked exception, " + e);

+        }

+    }

+       

     private final void processStartTimedOutLocked(ProcessRecord app) {

         final int pid = app.pid;

         boolean gone = false;

@@ [-12124,11](http://192.168.11.104/gitweb/?p=alps-mp-o1.mp1-V1.git;a=blob;f=alps/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java;h=d5e2e1411f3698a829e997d402c7482ec277fa8c;hb=d5e2e1411f3698a829e997d402c7482ec277fa8c#l12124) [+12157,33](http://192.168.11.104/gitweb/?p=alps-mp-o1.mp1-V1.git;a=blob;f=alps/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java;h=03208f78a2bf3167b4f0790019326e3939cc5444;hb=03208f78a2bf3167b4f0790019326e3939cc5444#l12157) @@ public class ActivityManagerService extends IActivityManager.Stub

                     if (conn != null) {

                         conn.waiting = true;

                     }

+                                       // add 20s wait timeout,avoid 

+                    if (!mHandler.hasMessages(CONTENT_PROVIDER_WAIT_TIMEOUT_MSG, cpr)) {

+                        if (DEBUG_MU) Slog.v(TAG_MU,

+                            "SendMessageDelayed CONTENT_PROVIDER_WAIT_TIMEOUT_MSG, " + cpr

+                            + " launchingApp=" + cpr.launchingApp);

+                        Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_WAIT_TIMEOUT_MSG);

+                        msg.obj = cpr;

+                        mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_WAIT_TIMEOUT);

+                    } else {

+                        if (DEBUG_MU) Slog.v(TAG_MU,

+                            "There is another waiting to start provider " + cpr

+                            + " launchingApp=" + cpr.launchingApp

+                            + ", not send CONTENT_PROVIDER_WAIT_TIMEOUT_MSG again");

+                    }

+                                       

                     cpr.wait();

                 } catch (InterruptedException ex) {

                 } finally {

                     if (conn != null) {

                         conn.waiting = false;

+                    }

+                                       // remove wait time out message

+                    if (mHandler.hasMessages(CONTENT_PROVIDER_WAIT_TIMEOUT_MSG, cpr)) {

+                        if (DEBUG_MU) Slog.v(TAG_MU,

+                            "After wait removeMessages CONTENT_PROVIDER_WAIT_TIMEOUT_MSG, "

+                            + cpr + " launchingApp=" + cpr.launchingApp);

+                            mHandler.removeMessages(CONTENT_PROVIDER_WAIT_TIMEOUT_MSG, cpr);

                     }

                 }

             }

长按识别二维码,领福利

至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

如有侵权,请联系小编,小编对此深感抱歉,届时小编会删除文章,立即停止侵权行为,请您多多包涵。

小礼物走一走,来简书关注我

<think> 我们正在讨论的是SWT(Software Watchdog)问题,尤其是在Android系统中的表现。SWT是Android系统中用于监控系统服务响应的种看门狗机制,当系统服务(如主线程)长时间未响应时,SWT会触发系统重启以防止系统挂死。根据引用[2]和引用[3],我们可以了解到SWT的原理和常见原因。 用户提到想查找关于SWT问题的相关解决方案或信息。结合引用[2]中的内容,我们了解到SWT重启的原因可能包括: 1. 主线程(UI线程)被阻塞(如锁竞争、死锁、长时间操作) 2. Binder通信超时(Server端未及时响应) 3. Native方法执行时间过长 4. SurfaceFlinger卡住 5. Zygote Fork进程卡住 6. Dump时间过长(如生成ANR日志耗时太久) 另外,引用[3]解释了UI线程的重要性,即所有UI操作必须在同线程中执行,否则会导致资源竞争和效率低下。 因此,针对SWT问题,我们可以从以下几个方面提供解决方案: ### 1. **分析日志定位问题** 根据引用[2]: - 搜索日志中的关键字`watchdog`,找到触发SWT的具体服务(如`ActivityManager`、`SurfaceFlinger`等)。 - 搜索关键字`held by`,检查是否有线程持有锁时间过长。 - 检查Binder的Server端(如AMS、WMS等)是否响应超时,通过Binder线程的调用栈分析。 ### 2. **解决主线程阻塞** - **避免在主线程执行耗时操作**:如网络请求、数据库操作、复杂计算等,应使用工作线程(如`AsyncTask`、`HandlerThread`、`ThreadPoolExecutor`)处理。 - **减少同步锁竞争**:避免在主线程中等待其他线程的锁,尤其是跨进程的Binder调用。如果必须使用锁,确保锁的持有时间尽可能短。 - **检查死锁**:使用工具(如`adb shell dumpsys window`或`adb shell dumpsys activity`)检查主线程的锁持有情况,排查循环等待。 ### 3. **优化Binder通信** - **确保Binder服务端及时响应**:Binder调用(尤其是非oneway)应在5秒内完成,否则会触发ANR或SWT。优化服务端逻辑,避免阻塞。 - 使用`adb shell dumpsys batterystats --binder`监控Binder调用耗时。 - 如果Binder调用对端进程繁忙,可考虑增加Binder线程池大小(通过`ProcessState::setThreadPoolMaxThreadCount`在Native层或`Binder.setMaxThreads`在Java层)。 ### 4. **处理Native层问题** - 如果日志显示Native方法执行时间过长(如引用[2]中的案例4.4),使用`perfetto`或`systrace`工具分析CPU使用情况。 - 检查JNI方法是否执行了复杂操作,优化算法或移到子线程。 ### 5. **SurfaceFlinger和图形系统** - 如果SurfaceFlinger卡住(引用[2]中4.5),检查GPU驱动或硬件合成器(HWC)是否异常。更新GPU驱动或禁用硬件加速测试。 - 减少过度绘制,优化UI布局。 ### 6. **Zygote优化** - Zygote fork进程耗时过长(引用[2]中4.6)通常由资源竞争引起。确保Zygote启动时加载的预加载类/资源不过多。可通过`adb shell dumpsys meminfo zygote`检查内存。 ### 7. **避免Dump操作超时** - 生成ANR日志或`dumpsys`输出时,避免在系统服务中保存过多历史数据。优化`dump`方法,分页输出或异步处理。 ### 示例:解决主线程阻塞导致的SWT ```java // 错误示例:在主线程执行耗时操作 public void onClick(View view) { // 模拟耗时操作(>5秒) try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } // 正确做法:使用工作线程 public void onClick(View view) { new Thread(() -> { // 执行耗时操作 try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } // 更新UI需切回主线程 runOnUiThread(() -> textView.setText("Done")); }).start(); } ``` ### 总结 解决SWT问题的核心是**确保系统关键服务(尤其是主线程和Binder线程)及时响应**。通过日志分析定位阻塞点,优化代码逻辑,避免长时间阻塞。同时,监控工具(如`systrace`、`perfetto`)和系统命令(如`dumpsys`)是辅助分析的关键[^2][^3]。 §§相关问题§§ 1. 如何通过日志分析Android SWT重启的具体原因? 2. 有哪些工具可以监控Android主线程的阻塞情况? 3. 如何优化Binder通信以避免超时? </think> ### SWT问题分析与解决方案 SWT(Software Watchdog)是Android系统的软件看门狗机制,用于监控系统关键服务响应状态。当系统服务响应超时(默认5秒)时,SWT会触发系统重启以防止系统完全挂死。以下是针对SWT问题的全面分析与解决方案: #### 1. **SWT问题诊断方法** [^2] - **日志关键字段搜索**: - `adb logcat | grep "watchdog"`:定位SWT重启事件 - `adb logcat | grep "held by"`:查找锁竞争导致的线程阻塞 - `adb shell dumpsys activity processes`:检查Binder服务端状态 - **线程阻塞分析**: ```bash # 检查持有锁的线程 adb shell dumpsys window | grep -A 10 "Blocked in" ``` #### 2. **常见原因与解决方案** - **主线程阻塞**(UI线程)[^3]: - **现象**:UI无响应导致SWT重启 - **解决**: ```java // 将耗时操作移出主线程 new Thread(() -> { // 后台任务(如网络请求/数据库操作) runOnUiThread(() -> updateUI()); // UI更新需切回主线程 }).start(); ``` - **Binder通信超时**: - **诊断**:检查Binder对端服务是否阻塞(`dumpsys activity top`) - **优化**: - 服务端添加`oneway`关键字(异步调用) - 增大Binder线程池:`BinderInternal.setMaxThreads(32)` - **Native方法卡死** [^2]: - **现象**:`SystemServer`卡在JNI调用 - **工具**:使用`perfetto`抓取Native调用栈 - **滚动视图问题**SWT组件相关)[^4]: - **修复滚动条异常**: ```java // 避免使用getOrigin()获取大偏移量 ScrollBar hBar = scrolledComposite.getHorizontalBar(); int scrollPos = hBar.getSelection(); // 正确获取滚动位置 ``` #### 3. **预防性措施** - **锁优化**: - 使用`tryLock()`替代阻塞锁 - 设置锁超时:`lock.tryLock(500, TimeUnit.MILLISECONDS)` - **性能监控**: ```bash adb shell am hang --allow-restart # 模拟ANR测试 ``` - **系统参数调整**: ```bash adb shell setprop debug.checkjni 1 # 开启JNI检查 adb shell setprop persist.sys.watchdog.timeout 10000 # 延长超时阈值(ms) ``` #### 4. **典型案例分析** [^2] - **SurfaceFlinger卡死**: - 现象:图形合成器未及时返回`VSYNC` - 解决:更新GPU驱动或禁用硬件加速 - **Zygote进程卡住**: - 诊断:`adb shell ps | grep zygote` - 措施:清理预加载资源或重启`zygote` > **关键提示**:80%的SWT问题由主线程阻塞或跨进程死锁引起,优先检查UI线程和Binder通信链[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员Android

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值