anr log打印流程---Java层

news/2024/10/20 14:10:39/

前言

本问介绍一下anr之后,系统打印log的流程。加深对anr问题的理解。

anr触发原理分析可以看看这个文章http://gityuan.com/2017/01/01/input-anr/

cpp代码比较多,我选择放弃了。从java层log往后看吧。。。

ANR Log

anr触发在native层,触发后回调Java层打印anr log和cpu信息等。
本文以input事件anr为例,进行调试。

1、frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

private void notifyWindowUnresponsive(IBinder token, int pid, boolean isPidValid,String reason) {mWindowManagerCallbacks.notifyWindowUnresponsive(token,isPidValid ? OptionalInt.of(pid) : OptionalInt.empty(), reason);}

2、frameworks/base/services/core/java/com/android/server/wm/InputManagerCallback.java

public void notifyWindowUnresponsive(@NonNull IBinder token, @NonNull OptionalInt pid,@NonNull String reason) {mService.mAnrController.notifyWindowUnresponsive(token, pid, reason);}

3、frameworks/base/services/core/java/com/android/server/wm/AnrController.java

void notifyWindowUnresponsive(@NonNull IBinder token, @NonNull OptionalInt pid,@NonNull String reason) {if (notifyWindowUnresponsive(token, reason)) {return;}if (!pid.isPresent()) {Slog.w(TAG_WM, "Failed to notify that window token=" + token + " was unresponsive.");return;}notifyWindowUnresponsive(pid.getAsInt(), reason);}private boolean notifyWindowUnresponsive(@NonNull IBinder inputToken, String reason) {preDumpIfLockTooSlow();final int pid;final boolean aboveSystem;final ActivityRecord activity;synchronized (mService.mGlobalLock) {InputTarget target = mService.getInputTargetFromToken(inputToken);if (target == null) {return false;}WindowState windowState = target.getWindowState();pid = target.getPid();// Blame the activity if the input token belongs to the window. If the target is// embedded, then we will blame the pid instead.activity = (windowState.mInputChannelToken == inputToken)? windowState.mActivityRecord : null;Slog.i(TAG_WM, "ANR in " + target + ". Reason:" + reason);//触发anr的第一个logaboveSystem = isWindowAboveSystem(windowState);dumpAnrStateLocked(activity, windowState, reason);//dump anr log}if (activity != null) {activity.inputDispatchingTimedOut(reason, pid);//anr in cpu那段log} else {mService.mAmInternal.inputDispatchingTimedOut(pid, aboveSystem, reason);}return true;}
private void dumpAnrStateLocked(ActivityRecord activity, WindowState windowState,String reason) {mService.saveANRStateLocked(activity, windowState, reason);mService.mAtmService.saveANRState(reason);}
3.1、frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

saveANRStateLocked

vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/wm/UnisocWindowManagerService.java
saveANRStateLocked

@Overridepublic void saveANRStateLocked(ActivityRecord activity, WindowState windowState,String reason) {super.saveANRStateLocked(activity, windowState, reason);dumpWindowStatusLocked(activity);//dump windowStatusdumpAllWindowStatusLocked();//dump all windowStatus//Unisoc:add WMS eventId(102200000) for UniEventif (windowState != null) {UniEvent uniEvent = new UniEvent(102200000);uniEvent.putInt("Visible",windowState.mViewVisibility).putInt("State",windowState.mWinAnimator.mDrawState);UniView.report(uniEvent);}}
3.2、frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
        @Overridepublic boolean inputDispatchingTimedOut(Object proc, String activityShortComponentName,ApplicationInfo aInfo, String parentShortComponentName, Object parentProc,boolean aboveSystem, String reason) {return ActivityManagerService.this.inputDispatchingTimedOut((ProcessRecord) proc,activityShortComponentName, aInfo, parentShortComponentName,(WindowProcessController) parentProc, aboveSystem, reason);}boolean inputDispatchingTimedOut(ProcessRecord proc, String activityShortComponentName,ApplicationInfo aInfo, String parentShortComponentName,WindowProcessController parentProcess, boolean aboveSystem, String reason) {...checkDevicePowerOnOrPowerOff();//自己加的log,anr之前打印一下是否灭屏//最终会调用到这里mAnrHelper.appNotResponding(proc, activityShortComponentName, aInfo,parentShortComponentName, parentProcess, aboveSystem, annotation);}return true;}
3.2.1、frameworks/base/services/core/java/com/android/server/am/AnrHelper.java
    void appNotResponding(ProcessRecord anrProcess, String activityShortComponentName,ApplicationInfo aInfo, String parentShortComponentName,WindowProcessController parentProcess, boolean aboveSystem, String annotation) {final int incomingPid = anrProcess.mPid;synchronized (mAnrRecords) {...//add new AnrRecordmAnrRecords.add(new AnrRecord(anrProcess, activityShortComponentName, aInfo,parentShortComponentName, parentProcess, aboveSystem, annotation));}//start 循环mAnrRecordsstartAnrConsumerIfNeeded();}private void startAnrConsumerIfNeeded() {if (mRunning.compareAndSet(false, true)) {new AnrConsumerThread().start();}}

private class AnrConsumerThread extends Thread是AnrHelper的内部类
直接看run方法

        @Overridepublic void run() {AnrRecord r;while ((r = next()) != null) {...final long startTime = SystemClock.uptimeMillis();// If there are many ANR at the same time, the latency may be larger. If the latency// is too large, the stack trace might not be meaningful.final long reportLatency = startTime - r.mTimestamp;final boolean onlyDumpSelf = reportLatency > EXPIRED_REPORT_TIME_MS;r.appNotResponding(onlyDumpSelf);//anr log//anr log打印完成final long endTime = SystemClock.uptimeMillis();Slog.d(TAG, "Completed ANR of " + r.mApp.processName + " in "+ (endTime - startTime) + "ms, latency " + reportLatency+ (onlyDumpSelf ? "ms (expired, only dump ANR app)" : "ms"));}...}}

r.appNotResponding

        void appNotResponding(boolean onlyDumpSelf) {mApp.mErrorState.appNotResponding(mActivityShortComponentName, mAppInfo,mParentShortComponentName, mParentProcess, mAboveSystem, mAnnotation,onlyDumpSelf);}
3.2.2、frameworks/base/services/core/java/com/android/server/am/ProcessErrorStateRecord.java

appNotResponding
这个方法巨长无比,大概有三四百行,简单看一下log信息。
基本上做了这么几件事
1、更新cpu信息
2、am_amr log
2.1、anr 主体log
2.2、Output from /proc/pressure/memory
2.3、printCurrentCpuState
3、tracesFile保存
4、bg anr,直接kill
5、anr dialog弹窗,test的时候不会弹

    void appNotResponding(String activityShortComponentName, ApplicationInfo aInfo,String parentShortComponentName, WindowProcessController parentProcess,boolean aboveSystem, String annotation, boolean onlyDumpSelf) {ArrayList<Integer> firstPids = new ArrayList<>(5);SparseArray<Boolean> lastPids = new SparseArray<>(20);...if (isMonitorCpuUsage()) {mService.updateCpuStatsNow();//更新cpu信息}final boolean isSilentAnr;final int pid = mApp.getPid();final UUID errorId;synchronized (mService) {//am_amr这一行log// Log the ANR to the event log.EventLog.writeEvent(EventLogTags.AM_ANR, mApp.userId, pid, mApp.processName,mApp.info.flags, annotation);...//anr 主体log// Log the ANR to the main log.StringBuilder info = new StringBuilder();info.setLength(0);info.append("ANR in ").append(mApp.processName);if (activityShortComponentName != null) {info.append(" (").append(activityShortComponentName).append(")");}info.append("\n");info.append("PID: ").append(pid).append("\n");if (annotation != null) {info.append("Reason: ").append(annotation).append("\n");}if (parentShortComponentName != null&& parentShortComponentName.equals(activityShortComponentName)) {info.append("Parent: ").append(parentShortComponentName).append("\n");}if (errorId != null) {info.append("ErrorId: ").append(errorId.toString()).append("\n");}info.append("Frozen: ").append(mApp.mOptRecord.isFrozen()).append("\n");...//----- Output from /proc/pressure/memory -----//内存压力logStringBuilder report = new StringBuilder();report.append(MemoryPressureUtil.currentPsiState());ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);//Unisoc: if the ANR is simulated by cts, native backtrace will be ignoredboolean ctsUnresponsive = false;if(Build.IS_DEBUGGABLE && (".unresponsive_activity_process".equals(mApp.processName) || ".render_process".equals(mApp.processName)))ctsUnresponsive = true;// don't dump native PIDs for background ANRs unless it is the process of interestString[] nativeProcs = null;if (isSilentAnr || onlyDumpSelf || ctsUnresponsive) {for (int i = 0; i < NATIVE_STACKS_OF_INTEREST.length; i++) {if (NATIVE_STACKS_OF_INTEREST[i].equals(mApp.processName)) {nativeProcs = new String[] { mApp.processName };break;}}} else {nativeProcs = NATIVE_STACKS_OF_INTEREST;}int[] pids = nativeProcs == null ? null : Process.getPidsForCommands(nativeProcs);ArrayList<Integer> nativePids = null;if (pids != null) {nativePids = new ArrayList<>(pids.length);for (int i : pids) {nativePids.add(i);}}// For background ANRs, don't pass the ProcessCpuTracker to// avoid spending 1/2 second collecting stats to rank lastPids.StringWriter tracesFileException = new StringWriter();// To hold the start and end offset to the ANR trace file respectively.final long[] offsets = new long[2];//tracesFileFile tracesFile = ActivityManagerService.dumpStackTraces(firstPids,isSilentAnr ? null : processCpuTracker, isSilentAnr ? null : lastPids,nativePids, tracesFileException, offsets, annotation, criticalEventLog);if (isMonitorCpuUsage()) {mService.updateCpuStatsNow();mService.mAppProfiler.printCurrentCpuState(report, anrTime);//cpu状态添加到report字符串info.append(processCpuTracker.printCurrentLoad());info.append(report);//最终都添加到info字符串里了}report.append(tracesFileException.getBuffer());info.append(processCpuTracker.printCurrentState(anrTime));// Dumps tasks that are in uninterrruptable state(D-state)if (Build.IS_DEBUGGABLE && !lowram) {doSysrq('w');}//anr main log 打印Slog.e(TAG, info.toString());if (tracesFile == null) {// There is no trace file, so dump (only) the alleged culprit's threads to the logProcess.sendSignal(pid, Process.SIGNAL_QUIT);} else if (offsets[1] > 0) {//保存tracesFile// We've dumped into the trace file successfullymService.mProcessList.mAppExitInfoTracker.scheduleLogAnrTrace(pid, mApp.uid, mApp.getPackageList(), tracesFile, offsets[0], offsets[1]);}// Check if package is still being loadedfloat loadingProgress = 1;IncrementalMetrics incrementalMetrics = null;final PackageManagerInternal packageManagerInternal = mService.getPackageManagerInternal();if (mApp.info != null && mApp.info.packageName != null && packageManagerInternal != null) {IncrementalStatesInfo incrementalStatesInfo =packageManagerInternal.getIncrementalStatesInfo(mApp.info.packageName, SYSTEM_UID, mApp.userId);if (incrementalStatesInfo != null) {loadingProgress = incrementalStatesInfo.getProgress();}final String codePath = mApp.info.getCodePath();if (codePath != null && !codePath.isEmpty()&& IncrementalManager.isIncrementalPath(codePath)) {// Report in the main log that the incremental package is still loadingSlog.e(TAG, "App ANR on incremental package " + mApp.info.packageName+ " which is " + ((int) (loadingProgress * 100)) + "% loaded.");final IBinder incrementalService = ServiceManager.getService(Context.INCREMENTAL_SERVICE);if (incrementalService != null) {final IncrementalManager incrementalManager = new IncrementalManager(IIncrementalService.Stub.asInterface(incrementalService));incrementalMetrics = incrementalManager.getMetrics(codePath);}}}if (incrementalMetrics != null) {// Report in the main log about the incremental packageinfo.append("Package is ").append((int) (loadingProgress * 100)).append("% loaded.\n");}...if (mApp.getWindowProcessController().appNotResponding(info.toString(),() -> {synchronized (mService) {mApp.killLocked("anr", ApplicationExitInfo.REASON_ANR, true);}},() -> {synchronized (mService) {mService.mServices.scheduleServiceTimeoutLocked(mApp);}})) {return;}synchronized (mService) {// mBatteryStatsService can be null if the AMS is constructed with injector only. This// will only happen in tests.if (mService.mBatteryStatsService != null) {mService.mBatteryStatsService.noteProcessAnr(mApp.processName, mApp.uid);}//bg anr,直接killif (isSilentAnr() && !mApp.isDebugging()) {mApp.killLocked("bg anr", ApplicationExitInfo.REASON_ANR, true);return;}synchronized (mProcLock) {// Set the app's notResponding state, and look up the errorReportReceivermakeAppNotRespondingLSP(activityShortComponentName,annotation != null ? "ANR " + annotation : "ANR", info.toString());mDialogController.setAnrController(anrController);}//anr ui弹框// mUiHandler can be null if the AMS is constructed with injector only. This will only// happen in tests.if (mService.mUiHandler != null) {// Bring up the infamous App Not Responding dialogMessage msg = Message.obtain();msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;msg.obj = new AppNotRespondingDialog.Data(mApp, aInfo, aboveSystem);mService.mUiHandler.sendMessageDelayed(msg, anrDialogDelayMs);}}}

vendor/sprd/platform/frameworks/base/services/ex-interface/core/java/com/android/server/am/UnisocProcessErrorStateRecord.java
appNotResponding
展锐平台自定义的类,为了额外dump一些log信息。

结尾

啊 心好累,第一次跟踪anr log流程,相关的类太多了。

相关的类都在frameworks/base/services/core/java/com/android/server下面
主流程就在这些类里,里面可能会调用其它相关的类dump当前状态的log。
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
frameworks/base/services/core/java/com/android/server/wm/InputManagerCallback.java
frameworks/base/services/core/java/com/android/server/wm/AnrController.java
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/wm/UnisocWindowManagerService.java
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
frameworks/base/services/core/java/com/android/server/am/AnrHelper.java
frameworks/base/services/core/java/com/android/server/am/ProcessErrorStateRecord.java


http://www.ppmy.cn/news/90014.html

相关文章

11-FastDFS文件服务器 和 Nginx

1、什么是FastDFS 1、开源的轻量级分布式文件系统,用于解决大数据量存储和负载均衡等问题。 2、优点: 支持HTTP协议传输文件(结合Nginx); 对文件内容做Hash处理,节约磁盘空间; 支持负载均衡、整体性能较佳。 3、FastDFS的二个角色:跟踪服务器(Tracker)、存储服务器…

ApplicationRunner使用

本文来说下CommandLineRunner和ApplicationRunner的使用 文章目录 ApplicationRunner使用示例程序结果 CommandLineRunner使用示例程序结果 ApplicationListener触发时机使用实例程序结果注意问题 ApplicationRunner 使用起来很简单&#xff0c;只需要实现CommandLineRunner或者…

第三十四回:AlertDialog Widget

文章目录 概念介绍使用方法示例代码 我们在上一章回中介绍了Dismissible Widget相关的内容,本章回中将介绍 AlertDialog Widget.闲话休提&#xff0c;让我们一起Talk Flutter吧。 概念介绍 我们介绍的AlertDialog是指程序中弹出的确认窗口&#xff0c;其实我们在上一章回中删…

网易易盾流量多发反外挂落地实践

背景及目的 环境迁移 反外挂服务建德机房线上迁移&#xff0c;采取的方案是&#xff1a;建德机房独立部署一套完整的集群&#xff0c;统一经由完整的性能测试、故障演练、功能回归后&#xff0c;通过线上分阶段切换流量的方式来切服务。QA 需要比对验证 2 个不同环境下核心接口…

多目标遗传算法NSGA-II改进策略

上篇写道了关于多目标遗传算法NSGA-II原理详解及算法代码实现&#xff0c;本文将继续在这篇文章的基础上更深一步的向前探索&#xff0c;探索方向为&#xff1a; 基于NSGA-II算法的固有缺点&#xff0c;着重对其算法提出改进策略&#xff0c;并予以代码实现。同样&#xff0c;本…

1112 Stucked Keyboard (PAT甲级)

写完后看柳婼的解法&#xff0c;其实可以直接数重复了几次&#xff0c;我这个写法有点复杂化了。 原代码&#xff1a; #include <iostream> #include <string> #include <set>int main(){int k, j;bool flag;std::set<char> st, printed;std::string…

codeforce第874轮(div3)

地址&#xff1a;codeforce第84轮&#xff08;div3&#xff09; A&#xff1a; 题目的意思是&#xff1a;给定我们一堆包含两个字符的字符串&#xff0c;字符串a和字符串b只要a的后一个字母和b的前一个字母相等即可链接&#xff0c;现在给出最后链接好的字符串&#xff0c;问…

〖Web全栈开发⑤〗— CSS基础

〖Web全栈开发⑤〗— CSS基础 (一)CSS基础1.1CSS介绍1.2CSS样式1.3CSS 格式 &#xff08;二&#xff09;CSS 选择器2.1标签选择器2.2类选择器2.3层级选择器2.4id选择器2.5组选择器2.6伪类选择器2.7通配符选择器 &#xff08;三&#xff09;样式表引入3.1外部样式表3.2内部样式表…