anr log打印流程---Java层

前言

本问介绍一下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的第一个log
            aboveSystem = 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

@Override
    public void saveANRStateLocked(ActivityRecord activity, WindowState windowState,
                                   String reason) {
        super.saveANRStateLocked(activity, windowState, reason);
        dumpWindowStatusLocked(activity);//dump windowStatus
        dumpAllWindowStatusLocked();//dump all windowStatus
        //Unisoc:add WMS eventId(102200000) for UniEvent
        if (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
        @Override
        public 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 AnrRecord
            mAnrRecords.add(new AnrRecord(anrProcess, activityShortComponentName, aInfo,
                    parentShortComponentName, parentProcess, aboveSystem, annotation));
        }
        //start 循环mAnrRecords
        startAnrConsumerIfNeeded();
    }
    private void startAnrConsumerIfNeeded() {
        if (mRunning.compareAndSet(false, true)) {
            new AnrConsumerThread().start();
        }
    }

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

        @Override
        public 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 -----
		//内存压力log
        StringBuilder report = new StringBuilder();
        report.append(MemoryPressureUtil.currentPsiState());
        ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);

        //Unisoc: if the ANR is simulated by cts, native backtrace will be ignored
        boolean 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 interest
        String[] 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];
		//tracesFile
        File 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 log
            Process.sendSignal(pid, Process.SIGNAL_QUIT);
        } else if (offsets[1] > 0) {
			//保存tracesFile
            // We've dumped into the trace file successfully
            mService.mProcessList.mAppExitInfoTracker.scheduleLogAnrTrace(
                    pid, mApp.uid, mApp.getPackageList(), tracesFile, offsets[0], offsets[1]);
        }

        // Check if package is still being loaded
        float 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 loading
                Slog.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 package
            info.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,直接kill
            if (isSilentAnr() && !mApp.isDebugging()) {
                mApp.killLocked("bg anr", ApplicationExitInfo.REASON_ANR, true);
                return;
            }

            synchronized (mProcLock) {
                // Set the app's notResponding state, and look up the errorReportReceiver
                makeAppNotRespondingLSP(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 dialog
                Message 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

你可能感兴趣的:(稳定性,frameworks,log分析,java,android,开发语言)