Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 09934793 authored by Andrii Kulian's avatar Andrii Kulian Committed by Android (Google) Code Review
Browse files

Merge "Fix crash loop when activity controller was set" into nyc-dev

parents e0c73c3f fa3991aa
Loading
Loading
Loading
Loading
+130 −117
Original line number Diff line number Diff line
@@ -304,6 +304,15 @@ class AppErrors {
     * @param crashInfo describing the failure
     */
    void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
        final long origId = Binder.clearCallingIdentity();
        try {
            crashApplicationInner(r, crashInfo);
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

    void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
        long timeMillis = System.currentTimeMillis();
        String shortMsg = crashInfo.exceptionClassName;
        String longMsg = crashInfo.exceptionMessage;
@@ -317,49 +326,20 @@ class AppErrors {
        AppErrorResult result = new AppErrorResult();
        TaskRecord task;
        synchronized (mService) {
            if (mService.mController != null) {
                try {
                    String name = r != null ? r.processName : null;
                    int pid = r != null ? r.pid : Binder.getCallingPid();
                    int uid = r != null ? r.info.uid : Binder.getCallingUid();
                    if (!mService.mController.appCrashed(name, pid,
                            shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
                        if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
                                && "Native crash".equals(crashInfo.exceptionClassName)) {
                            Slog.w(TAG, "Skip killing native crashed app " + name
                                    + "(" + pid + ") during testing");
                        } else {
                            Slog.w(TAG, "Force-killing crashed app " + name
                                    + " at watcher's request");
                            if (r != null) {
                                r.kill("crash", true);
                            } else {
                                // Huh.
                                Process.killProcess(pid);
                                ActivityManagerService.killProcessGroup(uid, pid);
                            }
                        }
            /**
             * If crash is handled by instance of {@link android.app.IActivityController},
             * finish now and don't show the app error dialog.
             */
            if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace,
                    timeMillis)) {
                return;
            }
                } catch (RemoteException e) {
                    mService.mController = null;
                    Watchdog.getInstance().setActivityController(null);
                }
            }

            final long origId = Binder.clearCallingIdentity();

            // If this process is running instrumentation, finish it.
            /**
             * If this process was running instrumentation, finish now - it will be handled in
             * {@link ActivityManagerService#handleAppDiedLocked}.
             */
            if (r != null && r.instrumentationClass != null) {
                Slog.w(TAG, "Error in app " + r.processName
                        + " running instrumentation " + r.instrumentationClass + ":");
                if (shortMsg != null) Slog.w(TAG, "  " + shortMsg);
                if (longMsg != null) Slog.w(TAG, "  " + longMsg);
                Bundle info = new Bundle();
                info.putString("shortMsg", shortMsg);
                info.putString("longMsg", longMsg);
                mService.finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
                Binder.restoreCallingIdentity(origId);
                return;
            }

@@ -375,7 +355,6 @@ class AppErrors {
            // If we can't identify the process or it's already exceeded its crash quota,
            // quit right away without showing a crash dialog.
            if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) {
                Binder.restoreCallingIdentity(origId);
                return;
            }

@@ -385,15 +364,11 @@ class AppErrors {
            task = data.task;
            msg.obj = data;
            mService.mUiHandler.sendMessage(msg);

            Binder.restoreCallingIdentity(origId);
        }

        int res = result.get();

        Intent appErrorIntent = null;
        final long ident = Binder.clearCallingIdentity();
        try {
        MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res);
        if (res == AppErrorDialog.TIMEOUT) {
            res = AppErrorDialog.FORCE_QUIT;
@@ -474,9 +449,6 @@ class AppErrors {
                        SystemClock.uptimeMillis());
            }
        }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }

        if (appErrorIntent != null) {
            try {
@@ -487,6 +459,47 @@ class AppErrors {
        }
    }

    private boolean handleAppCrashInActivityController(ProcessRecord r,
                                                       ApplicationErrorReport.CrashInfo crashInfo,
                                                       String shortMsg, String longMsg,
                                                       String stackTrace, long timeMillis) {
        if (mService.mController == null) {
            return false;
        }

        try {
            String name = r != null ? r.processName : null;
            int pid = r != null ? r.pid : Binder.getCallingPid();
            int uid = r != null ? r.info.uid : Binder.getCallingUid();
            if (!mService.mController.appCrashed(name, pid,
                    shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
                if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
                        && "Native crash".equals(crashInfo.exceptionClassName)) {
                    Slog.w(TAG, "Skip killing native crashed app " + name
                            + "(" + pid + ") during testing");
                } else {
                    Slog.w(TAG, "Force-killing crashed app " + name
                            + " at watcher's request");
                    if (r != null) {
                        if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null))
                        {
                            r.kill("crash", true);
                        }
                    } else {
                        // Huh.
                        Process.killProcess(pid);
                        ActivityManagerService.killProcessGroup(uid, pid);
                    }
                }
                return true;
            }
        } catch (RemoteException e) {
            mService.mController = null;
            Watchdog.getInstance().setActivityController(null);
        }
        return false;
    }

    private boolean makeAppCrashingLocked(ProcessRecord app,
            String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
        app.crashing = true;