processus d'impression du journal anr --- couche Java

avant-propos

Cette question présente le processus par lequel le système imprime le journal après anr. Approfondir la compréhension de tous les problèmes.

L'analyse du principe de déclenchement Anr peut voir cet article http://gityuan.com/2017/01/01/input-anr/

Il y a plus de codes cpp, j'ai donc choisi d'abandonner. Revenons sur le journal de la couche Java. . .

Journal ANR

anr est déclenché sur la couche native, et après le déclenchement, il rappelle la couche Java pour imprimer le journal anr et les informations sur le processeur.
Cet article prend l'événement d'entrée anr comme exemple pour déboguer.

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

fournisseur/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();
        }
    }

classe privée AnrConsumerThread extends Thread est la classe interne d'AnrHelper,
voir directement la méthode 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

La méthode appNotResponding
est extrêmement longue, avec environ trois ou quatre cents lignes. Il suffit de regarder les informations du journal.
En gros, j'ai fait quelques choses
1. Mettre à jour les informations sur le processeur
2. Journal am_amr
2.1, journal du corps principal et anr
2.2, sortie de /proc/pression/memory 2.3
, printCurrentCpuState
3, enregistrer tracesFile
4, bg anr, tuer directement
5, et boîte de dialogue Pop- fenêtre ouverte, elle ne s'affichera pas pendant le 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);
            }
        }
    }

seller/sprd/platform/frameworks/base/services/ex-interface/core/java/com/android/server/am/UnisocProcessErrorStateRecord.java appNotResponding Classe personnalisée
de la plateforme Zhanrui
, afin de vider certaines informations de journal supplémentaires.

fin

Ah, je suis tellement fatiguée. C'est la première fois que je suis en train de suivre le processus de journalisation de l'anr. Il y a trop de classes liées.

Les classes pertinentes se trouvent toutes sous frameworks/base/services/core/java/com/android/server
. Le processus principal se trouve dans ces classes, qui peuvent appeler d'autres classes associées pour vider le journal d'état actuel.
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
supplier/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

Guess you like

Origin blog.csdn.net/a396604593/article/details/130885779